Merge m-c to fx-team. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 11 Feb 2015 16:30:25 -0500
changeset 228869 2273277538f8de702794f630df2187dfd2f6eef5
parent 228868 c11a0930afc24693fb9f316ac28491142668a20d (current diff)
parent 228702 650863f6987b37f96a4b9b234a6ff00ff4323a1e (diff)
child 228870 aa618f42c5a61f25423d59eebbcac0dfb5b33b35
push idunknown
push userunknown
push dateunknown
reviewersmerge
milestone38.0a1
Merge m-c to fx-team. a=merge
dom/base/nsElementFrameLoaderOwner.cpp
dom/base/nsElementFrameLoaderOwner.h
security/sandbox/chromium-shim/base/threading/thread_local_storage.h
security/sandbox/chromium/base/atomicops_internals_tsan.h
security/sandbox/chromium/base/file_util.h
security/sandbox/chromium/base/file_util_win.cc
security/sandbox/chromium/sandbox/linux/seccomp-bpf/demo.cc
security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_compatibility_policy.h
security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_policy.cc
security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_policy.h
security/sandbox/chromium/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
testing/mozbase/manifestparser/manifestparser/manifestparser.py
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="6295c4eb38de793159368aa7f745ef3faf7208aa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
@@ -126,13 +126,13 @@
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="f3cedd7fd9b1649aa5107d466be9078bb7602af6"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f5f7fa2fc26b96d2cbd0af4569c0036fe034bb43"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
-  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="7de2e90f8d27aa7047978aa10c911f1035fe57dd"/>
+  <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="c3971822a2b6ddddf92be818083717959af10304"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="6295c4eb38de793159368aa7f745ef3faf7208aa">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="f47964c89a9c34d9a2e77afa3608d9ec604c3d20">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "462a2ef9e98134255c144e373c7392440e3ee03b", 
+        "git_revision": "e280a660955bbdab265d50f8d9e009de34082332", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "e6a1cfc70305b3695b694d7e66b03c51f2a45b1f", 
+    "revision": "c652fe8c56b48721611f4a004ba1324c5279c3d8", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ac778ae59be38aea284a04c89640b1a11c26a5de">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="462a2ef9e98134255c144e373c7392440e3ee03b"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e280a660955bbdab265d50f8d9e009de34082332"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="da777082e02eec11c4b7e27679bdb15f47a44f66"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -589,16 +589,17 @@
 @BINPATH@/components/InterAppMessagePort.js
 
 @BINPATH@/components/nsDOMIdentity.js
 @BINPATH@/components/nsIDService.js
 @BINPATH@/components/Identity.manifest
 
 @BINPATH@/components/SystemMessageInternal.js
 @BINPATH@/components/SystemMessageManager.js
+@BINPATH@/components/SystemMessageCache.js
 @BINPATH@/components/SystemMessageManager.manifest
 @BINPATH@/components/HCIEventTransactionSystemMessage.manifest
 @BINPATH@/components/HCIEventTransactionSystemMessageConfigurator.js
 
 @BINPATH@/components/Activities.manifest
 @BINPATH@/components/ActivityProxy.js
 @BINPATH@/components/ActivityRequestHandler.js
 @BINPATH@/components/ActivityWrapper.js
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -574,16 +574,17 @@
 #endif
 
 @RESPATH@/components/TCPSocket.js
 @RESPATH@/components/TCPServerSocket.js
 @RESPATH@/components/TCPSocketParentIntermediary.js
 @RESPATH@/components/TCPSocket.manifest
 
 #ifdef MOZ_ACTIVITIES
+@RESPATH@/components/SystemMessageCache.js
 @RESPATH@/components/SystemMessageInternal.js
 @RESPATH@/components/SystemMessageManager.js
 @RESPATH@/components/SystemMessageManager.manifest
 
 @RESPATH@/components/Activities.manifest
 @RESPATH@/components/ActivityProxy.js
 @RESPATH@/components/ActivityRequestHandler.js
 @RESPATH@/components/ActivityWrapper.js
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1153,17 +1153,17 @@ endif
 
 ################################################################################
 # Install a linked .xpt into the appropriate place.
 # This should ideally be performed by the non-recursive idl make file. Some day.
 ifdef XPT_NAME #{
 
 ifndef NO_DIST_INSTALL
 ifndef NO_INTERFACES_MANIFEST
-misc:: $(call mkdir_deps,$(FINAL_TARGET)/components)
+export:: $(call mkdir_deps,$(FINAL_TARGET)/components)
 	$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)')
 	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/interfaces.manifest')
 endif
 endif
 
 endif #} XPT_NAME
 
 ################################################################################
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -66,17 +66,16 @@ EXPORTS += [
     'nsDocumentWarningList.h',
     'nsDOMAttributeMap.h',
     'nsDOMCID.h',
     'nsDOMClassInfoClasses.h',
     'nsDOMClassInfoID.h',
     'nsDOMJSUtils.h',
     'nsDOMNavigationTiming.h',
     'nsDOMString.h',
-    'nsElementFrameLoaderOwner.h',
     'nsFocusManager.h',
     'nsFrameMessageManager.h',
     'nsGenericDOMDataNode.h',
     'nsGkAtomList.h',
     'nsGkAtoms.h',
     'nsHostObjectProtocolHandler.h',
     'nsIAttribute.h',
     'nsIContent.h',
@@ -255,17 +254,16 @@ UNIFIED_SOURCES += [
     'nsDOMFileReader.cpp',
     'nsDOMMutationObserver.cpp',
     'nsDOMNavigationTiming.cpp',
     'nsDOMScriptObjectFactory.cpp',
     'nsDOMSerializer.cpp',
     'nsDOMSettableTokenList.cpp',
     'nsDOMTokenList.cpp',
     'nsDOMWindowList.cpp',
-    'nsElementFrameLoaderOwner.cpp',
     'nsFocusManager.cpp',
     'nsFormData.cpp',
     'nsFrameLoader.cpp',
     'nsGenConImageContent.cpp',
     'nsGenericDOMDataNode.cpp',
     'nsGkAtoms.cpp',
     'nsGlobalWindowCommands.cpp',
     'nsHistory.cpp',
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -374,23 +374,21 @@ public:
 
 protected:          // declared protected to silence clang warnings
   const void *mKey; // must be first, to look like PLDHashEntryStub
 
 public:
   nsRefPtr<EventListenerManager> mListenerManager;
 };
 
-static bool
-EventListenerManagerHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
-                                  const void *key)
+static void
+EventListenerManagerHashInitEntry(PLDHashEntryHdr *entry, const void *key)
 {
   // Initialize the entry with placement new
   new (entry) EventListenerManagerMapEntry(key);
-  return true;
 }
 
 static void
 EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
   EventListenerManagerMapEntry *lm =
     static_cast<EventListenerManagerMapEntry *>(entry);
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3952,28 +3952,27 @@ SubDocClearEntry(PLDHashTable *table, PL
 
   NS_RELEASE(e->mKey);
   if (e->mSubDocument) {
     e->mSubDocument->SetParentDocument(nullptr);
     NS_RELEASE(e->mSubDocument);
   }
 }
 
-static bool
-SubDocInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry, const void *key)
+static void
+SubDocInitEntry(PLDHashEntryHdr *entry, const void *key)
 {
   SubDocMapEntry *e =
     const_cast<SubDocMapEntry *>
               (static_cast<const SubDocMapEntry *>(entry));
 
   e->mKey = const_cast<Element*>(static_cast<const Element*>(key));
   NS_ADDREF(e->mKey);
 
   e->mSubDocument = nullptr;
-  return true;
 }
 
 nsresult
 nsDocument::SetSubDocumentFor(Element* aElement, nsIDocument* aSubDoc)
 {
   NS_ENSURE_TRUE(aElement, NS_ERROR_UNEXPECTED);
 
   if (!aSubDoc) {
deleted file mode 100644
--- a/dom/base/nsElementFrameLoaderOwner.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsElementFrameLoaderOwner.h"
-
-#include "nsIDOMDocument.h"
-#include "nsIInterfaceRequestorUtils.h"
-#include "nsContentUtils.h"
-#include "mozilla/Preferences.h"
-#include "mozilla/ErrorResult.h"
-#include "nsIAppsService.h"
-#include "nsServiceManagerUtils.h"
-#include "mozIApplication.h"
-#include "nsIPermissionManager.h"
-#include "GeckoProfiler.h"
-#include "nsIDocument.h"
-#include "nsPIDOMWindow.h"
-
-using namespace mozilla;
-using namespace mozilla::dom;
-
-nsElementFrameLoaderOwner::~nsElementFrameLoaderOwner()
-{
-  if (mFrameLoader) {
-    mFrameLoader->Destroy();
-  }
-}
-
-nsresult
-nsElementFrameLoaderOwner::GetContentDocument(nsIDOMDocument** aContentDocument)
-{
-  NS_PRECONDITION(aContentDocument, "Null out param");
-  nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument());
-  document.forget(aContentDocument);
-  return NS_OK;
-}
-
-nsIDocument*
-nsElementFrameLoaderOwner::GetContentDocument()
-{
-  nsCOMPtr<nsPIDOMWindow> win = GetContentWindow();
-  if (!win) {
-    return nullptr;
-  }
-
-  nsIDocument *doc = win->GetDoc();
-
-  // Return null for cross-origin contentDocument.
-  if (!nsContentUtils::SubjectPrincipal()->
-        SubsumesConsideringDomain(doc->NodePrincipal())) {
-    return nullptr;
-  }
-  return doc;
-}
-
-nsresult
-nsElementFrameLoaderOwner::GetContentWindow(nsIDOMWindow** aContentWindow)
-{
-  NS_PRECONDITION(aContentWindow, "Null out param");
-  nsCOMPtr<nsPIDOMWindow> window = GetContentWindow();
-  window.forget(aContentWindow);
-  return NS_OK;
-}
-
-already_AddRefed<nsPIDOMWindow>
-nsElementFrameLoaderOwner::GetContentWindow()
-{
-  EnsureFrameLoader();
-
-  if (!mFrameLoader) {
-    return nullptr;
-  }
-
-  bool depthTooGreat = false;
-  mFrameLoader->GetDepthTooGreat(&depthTooGreat);
-  if (depthTooGreat) {
-    // Claim to have no contentWindow
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIDocShell> doc_shell;
-  mFrameLoader->GetDocShell(getter_AddRefs(doc_shell));
-
-  nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(doc_shell);
-
-  if (!win) {
-    return nullptr;
-  }
-
-  NS_ASSERTION(win->IsOuterWindow(),
-               "Uh, this window should always be an outer window!");
-
-  return win.forget();
-}
-
-void
-nsElementFrameLoaderOwner::EnsureFrameLoader()
-{
-  Element* thisElement = ThisFrameElement();
-  if (!thisElement->IsInDoc() ||
-      mFrameLoader ||
-      mFrameLoaderCreationDisallowed) {
-    // If frame loader is there, we just keep it around, cached
-    return;
-  }
-
-  // Strangely enough, this method doesn't actually ensure that the
-  // frameloader exists.  It's more of a best-effort kind of thing.
-  mFrameLoader = nsFrameLoader::Create(thisElement, mNetworkCreated);
-  if (mIsPrerendered) {
-    mFrameLoader->SetIsPrerendered();
-  }
-}
-
-NS_IMETHODIMP
-nsElementFrameLoaderOwner::GetFrameLoader(nsIFrameLoader **aFrameLoader)
-{
-  NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
-  return NS_OK;
-}
-
-NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
-nsElementFrameLoaderOwner::GetFrameLoader()
-{
-  nsRefPtr<nsFrameLoader> loader = mFrameLoader;
-  return loader.forget();
-}
-
-NS_IMETHODIMP
-nsElementFrameLoaderOwner::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
-{
-  // We don't support this yet
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-NS_IMETHODIMP
-nsElementFrameLoaderOwner::SetIsPrerendered()
-{
-  MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created");
-  mIsPrerendered = true;
-  return NS_OK;
-}
-
-nsresult
-nsElementFrameLoaderOwner::LoadSrc()
-{
-  EnsureFrameLoader();
-
-  if (!mFrameLoader) {
-    return NS_OK;
-  }
-
-  nsresult rv = mFrameLoader->LoadFrame();
-#ifdef DEBUG
-  if (NS_FAILED(rv)) {
-    NS_WARNING("failed to load URL");
-  }
-#endif
-
-  return rv;
-}
-
-void
-nsElementFrameLoaderOwner::SwapFrameLoaders(nsXULElement& aOtherOwner,
-                                            ErrorResult& aError)
-{
-  aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
-}
deleted file mode 100644
--- a/dom/base/nsElementFrameLoaderOwner.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
-
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsElementFrameLoaderOwner_h
-#define nsElementFrameLoaderOwner_h
-
-#include "mozilla/Attributes.h"
-#include "mozilla/dom/Element.h"
-#include "nsIFrameLoader.h"
-#include "nsIDOMEventListener.h"
-#include "mozilla/dom/FromParser.h"
-#include "mozilla/ErrorResult.h"
-
-#include "nsFrameLoader.h"
-
-namespace mozilla {
-namespace dom {
-class Element;
-} // namespace dom
-} // namespace mozilla
-
-class nsXULElement;
-
-/**
- * A helper class for frame elements
- */
-class nsElementFrameLoaderOwner : public nsIFrameLoaderOwner
-{
-public:
-  explicit nsElementFrameLoaderOwner(mozilla::dom::FromParser aFromParser)
-    : mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
-    , mIsPrerendered(false)
-    , mBrowserFrameListenersRegistered(false)
-    , mFrameLoaderCreationDisallowed(false)
-  {
-  }
-
-  virtual ~nsElementFrameLoaderOwner();
-
-  NS_DECL_NSIFRAMELOADEROWNER
-
-  // nsIContent
-  void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
-
-protected:
-  // This doesn't really ensure a frame loader in all cases, only when
-  // it makes sense.
-  void EnsureFrameLoader();
-  nsresult LoadSrc();
-  nsIDocument* GetContentDocument();
-  nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
-  already_AddRefed<nsPIDOMWindow> GetContentWindow();
-  nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
-
-  /**
-   * Get element for this frame. Avoids diamond inheritance problem.
-   * @return Element for this node
-   */
-  virtual mozilla::dom::Element* ThisFrameElement() = 0;
-
-  nsRefPtr<nsFrameLoader> mFrameLoader;
-
-  /**
-   * True when the element is created by the parser using the
-   * NS_FROM_PARSER_NETWORK flag.
-   * If the element is modified, it may lose the flag.
-   */
-  bool mNetworkCreated;
-
-  bool mIsPrerendered;
-  bool mBrowserFrameListenersRegistered;
-  bool mFrameLoaderCreationDisallowed;
-};
-
-#endif // nsElementFrameLoaderOwner_h
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -94,30 +94,28 @@ GlobalNameHashClearEntry(PLDHashTable *t
     delete e->mGlobalName.mAlias;
   }
 
   // This will set e->mGlobalName.mType to
   // nsGlobalNameStruct::eTypeNotInitialized
   memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct));
 }
 
-static bool
-GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
-                        const void *key)
+static void
+GlobalNameHashInitEntry(PLDHashEntryHdr *entry, const void *key)
 {
   GlobalNameMapEntry *e = static_cast<GlobalNameMapEntry *>(entry);
   const nsAString *keyStr = static_cast<const nsAString *>(key);
 
   // Initialize the key in the entry with placement new
   new (&e->mKey) nsString(*keyStr);
 
   // This will set e->mGlobalName.mType to
   // nsGlobalNameStruct::eTypeNotInitialized
   memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct));
-  return true;
 }
 
 NS_IMPL_ISUPPORTS(
   nsScriptNameSpaceManager,
   nsIObserver,
   nsISupportsWeakReference,
   nsIMemoryReporter)
 
--- a/dom/bluetooth2/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothA2dpManager.cpp
@@ -115,17 +115,18 @@ AvStatusToSinkString(BluetoothA2dpConnec
       aString.AssignLiteral("disconnecting");
       break;
     default:
       BT_WARNING("Unknown sink state %d", static_cast<int>(aState));
       return;
   }
 }
 
-class InitAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
+class BluetoothA2dpManager::InitAvrcpResultHandler MOZ_FINAL
+  : public BluetoothAvrcpResultHandler
 {
 public:
   InitAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -150,17 +151,18 @@ public:
       mRes->Init();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class InitA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
+class BluetoothA2dpManager::InitA2dpResultHandler MOZ_FINAL
+  : public BluetoothA2dpResultHandler
 {
 public:
   InitA2dpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -192,17 +194,18 @@ public:
     BluetoothA2dpManager* a2dpManager = BluetoothA2dpManager::Get();
     sBtAvrcpInterface->Init(a2dpManager, new InitAvrcpResultHandler(mRes));
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothA2dpManager::OnErrorProfileResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
                                       nsresult aRv)
   : mRes(aRes)
   , mRv(aRv)
   {
     MOZ_ASSERT(mRes);
@@ -323,17 +326,18 @@ BluetoothA2dpManager::Get()
   NS_ENSURE_FALSE(sInShutdown, nullptr);
 
   // Create a new instance, register, and return
   BluetoothA2dpManager* manager = new BluetoothA2dpManager();
   sBluetoothA2dpManager = manager;
   return sBluetoothA2dpManager;
 }
 
-class CleanupAvrcpResultHandler MOZ_FINAL : public BluetoothAvrcpResultHandler
+class BluetoothA2dpManager::CleanupAvrcpResultHandler MOZ_FINAL
+  : public BluetoothAvrcpResultHandler
 {
 public:
   CleanupAvrcpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -359,17 +363,18 @@ public:
       mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class CleanupA2dpResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
+class BluetoothA2dpManager::CleanupA2dpResultHandler MOZ_FINAL
+  : public BluetoothA2dpResultHandler
 {
 public:
   CleanupA2dpResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -392,17 +397,18 @@ public:
       mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class CleanupA2dpResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothA2dpManager::CleanupA2dpResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   CleanupA2dpResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   NS_IMETHOD Run() MOZ_OVERRIDE
   {
@@ -456,17 +462,18 @@ BluetoothA2dpManager::OnConnectError()
   MOZ_ASSERT(NS_IsMainThread());
 
   mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
 
   mController = nullptr;
   mDeviceAddress.Truncate();
 }
 
-class ConnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
+class BluetoothA2dpManager::ConnectResultHandler MOZ_FINAL
+  : public BluetoothA2dpResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_LOGR("BluetoothA2dpInterface::Connect failed: %d", (int)aStatus);
 
     NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
     sBluetoothA2dpManager->OnConnectError();
@@ -507,17 +514,18 @@ BluetoothA2dpManager::Connect(const nsAS
 void
 BluetoothA2dpManager::OnDisconnectError()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mController->NotifyCompletion(NS_LITERAL_STRING(ERR_DISCONNECTION_FAILED));
 }
 
-class DisconnectResultHandler MOZ_FINAL : public BluetoothA2dpResultHandler
+class BluetoothA2dpManager::DisconnectResultHandler MOZ_FINAL
+  : public BluetoothA2dpResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_LOGR("BluetoothA2dpInterface::Disconnect failed: %d", (int)aStatus);
 
     NS_ENSURE_TRUE_VOID(sBluetoothA2dpManager);
     sBluetoothA2dpManager->OnDisconnectError();
--- a/dom/bluetooth2/bluedroid/BluetoothA2dpManager.h
+++ b/dom/bluetooth2/bluedroid/BluetoothA2dpManager.h
@@ -61,16 +61,25 @@ public:
   ControlPlayStatus GetPlayStatus();
   uint32_t GetPosition();
   uint64_t GetMediaNumber();
   uint64_t GetTotalMediaNumber();
   void GetTitle(nsAString& aTitle);
   void GetArtist(nsAString& aArtist);
 
 private:
+  class CleanupA2dpResultHandler;
+  class CleanupA2dpResultHandlerRunnable;
+  class CleanupAvrcpResultHandler;
+  class ConnectResultHandler;
+  class DisconnectResultHandler;
+  class InitA2dpResultHandler;
+  class InitAvrcpResultHandler;
+  class OnErrorProfileResultHandlerRunnable;
+
   BluetoothA2dpManager();
   void ResetA2dp();
   void ResetAvrcp();
 
   void HandleShutdown();
   void NotifyConnectionStatusChanged();
 
   void ConnectionStateNotification(BluetoothA2dpConnectionState aState,
--- a/dom/bluetooth2/bluedroid/BluetoothGattManager.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothGattManager.cpp
@@ -44,17 +44,18 @@ BluetoothGattManager::Get()
   NS_ENSURE_FALSE(mInShutdown, nullptr);
 
   // Create a new instance, register, and return
   BluetoothGattManager* manager = new BluetoothGattManager();
   sBluetoothGattManager = manager;
   return sBluetoothGattManager;
 }
 
-class InitGattResultHandler MOZ_FINAL : public BluetoothGattResultHandler
+class BluetoothGattManager::InitGattResultHandler MOZ_FINAL
+  : public BluetoothGattResultHandler
 {
 public:
   InitGattResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -102,17 +103,18 @@ BluetoothGattManager::InitGattInterface(
     sBluetoothGattInterface->GetBluetoothGattClientInterface();
   NS_ENSURE_TRUE_VOID(sBluetoothGattClientInterface);
 
   BluetoothGattManager* gattManager = BluetoothGattManager::Get();
   sBluetoothGattInterface->Init(gattManager,
                                 new InitGattResultHandler(aRes));
 }
 
-class CleanupResultHandler MOZ_FINAL : public BluetoothGattResultHandler
+class BluetoothGattManager::CleanupResultHandler MOZ_FINAL
+  : public BluetoothGattResultHandler
 {
 public:
   CleanupResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -131,17 +133,18 @@ public:
       mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class CleanupResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothGattManager::CleanupResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   CleanupResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   {
     MOZ_ASSERT(mRes);
   }
 
--- a/dom/bluetooth2/bluedroid/BluetoothGattManager.h
+++ b/dom/bluetooth2/bluedroid/BluetoothGattManager.h
@@ -20,16 +20,20 @@ public:
   NS_DECL_NSIOBSERVER
 
   static BluetoothGattManager* Get();
   static void InitGattInterface(BluetoothProfileResultHandler* aRes);
   static void DeinitGattInterface(BluetoothProfileResultHandler* aRes);
   virtual ~BluetoothGattManager();
 
 private:
+  class CleanupResultHandler;
+  class CleanupResultHandlerRunnable;
+  class InitGattResultHandler;
+
   BluetoothGattManager();
 
   void HandleShutdown();
 
   void RegisterClientNotification(int aStatus,
                                   int aClientIf,
                                   const BluetoothUuid& aAppUuid) MOZ_OVERRIDE;
 
--- a/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth2/bluedroid/BluetoothOppManager.cpp
@@ -82,17 +82,17 @@ BluetoothOppManager::Observe(nsISupports
     HandleShutdown();
     return NS_OK;
   }
 
   MOZ_ASSERT(false, "BluetoothOppManager got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
-class SendSocketDataTask : public nsRunnable
+class BluetoothOppManager::SendSocketDataTask : public nsRunnable
 {
 public:
   SendSocketDataTask(uint8_t* aStream, uint32_t aSize)
     : mStream(aStream)
     , mSize(aSize)
   {
     MOZ_ASSERT(!NS_IsMainThread());
   }
@@ -106,17 +106,17 @@ public:
     return NS_OK;
   }
 
 private:
   nsAutoArrayPtr<uint8_t> mStream;
   uint32_t mSize;
 };
 
-class ReadFileTask : public nsRunnable
+class BluetoothOppManager::ReadFileTask : public nsRunnable
 {
 public:
   ReadFileTask(nsIInputStream* aInputStream,
                uint32_t aRemoteMaxPacketSize) : mInputStream(aInputStream)
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     mAvailablePacketSize = aRemoteMaxPacketSize - kPutRequestHeaderSize;
@@ -151,17 +151,17 @@ public:
     return NS_OK;
   };
 
 private:
   nsCOMPtr<nsIInputStream> mInputStream;
   uint32_t mAvailablePacketSize;
 };
 
-class CloseSocketTask : public Task
+class BluetoothOppManager::CloseSocketTask : public Task
 {
 public:
   CloseSocketTask(BluetoothSocket* aSocket) : mSocket(aSocket)
   {
     MOZ_ASSERT(aSocket);
   }
 
   void Run() MOZ_OVERRIDE
--- a/dom/bluetooth2/bluedroid/BluetoothOppManager.h
+++ b/dom/bluetooth2/bluedroid/BluetoothOppManager.h
@@ -69,16 +69,20 @@ public:
   void ReceiveSocketData(
     BluetoothSocket* aSocket,
     nsAutoPtr<mozilla::ipc::UnixSocketRawData>& aMessage) MOZ_OVERRIDE;
   virtual void OnSocketConnectSuccess(BluetoothSocket* aSocket) MOZ_OVERRIDE;
   virtual void OnSocketConnectError(BluetoothSocket* aSocket) MOZ_OVERRIDE;
   virtual void OnSocketDisconnect(BluetoothSocket* aSocket) MOZ_OVERRIDE;
 
 private:
+  class CloseSocketTask;
+  class ReadFileTask;
+  class SendSocketDataTask;
+
   BluetoothOppManager();
   bool Init();
   void HandleShutdown();
 
   void StartFileTransfer();
   void StartSendingNextFile();
   void FileTransferComplete();
   void UpdateProgress();
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -255,17 +255,18 @@ BluetoothHfpManager::Init()
 
   nsRefPtr<GetVolumeTask> callback = new GetVolumeTask();
   rv = settingsLock->Get(AUDIO_VOLUME_BT_SCO_ID, callback);
   NS_ENSURE_SUCCESS(rv, false);
 
   return true;
 }
 
-class CleanupInitResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::CleanupInitResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   CleanupInitResultHandler(BluetoothHandsfreeInterface* aInterface,
                            BluetoothProfileResultHandler* aRes)
   : mInterface(aInterface)
   , mRes(aRes)
   {
     MOZ_ASSERT(mInterface);
@@ -304,17 +305,18 @@ public:
     mInterface->Init(hfpManager, this);
   }
 
 private:
   BluetoothHandsfreeInterface* mInterface;
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class InitResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothHfpManager::InitResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   InitResultHandlerRunnable(CleanupInitResultHandler* aRes)
   : mRes(aRes)
   {
     MOZ_ASSERT(mRes);
   }
 
@@ -323,17 +325,18 @@ public:
     mRes->RunInit();
     return NS_OK;
   }
 
 private:
   nsRefPtr<CleanupInitResultHandler> mRes;
 };
 
-class OnErrorProfileResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothHfpManager::OnErrorProfileResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   OnErrorProfileResultHandlerRunnable(BluetoothProfileResultHandler* aRes,
                                       nsresult aRv)
   : mRes(aRes)
   , mRv(aRv)
   {
     MOZ_ASSERT(mRes);
@@ -408,17 +411,18 @@ BluetoothHfpManager::~BluetoothHfpManage
   if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) ||
       NS_FAILED(obs->RemoveObserver(this, MOZSETTINGS_CHANGED_ID))) {
     BT_WARNING("Failed to remove observers!");
   }
 
   hal::UnregisterBatteryObserver(this);
 }
 
-class CleanupResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::CleanupResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   CleanupResultHandler(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   { }
 
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
@@ -435,17 +439,18 @@ public:
       mRes->Deinit();
     }
   }
 
 private:
   nsRefPtr<BluetoothProfileResultHandler> mRes;
 };
 
-class DeinitResultHandlerRunnable MOZ_FINAL : public nsRunnable
+class BluetoothHfpManager::DeinitResultHandlerRunnable MOZ_FINAL
+  : public nsRunnable
 {
 public:
   DeinitResultHandlerRunnable(BluetoothProfileResultHandler* aRes)
   : mRes(aRes)
   {
     MOZ_ASSERT(mRes);
   }
 
@@ -585,18 +590,18 @@ BluetoothHfpManager::NotifyDialer(const 
   NS_NAMED_LITERAL_STRING(type, "bluetooth-dialer-command");
   InfallibleTArray<BluetoothNamedValue> parameters;
 
   BT_APPEND_NAMED_VALUE(parameters, "command", nsString(aCommand));
 
   BT_ENSURE_TRUE_VOID_BROADCAST_SYSMSG(type, parameters);
 }
 
-class VolumeControlResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::VolumeControlResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::VolumeControl failed: %d",
                (int)aStatus);
   }
 };
@@ -723,17 +728,17 @@ BluetoothHfpManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
   Disconnect(nullptr);
   DisconnectSco();
   sBluetoothHfpManager = nullptr;
 }
 
-class ClccResponseResultHandler MOZ_FINAL
+class BluetoothHfpManager::ClccResponseResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::ClccResponse failed: %d",
                (int)aStatus);
   }
@@ -760,18 +765,18 @@ BluetoothHfpManager::SendCLCC(Call& aCal
   }
 
   sBluetoothHfpInterface->ClccResponse(
     aIndex, aCall.mDirection, callState, HFP_CALL_MODE_VOICE,
     HFP_CALL_MPTY_TYPE_SINGLE, aCall.mNumber,
     aCall.mType, new ClccResponseResultHandler());
 }
 
-class FormattedAtResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::FormattedAtResponseResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::FormattedAtResponse failed: %d",
                (int)aStatus);
   }
 };
@@ -780,18 +785,18 @@ void
 BluetoothHfpManager::SendLine(const char* aMessage)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->FormattedAtResponse(
     aMessage, new FormattedAtResponseResultHandler());
 }
 
-class AtResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::AtResponseResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::AtResponse failed: %d",
                (int)aStatus);
   }
 };
@@ -800,18 +805,18 @@ void
 BluetoothHfpManager::SendResponse(BluetoothHandsfreeAtResponse aResponseCode)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   sBluetoothHfpInterface->AtResponse(
     aResponseCode, 0, new AtResponseResultHandler());
 }
 
-class PhoneStateChangeResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::PhoneStateChangeResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::PhoneStateChange failed: %d",
                (int)aStatus);
   }
 };
@@ -832,17 +837,17 @@ BluetoothHfpManager::UpdatePhoneCIND(uin
           numActive, numHeld, callSetupState);
 
   sBluetoothHfpInterface->PhoneStateChange(
     numActive, numHeld, callSetupState,
     mCurrentCallArray[aCallIndex].mNumber, type,
     new PhoneStateChangeResultHandler());
 }
 
-class DeviceStatusNotificationResultHandler MOZ_FINAL
+class BluetoothHfpManager::DeviceStatusNotificationResultHandler MOZ_FINAL
 : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING(
       "BluetoothHandsfreeInterface::DeviceStatusNotification failed: %d",
       (int)aStatus);
@@ -1088,18 +1093,18 @@ BluetoothHfpManager::ToggleCalls()
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
                              nsITelephonyService::CALL_STATE_HELD :
                              nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
-class ConnectAudioResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::ConnectAudioResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::ConnectAudio failed: %d",
                (int)aStatus);
   }
 };
@@ -1114,18 +1119,18 @@ BluetoothHfpManager::ConnectSco()
   NS_ENSURE_TRUE(sBluetoothHfpInterface, false);
 
   sBluetoothHfpInterface->ConnectAudio(mDeviceAddress,
                                        new ConnectAudioResultHandler());
 
   return true;
 }
 
-class DisconnectAudioResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::DisconnectAudioResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::DisconnectAudio failed: %d",
                (int)aStatus);
   }
 };
@@ -1160,17 +1165,18 @@ BluetoothHfpManager::OnConnectError()
   MOZ_ASSERT(NS_IsMainThread());
 
   mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
 
   mController = nullptr;
   mDeviceAddress.Truncate();
 }
 
-class ConnectResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::ConnectResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   ConnectResultHandler(BluetoothHfpManager* aHfpManager)
   : mHfpManager(aHfpManager)
   {
     MOZ_ASSERT(mHfpManager);
   }
 
@@ -1213,17 +1219,18 @@ BluetoothHfpManager::Connect(const nsASt
 void
 BluetoothHfpManager::OnDisconnectError()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mController->NotifyCompletion(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
 }
 
-class DisconnectResultHandler MOZ_FINAL : public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::DisconnectResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   DisconnectResultHandler(BluetoothHfpManager* aHfpManager)
   : mHfpManager(aHfpManager)
   {
     MOZ_ASSERT(mHfpManager);
   }
 
@@ -1486,18 +1493,18 @@ BluetoothHfpManager::CnumNotification()
     message.AppendLiteral(",,4");
 
     SendLine(message.get());
   }
 
   SendResponse(HFP_AT_RESPONSE_OK);
 }
 
-class CindResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::CindResponseResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CindResponse failed: %d",
                (int)aStatus);
   }
 };
@@ -1514,18 +1521,18 @@ BluetoothHfpManager::CindNotification()
   BluetoothHandsfreeCallState callState =
     ConvertToBluetoothHandsfreeCallState(GetCallSetupState());
 
   sBluetoothHfpInterface->CindResponse(mService, numActive, numHeld,
                                        callState, mSignal, mRoam, mBattChg,
                                        new CindResponseResultHandler());
 }
 
-class CopsResponseResultHandler MOZ_FINAL
-: public BluetoothHandsfreeResultHandler
+class BluetoothHfpManager::CopsResponseResultHandler MOZ_FINAL
+  : public BluetoothHandsfreeResultHandler
 {
 public:
   void OnError(BluetoothStatus aStatus) MOZ_OVERRIDE
   {
     BT_WARNING("BluetoothHandsfreeInterface::CopsResponse failed: %d",
                (int)aStatus);
   }
 };
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.h
@@ -127,20 +127,37 @@ public:
   void CnumNotification() MOZ_OVERRIDE;
   void CindNotification() MOZ_OVERRIDE;
   void CopsNotification() MOZ_OVERRIDE;
   void ClccNotification() MOZ_OVERRIDE;
   void UnknownAtNotification(const nsACString& aAtString) MOZ_OVERRIDE;
   void KeyPressedNotification() MOZ_OVERRIDE;
 
 private:
+  class AtResponseResultHandler;
   class GetVolumeTask;
+  class CindResponseResultHandler;
+  class ClccResponseResultHandler;
+  class CleanupResultHandler;
+  class CleanupInitResultHandler;
   class CloseScoTask;
   class CloseScoRunnable;
+  class ConnectAudioResultHandler;
+  class ConnectResultHandler;
+  class CopsResponseResultHandler;
+  class DeinitResultHandlerRunnable;
+  class DeviceStatusNotificationResultHandler;
+  class DisconnectAudioResultHandler;
+  class DisconnectResultHandler;
+  class FormattedAtResponseResultHandler;
+  class InitResultHandlerRunnable;
+  class OnErrorProfileResultHandlerRunnable;
+  class PhoneStateChangeResultHandler;
   class RespondToBLDNTask;
+  class VolumeControlResultHandler;
 
   friend class BluetoothHfpManagerObserver;
   friend class GetVolumeTask;
   friend class CloseScoTask;
   friend class RespondToBLDNTask;
   friend class MainThreadTask;
 
   BluetoothHfpManager();
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -37,28 +37,118 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserElementAPI)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_ADDREF_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement)
 NS_IMPL_RELEASE_INHERITED(nsGenericHTMLFrameElement, nsGenericHTMLElement)
 
 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement)
   NS_INTERFACE_TABLE_INHERITED(nsGenericHTMLFrameElement,
+                               nsIFrameLoaderOwner,
                                nsIDOMMozBrowserFrame,
-                               nsIMozBrowserFrame,
-                               nsIFrameLoaderOwner)
+                               nsIMozBrowserFrame)
 NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
 NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
 
 int32_t
 nsGenericHTMLFrameElement::TabIndexDefault()
 {
   return 0;
 }
 
+nsGenericHTMLFrameElement::~nsGenericHTMLFrameElement()
+{
+  if (mFrameLoader) {
+    mFrameLoader->Destroy();
+  }
+}
+
+nsresult
+nsGenericHTMLFrameElement::GetContentDocument(nsIDOMDocument** aContentDocument)
+{
+  NS_PRECONDITION(aContentDocument, "Null out param");
+  nsCOMPtr<nsIDOMDocument> document = do_QueryInterface(GetContentDocument());
+  document.forget(aContentDocument);
+  return NS_OK;
+}
+
+nsIDocument*
+nsGenericHTMLFrameElement::GetContentDocument()
+{
+  nsCOMPtr<nsPIDOMWindow> win = GetContentWindow();
+  if (!win) {
+    return nullptr;
+  }
+
+  nsIDocument *doc = win->GetDoc();
+
+  // Return null for cross-origin contentDocument.
+  if (!nsContentUtils::SubjectPrincipal()->
+        SubsumesConsideringDomain(doc->NodePrincipal())) {
+    return nullptr;
+  }
+  return doc;
+}
+
+nsresult
+nsGenericHTMLFrameElement::GetContentWindow(nsIDOMWindow** aContentWindow)
+{
+  NS_PRECONDITION(aContentWindow, "Null out param");
+  nsCOMPtr<nsPIDOMWindow> window = GetContentWindow();
+  window.forget(aContentWindow);
+  return NS_OK;
+}
+
+already_AddRefed<nsPIDOMWindow>
+nsGenericHTMLFrameElement::GetContentWindow()
+{
+  EnsureFrameLoader();
+
+  if (!mFrameLoader) {
+    return nullptr;
+  }
+
+  bool depthTooGreat = false;
+  mFrameLoader->GetDepthTooGreat(&depthTooGreat);
+  if (depthTooGreat) {
+    // Claim to have no contentWindow
+    return nullptr;
+  }
+
+  nsCOMPtr<nsIDocShell> doc_shell;
+  mFrameLoader->GetDocShell(getter_AddRefs(doc_shell));
+
+  nsCOMPtr<nsPIDOMWindow> win = do_GetInterface(doc_shell);
+
+  if (!win) {
+    return nullptr;
+  }
+
+  NS_ASSERTION(win->IsOuterWindow(),
+               "Uh, this window should always be an outer window!");
+
+  return win.forget();
+}
+
+void
+nsGenericHTMLFrameElement::EnsureFrameLoader()
+{
+  if (!IsInDoc() || mFrameLoader || mFrameLoaderCreationDisallowed) {
+    // If frame loader is there, we just keep it around, cached
+    return;
+  }
+
+  // Strangely enough, this method doesn't actually ensure that the
+  // frameloader exists.  It's more of a best-effort kind of thing.
+  mFrameLoader = nsFrameLoader::Create(this, mNetworkCreated);
+  if (mIsPrerendered) {
+    mFrameLoader->SetIsPrerendered();
+  }
+}
+
 nsresult
 nsGenericHTMLFrameElement::CreateRemoteFrameLoader(nsITabParent* aTabParent)
 {
   MOZ_ASSERT(!mFrameLoader);
   EnsureFrameLoader();
   NS_ENSURE_STATE(mFrameLoader);
   mFrameLoader->SetRemoteBrowser(aTabParent);
 
@@ -67,16 +157,64 @@ nsGenericHTMLFrameElement::CreateRemoteF
     // for the iframe creation. Therefore the subdoc frame didn't have a
     // frameloader when UpdatePositionAndSize was supposed to be called in
     // ReflowFinished, and we need to do it properly now.
     mFrameLoader->UpdatePositionAndSize(subdocFrame);
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::GetFrameLoader(nsIFrameLoader **aFrameLoader)
+{
+  NS_IF_ADDREF(*aFrameLoader = mFrameLoader);
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(already_AddRefed<nsFrameLoader>)
+nsGenericHTMLFrameElement::GetFrameLoader()
+{
+  nsRefPtr<nsFrameLoader> loader = mFrameLoader;
+  return loader.forget();
+}
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::SwapFrameLoaders(nsIFrameLoaderOwner* aOtherOwner)
+{
+  // We don't support this yet
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+nsGenericHTMLFrameElement::SetIsPrerendered()
+{
+  MOZ_ASSERT(!mFrameLoader, "Please call SetIsPrerendered before frameLoader is created");
+  mIsPrerendered = true;
+  return NS_OK;
+}
+
+nsresult
+nsGenericHTMLFrameElement::LoadSrc()
+{
+  EnsureFrameLoader();
+
+  if (!mFrameLoader) {
+    return NS_OK;
+  }
+
+  nsresult rv = mFrameLoader->LoadFrame();
+#ifdef DEBUG
+  if (NS_FAILED(rv)) {
+    NS_WARNING("failed to load URL");
+  }
+#endif
+
+  return rv;
+}
+
 nsresult
 nsGenericHTMLFrameElement::BindToTree(nsIDocument* aDocument,
                                       nsIContent* aParent,
                                       nsIContent* aBindingParent,
                                       bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
                                                  aBindingParent,
@@ -502,8 +640,16 @@ nsGenericHTMLFrameElement::AllowCreateFr
 
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::InitializeBrowserAPI()
 {
   MOZ_ASSERT(mFrameLoader);
   InitBrowserElementAPI();
   return NS_OK;
 }
+
+void
+nsGenericHTMLFrameElement::SwapFrameLoaders(nsXULElement& aOtherOwner,
+                                            ErrorResult& aError)
+{
+  aError.Throw(NS_ERROR_NOT_IMPLEMENTED);
+}
+
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -7,44 +7,47 @@
 
 #ifndef nsGenericHTMLFrameElement_h
 #define nsGenericHTMLFrameElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/nsBrowserElement.h"
 
-#include "nsElementFrameLoaderOwner.h"
 #include "nsFrameLoader.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrameLoader.h"
 #include "nsIMozBrowserFrame.h"
 
 class nsXULElement;
 
 /**
  * A helper class for frame elements
  */
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
-                                  public nsElementFrameLoaderOwner,
+                                  public nsIFrameLoaderOwner,
                                   public mozilla::nsBrowserElement,
                                   public nsIMozBrowserFrame
 {
 public:
   nsGenericHTMLFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                             mozilla::dom::FromParser aFromParser)
     : nsGenericHTMLElement(aNodeInfo)
-    , nsElementFrameLoaderOwner(aFromParser)
     , nsBrowserElement()
+    , mNetworkCreated(aFromParser == mozilla::dom::FROM_PARSER_NETWORK)
+    , mIsPrerendered(false)
+    , mBrowserFrameListenersRegistered(false)
+    , mFrameLoaderCreationDisallowed(false)
   {
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
+  NS_DECL_NSIFRAMELOADEROWNER
   NS_DECL_NSIDOMMOZBROWSERFRAME
   NS_DECL_NSIMOZBROWSERFRAME
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) MOZ_OVERRIDE;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
@@ -67,46 +70,52 @@ public:
 
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
 
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsGenericHTMLFrameElement,
                                                      nsGenericHTMLElement)
 
-  static bool BrowserFramesEnabled();
+  void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& aError);
 
-  /**
-   * nsIFrameLoaderOwner defines two GetFrameLoader() overloads. One
-   * is XPCOM style interface, the other one is C++ only.  "using" pulls
-   * them both in, now GetFrameLoader() is ambiguous because
-   * nsBrowserElement also has GetFrameLoader(). Explicit redefine
-   * GetFrameLoader() to choose nsElementFrameLoaderOwner::GetFrameLoader()
-   */
-  using nsElementFrameLoaderOwner::GetFrameLoader;
-  NS_IMETHOD_(already_AddRefed<nsFrameLoader>) GetFrameLoader() MOZ_OVERRIDE
-  {
-    return nsElementFrameLoaderOwner::GetFrameLoader();
-  }
+  static bool BrowserFramesEnabled();
 
   /**
    * Helper method to map a HTML 'scrolling' attribute value to a nsIScrollable
    * enum value.  scrolling="no" (and its synonyms) maps to
    * nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps
    * to nsIScrollable::Scrollbar_Auto.
    * @param aValue the attribute value to map or nullptr
    * @return nsIScrollable::Scrollbar_Never or nsIScrollable::Scrollbar_Auto
    */
   static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
 
 protected:
-  virtual ~nsGenericHTMLFrameElement() {}
+  virtual ~nsGenericHTMLFrameElement();
+
+  // This doesn't really ensure a frame loader in all cases, only when
+  // it makes sense.
+  void EnsureFrameLoader();
+  nsresult LoadSrc();
+  nsIDocument* GetContentDocument();
+  nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
+  already_AddRefed<nsPIDOMWindow> GetContentWindow();
+  nsresult GetContentWindow(nsIDOMWindow** aContentWindow);
 
-  virtual mozilla::dom::Element* ThisFrameElement() MOZ_OVERRIDE
-  {
-    return this;
-  }
+  nsRefPtr<nsFrameLoader> mFrameLoader;
+
+  /**
+   * True when the element is created by the parser using the
+   * NS_FROM_PARSER_NETWORK flag.
+   * If the element is modified, it may lose the flag.
+   */
+  bool mNetworkCreated;
+
+  bool mIsPrerendered;
+  bool mBrowserFrameListenersRegistered;
+  bool mFrameLoaderCreationDisallowed;
 
 private:
   void GetManifestURLByType(nsIAtom *aAppType, nsAString& aOut);
 };
 
 #endif // nsGenericHTMLFrameElement_h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -86,16 +86,17 @@
 #include "nsDebugImpl.h"
 #include "nsHashPropertyBag.h"
 #include "nsLayoutStylesheetCache.h"
 #include "nsIJSRuntimeService.h"
 #include "nsThreadManager.h"
 #include "nsAnonymousTemporaryFile.h"
 #include "nsISpellChecker.h"
 #include "nsClipboardProxy.h"
+#include "nsISystemMessageCache.h"
 
 #include "IHistory.h"
 #include "nsNetUtil.h"
 
 #include "base/message_loop.h"
 #include "base/process_util.h"
 #include "base/task.h"
 
@@ -525,16 +526,20 @@ InitOnContentProcessCreated()
 #ifdef MOZ_NUWA_PROCESS
     // Wait until we are forked from Nuwa
     if (IsNuwaProcess()) {
         return;
     }
     PostForkPreload();
 #endif
 
+    nsCOMPtr<nsISystemMessageCache> smc =
+        do_GetService("@mozilla.org/system-message-cache;1");
+    NS_WARN_IF(!smc);
+
     // This will register cross-process observer.
     mozilla::dom::time::InitializeDateCacheCleaner();
 }
 
 #if defined(MOZ_TASK_TRACER) && defined(MOZ_NUWA_PROCESS)
 static void
 ReinitTaskTracer(void* /*aUnused*/)
 {
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -114,16 +114,17 @@
 #include "nsIMutable.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIScriptError.h"
 #include "nsISiteSecurityService.h"
 #include "nsISpellChecker.h"
 #include "nsIStyleSheet.h"
 #include "nsISupportsPrimitives.h"
+#include "nsISystemMessagesInternal.h"
 #include "nsITimer.h"
 #include "nsIURIFixup.h"
 #include "nsIWindowWatcher.h"
 #include "nsIXULRuntime.h"
 #include "nsMemoryInfoDumper.h"
 #include "nsMemoryReporterManager.h"
 #include "nsServiceManagerUtils.h"
 #include "nsStyleSheetService.h"
@@ -1319,21 +1320,31 @@ ContentParent::ForwardKnownInfo()
 {
     MOZ_ASSERT(mMetamorphosed);
     if (!mMetamorphosed) {
         return;
     }
 #ifdef MOZ_WIDGET_GONK
     InfallibleTArray<VolumeInfo> volumeInfo;
     nsRefPtr<nsVolumeService> vs = nsVolumeService::GetSingleton();
-    if (vs) {
+    if (vs && !mIsForBrowser) {
         vs->GetVolumesForIPC(&volumeInfo);
         unused << SendVolumes(volumeInfo);
     }
 #endif /* MOZ_WIDGET_GONK */
+
+    nsCOMPtr<nsISystemMessagesInternal> systemMessenger =
+        do_GetService("@mozilla.org/system-message-internal;1");
+    if (systemMessenger && !mIsForBrowser) {
+        nsCOMPtr<nsIURI> manifestURI;
+        nsresult rv = NS_NewURI(getter_AddRefs(manifestURI), mAppManifestURL);
+        if (NS_SUCCEEDED(rv)) {
+            systemMessenger->RefreshCache(mMessageManager, manifestURI);
+        }
+    }
 }
 
 namespace {
 
 class SystemMessageHandledListener MOZ_FINAL
     : public nsITimerCallback
     , public LinkedListElement<SystemMessageHandledListener>
 {
--- a/dom/media/VideoFrameContainer.cpp
+++ b/dom/media/VideoFrameContainer.cpp
@@ -136,17 +136,17 @@ void VideoFrameContainer::InvalidateWith
   bool asyncInvalidate = mImageContainer &&
                          mImageContainer->IsAsync() &&
                          !(aFlags & INVALIDATE_FORCE);
 
   if (frame) {
     if (invalidateFrame) {
       frame->InvalidateFrame();
     } else {
-      frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO, nullptr,
+      frame->InvalidateLayer(nsDisplayItem::TYPE_VIDEO, nullptr, nullptr,
                              asyncInvalidate ? nsIFrame::UPDATE_IS_ASYNC : 0);
     }
   }
 
   nsSVGEffects::InvalidateDirectRenderingObservers(mElement);
 }
 
 }
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -60,33 +60,16 @@ TrackBuffer::TrackBuffer(MediaSourceDeco
   MSE_DEBUG("TrackBuffer(%p) created for parent decoder %p", this, aParentDecoder);
 }
 
 TrackBuffer::~TrackBuffer()
 {
   MOZ_COUNT_DTOR(TrackBuffer);
 }
 
-class ReleaseDecoderTask : public nsRunnable {
-public:
-  explicit ReleaseDecoderTask(SourceBufferDecoder* aDecoder)
-    : mDecoder(aDecoder)
-  {
-  }
-
-  NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
-    mDecoder->GetReader()->BreakCycles();
-    mDecoder = nullptr;
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<SourceBufferDecoder> mDecoder;
-};
-
 class MOZ_STACK_CLASS DecodersToInitialize MOZ_FINAL {
 public:
   explicit DecodersToInitialize(TrackBuffer* aOwner)
     : mOwner(aOwner)
   {
   }
 
   ~DecodersToInitialize()
@@ -148,17 +131,17 @@ TrackBuffer::ContinueShutdown()
     mDecoders[0]->GetReader()->Shutdown()
                 ->Then(mParentDecoder->GetReader()->GetTaskQueue(), __func__, this,
                        &TrackBuffer::ContinueShutdown, &TrackBuffer::ContinueShutdown);
     mShutdownDecoders.AppendElement(mDecoders[0]);
     mDecoders.RemoveElementAt(0);
     return;
   }
 
-  mCurrentDecoder = nullptr;
+  MOZ_ASSERT(!mCurrentDecoder, "Detach() should have been called");
   mInitializedDecoders.Clear();
   mParentDecoder = nullptr;
 
   mShutdownPromise.Resolve(true, __func__);
 }
 
 nsRefPtr<TrackBufferAppendPromise>
 TrackBuffer::AppendData(LargeDataBuffer* aData, int64_t aTimestampOffset)
@@ -686,16 +669,17 @@ TrackBuffer::RegisterDecoder(SourceBuffe
   mInitializedDecoders.AppendElement(aDecoder);
   mParentDecoder->NotifyTimeRangesChanged();
   return true;
 }
 
 void
 TrackBuffer::DiscardCurrentDecoder()
 {
+  MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   EndCurrentDecoder();
   mCurrentDecoder = nullptr;
 }
 
 void
 TrackBuffer::EndCurrentDecoder()
 {
@@ -837,56 +821,77 @@ TrackBuffer::Dump(const char* aPath)
     PR_snprintf(buf, sizeof(buf), "%s/reader-%p", path, mDecoders[i]->GetReader());
     PR_MkDir(buf, 0700);
 
     mDecoders[i]->GetResource()->Dump(buf);
   }
 }
 #endif
 
+class ReleaseDecoderTask : public nsRunnable {
+public:
+  ReleaseDecoderTask(SourceBufferDecoder* aDecoder, TrackBuffer* aTrackBuffer)
+    : mDecoder(aDecoder)
+    , mTrackBuffer(aTrackBuffer)
+  {
+  }
+
+  NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
+    if (mTrackBuffer->mCurrentDecoder == mDecoder) {
+      mTrackBuffer->DiscardCurrentDecoder();
+    }
+
+    mDecoder->GetReader()->BreakCycles();
+    mDecoder = nullptr;
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<TrackBuffer> mTrackBuffer;
+};
+
 class DelayedDispatchToMainThread : public nsRunnable {
 public:
-  explicit DelayedDispatchToMainThread(SourceBufferDecoder* aDecoder)
+  DelayedDispatchToMainThread(SourceBufferDecoder* aDecoder, TrackBuffer* aTrackBuffer)
     : mDecoder(aDecoder)
+    , mTrackBuffer(aTrackBuffer)
   {
   }
 
   NS_IMETHOD Run() MOZ_OVERRIDE MOZ_FINAL {
     // Shutdown the reader, and remove its reference to the decoder
     // so that it can't accidentally read it after the decoder
     // is destroyed.
     mDecoder->GetReader()->Shutdown();
     mDecoder->GetReader()->ClearDecoder();
-    RefPtr<nsIRunnable> task = new ReleaseDecoderTask(mDecoder);
+    RefPtr<nsIRunnable> task = new ReleaseDecoderTask(mDecoder, mTrackBuffer);
     mDecoder = nullptr;
     // task now holds the only ref to the decoder.
     NS_DispatchToMainThread(task);
     return NS_OK;
   }
 
 private:
-  RefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<SourceBufferDecoder> mDecoder;
+  nsRefPtr<TrackBuffer> mTrackBuffer;
 };
 
 void
 TrackBuffer::RemoveDecoder(SourceBufferDecoder* aDecoder)
 {
-  RefPtr<nsIRunnable> task = new DelayedDispatchToMainThread(aDecoder);
-
+  MSE_DEBUG("TrackBuffer(%p)::RemoveDecoder(%p, %p)", this, aDecoder, aDecoder->GetReader());
+  RefPtr<nsIRunnable> task = new DelayedDispatchToMainThread(aDecoder, this);
   {
     ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
     // There should be no other references to the decoder. Assert that
     // we aren't using it in the MediaSourceReader.
     MOZ_ASSERT(!mParentDecoder->IsActiveReader(aDecoder->GetReader()));
     mInitializedDecoders.RemoveElement(aDecoder);
     mDecoders.RemoveElement(aDecoder);
-
-    if (mCurrentDecoder == aDecoder) {
-      DiscardCurrentDecoder();
-    }
   }
   aDecoder->GetReader()->GetTaskQueue()->Dispatch(task);
 }
 
 bool
 TrackBuffer::RangeRemoval(int64_t aStart, int64_t aEnd)
 {
   MOZ_ASSERT(NS_IsMainThread());
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -56,17 +56,17 @@ public:
   void EvictBefore(double aTime);
 
   // Returns the highest end time of all of the buffered ranges in the
   // decoders managed by this TrackBuffer, and returns the union of the
   // decoders buffered ranges in aRanges. This may be called on any thread.
   double Buffered(dom::TimeRanges* aRanges);
 
   // Mark the current decoder's resource as ended, clear mCurrentDecoder and
-  // reset mLast{Start,End}Timestamp.
+  // reset mLast{Start,End}Timestamp.  Main thread only.
   void DiscardCurrentDecoder();
   // Mark the current decoder's resource as ended.
   void EndCurrentDecoder();
 
   void Detach();
 
   // Returns true if an init segment has been appended.
   bool HasInitSegment();
@@ -109,16 +109,17 @@ public:
 #endif
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif
 
 private:
   friend class DecodersToInitialize;
+  friend class ReleaseDecoderTask;
   ~TrackBuffer();
 
   // Create a new decoder, set mCurrentDecoder to the new decoder and
   // returns it. The new decoder must be queued using QueueInitializeDecoder
   // for initialization.
   // The decoder is not considered initialized until it is added to
   // mInitializedDecoders.
   already_AddRefed<SourceBufferDecoder> NewDecoder(int64_t aTimestampOffset /* microseconds */);
@@ -176,16 +177,17 @@ private:
   // Access protected by mParentDecoder's monitor.
   nsTArray<nsRefPtr<SourceBufferDecoder>> mInitializedDecoders;
 
   // Decoders which are waiting on a Content Decryption Module to be able to
   // finish ReadMetadata.
   nsTArray<nsRefPtr<SourceBufferDecoder>> mWaitingDecoders;
 
   // The decoder that the owning SourceBuffer is currently appending data to.
+  // Modified on the main thread only.
   nsRefPtr<SourceBufferDecoder> mCurrentDecoder;
 
   nsRefPtr<MediaSourceDecoder> mParentDecoder;
   const nsCString mType;
 
   // The last start and end timestamps added to the TrackBuffer via
   // AppendData.  Accessed on the main thread only.
   int64_t mLastStartTimestamp;
new file mode 100644
--- /dev/null
+++ b/dom/messages/SystemMessageCache.js
@@ -0,0 +1,84 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
+
+function debug(aMsg) {
+   // dump("-- SystemMessageCache " + Date.now() + " : " + aMsg + "\n");
+}
+
+const kMessages = ["SystemMessageCache:RefreshCache"];
+
+function SystemMessageCache() {
+  debug("init");
+
+  this._pagesCache = [];
+
+  dump("SystemMessageCache: init");
+  Services.obs.addObserver(this, "xpcom-shutdown", false);
+  kMessages.forEach(function(aMessage) {
+    cpmm.addMessageListener(aMessage, this);
+  }, this);
+}
+
+SystemMessageCache.prototype = {
+
+  observe: function(aSubject, aTopic, aData) {
+    switch (aTopic) {
+    case "xpcom-shutdown":
+      debug("received xpcom-shutdown");
+      kMessages.forEach(function(aMessage) {
+        cpmm.removeMessageListener(aMessage, this);
+      }, this);
+      Services.obs.removeObserver(this, "xpcom-shutdown");
+      cpmm = null;
+      break;
+    default:
+      break;
+    }
+  },
+
+  receiveMessage: function(aMessage) {
+    switch (aMessage.name) {
+    case "SystemMessageCache:RefreshCache":
+      this._pagesCache = aMessage.data;
+      debug("received RefreshCache");
+      break;
+    default:
+      debug("received unknown message " + aMessage.name);
+      break;
+    }
+  },
+
+  hasPendingMessage: function(aType, aPageURL, aManifestURL) {
+    let hasMessage = this._pagesCache.some(function(aPage) {
+      if (aPage.type === aType &&
+          aPage.pageURL === aPageURL &&
+          aPage.manifestURL === aManifestURL) {
+        return true;
+      }
+      return false;
+    }, this);
+    debug("hasPendingMessage " + aType + " " + aPageURL + " " +
+          aManifestURL + ": " + hasMessage);
+    return hasMessage;
+  },
+
+  classID: Components.ID("{5a19d86a-21e5-4ac8-9634-8c364c73f87f}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemMessageCache,
+                                         Ci.nsIMessageListener,
+                                         Ci.nsIObserver])
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SystemMessageCache]);
--- a/dom/messages/SystemMessageInternal.js
+++ b/dom/messages/SystemMessageInternal.js
@@ -35,24 +35,23 @@ try {
   kMaxPendingMessages =
     Services.prefs.getIntPref("dom.messages.maxPendingMessages");
 } catch(e) {
   // getIntPref throws when the pref is not set.
   kMaxPendingMessages = 5;
 }
 
 const kMessages =["SystemMessageManager:GetPendingMessages",
-                  "SystemMessageManager:HasPendingMessages",
                   "SystemMessageManager:Register",
                   "SystemMessageManager:Unregister",
                   "SystemMessageManager:Message:Return:OK",
                   "SystemMessageManager:AskReadyToRegister",
                   "SystemMessageManager:HandleMessagesDone",
                   "SystemMessageManager:HandleMessageDone",
-                  "child-process-shutdown"]
+                  "child-process-shutdown"];
 
 function debug(aMsg) {
   // dump("-- SystemMessageInternal " + Date.now() + " : " + aMsg + "\n");
 }
 
 
 let defaultMessageConfigurator = {
   get mustShowRunningApp() {
@@ -173,16 +172,29 @@ SystemMessageInternal.prototype = {
       if (this._isPageMatched(aPage, aType, aPageURL, aManifestURL)) {
         page = aPage;
       }
       return page !== null;
     }, this);
     return page;
   },
 
+  _findCacheForApp: function(aManifestURL) {
+    let cache = [];
+    this._pages.forEach(function(aPage) {
+      if (aPage.manifestURL === aManifestURL &&
+          aPage.pendingMessages.length != 0) {
+        cache.push({ type: aPage.type,
+                     pageURL: aPage.pageURL,
+                     manifestURL: aPage.manifestURL });
+      }
+    });
+    return cache;
+  },
+
   sendMessage: function(aType, aMessage, aPageURI, aManifestURI, aExtra) {
     return new Promise((aResolve, aReject) => {
       this.sendMessageInternal(aType, aMessage, aPageURI, aManifestURI, aExtra,
                                aResolve, aReject);
     });
   },
 
   sendMessageInternal: function(aType, aMessage, aPageURI, aManifestURI,
@@ -344,16 +356,28 @@ SystemMessageInternal.prototype = {
     }
 
     this._pages.push({ type: aType,
                        pageURL: pageURL,
                        manifestURL: manifestURL,
                        pendingMessages: [] });
   },
 
+  refreshCache: function(aChildMM, aManifestURI) {
+    if (!aManifestURI) {
+      throw Cr.NS_ERROR_INVALID_ARG;
+    }
+    this._refreshCacheInternal(aChildMM, aManifestURI.spec);
+  },
+
+  _refreshCacheInternal: function(aChildMM, aManifestURL) {
+    let cache = this._findCacheForApp(aManifestURL);
+    aChildMM.sendAsyncMessage("SystemMessageCache:RefreshCache", cache);
+  },
+
   _findTargetIndex: function(aTargets, aTarget) {
     if (!aTargets || !aTarget) {
       return -1;
     }
     for (let index = 0; index < aTargets.length; ++index) {
       let target = aTargets[index];
       if (target.target === aTarget) {
         return index;
@@ -412,17 +436,16 @@ SystemMessageInternal.prototype = {
     let msg = aMessage.json;
 
     // To prevent the hacked child process from sending commands to parent
     // to manage system messages, we need to check its manifest URL.
     if (["SystemMessageManager:Register",
          // TODO: fix bug 988142 to re-enable.
          // "SystemMessageManager:Unregister",
          "SystemMessageManager:GetPendingMessages",
-         "SystemMessageManager:HasPendingMessages",
          "SystemMessageManager:Message:Return:OK",
          "SystemMessageManager:HandleMessagesDone",
          "SystemMessageManager:HandleMessageDone"].indexOf(aMessage.name) != -1) {
       if (!aMessage.target.assertContainApp(msg.manifestURL)) {
         debug("Got message from a child process containing illegal manifest URL.");
         return null;
       }
     }
@@ -451,16 +474,17 @@ SystemMessageInternal.prototype = {
           let winCounts = targets[index].winCounts;
           if (winCounts[pageURL] === undefined) {
             winCounts[pageURL] = 1;
           } else {
             winCounts[pageURL]++;
           }
         }
 
+        this._refreshCacheInternal(aMessage.target, msg.manifestURL);
         debug("listeners for " + msg.manifestURL +
               " innerWinID " + msg.innerWindowID);
         break;
       }
       case "child-process-shutdown":
       {
         debug("Got child-process-shutdown from " + aMessage.target);
         for (let manifestURL in this._listeners) {
@@ -509,31 +533,17 @@ SystemMessageInternal.prototype = {
 
         // Send the array of pending messages.
         aMessage.target
                 .sendAsyncMessage("SystemMessageManager:GetPendingMessages:Return",
                                   { type: msg.type,
                                     manifestURL: msg.manifestURL,
                                     pageURL: msg.pageURL,
                                     msgQueue: pendingMessages });
-        break;
-      }
-      case "SystemMessageManager:HasPendingMessages":
-      {
-        debug("received SystemMessageManager:HasPendingMessages " + msg.type +
-          " for " + msg.pageURL + " @ " + msg.manifestURL);
-
-        // This is a sync call used to return if a page has pending messages.
-        // Find the right page to get its corresponding pending messages.
-        let page = this._findPage(msg.type, msg.pageURL, msg.manifestURL);
-        if (!page) {
-          return false;
-        }
-
-        return page.pendingMessages.length != 0;
+        this._refreshCacheInternal(aMessage.target, msg.manifestURL);
         break;
       }
       case "SystemMessageManager:Message:Return:OK":
       {
         debug("received SystemMessageManager:Message:Return:OK " + msg.type +
           " for " + msg.pageURL + " @ " + msg.manifestURL);
 
         // We need to clean up the pending message since the app has already
@@ -692,17 +702,17 @@ SystemMessageInternal.prototype = {
     } else {
       debug("Error! The UI glue component is not implemented.");
     }
   },
 
   _isPageMatched: function(aPage, aType, aPageURL, aManifestURL) {
     return (aPage.type === aType &&
             aPage.manifestURL === aManifestURL &&
-            aPage.pageURL === aPageURL)
+            aPage.pageURL === aPageURL);
   },
 
   _createKeyForPage: function _createKeyForPage(aPage) {
     let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                       .createInstance(Ci.nsIScriptableUnicodeConverter);
     converter.charset = "UTF-8";
 
     let hasher = Cc["@mozilla.org/security/hash;1"]
--- a/dom/messages/SystemMessageManager.js
+++ b/dom/messages/SystemMessageManager.js
@@ -188,20 +188,26 @@ SystemMessageManager.prototype = {
       return false;
     }
 
     // If we have a handler for this type, we can't have any pending message.
     if (aType in this._dispatchers) {
       return false;
     }
 
-    return cpmm.sendSyncMessage("SystemMessageManager:HasPendingMessages",
-                                { type: aType,
-                                  pageURL: this._pageURL,
-                                  manifestURL: this._manifestURL })[0];
+
+    /*
+     * NB: If the system message is fired after we received the cache
+     *     and before we registered the pageURL we will get false
+     *     negative however this is unlikely and will do no harm.
+     */
+    let cache = Cc["@mozilla.org/system-message-cache;1"]
+                  .getService(Ci.nsISystemMessageCache);
+
+    return cache.hasPendingMessage(aType, this._pageURL, this._manifestURL);
   },
 
   mozIsHandlingMessage: function() {
     debug("is handling message: " + this._isHandling);
     return this._isHandling;
   },
 
   mozSetMessageHandlerPromise: function(aPromise) {
--- a/dom/messages/SystemMessageManager.manifest
+++ b/dom/messages/SystemMessageManager.manifest
@@ -1,5 +1,8 @@
 component {bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2} SystemMessageManager.js
 contract @mozilla.org/system-message-manager;1 {bc076ea0-609b-4d8f-83d7-5af7cbdc3bb2}
 
 component {70589ca5-91ac-4b9e-b839-d6a88167d714} SystemMessageInternal.js
 contract @mozilla.org/system-message-internal;1 {70589ca5-91ac-4b9e-b839-d6a88167d714}
+
+component {5a19d86a-21e5-4ac8-9634-8c364c73f87f} SystemMessageCache.js
+contract @mozilla.org/system-message-cache;1 {5a19d86a-21e5-4ac8-9634-8c364c73f87f}
--- a/dom/messages/interfaces/moz.build
+++ b/dom/messages/interfaces/moz.build
@@ -1,14 +1,15 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
     'nsIDOMNavigatorSystemMessages.idl',
+    'nsISystemMessageCache.idl',
     'nsISystemMessageGlue.idl',
     'nsISystemMessagesInternal.idl',
 ]
 
 XPIDL_MODULE = 'dom_messages'
 
new file mode 100644
--- /dev/null
+++ b/dom/messages/interfaces/nsISystemMessageCache.idl
@@ -0,0 +1,13 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(e888447c-6d4d-4045-92bd-1a5985404375)]
+interface nsISystemMessageCache : nsISupports
+{
+  boolean hasPendingMessage(in DOMString type,
+                            in DOMString pageURL,
+                            in DOMString manifestURL);
+};
--- a/dom/messages/interfaces/nsISystemMessagesInternal.idl
+++ b/dom/messages/interfaces/nsISystemMessagesInternal.idl
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "domstubs.idl"
 
 interface nsIURI;
 interface nsIDOMWindow;
+interface nsIMessageSender;
 
 // Implemented by the contract id @mozilla.org/system-message-internal;1
 
 [scriptable, uuid(54c8e274-decb-4258-9a24-4ebfcbf3d00a)]
 interface nsISystemMessagesInternal : nsISupports
 {
   /*
    * Allow any internal user to send a message of a given type to a given page
@@ -40,16 +41,22 @@ interface nsISystemMessagesInternal : ns
 
   /*
    * Registration of a page that wants to be notified of a message type.
    * @param type          The message type.
    * @param pageURI       The URI of the page that will be opened.
    * @param manifestURI   The webapp's manifest URI.
    */
   void registerPage(in DOMString type, in nsIURI pageURI, in nsIURI manifestURI);
+
+  /*
+   * Refresh the system message cache in a content process.
+   * @param manifestURI The webapp's manifest URI.
+   */
+  void refreshCache(in nsIMessageSender childMM, in nsIURI manifestURI);
 };
 
 [scriptable, uuid(002f0e82-91f0-41de-ad43-569a2b9d12df)]
 interface nsISystemMessagesWrapper: nsISupports
 {
   /*
    * Wrap a message and gives back any kind of object.
    * @param message  The json blob to wrap.
--- a/dom/messages/moz.build
+++ b/dom/messages/moz.build
@@ -2,16 +2,17 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 DIRS += ['interfaces']
 
 EXTRA_COMPONENTS += [
+    'SystemMessageCache.js',
     'SystemMessageInternal.js',
     'SystemMessageManager.js',
     'SystemMessageManager.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'SystemMessagePermissionsChecker.jsm',
 ]
--- a/dom/requestsync/RequestSyncManager.js
+++ b/dom/requestsync/RequestSyncManager.js
@@ -29,17 +29,18 @@ RequestSyncManager.prototype = {
   classDescription: 'RequestSyncManager XPCOM Component',
   classID: Components.ID('{e6f55080-e549-4e30-9d00-15f240fb763c}'),
   contractID: '@mozilla.org/dom/request-sync-manager;1',
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
                                          Ci.nsIObserver,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 
   _messages: [ "RequestSyncManager:Registrations:Return",
-               "RequestSyncManager:SetPolicy:Return" ],
+               "RequestSyncManager:SetPolicy:Return",
+               "RequestSyncManager:RunTask:Return" ],
 
   init: function(aWindow) {
     debug("init");
 
     // DOMRequestIpcHelper.initHelper sets this._window
     this.initDOMRequestHelper(aWindow, this._messages);
   },
 
@@ -66,16 +67,26 @@ RequestSyncManager.prototype = {
       { task: aTask,
         origin: aOrigin,
         manifestURL: aManifestURL,
         isInBrowserElement: aIsInBrowserElement,
         state: aState,
         overwrittenMinInterval: aOverwrittenMinInterval });
   },
 
+  runTask: function(aTask, aOrigin, aManifestURL, aIsInBrowserElement) {
+    debug('runTask');
+
+    return this.sendMessage("RequestSyncManager:RunTask",
+      { task: aTask,
+        origin: aOrigin,
+        manifestURL: aManifestURL,
+        isInBrowserElement: aIsInBrowserElement });
+  },
+
   registrationsResult: function(aData) {
     debug("registrationsResult");
 
     let results = new this._window.Array();
     for (let i = 0; i < aData.length; ++i) {
       if (!("app" in aData[i])) {
         dump("ERROR - Serialization error in RequestSyncManager.\n");
         continue;
--- a/dom/requestsync/RequestSyncService.jsm
+++ b/dom/requestsync/RequestSyncService.jsm
@@ -51,17 +51,18 @@ this.RequestSyncService = {
 
   children: [],
 
   _messages: [ "RequestSync:Register",
                "RequestSync:Unregister",
                "RequestSync:Registrations",
                "RequestSync:Registration",
                "RequestSyncManager:Registrations",
-               "RequestSyncManager:SetPolicy" ],
+               "RequestSyncManager:SetPolicy",
+               "RequestSyncManager:RunTask" ],
 
   _pendingOperation: false,
   _pendingMessages: [],
 
   _registrations: {},
 
   _wifi: false,
 
@@ -322,16 +323,20 @@ this.RequestSyncService = {
       case "RequestSyncManager:Registrations":
         this.managerRegistrations(aMessage.target, aMessage.data, principal);
         break;
 
       case "RequestSyncManager:SetPolicy":
         this.managerSetPolicy(aMessage.target, aMessage.data, principal);
         break;
 
+      case "RequestSyncManager:RunTask":
+        this.managerRunTask(aMessage.target, aMessage.data, principal);
+        break;
+
       default:
         debug("Wrong message: " + aMessage.name);
         break;
     }
   },
 
   // Basic validation.
   validateRegistrationParams: function(aParams) {
@@ -392,17 +397,18 @@ this.RequestSyncService = {
                 aPrincipal.appId + '|' +
                 aPrincipal.isInBrowserElement + '|' +
                 aPrincipal.origin;
 
     let data = { principal: aPrincipal,
                  dbKey: dbKey,
                  data: aData.params,
                  active: true,
-                 timer: null };
+                 timer: null,
+                 requestIDs: [] };
 
     let self = this;
     this.dbTxn('readwrite', function(aStore) {
       aStore.put(data, data.dbKey);
     },
     function() {
       self.addRegistration(data);
       aTarget.sendAsyncMessage("RequestSync:Register:Return",
@@ -498,16 +504,20 @@ this.RequestSyncService = {
 
   // Set a policy to a task.
   managerSetPolicy: function(aTarget, aData, aPrincipal) {
     debug("managerSetPolicy");
 
     let toSave = null;
     let self = this;
     this.forEachRegistration(function(aObj) {
+      if (aObj.data.task != aData.task) {
+        return;
+      }
+
       if (aObj.principal.isInBrowserElement != aData.isInBrowserElement ||
           aObj.principal.origin != aData.origin) {
         return;
       }
 
       let app = appsService.getAppByLocalId(aObj.principal.appId);
       if (app && app.manifestURL != aData.manifestURL ||
           (!app && aData.manifestURL != "")) {
@@ -536,16 +546,56 @@ this.RequestSyncService = {
 
     this.updateObjectInDB(toSave, function() {
       self.scheduleTimer(toSave);
       aTarget.sendAsyncMessage("RequestSyncManager:SetPolicy:Return",
                                { requestID: aData.requestID });
     });
   },
 
+  // Run a task now.
+  managerRunTask: function(aTarget, aData, aPrincipal) {
+    debug("runTask");
+
+    let task = null;
+    this.forEachRegistration(function(aObj) {
+      if (aObj.data.task != aData.task) {
+        return;
+      }
+
+      if (aObj.principal.isInBrowserElement != aData.isInBrowserElement ||
+          aObj.principal.origin != aData.origin) {
+        return;
+      }
+
+      let app = appsService.getAppByLocalId(aObj.principal.appId);
+      if (app && app.manifestURL != aData.manifestURL ||
+          (!app && aData.manifestURL != "")) {
+        return;
+      }
+
+      if (task) {
+        dump("ERROR!! RequestSyncService - RunTask matches more than 1 task.\n");
+        return;
+      }
+
+      task = aObj;
+    });
+
+    if (!task) {
+      aTarget.sendAsyncMessage("RequestSyncManager:RunTask:Return",
+                               { requestID: aData.requestID, error: "UnknownTaskError" });
+      return;
+    }
+
+    // Storing the requestID into the task for the callback.
+    task.requestIDs.push({ target: aTarget, requestID: aData.requestID });
+    this.timeout(task);
+  },
+
   // We cannot expose the full internal object to content but just a subset.
   // This method creates this subset.
   createPartialTaskObject: function(aObj) {
     return { task: aObj.task,
              lastSync: aObj.lastSync,
              oneShot: aObj.oneShot,
              minInterval: aObj.minInterval,
              wakeUpPage: aObj.wakeUpPage,
@@ -700,16 +750,26 @@ this.RequestSyncService = {
       dump("ERROR!! RequestSyncService - OperationCompleted called without an active task\n");
       return;
     }
 
     // One shot? Then this is not active.
     this._activeTask.active = !this._activeTask.data.oneShot;
     this._activeTask.data.lastSync = new Date();
 
+    if (this._activeTask.requestIDs.length) {
+      for (let i = 0; i < this._activeTask.requestIDs.length; ++i) {
+        this._activeTask.requestIDs[i]
+            .target.sendAsyncMessage("RequestSyncManager:RunTask:Return",
+                                     { requestID: this._activeTask.requestIDs[i].requestID });
+      }
+
+      this._activeTask.requestIDs = [];
+    }
+
     let self = this;
     this.updateObjectInDB(this._activeTask, function() {
       // SchedulerTimer creates a timer and a nsITimer cannot be cloned. This
       // is the reason why this operation has to be done after storing the task
       // into IDB.
       if (!self._activeTask.data.oneShot) {
         self.scheduleTimer(self._activeTask);
       }
--- a/dom/requestsync/RequestSyncTask.jsm
+++ b/dom/requestsync/RequestSyncTask.jsm
@@ -92,10 +92,17 @@ this.RequestSyncTask.prototype = {
 
       // Set the new value only when the promise is resolved.
       p.then(function() {
         self._state = aState;
         self._overwrittenMinInterval = aOverwrittenMinInterval;
         aResolve();
       }, aReject);
     });
+  },
+
+  runNow: function() {
+    debug("runNow");
+    return this._manager.runTask(this._task, this._app.origin,
+                                 this._app.manifestURL,
+                                 this._app.isInBrowserElement);
   }
 };
--- a/dom/requestsync/tests/common_basic.js
+++ b/dom/requestsync/tests/common_basic.js
@@ -164,16 +164,17 @@ function test_managerRegistrations(state
     ok("data" in results[0], "navigator.sync.registrations()[0].data is correct");
     ok("app" in results[0], "navigator.sync.registrations()[0].app is correct");
     ok("manifestURL" in results[0].app, "navigator.sync.registrations()[0].app.manifestURL is correct");
     is(results[0].app.origin, 'http://mochi.test:8888', "navigator.sync.registrations()[0].app.origin is correct");
     is(results[0].app.isInBrowserElement, false, "navigator.sync.registrations()[0].app.isInBrowserElement is correct");
     is(results[0].state, state, "navigator.sync.registrations()[0].state is correct");
     is(results[0].overwrittenMinInterval, overwrittenMinInterval, "navigator.sync.registrations()[0].overwrittenMinInterval is correct");
     ok("setPolicy" in results[0], "navigator.sync.registrations()[0].setPolicy is correct");
+    ok("runNow" in results[0], "navigator.sync.registrations()[0].runNow is correct");
     runTests();
   },
   genericError);
 }
 
 function test_managerSetPolicy(state, overwrittenMinInterval) {
   navigator.syncManager.registrations().then(
   function(results) {
--- a/dom/requestsync/tests/mochitest.ini
+++ b/dom/requestsync/tests/mochitest.ini
@@ -9,9 +9,11 @@ support-files =
 
 [test_webidl.html]
 [test_minInterval.html]
 [test_basic.html]
 [test_basic_app.html]
 run-if = buildapp != 'b2g'
 [test_wakeUp.html]
 run-if = buildapp == 'b2g' && toolkit == 'gonk'
+[test_runNow.html]
+run-if = buildapp == 'b2g' && toolkit == 'gonk'
 [test_promise.html]
--- a/dom/requestsync/tests/test_minInterval.html
+++ b/dom/requestsync/tests/test_minInterval.html
@@ -14,17 +14,23 @@
     function() {
       ok(expected, "MinInterval succeeded");
     },
     function(e) {
       ok(!expected, "MinInterval failed");
       is(e, "ParamsError", "Correct error received");
     })
 
-    .then(runTests);
+    .then(function() {
+      if (expected) {
+        navigator.sync.unregister('foobar').then(runTests);
+      } else {
+        runTests();
+      }
+    });
   }
 
   var tests = [
     function() {
       if (SpecialPowers.isMainProcess()) {
         SpecialPowers.Cu.import("resource://gre/modules/RequestSyncService.jsm");
       }
       runTests();
new file mode 100644
--- /dev/null
+++ b/dom/requestsync/tests/test_runNow.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for requestSync - runNow</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="application/javascript" src="common_basic.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<div id="container"></div>
+  <script type="application/javascript;version=1.7">
+
+  var taskExecuted = false;
+
+  function setMessageHandler() {
+    navigator.mozSetMessageHandler('request-sync', function(e) {
+      ok(true, "One event has been received!");
+
+      if (e.task == "oneShot") {
+        is(e.data, 42, "e.data is correct");
+        is(e.lastSync, 0, "e.lastSync is correct");
+        is(e.oneShot, true, "e.oneShot is correct");
+        is(e.minInterval, 1024, "e.minInterval is correct");
+        is(e.wifiOnly, false, "e.wifiOnly is correct");
+        taskExecuted = true;
+      } else {
+        ok(false, "Unknown event has been received!");
+      }
+    });
+
+    runTests();
+  }
+
+  function test_register_oneShot() {
+    navigator.sync.register('oneShot', { minInterval: 1024,
+                                         oneShot: true,
+                                         data: 42,
+                                         wifiOnly: false,
+                                         wakeUpPage: location.href }).then(
+    function() {
+      ok(true, "navigator.sync.register() oneShot done");
+      runTests();
+    }, genericError);
+  }
+
+  function test_unregister_oneShot() {
+    navigator.sync.unregister('oneShot').then(
+    function() {
+      ok(true, "navigator.sync.unregister() oneShot done");
+      runTests();
+    }, genericError);
+  }
+
+  function test_runNow() {
+    navigator.syncManager.registrations().then(
+    function(array) {
+      for (var i = 0; i < array.length; ++i) { info(array[i].task); }
+      is(array.length, 1, "One registration found.");
+      array[0].runNow().then(function() {
+        ok(taskExecuted, "Task has been executed");
+        runTests();
+      });
+    }, genericError);
+  }
+
+  var tests = [
+    function() {
+      SpecialPowers.pushPrefEnv({"set": [["dom.sysmsg.enabled", true],
+                                         ["dom.requestSync.enabled", true],
+                                         ["dom.requestSync.minInterval", 1],
+                                         ["dom.requestSync.maxTaskTimeout", 10000 /* 10 seconds */],
+                                         ["dom.ignore_webidl_scope_checks", true]]}, runTests);
+    },
+
+    function() {
+      SpecialPowers.pushPermissions(
+        [{ "type": "requestsync-manager", "allow": 1, "context": document } ], runTests);
+    },
+
+    function() {
+      if (SpecialPowers.isMainProcess()) {
+        SpecialPowers.Cu.import("resource://gre/modules/RequestSyncService.jsm");
+      }
+      runTests();
+    },
+
+    setMessageHandler,
+
+    test_register_oneShot,
+
+    test_runNow,
+
+    test_unregister_oneShot,
+  ];
+
+  function runTests() {
+    if (!tests.length) {
+      SimpleTest.finish();
+      return;
+    }
+
+    var test = tests.shift();
+    test();
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  runTests();
+  </script>
+</body>
+</html>
--- a/dom/webidl/RequestSyncManager.webidl
+++ b/dom/webidl/RequestSyncManager.webidl
@@ -36,16 +36,18 @@ interface RequestSyncTask {
   readonly attribute USVString wakeUpPage;
   readonly attribute boolean oneShot;
   readonly attribute long minInterval;
   readonly attribute boolean wifiOnly;
   readonly attribute any data;
 
   Promise<void> setPolicy(RequestSyncTaskPolicyState aState,
                           optional long ovewrittenMinInterval);
+
+  Promise<void> runNow();
 };
 
 [NavigatorProperty="syncManager",
  AvailableIn=CertifiedApps,
  Pref="dom.requestSync.enabled",
  CheckPermissions="requestsync-manager",
  JSImplementation="@mozilla.org/dom/request-sync-manager;1"]
 // This interface will be used only by the B2G SystemApp
--- a/image/decoders/nsPNGDecoder.cpp
+++ b/image/decoders/nsPNGDecoder.cpp
@@ -164,17 +164,16 @@ void nsPNGDecoder::CreateFrame(png_uint_
     }
 
     NeedNewFrame(mNumFrames, x_offset, y_offset, width, height, format);
   } else if (mNumFrames != 0) {
     NeedNewFrame(mNumFrames, x_offset, y_offset, width, height, format);
   }
 
   mFrameRect = neededRect;
-  mFrameHasNoAlpha = true;
 
   PR_LOG(GetPNGDecoderAccountingLog(), PR_LOG_DEBUG,
          ("PNGDecoderAccounting: nsPNGDecoder::CreateFrame -- created "
           "image frame with %dx%d pixels in container %p",
           width, height,
           &mImage));
 
 #ifdef PNG_APNG_SUPPORTED
@@ -196,17 +195,17 @@ nsPNGDecoder::EndImageFrame()
 {
   if (mFrameIsHidden) {
     return;
   }
 
   mNumFrames++;
 
   Opacity opacity = Opacity::SOME_TRANSPARENCY;
-  if (format == gfx::SurfaceFormat::B8G8R8X8 || mFrameHasNoAlpha) {
+  if (format == gfx::SurfaceFormat::B8G8R8X8) {
     opacity = Opacity::OPAQUE;
   }
 
 #ifdef PNG_APNG_SUPPORTED
   uint32_t numFrames = GetFrameCount();
 
   // We can't use mPNG->num_frames_read as it may be one ahead.
   if (numFrames > 1) {
@@ -734,17 +733,16 @@ nsPNGDecoder::row_callback(png_structp p
     png_bytep line = new_row;
     if (decoder->interlacebuf) {
       line = decoder->interlacebuf + (row_num * decoder->mChannels * width);
       png_progressive_combine_row(png_ptr, line, new_row);
     }
 
     uint32_t bpr = width * sizeof(uint32_t);
     uint32_t* cptr32 = (uint32_t*)(decoder->mImageData + (row_num*bpr));
-    bool rowHasNoAlpha = true;
 
     if (decoder->mTransform) {
       if (decoder->mCMSLine) {
         qcms_transform_data(decoder->mTransform, line, decoder->mCMSLine,
                             iwidth);
         // copy alpha over
         uint32_t channels = decoder->mChannels;
         if (channels == 2 || channels == 4) {
@@ -783,41 +781,31 @@ nsPNGDecoder::row_callback(png_structp p
           line += 3;
         }
       }
       break;
       case gfx::SurfaceFormat::B8G8R8A8: {
         if (!decoder->mDisablePremultipliedAlpha) {
           for (uint32_t x=width; x>0; --x) {
             *cptr32++ = gfxPackedPixel(line[3], line[0], line[1], line[2]);
-            if (line[3] != 0xff) {
-              rowHasNoAlpha = false;
-            }
             line += 4;
           }
         } else {
           for (uint32_t x=width; x>0; --x) {
             *cptr32++ = gfxPackedPixelNoPreMultiply(line[3], line[0], line[1],
                                                     line[2]);
-            if (line[3] != 0xff) {
-              rowHasNoAlpha = false;
-            }
             line += 4;
           }
         }
       }
       break;
       default:
         png_longjmp(decoder->mPNG, 1);
     }
 
-    if (!rowHasNoAlpha) {
-      decoder->mFrameHasNoAlpha = false;
-    }
-
     if (decoder->mNumFrames <= 1) {
       // Only do incremental image display for the first frame
       // XXXbholley - this check should be handled in the superclass
       nsIntRect r(0, row_num, width, 1);
       decoder->PostInvalidation(r);
     }
   }
 }
--- a/image/decoders/nsPNGDecoder.h
+++ b/image/decoders/nsPNGDecoder.h
@@ -81,17 +81,16 @@ public:
   // For size decodes
   uint8_t mSizeBytes[8]; // Space for width and height, both 4 bytes
   uint32_t mHeaderBytesRead;
 
   // whether CMS or premultiplied alpha are forced off
   uint32_t mCMSMode;
 
   uint8_t mChannels;
-  bool mFrameHasNoAlpha;
   bool mFrameIsHidden;
   bool mDisablePremultipliedAlpha;
 
   struct AnimFrameInfo
   {
     AnimFrameInfo();
 #ifdef PNG_APNG_SUPPORTED
     AnimFrameInfo(png_structp aPNG, png_infop aInfo);
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/scripted-getter-setter.js
@@ -0,0 +1,59 @@
+if (getJitCompilerOptions()["ion.warmup.trigger"] > 50)
+    setJitCompilerOption("ion.warmup.trigger", 50);
+
+function getObjects() {
+    var objs = [];
+
+    // Own scripted getter/setter.
+    objs.push({x: 0, get prop() {
+        assertJitStackInvariants();
+        return ++this.x;
+    }, set prop(v) {
+        assertJitStackInvariants();
+        this.x += v;
+    }});
+
+    // Scripted getter/setter on prototype. Also verify extra formal args are
+    // handled correctly.
+    function getter(a, b, c) {
+        assertEq(arguments.length, 0);
+        assertEq(a, undefined);
+        assertEq(b, undefined);
+        assertEq(c, undefined);
+        assertJitStackInvariants();
+        bailout();
+        return ++this.y;
+    }
+    function setter1(a, b) {
+        assertEq(arguments.length, 1);
+        assertEq(b, undefined);
+        assertJitStackInvariants();
+        this.y = a;
+        bailout();
+        return "unused";
+    }
+    var proto = {};
+    Object.defineProperty(proto, "prop", {get: getter, set: setter1});
+    objs.push(Object.create(proto));
+
+    function setter2() {
+        assertEq(arguments.length, 1);
+        assertJitStackInvariants();
+        this.y = arguments[0];
+    }
+    proto = {};
+    Object.defineProperty(proto, "prop", {get: getter, set: setter2});
+    objs.push(Object.create(proto));
+    return objs;
+}
+function f() {
+    var objs = getObjects();
+    var res = 0;
+    for (var i=0; i<200; i++) {
+        var o = objs[i % objs.length];
+        o.prop = 2;
+        res += o.prop;
+    }
+    assertEq(res, 7233);
+}
+f();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/profiler/getter-setter-ic.js
@@ -0,0 +1,32 @@
+// Ensure readSPSProfilingStack() doesn't crash with Ion
+// getter/setter ICs on the stack.
+function getObjects() {
+    var objs = [];
+    objs.push({x: 0, get prop() {
+	readSPSProfilingStack();
+	return ++this.x;
+    }, set prop(v) {
+	readSPSProfilingStack();
+	this.x = v + 2;
+    }});
+    objs.push({x: 0, y: 0, get prop() {
+	readSPSProfilingStack();
+	return this.y;
+    }, set prop(v) {
+	readSPSProfilingStack();
+	this.y = v;
+    }});
+    return objs;
+}
+function f() {
+    var objs = getObjects();
+    var res = 0;
+    for (var i=0; i<100; i++) {
+	var o = objs[i % objs.length];
+	res += o.prop;
+	o.prop = i;
+    }
+    assertEq(res, 4901);
+}
+enableSPSProfiling();
+f();
--- a/js/src/jit/BaselineBailouts.cpp
+++ b/js/src/jit/BaselineBailouts.cpp
@@ -1,15 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jsprf.h"
+#include "jsutil.h"
 #include "jit/arm/Simulator-arm.h"
 #include "jit/BaselineIC.h"
 #include "jit/BaselineJIT.h"
 #include "jit/CompileInfo.h"
 #include "jit/JitSpewer.h"
 #include "jit/mips/Simulator-mips.h"
 #include "jit/Recover.h"
 #include "jit/RematerializedFrame.h"
@@ -234,16 +235,28 @@ struct BaselineStackBuilder
             JitSpew(JitSpew_BaselineBailouts,
                     "      WRITE_VAL %p/%p %-15s %016llx",
                     header_->copyStackBottom, virtualPointerAtStackOffset(0), info,
                     *((uint64_t *) &val));
         }
         return true;
     }
 
+    bool maybeWritePadding(size_t alignment, size_t after, const char *info) {
+        MOZ_ASSERT(framePushed_ % sizeof(Value) == 0);
+        MOZ_ASSERT(after % sizeof(Value) == 0);
+        size_t offset = ComputeByteAlignment(after, alignment);
+        while (framePushed_ % alignment != offset) {
+            if (!writeValue(MagicValue(JS_ARG_POISON), info))
+                return false;
+        }
+
+        return true;
+    }
+
     Value popValue() {
         MOZ_ASSERT(bufferUsed_ >= sizeof(Value));
         MOZ_ASSERT(framePushed_ >= sizeof(Value));
         bufferAvail_ += sizeof(Value);
         bufferUsed_ -= sizeof(Value);
         framePushed_ -= sizeof(Value);
         Value result = *((Value *) header_->copyStackBottom);
         header_->copyStackBottom += sizeof(Value);
@@ -324,20 +337,21 @@ struct BaselineStackBuilder
     // cases, this value can be bogus since we can ensure that the caller would have saved
     // it anyway.
     //
     void *calculatePrevFramePtr() {
         // Get the incoming frame.
         BufferPointer<JitFrameLayout> topFrame = topFrameAddress();
         FrameType type = topFrame->prevType();
 
-        // For IonJS and Entry frames, the "saved" frame pointer in the baseline
-        // frame is meaningless, since Ion saves all registers before calling other ion
-        // frames, and the entry frame saves all registers too.
-        if (type == JitFrame_IonJS || type == JitFrame_Entry)
+        // For IonJS, IonAccessorIC and Entry frames, the "saved" frame pointer
+        // in the baseline frame is meaningless, since Ion saves all registers
+        // before calling other ion frames, and the entry frame saves all
+        // registers too.
+        if (type == JitFrame_IonJS || type == JitFrame_Entry || type == JitFrame_IonAccessorIC)
             return nullptr;
 
         // BaselineStub - Baseline calling into Ion.
         //  PrevFramePtr needs to point to the BaselineStubFrame's saved frame pointer.
         //      STACK_START_ADDR + JitFrameLayout::Size() + PREV_FRAME_SIZE
         //                      - BaselineStubFrameLayout::reverseOffsetOfSavedFramePtr()
         if (type == JitFrame_BaselineStub) {
             size_t offset = JitFrameLayout::Size() + topFrame->prevFrameLocalSize() +
@@ -501,40 +515,44 @@ HasLiveIteratorAtStackDepth(JSScript *sc
 //         |   --   |   +---------------+  --- IF NOT LAST INLINE FRAME,
 //         +------------|  Descr(BLJS)  |  --- CALLING INFO STARTS HERE
 //                  |   +---------------+
 //                  |   |  ReturnAddr   | <-- return into main jitcode after IC
 //             --   |   +===============+
 //             |    |   |    StubPtr    |
 //             |    |   +---------------+
 //             |    +---|   FramePtr    |
-//             |        +---------------+
-//             |        |     ArgA      |
+//             |        +---------------+  --- The inlined frame might OSR in Ion
+//             |        |   Padding?    |  --- Thus the return address should be aligned.
 //             |        +---------------+
-//             |        |     ...       |
-//         +--<         +---------------+
+//         +--<         |     ArgA      |
+//         |   |        +---------------+
+//         |   |        |     ...       |
+//         |   |        +---------------+
 //         |   |        |     Arg0      |
 //         |   |        +---------------+
 //         |   |        |     ThisV     |
 //         |   --       +---------------+
 //         |            |  ActualArgC   |
 //         |            +---------------+
 //         |            |  CalleeToken  |
 //         |            +---------------+
 //         +------------| Descr(BLStub) |
 //                      +---------------+
 //                      |  ReturnAddr   | <-- return into ICCall_Scripted IC
 //             --       +===============+ --- IF CALLEE FORMAL ARGS > ActualArgC
+//             |        |   Padding?    |
+//             |        +---------------+
 //             |        |  UndefinedU   |
 //             |        +---------------+
 //             |        |     ...       |
 //             |        +---------------+
 //             |        |  Undefined0   |
-//             |        +---------------+
-//         +--<         |     ArgA      |
+//         +--<         +---------------+
+//         |   |        |     ArgA      |
 //         |   |        +---------------+
 //         |   |        |     ...       |
 //         |   |        +---------------+
 //         |   |        |     Arg0      |
 //         |   |        +---------------+
 //         |   |        |     ThisV     |
 //         |   --       +---------------+
 //         |            |  ActualArgC   |
@@ -1131,16 +1149,18 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
 
     // Build baseline stub frame:
     // +===============+
     // |    StubPtr    |
     // +---------------+
     // |   FramePtr    |
     // +---------------+
+    // |   Padding?    |
+    // +---------------+
     // |     ArgA      |
     // +---------------+
     // |     ...       |
     // +---------------+
     // |     Arg0      |
     // +---------------+
     // |     ThisV     |
     // +---------------+
@@ -1174,30 +1194,41 @@ InitFromBailout(JSContext *cx, HandleScr
     if (needToSaveArgs) {
         // For FUNAPPLY or an accessor, the arguments are not on the stack anymore,
         // but they are copied in a vector and are written here.
         if (op == JSOP_FUNAPPLY)
             actualArgc = blFrame->numActualArgs();
         else
             actualArgc = IsSetPropPC(pc);
 
+        // Align the stack based on the number of arguments.
+        size_t afterFrameSize = (actualArgc + 1) * sizeof(Value) + JitFrameLayout::Size();
+        if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+            return false;
+
+        // Push arguments.
         MOZ_ASSERT(actualArgc + 2 <= exprStackSlots);
         MOZ_ASSERT(savedCallerArgs.length() == actualArgc + 2);
         for (unsigned i = 0; i < actualArgc + 1; i++) {
             size_t arg = savedCallerArgs.length() - (i + 1);
             if (!builder.writeValue(savedCallerArgs[arg], "ArgVal"))
                 return false;
         }
     } else {
         actualArgc = GET_ARGC(pc);
         if (op == JSOP_FUNCALL) {
             MOZ_ASSERT(actualArgc > 0);
             actualArgc--;
         }
 
+        // Align the stack based on the number of arguments.
+        size_t afterFrameSize = (actualArgc + 1) * sizeof(Value) + JitFrameLayout::Size();
+        if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+            return false;
+
         MOZ_ASSERT(actualArgc + 2 <= exprStackSlots);
         for (unsigned i = 0; i < actualArgc + 1; i++) {
             size_t argSlot = (script->nfixed() + exprStackSlots) - (i + 1);
             if (!builder.writeValue(*blFrame->valueSlot(argSlot), "ArgVal"))
                 return false;
         }
     }
 
@@ -1238,24 +1269,27 @@ InitFromBailout(JSContext *cx, HandleScr
     if (!builder.writeWord(baselineStubFrameDescr, "Descriptor"))
         return false;
 
     // Push return address into ICCall_Scripted stub, immediately after the call.
     void *baselineCallReturnAddr = GetStubReturnAddress(cx, pc);
     MOZ_ASSERT(baselineCallReturnAddr);
     if (!builder.writePtr(baselineCallReturnAddr, "ReturnAddr"))
         return false;
+    MOZ_ASSERT(builder.framePushed() % JitStackAlignment == 0);
 
     // If actualArgc >= fun->nargs, then we are done.  Otherwise, we need to push on
     // a reconstructed rectifier frame.
     if (actualArgc >= calleeFun->nargs())
         return true;
 
     // Push a reconstructed rectifier frame.
     // +===============+
+    // |   Padding?    |
+    // +---------------+
     // |  UndefinedU   |
     // +---------------+
     // |     ...       |
     // +---------------+
     // |  Undefined0   |
     // +---------------+
     // |     ArgA      |
     // +---------------+
@@ -1277,18 +1311,27 @@ InitFromBailout(JSContext *cx, HandleScr
     JitSpew(JitSpew_BaselineBailouts, "      [RECTIFIER FRAME]");
 
     size_t startOfRectifierFrame = builder.framePushed();
 
     // On x86-only, the frame pointer is saved again in the rectifier frame.
 #if defined(JS_CODEGEN_X86)
     if (!builder.writePtr(prevFramePtr, "PrevFramePtr-X86Only"))
         return false;
+    // Follow the same logic as in JitRuntime::generateArgumentsRectifier.
+    prevFramePtr = builder.virtualPointerAtStackOffset(0);
+    if (!builder.writePtr(prevFramePtr, "Padding-X86Only"))
+        return false;
 #endif
 
+    // Align the stack based on the number of arguments.
+    size_t afterFrameSize = (calleeFun->nargs() + 1) * sizeof(Value) + RectifierFrameLayout::Size();
+    if (!builder.maybeWritePadding(JitStackAlignment, afterFrameSize, "Padding"))
+        return false;
+
     // Push undefined for missing arguments.
     for (unsigned i = 0; i < (calleeFun->nargs() - actualArgc); i++) {
         if (!builder.writeValue(UndefinedValue(), "FillerVal"))
             return false;
     }
 
     // Copy arguments + thisv from BaselineStub frame.
     if (!builder.subtract((actualArgc + 1) * sizeof(Value), "CopiedArgs"))
@@ -1317,16 +1360,17 @@ InitFromBailout(JSContext *cx, HandleScr
         return false;
 
     // Push return address into the ArgumentsRectifier code, immediately after the ioncode
     // call.
     void *rectReturnAddr = cx->runtime()->jitRuntime()->getArgumentsRectifierReturnAddr();
     MOZ_ASSERT(rectReturnAddr);
     if (!builder.writePtr(rectReturnAddr, "ReturnAddr"))
         return false;
+    MOZ_ASSERT(builder.framePushed() % JitStackAlignment == 0);
 
     return true;
 }
 
 uint32_t
 jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
                           bool invalidate, BaselineBailoutInfo **bailoutInfo,
                           const ExceptionBailoutInfo *excInfo)
@@ -1343,17 +1387,18 @@ jit::BailoutIonToBaseline(JSContext *cx,
     //      BaselineStub - Baseline calling into Ion.
     //      Entry - Interpreter or other calling into Ion.
     //      Rectifier - Arguments rectifier calling into Ion.
     MOZ_ASSERT(iter.isBailoutJS());
     FrameType prevFrameType = iter.prevType();
     MOZ_ASSERT(prevFrameType == JitFrame_IonJS ||
                prevFrameType == JitFrame_BaselineStub ||
                prevFrameType == JitFrame_Entry ||
-               prevFrameType == JitFrame_Rectifier);
+               prevFrameType == JitFrame_Rectifier ||
+               prevFrameType == JitFrame_IonAccessorIC);
 
     // All incoming frames are going to look like this:
     //
     //      +---------------+
     //      |     ...       |
     //      +---------------+
     //      |     Args      |
     //      |     ...       |
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2502,20 +2502,24 @@ InvalidateActivation(FreeOp *fop, const 
             JitSpew(JitSpew_IonInvalidate, "#%d baseline stub frame @ %p", frameno, it.fp());
             break;
           case JitFrame_Rectifier:
             JitSpew(JitSpew_IonInvalidate, "#%d rectifier frame @ %p", frameno, it.fp());
             break;
           case JitFrame_Unwound_IonJS:
           case JitFrame_Unwound_BaselineJS:
           case JitFrame_Unwound_BaselineStub:
+          case JitFrame_Unwound_IonAccessorIC:
             MOZ_CRASH("invalid");
           case JitFrame_Unwound_Rectifier:
             JitSpew(JitSpew_IonInvalidate, "#%d unwound rectifier frame @ %p", frameno, it.fp());
             break;
+          case JitFrame_IonAccessorIC:
+            JitSpew(JitSpew_IonInvalidate, "#%d ion IC getter/setter frame @ %p", frameno, it.fp());
+            break;
           case JitFrame_Entry:
             JitSpew(JitSpew_IonInvalidate, "#%d entry frame @ %p", frameno, it.fp());
             break;
         }
 #endif
 
         if (!it.isIonScripted())
             continue;
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -7760,17 +7760,16 @@ IonBuilder::pushDerivedTypedObject(bool 
     }
     const TypedProto *expectedProto = derivedPrediction.getKnownPrototype();
     MOZ_ASSERT_IF(expectedClass, IsTypedObjectClass(expectedClass));
 
     // Determine (if possible) the class/proto that the observed type set
     // describes.
     TemporaryTypeSet *observedTypes = bytecodeTypes(pc);
     const Class *observedClass = observedTypes->getKnownClass(constraints());
-    JSObject *observedProto = observedTypes->getCommonPrototype(constraints());
 
     // If expectedClass/expectedProto are both non-null (and hence known), we
     // can predict precisely what object group derivedTypedObj will have.
     // Therefore, if we observe that this group is already contained in the set
     // of observedTypes, we can skip the barrier.
     //
     // Barriers still wind up being needed in some relatively
     // rare cases:
@@ -7779,17 +7778,19 @@ IonBuilder::pushDerivedTypedObject(bool 
     //   in which case we will not be able to predict expectedClass
     //   nor expectedProto.
     //
     // - if the code has never executed, in which case the set of
     //   observed types will be incomplete.
     //
     // Barriers are particularly expensive here because they prevent
     // us from optimizing the MNewDerivedTypedObject away.
-    if (observedClass && observedProto && observedClass == expectedClass &&
+    JSObject *observedProto;
+    if (observedTypes->getCommonPrototype(constraints(), &observedProto) &&
+        observedClass && observedProto && observedClass == expectedClass &&
         observedProto == expectedProto)
     {
         derivedTypedObj->setResultTypeSet(observedTypes);
     } else {
         if (!pushTypeBarrier(derivedTypedObj, observedTypes, BarrierKind::TypeSet))
             return false;
     }
 
--- a/js/src/jit/IonCaches.cpp
+++ b/js/src/jit/IonCaches.cpp
@@ -648,16 +648,36 @@ IsCacheableGetPropCallNative(JSObject *o
 
     // For getters that need an outerized this object, don't cache if
     // obj has an outerObject hook, since our cache will pass obj
     // itself without outerizing.
     return !obj->getClass()->ext.outerObject;
 }
 
 static bool
+IsCacheableGetPropCallScripted(JSObject *obj, JSObject *holder, Shape *shape)
+{
+    if (!shape || !IsCacheableProtoChainForIon(obj, holder))
+        return false;
+
+    if (!shape->hasGetterValue() || !shape->getterValue().isObject())
+        return false;
+
+    if (!shape->getterValue().toObject().is<JSFunction>())
+        return false;
+
+    JSFunction& getter = shape->getterValue().toObject().as<JSFunction>();
+    if (!getter.hasJITCode())
+        return false;
+
+    // See IsCacheableGetPropCallNative.
+    return !obj->getClass()->ext.outerObject;
+}
+
+static bool
 IsCacheableGetPropCallPropertyOp(JSObject *obj, JSObject *holder, Shape *shape)
 {
     if (!shape || !IsCacheableProtoChainForIon(obj, holder))
         return false;
 
     if (shape->hasSlot() || shape->hasGetterValue() || shape->hasDefaultGetter())
         return false;
 
@@ -915,30 +935,25 @@ EmitGetterCall(JSContext *cx, MacroAssem
     // so leave it alone.
     RegisterSet regSet(RegisterSet::All());
     regSet.take(AnyRegister(object));
 
     // This is a slower stub path, and we're going to be doing a call anyway.  Don't need
     // to try so hard to not use the stack.  Scratch regs are just taken from the register
     // set not including the input, current value saved on the stack, and restored when
     // we're done with it.
-    Register scratchReg      = regSet.takeGeneral();
-    Register argJSContextReg = regSet.takeGeneral();
-    Register argUintNReg     = regSet.takeGeneral();
-    Register argVpReg        = regSet.takeGeneral();
-
-    // Shape has a getter function.
-    bool callNative = IsCacheableGetPropCallNative(obj, holder, shape);
-    MOZ_ASSERT_IF(!callNative, IsCacheableGetPropCallPropertyOp(obj, holder, shape));
-
-    if (callNative) {
-        MOZ_ASSERT(shape->hasGetterValue() && shape->getterValue().isObject() &&
-                   shape->getterValue().toObject().is<JSFunction>());
+    Register scratchReg = regSet.takeGeneral();
+
+    // Shape has a JSNative, PropertyOp or scripted getter function.
+    if (IsCacheableGetPropCallNative(obj, holder, shape)) {
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argUintNReg     = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
+
         JSFunction *target = &shape->getterValue().toObject().as<JSFunction>();
-
         MOZ_ASSERT(target);
         MOZ_ASSERT(target->isNative());
 
         // Native functions have the signature:
         //  bool (*)(JSContext *, unsigned, Value *vp)
         // Where vp[0] is space for an outparam, vp[1] is |this|, and vp[2] onward
         // are the function arguments.
 
@@ -972,17 +987,20 @@ EmitGetterCall(JSContext *cx, MacroAssem
         masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
         // Load the outparam vp[0] into output register(s).
         Address outparam(StackPointer, IonOOLNativeExitFrameLayout::offsetOfResult());
         masm.loadTypedOrValue(outparam, output);
 
         // masm.leaveExitFrame & pop locals
         masm.adjustStack(IonOOLNativeExitFrameLayout::Size(0));
-    } else {
+    } else if (IsCacheableGetPropCallPropertyOp(obj, holder, shape)) {
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argUintNReg     = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
         Register argObjReg       = argUintNReg;
         Register argIdReg        = regSet.takeGeneral();
 
         PropertyOp target = shape->getterOp();
         MOZ_ASSERT(target);
 
         // Push stubCode for marking.
         attacher.pushStubCodePointer(masm);
@@ -1018,16 +1036,61 @@ EmitGetterCall(JSContext *cx, MacroAssem
         masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
         // Load the outparam vp[0] into output register(s).
         Address outparam(StackPointer, IonOOLPropertyOpExitFrameLayout::offsetOfResult());
         masm.loadTypedOrValue(outparam, output);
 
         // masm.leaveExitFrame & pop locals.
         masm.adjustStack(IonOOLPropertyOpExitFrameLayout::Size());
+    } else {
+        MOZ_ASSERT(IsCacheableGetPropCallScripted(obj, holder, shape));
+
+        JSFunction *target = &shape->getterValue().toObject().as<JSFunction>();
+        uint32_t framePushedBefore = masm.framePushed();
+
+        // Construct IonAccessorICFrameLayout.
+        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+        attacher.pushStubCodePointer(masm);
+        masm.Push(Imm32(descriptor));
+        masm.Push(ImmPtr(returnAddr));
+
+        // The JitFrameLayout pushed below will be aligned to JitStackAlignment,
+        // so we just have to make sure the stack is aligned after we push the
+        // |this| + argument Values.
+        uint32_t argSize = (target->nargs() + 1) * sizeof(Value);
+        uint32_t padding = ComputeByteAlignment(masm.framePushed() + argSize, JitStackAlignment);
+        MOZ_ASSERT(padding % sizeof(uintptr_t) == 0);
+        MOZ_ASSERT(padding < JitStackAlignment);
+        masm.reserveStack(padding);
+
+        for (size_t i = 0; i < target->nargs(); i++)
+            masm.Push(UndefinedValue());
+        masm.Push(TypedOrValueRegister(MIRType_Object, AnyRegister(object)));
+
+        masm.movePtr(ImmMaybeNurseryPtr(target), scratchReg);
+
+        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC);
+        masm.Push(Imm32(0)); // argc
+        masm.Push(scratchReg);
+        masm.Push(Imm32(descriptor));
+
+        // Check stack alignment. Add sizeof(uintptr_t) for the return address.
+        MOZ_ASSERT(((masm.framePushed() + sizeof(uintptr_t)) % JitStackAlignment) == 0);
+
+        // The getter has JIT code now and we will only discard the getter's JIT
+        // code when discarding all JIT code in the Zone, so we can assume it'll
+        // still have JIT code.
+        MOZ_ASSERT(target->hasJITCode());
+        masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg);
+        masm.loadBaselineOrIonRaw(scratchReg, scratchReg, nullptr);
+        masm.callJit(scratchReg);
+        masm.storeCallResultValue(output);
+
+        masm.freeStack(masm.framePushed() - framePushedBefore);
     }
 
     masm.icRestoreLive(liveRegs, aic);
     return true;
 }
 
 static bool
 GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
@@ -1235,22 +1298,23 @@ CanAttachNativeGetProp(typename GetPropC
     }
 
     // IonBuilder guarantees that it's impossible to generate a GetPropertyIC with
     // allowGetters() true and cache.output().hasValue() false. If this isn't true,
     // we will quickly assert during stub generation.
     //
     // Be careful when adding support for other getters here: for outer window
     // proxies, IonBuilder can innerize and pass us the inner window (the global),
-    // see IonBuilder::getPropTryInnerize. This is fine for native getters because
-    // IsCacheableGetPropCallNative checks they can handle both the inner and
-    // outer object, but scripted getters would need a similar mechanism.
+    // see IonBuilder::getPropTryInnerize. This is fine for native/scripted getters
+    // because IsCacheableGetPropCallNative and IsCacheableGetPropCallScripted
+    // handle this.
     if (cache.allowGetters() &&
         (IsCacheableGetPropCallNative(obj, holder, shape) ||
-         IsCacheableGetPropCallPropertyOp(obj, holder, shape)))
+         IsCacheableGetPropCallPropertyOp(obj, holder, shape) ||
+         IsCacheableGetPropCallScripted(obj, holder, shape)))
     {
         // Don't enable getter call if cache is idempotent, since they can be
         // effectful. This is handled by allowGetters()
         return GetPropertyIC::CanAttachCallGetter;
     }
 
     return GetPropertyIC::CanAttachNone;
 }
@@ -1991,16 +2055,29 @@ IsCacheableSetPropCallNative(HandleObjec
         return false;
 
     return shape->hasSetterValue() && shape->setterObject() &&
            shape->setterObject()->is<JSFunction>() &&
            shape->setterObject()->as<JSFunction>().isNative();
 }
 
 static bool
+IsCacheableSetPropCallScripted(HandleObject obj, HandleObject holder, HandleShape shape)
+{
+    MOZ_ASSERT(obj->isNative());
+
+    if (!shape || !IsCacheableProtoChainForIon(obj, holder))
+        return false;
+
+    return shape->hasSetterValue() && shape->setterObject() &&
+           shape->setterObject()->is<JSFunction>() &&
+           shape->setterObject()->as<JSFunction>().hasJITCode();
+}
+
+static bool
 IsCacheableSetPropCallPropertyOp(HandleObject obj, HandleObject holder, HandleShape shape)
 {
     MOZ_ASSERT(obj->isNative());
 
     if (!shape)
         return false;
 
     if (!IsCacheableProtoChainForIon(obj, holder))
@@ -2233,24 +2310,22 @@ GenerateCallSetter(JSContext *cx, IonScr
 
     // This is a slower stub path, and we're going to be doing a call anyway.  Don't need
     // to try so hard to not use the stack.  Scratch regs are just taken from the register
     // set not including the input, current value saved on the stack, and restored when
     // we're done with it.
     //
     // Be very careful not to use any of these before value is pushed, since they
     // might shadow.
-    Register scratchReg     = regSet.takeGeneral();
-    Register argJSContextReg = regSet.takeGeneral();
-    Register argVpReg        = regSet.takeGeneral();
-
-    bool callNative = IsCacheableSetPropCallNative(obj, holder, shape);
-    MOZ_ASSERT_IF(!callNative, IsCacheableSetPropCallPropertyOp(obj, holder, shape));
-
-    if (callNative) {
+    Register scratchReg = regSet.takeGeneral();
+
+    if (IsCacheableSetPropCallNative(obj, holder, shape)) {
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
+
         MOZ_ASSERT(shape->hasSetterValue() && shape->setterObject() &&
                    shape->setterObject()->is<JSFunction>());
         JSFunction *target = &shape->setterObject()->as<JSFunction>();
 
         MOZ_ASSERT(target->isNative());
 
         Register argUintNReg = regSet.takeGeneral();
 
@@ -2285,17 +2360,19 @@ GenerateCallSetter(JSContext *cx, IonScr
         masm.passABIArg(argVpReg);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target->native()));
 
         // Test for failure.
         masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
         // masm.leaveExitFrame & pop locals.
         masm.adjustStack(IonOOLNativeExitFrameLayout::Size(1));
-    } else {
+    } else if (IsCacheableSetPropCallPropertyOp(obj, holder, shape)) {
+        Register argJSContextReg = regSet.takeGeneral();
+        Register argVpReg        = regSet.takeGeneral();
         Register argObjReg       = regSet.takeGeneral();
         Register argIdReg        = regSet.takeGeneral();
         Register argStrictReg    = regSet.takeGeneral();
 
         attacher.pushStubCodePointer(masm);
 
         StrictPropertyOp target = shape->setterOp();
         MOZ_ASSERT(target);
@@ -2333,16 +2410,62 @@ GenerateCallSetter(JSContext *cx, IonScr
         masm.passABIArg(argVpReg);
         masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, target));
 
         // Test for failure.
         masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
         // masm.leaveExitFrame & pop locals.
         masm.adjustStack(IonOOLPropertyOpExitFrameLayout::Size());
+    } else {
+        MOZ_ASSERT(IsCacheableSetPropCallScripted(obj, holder, shape));
+
+        JSFunction *target = &shape->setterValue().toObject().as<JSFunction>();
+        uint32_t framePushedBefore = masm.framePushed();
+
+        // Construct IonAccessorICFrameLayout.
+        uint32_t descriptor = MakeFrameDescriptor(masm.framePushed(), JitFrame_IonJS);
+        attacher.pushStubCodePointer(masm);
+        masm.Push(Imm32(descriptor));
+        masm.Push(ImmPtr(returnAddr));
+
+        // The JitFrameLayout pushed below will be aligned to JitStackAlignment,
+        // so we just have to make sure the stack is aligned after we push the
+        // |this| + argument Values.
+        uint32_t numArgs = Max(size_t(1), target->nargs());
+        uint32_t argSize = (numArgs + 1) * sizeof(Value);
+        uint32_t padding = ComputeByteAlignment(masm.framePushed() + argSize, JitStackAlignment);
+        MOZ_ASSERT(padding % sizeof(uintptr_t) == 0);
+        MOZ_ASSERT(padding < JitStackAlignment);
+        masm.reserveStack(padding);
+
+        for (size_t i = 1; i < target->nargs(); i++)
+            masm.Push(UndefinedValue());
+        masm.Push(value);
+        masm.Push(TypedOrValueRegister(MIRType_Object, AnyRegister(object)));
+
+        masm.movePtr(ImmMaybeNurseryPtr(target), scratchReg);
+
+        descriptor = MakeFrameDescriptor(argSize + padding, JitFrame_IonAccessorIC);
+        masm.Push(Imm32(1)); // argc
+        masm.Push(scratchReg);
+        masm.Push(Imm32(descriptor));
+
+        // Check stack alignment. Add sizeof(uintptr_t) for the return address.
+        MOZ_ASSERT(((masm.framePushed() + sizeof(uintptr_t)) % JitStackAlignment) == 0);
+
+        // The setter has JIT code now and we will only discard the setter's JIT
+        // code when discarding all JIT code in the Zone, so we can assume it'll
+        // still have JIT code.
+        MOZ_ASSERT(target->hasJITCode());
+        masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg);
+        masm.loadBaselineOrIonRaw(scratchReg, scratchReg, nullptr);
+        masm.callJit(scratchReg);
+
+        masm.freeStack(masm.framePushed() - framePushedBefore);
     }
 
     masm.icRestoreLive(liveRegs, aic);
     return true;
 }
 
 static bool
 IsCacheableDOMProxyUnshadowedSetterCall(JSContext *cx, HandleObject obj, HandlePropertyName name,
@@ -2359,17 +2482,18 @@ IsCacheableDOMProxyUnshadowedSetterCall(
 
     if (!LookupProperty(cx, obj, name, holder, shape))
         return false;
 
     if (!holder)
         return true;
 
     if (!IsCacheableSetPropCallNative(checkObj, holder, shape) &&
-        !IsCacheableSetPropCallPropertyOp(checkObj, holder, shape))
+        !IsCacheableSetPropCallPropertyOp(checkObj, holder, shape) &&
+        !IsCacheableSetPropCallScripted(checkObj, holder, shape))
     {
         return true;
     }
 
     *isSetter = true;
     return true;
 }
 
@@ -2724,17 +2848,18 @@ CanAttachNativeSetProp(JSContext *cx, Ha
     // If the object doesn't have the property, we don't know if we can attach
     // a stub to add the property until we do the VM call to add. If the
     // property exists as a data property on the prototype, we should add
     // a new, shadowing property.
     if (!shape || (obj != holder && shape->hasDefaultSetter() && shape->hasSlot()))
         return SetPropertyIC::MaybeCanAttachAddSlot;
 
     if (IsCacheableSetPropCallPropertyOp(obj, holder, shape) ||
-        IsCacheableSetPropCallNative(obj, holder, shape))
+        IsCacheableSetPropCallNative(obj, holder, shape) ||
+        IsCacheableSetPropCallScripted(obj, holder, shape))
     {
         return SetPropertyIC::CanAttachCallSetter;
     }
 
     return SetPropertyIC::CanAttachNone;
 }
 
 static void
@@ -4090,17 +4215,18 @@ IsCacheableNameCallGetter(HandleObject s
         return false;
     if (!obj->is<GlobalObject>())
         return false;
 
     if (!IsCacheableScopeChain(scopeChain, obj))
         return false;
 
     return IsCacheableGetPropCallNative(obj, holder, shape) ||
-        IsCacheableGetPropCallPropertyOp(obj, holder, shape);
+        IsCacheableGetPropCallPropertyOp(obj, holder, shape) ||
+        IsCacheableGetPropCallScripted(obj, holder, shape);
 }
 
 bool
 NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
                MutableHandleValue vp)
 {
     void *returnAddr;
     RootedScript outerScript(cx, GetTopJitJSScript(cx, &returnAddr));
--- a/js/src/jit/JitFrameIterator.h
+++ b/js/src/jit/JitFrameIterator.h
@@ -39,28 +39,27 @@ enum FrameType
     // The entry frame is the initial prologue block transitioning from the VM
     // into the Ion world.
     JitFrame_Entry,
 
     // A rectifier frame sits in between two JS frames, adapting argc != nargs
     // mismatches in calls.
     JitFrame_Rectifier,
 
+    // Ion IC calling a scripted getter/setter.
+    JitFrame_IonAccessorIC,
+
     // An unwound JS frame is a JS frame signalling that its callee frame has been
     // turned into an exit frame (see EnsureExitFrame). Used by Ion bailouts and
     // Baseline exception unwinding.
     JitFrame_Unwound_BaselineJS,
     JitFrame_Unwound_IonJS,
-
-    // Like Unwound_IonJS, but the caller is a baseline stub frame.
     JitFrame_Unwound_BaselineStub,
-
-    // An unwound rectifier frame is a rectifier frame signalling that its callee
-    // frame has been turned into an exit frame (see EnsureExitFrame).
     JitFrame_Unwound_Rectifier,
+    JitFrame_Unwound_IonAccessorIC,
 
     // An exit frame is necessary for transitioning from a JS frame into C++.
     // From within C++, an exit frame is always the last frame in any
     // JitActivation.
     JitFrame_Exit,
 
     // A bailout frame is a special IonJS jit frame after a bailout, and before
     // the reconstruction of the BaselineJS frame. From within C++, a bailout
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -244,26 +244,30 @@ SizeOfFramePrefix(FrameType type)
         return EntryFrameLayout::Size();
       case JitFrame_BaselineJS:
       case JitFrame_IonJS:
       case JitFrame_Bailout:
       case JitFrame_Unwound_BaselineJS:
       case JitFrame_Unwound_IonJS:
         return JitFrameLayout::Size();
       case JitFrame_BaselineStub:
+      case JitFrame_Unwound_BaselineStub:
         return BaselineStubFrameLayout::Size();
       case JitFrame_Rectifier:
         return RectifierFrameLayout::Size();
       case JitFrame_Unwound_Rectifier:
         return IonUnwoundRectifierFrameLayout::Size();
       case JitFrame_Exit:
         return ExitFrameLayout::Size();
-      default:
-        MOZ_CRASH("unknown frame type");
+      case JitFrame_IonAccessorIC:
+      case JitFrame_Unwound_IonAccessorIC:
+        return IonAccessorICFrameLayout::Size();
     }
+
+    MOZ_CRASH("unknown frame type");
 }
 
 uint8_t *
 JitFrameIterator::prevFp() const
 {
     size_t currentSize = SizeOfFramePrefix(type_);
     // This quick fix must be removed as soon as bug 717297 land.  This is
     // needed because the descriptor size of JS-to-JS frame which is just after
@@ -297,16 +301,18 @@ JitFrameIterator::operator++()
     uint8_t *prev = prevFp();
     type_ = current()->prevType();
     if (type_ == JitFrame_Unwound_IonJS)
         type_ = JitFrame_IonJS;
     else if (type_ == JitFrame_Unwound_BaselineJS)
         type_ = JitFrame_BaselineJS;
     else if (type_ == JitFrame_Unwound_BaselineStub)
         type_ = JitFrame_BaselineStub;
+    else if (type_ == JitFrame_Unwound_IonAccessorIC)
+        type_ = JitFrame_IonAccessorIC;
     returnAddressToFp_ = current()->returnAddress();
     current_ = prev;
 
     return *this;
 }
 
 uintptr_t *
 JitFrameIterator::spillBase() const
@@ -884,53 +890,61 @@ HandleException(ResumeFromException *rfe
     }
 
     rfe->stackPointer = iter.fp();
 }
 
 void
 EnsureExitFrame(CommonFrameLayout *frame)
 {
-    if (frame->prevType() == JitFrame_Unwound_IonJS ||
-        frame->prevType() == JitFrame_Unwound_BaselineJS ||
-        frame->prevType() == JitFrame_Unwound_BaselineStub ||
-        frame->prevType() == JitFrame_Unwound_Rectifier)
-    {
+    switch (frame->prevType()) {
+      case JitFrame_Unwound_IonJS:
+      case JitFrame_Unwound_BaselineJS:
+      case JitFrame_Unwound_BaselineStub:
+      case JitFrame_Unwound_Rectifier:
+      case JitFrame_Unwound_IonAccessorIC:
         // Already an exit frame, nothing to do.
         return;
-    }
-
-    if (frame->prevType() == JitFrame_Entry) {
+
+      case JitFrame_Entry:
         // The previous frame type is the entry frame, so there's no actual
         // need for an exit frame.
         return;
-    }
-
-    if (frame->prevType() == JitFrame_Rectifier) {
+
+      case JitFrame_Rectifier:
         // The rectifier code uses the frame descriptor to discard its stack,
         // so modifying its descriptor size here would be dangerous. Instead,
         // we change the frame type, and teach the stack walking code how to
         // deal with this edge case. bug 717297 would obviate the need
         frame->changePrevType(JitFrame_Unwound_Rectifier);
         return;
-    }
-
-    if (frame->prevType() == JitFrame_BaselineStub) {
+
+      case JitFrame_BaselineStub:
         frame->changePrevType(JitFrame_Unwound_BaselineStub);
         return;
-    }
-
-
-    if (frame->prevType() == JitFrame_BaselineJS) {
+
+      case JitFrame_BaselineJS:
         frame->changePrevType(JitFrame_Unwound_BaselineJS);
         return;
+
+      case JitFrame_IonJS:
+        frame->changePrevType(JitFrame_Unwound_IonJS);
+        return;
+
+      case JitFrame_IonAccessorIC:
+        frame->changePrevType(JitFrame_Unwound_IonAccessorIC);
+        return;
+
+      case JitFrame_Exit:
+      case JitFrame_Bailout:
+        // Fall-through to MOZ_CRASH below.
+        break;
     }
 
-    MOZ_ASSERT(frame->prevType() == JitFrame_IonJS);
-    frame->changePrevType(JitFrame_Unwound_IonJS);
+    MOZ_CRASH("Unexpected frame type");
 }
 
 CalleeToken
 MarkCalleeToken(JSTracer *trc, CalleeToken token)
 {
     switch (CalleeTokenTag tag = GetCalleeTokenTag(token)) {
       case CalleeToken_Function:
       case CalleeToken_FunctionConstructing:
@@ -1164,16 +1178,24 @@ MarkBaselineStubFrame(JSTracer *trc, con
     BaselineStubFrameLayout *layout = (BaselineStubFrameLayout *)frame.fp();
 
     if (ICStub *stub = layout->maybeStubPtr()) {
         MOZ_ASSERT(ICStub::CanMakeCalls(stub->kind()));
         stub->trace(trc);
     }
 }
 
+static void
+MarkIonAccessorICFrame(JSTracer *trc, const JitFrameIterator &frame)
+{
+    MOZ_ASSERT(frame.type() == JitFrame_IonAccessorIC);
+    IonAccessorICFrameLayout *layout = (IonAccessorICFrameLayout *)frame.fp();
+    gc::MarkJitCodeRoot(trc, layout->stubCode(), "ion-ic-accessor-code");
+}
+
 void
 JitActivationIterator::jitStackRange(uintptr_t *&min, uintptr_t *&end)
 {
     JitFrameIterator frames(*this);
 
     if (frames.isFakeExitFrame()) {
         min = reinterpret_cast<uintptr_t *>(frames.fp());
     } else {
@@ -1436,22 +1458,27 @@ MarkJitActivation(JSTracer *trc, const J
           case JitFrame_IonJS:
             MarkIonJSFrame(trc, frames);
             break;
           case JitFrame_Bailout:
             MarkBailoutFrame(trc, frames);
             break;
           case JitFrame_Unwound_IonJS:
           case JitFrame_Unwound_BaselineJS:
+          case JitFrame_Unwound_BaselineStub:
+          case JitFrame_Unwound_IonAccessorIC:
             MOZ_CRASH("invalid");
           case JitFrame_Rectifier:
             MarkRectifierFrame(trc, frames);
             break;
           case JitFrame_Unwound_Rectifier:
             break;
+          case JitFrame_IonAccessorIC:
+            MarkIonAccessorICFrame(trc, frames);
+            break;
           default:
             MOZ_CRASH("unexpected frame type");
         }
     }
 }
 
 void
 MarkJitActivations(JSRuntime *rt, JSTracer *trc)
@@ -2655,16 +2682,21 @@ JitFrameIterator::dump() const
         }
         break;
       }
       case JitFrame_Rectifier:
       case JitFrame_Unwound_Rectifier:
         fprintf(stderr, " Rectifier frame\n");
         fprintf(stderr, "  Frame size: %u\n", unsigned(current()->prevFrameLocalSize()));
         break;
+      case JitFrame_IonAccessorIC:
+      case JitFrame_Unwound_IonAccessorIC:
+        fprintf(stderr, " Ion scripted accessor IC\n");
+        fprintf(stderr, "  Frame size: %u\n", unsigned(current()->prevFrameLocalSize()));
+        break;
       case JitFrame_Unwound_IonJS:
       case JitFrame_Unwound_BaselineJS:
         fprintf(stderr, "Warning! Unwound JS frames are not observable.\n");
         break;
       case JitFrame_Exit:
         break;
     };
     fputc('\n', stderr);
@@ -3007,16 +3039,28 @@ JitProfilingFrameIterator::operator++()
                     + jit::BaselineFrame::FramePointerOffset;
             type_ = JitFrame_BaselineJS;
             return;
         }
 
         MOZ_CRASH("Bad frame type prior to rectifier frame.");
     }
 
+    if (prevType == JitFrame_IonAccessorIC || prevType == JitFrame_Unwound_IonAccessorIC) {
+        IonAccessorICFrameLayout *accessorFrame =
+            GetPreviousRawFrame<JitFrameLayout, IonAccessorICFrameLayout *>(frame);
+
+        MOZ_ASSERT(accessorFrame->prevType() == JitFrame_IonJS);
+
+        returnAddressToFp_ = accessorFrame->returnAddress();
+        fp_ = GetPreviousRawFrame<IonAccessorICFrameLayout, uint8_t *>(accessorFrame);
+        type_ = JitFrame_IonJS;
+        return;
+    }
+
     if (prevType == JitFrame_Entry) {
         // No previous frame, set to null to indicate that JitFrameIterator is done()
         returnAddressToFp_ = nullptr;
         fp_ = nullptr;
         type_ = JitFrame_Entry;
         return;
     }
 
--- a/js/src/jit/JitFrames.h
+++ b/js/src/jit/JitFrames.h
@@ -423,16 +423,31 @@ class EntryFrameLayout : public JitFrame
 class RectifierFrameLayout : public JitFrameLayout
 {
   public:
     static inline size_t Size() {
         return sizeof(RectifierFrameLayout);
     }
 };
 
+class IonAccessorICFrameLayout : public CommonFrameLayout
+{
+  protected:
+    // Pointer to root the stub's JitCode.
+    JitCode *stubCode_;
+
+  public:
+    JitCode **stubCode() {
+        return &stubCode_;
+    }
+    static size_t Size() {
+        return sizeof(IonAccessorICFrameLayout);
+    }
+};
+
 // The callee token is now dead.
 class IonUnwoundRectifierFrameLayout : public RectifierFrameLayout
 {
   public:
     static inline size_t Size() {
         // It is not necessary to accout for an extra callee token here because
         // sizeof(ExitFrameLayout) == sizeof(RectifierFrameLayout) due to
         // extra padding.
--- a/js/src/jit/arm/Trampoline-arm.cpp
+++ b/js/src/jit/arm/Trampoline-arm.cpp
@@ -1125,23 +1125,25 @@ JitRuntime::generateProfilerExitFrameTai
     //      FrameDescriptor.type in scratch2
     masm.ma_and(Imm32((1 << FRAMESIZE_SHIFT) - 1), scratch1, scratch2);
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
 
     // Handling of each case is dependent on FrameDescriptor.type
     Label handle_IonJS;
     Label handle_BaselineStub;
     Label handle_Rectifier;
+    Label handle_IonAccessorIC;
     Label handle_Entry;
     Label end;
 
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineStub), &handle_BaselineStub);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Rectifier), &handle_Rectifier);
+    masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonAccessorIC), &handle_IonAccessorIC);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Entry), &handle_Entry);
 
     masm.assumeUnreachable("Invalid caller frame type when exiting from Ion frame.");
 
     //
     // JitFrame_IonJS
     //
     // Stack layout:
@@ -1302,16 +1304,64 @@ JitRuntime::generateProfilerExitFrameTai
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void *)));
         masm.loadPtr(stubFrameSavedFramePtr, scratch2);
         masm.addPtr(Imm32(sizeof(void *)), scratch2);
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
+    // JitFrame_IonAccessorIC
+    //
+    // The caller is always an IonJS frame.
+    //
+    //              Ion-Descriptor
+    //              Ion-ReturnAddr
+    //              ... ion frame data ... |- AccFrame-Descriptor.Size
+    //              StubCode             |
+    //              AccFrame-Descriptor  |- IonAccessorICFrameLayout::Size()
+    //              AccFrame-ReturnAddr  |
+    //              ... accessor frame data & args ... |- Descriptor.Size
+    //              ActualArgc      |
+    //              CalleeToken     |- JitFrameLayout::Size()
+    //              Descriptor      |
+    //    FP -----> ReturnAddr      |
+    masm.bind(&handle_IonAccessorIC);
+    {
+        // scratch2 := StackPointer + Descriptor.size + JitFrameLayout::Size()
+        masm.ma_add(StackPointer, scratch1, scratch2);
+        masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
+
+        // scratch3 := AccFrame-Descriptor.Size
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfDescriptor()), scratch3);
+#ifdef DEBUG
+        // Assert previous frame is an IonJS frame.
+        masm.movePtr(scratch3, scratch1);
+        masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch1);
+        {
+            Label checkOk;
+            masm.branch32(Assembler::Equal, scratch1, Imm32(JitFrame_IonJS), &checkOk);
+            masm.assumeUnreachable("IonAccessorIC frame must be preceded by IonJS frame");
+            masm.bind(&checkOk);
+        }
+#endif
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3);
+
+        // lastProfilingCallSite := AccFrame-ReturnAddr
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfReturnAddress()), scratch1);
+        masm.storePtr(scratch1, lastProfilingCallSite);
+
+        // lastProfilingFrame := AccessorFrame + AccFrame-Descriptor.Size +
+        //                       IonAccessorICFrameLayout::Size()
+        masm.ma_add(scratch2, scratch3, scratch1);
+        masm.addPtr(Imm32(IonAccessorICFrameLayout::Size()), scratch1);
+        masm.storePtr(scratch1, lastProfilingFrame);
+        masm.ret();
+    }
+
     //
     // JitFrame_Entry
     //
     // If at an entry frame, store null into both fields.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/mips/Trampoline-mips.cpp
+++ b/js/src/jit/mips/Trampoline-mips.cpp
@@ -1120,23 +1120,25 @@ JitRuntime::generateProfilerExitFrameTai
     //      FrameDescriptor.type in scratch2
     masm.ma_and(scratch2, scratch1, Imm32((1 << FRAMESIZE_SHIFT) - 1));
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
 
     // Handling of each case is dependent on FrameDescriptor.type
     Label handle_IonJS;
     Label handle_BaselineStub;
     Label handle_Rectifier;
+    Label handle_IonAccessorIC;
     Label handle_Entry;
     Label end;
 
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineStub), &handle_BaselineStub);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Rectifier), &handle_Rectifier);
+    masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonAccessorIC), &handle_IonAccessorIC);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Entry), &handle_Entry);
 
     masm.assumeUnreachable("Invalid caller frame type when exiting from Ion frame.");
 
     //
     // JitFrame_IonJS
     //
     // Stack layout:
@@ -1297,16 +1299,64 @@ JitRuntime::generateProfilerExitFrameTai
         Address stubFrameSavedFramePtr(scratch3,
                                        RectifierFrameLayout::Size() - (2 * sizeof(void *)));
         masm.loadPtr(stubFrameSavedFramePtr, scratch2);
         masm.addPtr(Imm32(sizeof(void *)), scratch2);
         masm.storePtr(scratch2, lastProfilingFrame);
         masm.ret();
     }
 
+    // JitFrame_IonAccessorIC
+    //
+    // The caller is always an IonJS frame.
+    //
+    //              Ion-Descriptor
+    //              Ion-ReturnAddr
+    //              ... ion frame data ... |- AccFrame-Descriptor.Size
+    //              StubCode             |
+    //              AccFrame-Descriptor  |- IonAccessorICFrameLayout::Size()
+    //              AccFrame-ReturnAddr  |
+    //              ... accessor frame data & args ... |- Descriptor.Size
+    //              ActualArgc      |
+    //              CalleeToken     |- JitFrameLayout::Size()
+    //              Descriptor      |
+    //    FP -----> ReturnAddr      |
+    masm.bind(&handle_IonAccessorIC);
+    {
+        // scratch2 := StackPointer + Descriptor.size + JitFrameLayout::Size()
+        masm.ma_addu(StackPointer, scratch1, scratch2);
+        masm.addPtr(Imm32(JitFrameLayout::Size()), scratch2);
+
+        // scratch3 := AccFrame-Descriptor.Size
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfDescriptor()), scratch3);
+#ifdef DEBUG
+        // Assert previous frame is an IonJS frame.
+        masm.movePtr(scratch3, scratch1);
+        masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch1);
+        {
+            Label checkOk;
+            masm.branch32(Assembler::Equal, scratch1, Imm32(JitFrame_IonJS), &checkOk);
+            masm.assumeUnreachable("IonAccessorIC frame must be preceded by IonJS frame");
+            masm.bind(&checkOk);
+        }
+#endif
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3);
+
+        // lastProfilingCallSite := AccFrame-ReturnAddr
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfReturnAddress()), scratch1);
+        masm.storePtr(scratch1, lastProfilingCallSite);
+
+        // lastProfilingFrame := AccessorFrame + AccFrame-Descriptor.Size +
+        //                       IonAccessorICFrameLayout::Size()
+        masm.ma_addu(scratch2, scratch3, scratch1);
+        masm.addPtr(Imm32(IonAccessorICFrameLayout::Size()), scratch1);
+        masm.storePtr(scratch1, lastProfilingFrame);
+        masm.ret();
+    }
+
     //
     // JitFrame_Entry
     //
     // If at an entry frame, store null into both fields.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/x64/Trampoline-x64.cpp
+++ b/js/src/jit/x64/Trampoline-x64.cpp
@@ -976,23 +976,25 @@ JitRuntime::generateProfilerExitFrameTai
     masm.movePtr(scratch1, scratch2);
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
     masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch2);
 
     // Handling of each case is dependent on FrameDescriptor.type
     Label handle_IonJS;
     Label handle_BaselineStub;
     Label handle_Rectifier;
+    Label handle_IonAccessorIC;
     Label handle_Entry;
     Label end;
 
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineStub), &handle_BaselineStub);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Rectifier), &handle_Rectifier);
+    masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonAccessorIC), &handle_IonAccessorIC);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Entry), &handle_Entry);
 
     masm.assumeUnreachable("Invalid caller frame type when exiting from Ion frame.");
 
     //
     // JitFrame_IonJS
     //
     // Stack layout:
@@ -1148,16 +1150,62 @@ JitRuntime::generateProfilerExitFrameTai
         BaseIndex stubFrameSavedFramePtr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() - (2 * sizeof(void *)));
         masm.loadPtr(stubFrameSavedFramePtr, scratch3);
         masm.addPtr(Imm32(sizeof(void *)), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
     }
 
+    // JitFrame_IonAccessorIC
+    //
+    // The caller is always an IonJS frame.
+    //
+    //              Ion-Descriptor
+    //              Ion-ReturnAddr
+    //              ... ion frame data ... |- AccFrame-Descriptor.Size
+    //              StubCode             |
+    //              AccFrame-Descriptor  |- IonAccessorICFrameLayout::Size()
+    //              AccFrame-ReturnAddr  |
+    //              ... accessor frame data & args ... |- Descriptor.Size
+    //              ActualArgc      |
+    //              CalleeToken     |- JitFrameLayout::Size()
+    //              Descriptor      |
+    //    FP -----> ReturnAddr      |
+    masm.bind(&handle_IonAccessorIC);
+    {
+        // scratch2 := StackPointer + Descriptor.size + JitFrameLayout::Size()
+        masm.lea(Operand(StackPointer, scratch1, TimesOne, JitFrameLayout::Size()), scratch2);
+
+        // scratch3 := AccFrame-Descriptor.Size
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfDescriptor()), scratch3);
+#ifdef DEBUG
+        // Assert previous frame is an IonJS frame.
+        masm.movePtr(scratch3, scratch1);
+        masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch1);
+        {
+            Label checkOk;
+            masm.branch32(Assembler::Equal, scratch1, Imm32(JitFrame_IonJS), &checkOk);
+            masm.assumeUnreachable("IonAccessorIC frame must be preceded by IonJS frame");
+            masm.bind(&checkOk);
+        }
+#endif
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3);
+
+        // lastProfilingCallSite := AccFrame-ReturnAddr
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfReturnAddress()), scratch1);
+        masm.storePtr(scratch1, lastProfilingCallSite);
+
+        // lastProfilingFrame := AccessorFrame + AccFrame-Descriptor.Size +
+        //                       IonAccessorICFrameLayout::Size()
+        masm.lea(Operand(scratch2, scratch3, TimesOne, IonAccessorICFrameLayout::Size()), scratch1);
+        masm.storePtr(scratch1, lastProfilingFrame);
+        masm.ret();
+    }
+
     //
     // JitFrame_Entry
     //
     // If at an entry frame, store null into both fields.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jit/x86/Trampoline-x86.cpp
+++ b/js/src/jit/x86/Trampoline-x86.cpp
@@ -1003,23 +1003,25 @@ JitRuntime::generateProfilerExitFrameTai
     masm.movePtr(scratch1, scratch2);
     masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch1);
     masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch2);
 
     // Handling of each case is dependent on FrameDescriptor.type
     Label handle_IonJS;
     Label handle_BaselineStub;
     Label handle_Rectifier;
+    Label handle_IonAccessorIC;
     Label handle_Entry;
     Label end;
 
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineJS), &handle_IonJS);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_BaselineStub), &handle_BaselineStub);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Rectifier), &handle_Rectifier);
+    masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_IonAccessorIC), &handle_IonAccessorIC);
     masm.branch32(Assembler::Equal, scratch2, Imm32(JitFrame_Entry), &handle_Entry);
 
     masm.assumeUnreachable("Invalid caller frame type when exiting from Ion frame.");
 
     //
     // JitFrame_IonJS
     //
     // Stack layout:
@@ -1177,16 +1179,62 @@ JitRuntime::generateProfilerExitFrameTai
         BaseIndex stubFrameSavedFramePtr(scratch2, scratch1, TimesOne,
                                          RectifierFrameLayout::Size() - (2 * sizeof(void *)));
         masm.loadPtr(stubFrameSavedFramePtr, scratch3);
         masm.addPtr(Imm32(sizeof(void *)), scratch3);
         masm.storePtr(scratch3, lastProfilingFrame);
         masm.ret();
     }
 
+    // JitFrame_IonAccessorIC
+    //
+    // The caller is always an IonJS frame.
+    //
+    //              Ion-Descriptor
+    //              Ion-ReturnAddr
+    //              ... ion frame data ... |- AccFrame-Descriptor.Size
+    //              StubCode             |
+    //              AccFrame-Descriptor  |- IonAccessorICFrameLayout::Size()
+    //              AccFrame-ReturnAddr  |
+    //              ... accessor frame data & args ... |- Descriptor.Size
+    //              ActualArgc      |
+    //              CalleeToken     |- JitFrameLayout::Size()
+    //              Descriptor      |
+    //    FP -----> ReturnAddr      |
+    masm.bind(&handle_IonAccessorIC);
+    {
+        // scratch2 := StackPointer + Descriptor.size + JitFrameLayout::Size()
+        masm.lea(Operand(StackPointer, scratch1, TimesOne, JitFrameLayout::Size()), scratch2);
+
+        // scratch3 := AccFrame-Descriptor.Size
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfDescriptor()), scratch3);
+#ifdef DEBUG
+        // Assert previous frame is an IonJS frame.
+        masm.movePtr(scratch3, scratch1);
+        masm.and32(Imm32((1 << FRAMETYPE_BITS) - 1), scratch1);
+        {
+            Label checkOk;
+            masm.branch32(Assembler::Equal, scratch1, Imm32(JitFrame_IonJS), &checkOk);
+            masm.assumeUnreachable("IonAccessorIC frame must be preceded by IonJS frame");
+            masm.bind(&checkOk);
+        }
+#endif
+        masm.rshiftPtr(Imm32(FRAMESIZE_SHIFT), scratch3);
+
+        // lastProfilingCallSite := AccFrame-ReturnAddr
+        masm.loadPtr(Address(scratch2, IonAccessorICFrameLayout::offsetOfReturnAddress()), scratch1);
+        masm.storePtr(scratch1, lastProfilingCallSite);
+
+        // lastProfilingFrame := AccessorFrame + AccFrame-Descriptor.Size +
+        //                       IonAccessorICFrameLayout::Size()
+        masm.lea(Operand(scratch2, scratch3, TimesOne, IonAccessorICFrameLayout::Size()), scratch1);
+        masm.storePtr(scratch1, lastProfilingFrame);
+        masm.ret();
+    }
+
     //
     // JitFrame_Entry
     //
     // If at an entry frame, store null into both fields.
     //
     masm.bind(&handle_Entry);
     {
         masm.movePtr(ImmPtr(nullptr), scratch1);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2963,19 +2963,19 @@ GCRuntime::refillFreeListFromMainThread(
 
     // Perform a last-ditch GC to hopefully free up some memory.
     {
         // If we are doing a fallible allocation, percolate up the OOM
         // instead of reporting it.
         if (!allowGC)
             return nullptr;
 
-        JS::PrepareZoneForGC(cx->zone());
+        JS::PrepareForFullGC(rt);
         AutoKeepAtoms keepAtoms(cx->perThreadData);
-        rt->gc.gc(GC_NORMAL, JS::gcreason::LAST_DITCH);
+        rt->gc.gc(GC_SHRINK, JS::gcreason::LAST_DITCH);
     }
 
     // Retry the allocation after the last-ditch GC.
     thing = tryRefillFreeListFromMainThread(cx, thingKind);
     if (thing)
         return thing;
 
     // We are really just totally out of memory.
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/misc/getter-setter-outerize-this.js
@@ -0,0 +1,21 @@
+if (typeof window === "undefined") {
+    // This test is meant to run in the browser, but it's easy to
+    // run it in the shell as well, even though it has no inner/outer
+    // windows.
+    window = this;
+}
+
+var res = false;
+Object.defineProperty(this, "foo", {configurable: true,
+				    get: function() { return this === window; },
+				    set: function(v) { res = this === window; }});
+
+(function() {
+    for (var i = 0; i < 3000; ++i) {
+	window.foo = i;
+	assertEq(res, true, "setter");
+	assertEq(window.foo, true, "getter");
+    }
+})();
+
+reportCompare(true, true);
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -2166,52 +2166,53 @@ TemporaryTypeSet::maybeEmulatesUndefined
             return true;
         if (!getObject(i)->hasStableClassAndProto(constraints))
             return true;
     }
 
     return false;
 }
 
-JSObject *
-TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints)
+bool
+TemporaryTypeSet::getCommonPrototype(CompilerConstraintList *constraints, JSObject **proto)
 {
     if (unknownObject())
-        return nullptr;
-
-    JSObject *proto = nullptr;
+        return false;
+
+    *proto = nullptr;
+    bool isFirst = true;
     unsigned count = getObjectCount();
 
     for (unsigned i = 0; i < count; i++) {
         ObjectKey *key = getObject(i);
         if (!key)
             continue;
 
         if (key->unknownProperties())
-            return nullptr;
+            return false;
 
         TaggedProto nproto = key->proto();
-        if (proto) {
-            if (nproto != TaggedProto(proto))
-                return nullptr;
+        if (isFirst) {
+            if (nproto.isLazy())
+                return false;
+            *proto = nproto.toObjectOrNull();
+            isFirst = false;
         } else {
-            if (!nproto.isObject())
-                return nullptr;
-            proto = nproto.toObject();
+            if (nproto != TaggedProto(*proto))
+                return false;
         }
     }
 
     // Guard against mutating __proto__.
     for (unsigned i = 0; i < count; i++) {
-        ObjectKey *key = getObject(i);
-        if (key)
+        if (ObjectKey *key = getObject(i))
             JS_ALWAYS_TRUE(key->hasStableClassAndProto(constraints));
     }
 
-    return proto;
+    return true;
 }
 
 bool
 TemporaryTypeSet::propertyNeedsBarrier(CompilerConstraintList *constraints, jsid id)
 {
     if (unknownObject())
         return true;
 
@@ -2276,19 +2277,22 @@ js::TypeCanHaveExtraIndexedProperties(Co
     // information, though these are all in bounds and will be accounted for
     // by JIT paths.
     if (!clasp || (ClassCanHaveExtraProperties(clasp) && !IsAnyTypedArrayClass(clasp)))
         return true;
 
     if (types->hasObjectFlags(constraints, OBJECT_FLAG_SPARSE_INDEXES))
         return true;
 
-    JSObject *proto = types->getCommonPrototype(constraints);
+    JSObject *proto;
+    if (!types->getCommonPrototype(constraints, &proto))
+        return true;
+
     if (!proto)
-        return true;
+        return false;
 
     return PrototypeHasIndexedProperty(constraints, proto);
 }
 
 void
 TypeZone::processPendingRecompiles(FreeOp *fop, RecompileInfoVector &recompiles)
 {
     MOZ_ASSERT(!recompiles.empty());
--- a/js/src/vm/TypeInference.h
+++ b/js/src/vm/TypeInference.h
@@ -666,18 +666,21 @@ class TemporaryTypeSet : public TypeSet
     };
 
     /* Apply func to the members of the set and return an appropriate result.
      * The iteration may end early if the result becomes known early.
      */
     ForAllResult forAllClasses(CompilerConstraintList *constraints,
                                bool (*func)(const Class *clasp));
 
-    /* Get the prototype shared by all objects in this set, or nullptr. */
-    JSObject *getCommonPrototype(CompilerConstraintList *constraints);
+    /*
+     * Returns true if all objects in this set have the same prototype, and
+     * assigns this object to *proto. The proto can be nullptr.
+     */
+    bool getCommonPrototype(CompilerConstraintList *constraints, JSObject **proto);
 
     /* Get the typed array type of all objects in this set, or Scalar::MaxTypedArrayViewType. */
     Scalar::Type getTypedArrayType(CompilerConstraintList *constraints);
 
     /* Get the shared typed array type of all objects in this set, or Scalar::MaxTypedArrayViewType. */
     Scalar::Type getSharedTypedArrayType(CompilerConstraintList *constraints);
 
     /* Whether all objects have JSCLASS_IS_DOMJSCLASS set. */
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -1217,34 +1217,35 @@ nsBidiPresUtils::ResolveParagraphWithinB
                                              BidiParagraphData* aBpd)
 {
   aBpd->ClearBidiControls();
   ResolveParagraph(aBlockFrame, aBpd);
   aBpd->ResetData();
 }
 
 void
-nsBidiPresUtils::ReorderFrames(nsIFrame*   aFirstFrameOnLine,
-                               int32_t     aNumFramesOnLine,
-                               WritingMode aLineWM,
-                               nscoord     aLineWidth,
-                               nscoord     aStart)
+nsBidiPresUtils::ReorderFrames(nsIFrame*     aFirstFrameOnLine,
+                               int32_t       aNumFramesOnLine,
+                               WritingMode   aLineWM,
+                               const nsSize& aContainerSize,
+                               nscoord       aStart)
 {
   // If this line consists of a line frame, reorder the line frame's children.
   if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
     aFirstFrameOnLine = aFirstFrameOnLine->GetFirstPrincipalChild();
     if (!aFirstFrameOnLine)
       return;
     // All children of the line frame are on the first line. Setting aNumFramesOnLine
     // to -1 makes InitLogicalArrayFromLine look at all of them.
     aNumFramesOnLine = -1;
   }
 
   BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
-  RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM, aLineWidth, aStart);
+  RepositionInlineFrames(&bld, aFirstFrameOnLine, aLineWM,
+                         aContainerSize, aStart);
 }
 
 nsIFrame*
 nsBidiPresUtils::GetFirstLeaf(nsIFrame* aFrame)
 {
   nsIFrame* firstLeaf = aFrame;
   while (!IsBidiLeaf(firstLeaf)) {
     nsIFrame* firstChild = firstLeaf->GetFirstPrincipalChild();
@@ -1395,17 +1396,17 @@ nsBidiPresUtils::IsFirstOrLast(nsIFrame*
 }
 
 void
 nsBidiPresUtils::RepositionFrame(nsIFrame*             aFrame,
                                  bool                  aIsEvenLevel,
                                  nscoord&              aStart,
                                  nsContinuationStates* aContinuationStates,
                                  WritingMode           aContainerWM,
-                                 nscoord               aContainerWidth)
+                                 const nsSize&         aContainerSize)
 {
   if (!aFrame)
     return;
 
   bool isFirst, isLast;
   WritingMode frameWM = aFrame->GetWritingMode();
   IsFirstOrLast(aFrame,
                 aContinuationStates,
@@ -1460,33 +1461,44 @@ nsBidiPresUtils::RepositionFrame(nsIFram
     nscoord iCoord = borderPadding.IStart(frameWM);
 
     while (frame) {
       RepositionFrame(frame,
                       aIsEvenLevel,
                       iCoord,
                       aContinuationStates,
                       frameWM,
-                      aFrame->GetLogicalSize(aContainerWM).Width(aContainerWM));
+                      aFrame->GetSize());
       index++;
       frame = reverseOrder ?
                 childList[childList.Length() - index - 1] :
                 frame->GetNextSibling();
     }
 
     aStart += iCoord + borderPadding.IEnd(frameWM);
   } else {
     aStart += aFrame->ISize(aContainerWM);
   }
 
-  LogicalRect logicalRect = aFrame->GetLogicalRect(aContainerWM,
-                                                   aContainerWidth);
-  logicalRect.IStart(aContainerWM) = start;
-  logicalRect.ISize(aContainerWM) = aStart - start;
-  aFrame->SetRect(aContainerWM, logicalRect, aContainerWidth);
+  // LogicalRect doesn't correctly calculate the vertical position
+  // in vertical writing modes with right-to-left direction (Bug 1131451).
+  // This does the correct calculation ad hoc pending the fix for that.
+  nsRect rect = aFrame->GetRect();
+  nscoord lineSize = aContainerWM.IsVertical()
+    ? aContainerSize.height : aContainerSize.width;
+  NS_ASSERTION(aContainerWM.IsBidiLTR() || lineSize != NS_UNCONSTRAINEDSIZE,
+               "Unconstrained inline line size in bidi frame reordering");
+
+  nscoord frameIStart = aContainerWM.IsBidiLTR() ? start : lineSize - aStart;
+  nscoord frameISize = aStart - start;
+
+  (aContainerWM.IsVertical() ? rect.y : rect.x) = frameIStart;
+  (aContainerWM.IsVertical() ? rect.height : rect.width) = frameISize;
+
+  aFrame->SetRect(rect);
 
   aStart += margin.IEnd(aContainerWM);
 }
 
 void
 nsBidiPresUtils::InitContinuationStates(nsIFrame*              aFrame,
                                         nsContinuationStates*  aContinuationStates)
 {
@@ -1505,17 +1517,17 @@ nsBidiPresUtils::InitContinuationStates(
     }
   }
 }
 
 void
 nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
                                         nsIFrame* aFirstChild,
                                         WritingMode aLineWM,
-                                        nscoord aLineWidth,
+                                        const nsSize& aContainerSize,
                                         nscoord aStart)
 {
   nscoord start = aStart;
   nsIFrame* frame;
   int32_t count = aBld->mVisualFrames.Length();
   int32_t index;
   nsContinuationStates continuationStates;
 
@@ -1538,17 +1550,17 @@ nsBidiPresUtils::RepositionInlineFrames(
   }
   for (; index != limit; index += step) {
     frame = aBld->VisualFrameAt(index);
     RepositionFrame(frame,
                     !(IS_LEVEL_RTL(aBld->mLevels[aBld->mIndexMap[index]])),
                     start,
                     &continuationStates,
                     aLineWM,
-                    aLineWidth);
+                    aContainerSize);
   }
 }
 
 bool
 nsBidiPresUtils::CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
                                 int32_t    aNumFramesOnLine,
                                 nsIFrame** aFirstVisual,
                                 nsIFrame** aLastVisual)
--- a/layout/base/nsBidiPresUtils.h
+++ b/layout/base/nsBidiPresUtils.h
@@ -20,16 +20,17 @@ struct BidiParagraphData;
 struct BidiLineData;
 class nsFontMetrics;
 class nsIFrame;
 class nsBlockFrame;
 class nsPresContext;
 class nsRenderingContext;
 class nsBlockInFlowLineIterator;
 class nsStyleContext;
+struct nsSize;
 template<class T> class nsTHashtable;
 namespace mozilla { class WritingMode; }
 
 /**
  * A structure representing some continuation state for each frame on the line,
  * used to determine the first and the last continuation frame for each
  * continuation chain on the line.
  */
@@ -156,17 +157,17 @@ public:
    * Reorder this line using Bidi engine.
    * Update frame array, following the new visual sequence.
    * 
    * @lina 05/02/2000
    */
   static void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
                             int32_t              aNumFramesOnLine,
                             mozilla::WritingMode aLineWM,
-                            nscoord              aLineWidth,
+                            const nsSize&        aContainerSize,
                             nscoord              aStart);
 
   /**
    * Format Unicode text, taking into account bidi capabilities
    * of the platform. The formatting includes: reordering, Arabic shaping,
    * symmetric and numeric swapping, removing control characters.
    *
    * @lina 06/18/2000 
@@ -425,17 +426,17 @@ private:
    *                             (after adding its inline-end margin)
    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
    */
   static void RepositionFrame(nsIFrame*              aFrame,
                               bool                   aIsEvenLevel,
                               nscoord&               aStart,
                               nsContinuationStates*  aContinuationStates,
                               mozilla::WritingMode   aContainerWM,
-                              nscoord                aContainerWidth);
+                              const nsSize&          aContainerSize);
 
   /*
    * Initialize the continuation state(nsFrameContinuationState) to
    * (nullptr, 0) for aFrame and its descendants.
    *
    * @param aFrame               The frame which itself and its descendants will
    *                             be initialized
    * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
@@ -478,17 +479,17 @@ private:
    *
    *  @param aFirstChild the first kid
    *
    *  @lina 04/11/2000
    */
   static void RepositionInlineFrames(BidiLineData* aBld,
                                      nsIFrame* aFirstChild,
                                      mozilla::WritingMode aLineWM,
-                                     nscoord aLineWidth,
+                                     const nsSize& aContainerSize,
                                      nscoord aStart);
   
   /**
    * Helper method for Resolve()
    * Truncate a text frame to the end of a single-directional run and possibly
    * create a continuation frame for the remainder of its content.
    *
    * @param aFrame       the original frame
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -5095,16 +5095,29 @@ nsLayoutUtils::GetSnappedBaselineY(nsIFr
   gfxFloat appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
   gfxFloat baseline = gfxFloat(aY) + aAscent;
   gfxRect putativeRect(0, baseline/appUnitsPerDevUnit, 1, 1);
   if (!aContext->UserToDevicePixelSnapped(putativeRect, true))
     return baseline;
   return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
 }
 
+gfxFloat
+nsLayoutUtils::GetSnappedBaselineX(nsIFrame* aFrame, gfxContext* aContext,
+                                   nscoord aX, nscoord aAscent)
+{
+  gfxFloat appUnitsPerDevUnit = aFrame->PresContext()->AppUnitsPerDevPixel();
+  gfxFloat baseline = gfxFloat(aX) + aAscent;
+  gfxRect putativeRect(baseline / appUnitsPerDevUnit, 0, 1, 1);
+  if (!aContext->UserToDevicePixelSnapped(putativeRect, true)) {
+    return baseline;
+  }
+  return aContext->DeviceToUser(putativeRect.TopLeft()).x * appUnitsPerDevUnit;
+}
+
 // Hard limit substring lengths to 8000 characters ... this lets us statically
 // size the cluster buffer array in FindSafeLength
 #define MAX_GFX_TEXT_BUF_SIZE 8000
 
 static int32_t FindSafeLength(const char16_t *aString, uint32_t aLength,
                               uint32_t aMaxChunkLength)
 {
   if (aLength <= aMaxChunkLength)
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1472,16 +1472,20 @@ public:
                                     nsRenderingContext* aRenderingContext);
 
   // Get a suitable foreground color for painting aProperty for aFrame.
   static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty);
 
   // Get a baseline y position in app units that is snapped to device pixels.
   static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
                                       nscoord aY, nscoord aAscent);
+  // Ditto for an x position (for vertical text). Note that for vertical-rl
+  // writing mode, the ascent value should be negated by the caller.
+  static gfxFloat GetSnappedBaselineX(nsIFrame* aFrame, gfxContext* aContext,
+                                      nscoord aX, nscoord aAscent);
 
   static nscoord AppUnitWidthOfString(char16_t aC,
                                       nsFontMetrics& aFontMetrics,
                                       nsRenderingContext& aContext) {
     return AppUnitWidthOfString(&aC, 1, aFontMetrics, aContext);
   }
   static nscoord AppUnitWidthOfString(const nsString& aString,
                                       nsFontMetrics& aFontMetrics,
--- a/layout/base/tests/marionette/test_selectioncarets.py
+++ b/layout/base/tests/marionette/test_selectioncarets.py
@@ -100,17 +100,17 @@ class SelectionCaretsTest(MarionetteTest
         x, y = self._first_word_location(el)
         self._long_press_to_select(el, x, y)
 
         # Move the right caret to the end of the content.
         (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
         self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
 
         # Move the left caret to the previous position of the right caret.
-        self.actions.flick(el, caret1_x, caret2_y, caret2_x, caret2_y).perform()
+        self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
 
         # Ignore extra spaces at the beginning of the content in comparison.
         assertFunc(target_content.lstrip(), sel.selected_content.lstrip())
 
     def _test_minimum_select_one_character(self, el, assertFunc,
                                            x=None, y=None):
         sel = SelectionManager(el)
         original_content = sel.content
@@ -135,17 +135,17 @@ class SelectionCaretsTest(MarionetteTest
         self._long_press_to_select(el, x, y)
 
         # Move the right caret to the end of the content.
         (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
         self.actions.flick(el, caret2_x, caret2_y, end_caret_x, end_caret_y).perform()
 
         # Move the right caret to the position of the left caret.
         (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
-        self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y,).perform()
+        self.actions.flick(el, caret2_x, caret2_y, caret1_x, caret1_y).perform()
 
         assertFunc(target_content, sel.selected_content)
 
     def _test_focus_obtained_by_long_press(self, el1, el2):
         '''Test the focus could be changed from el1 to el2 by long press.
 
         If the focus is changed to e2 successfully, SelectionCarets should
         appear and could be dragged.
@@ -157,43 +157,87 @@ class SelectionCaretsTest(MarionetteTest
         # We want to collect the location of the first word in el2 here
         # since self._first_word_location() has the side effect which would
         # change the focus.
         x, y = self._first_word_location(el2)
         el1.tap()
         self._test_minimum_select_one_character(el2, self.assertEqual,
                                                 x=x, y=y)
 
+    def _test_handle_tilt_when_carets_overlap_to_each_other(self, el, assertFunc):
+        '''Test tilt handling when carets overlap to each other.
+
+        Let SelectionCarets overlap to each other. If SelectionCarets are set
+        to tilted successfully, tapping the tilted carets should not cause the
+        selection to be collapsed and the carets should be draggable.
+        '''
+
+        sel = SelectionManager(el)
+        original_content = sel.content
+        words = original_content.split()
+        self.assertTrue(len(words) >= 1, 'Expect at least one word in the content.')
+
+        # Goal: Select the first word.
+        x, y = self._first_word_location(el)
+        self._long_press_to_select(el, x, y)
+        target_content = sel.selected_content
+
+        # Move the left caret to the position of the right caret to trigger
+        # carets overlapping.
+        (caret1_x, caret1_y), (caret2_x, caret2_y) = sel.selection_carets_location()
+        self.actions.flick(el, caret1_x, caret1_y, caret2_x, caret2_y).perform()
+
+        # Caret width is 29px, so we make a series of hit tests for the two
+        # tilted carets. If any of the hits is missed, selection would be
+        # collapsed and both two carets should not be draggable.
+        (caret3_x, caret3_y), (caret4_x, caret4_y) = sel.selection_carets_location()
+        right_x = int(caret4_x + 0.5)
+        for i in range (right_x, right_x + 29, + 1):
+            self.actions.press(el, i, caret4_y).release().perform()
+
+        left_x = int(caret3_x - 0.5)
+        for i in range (left_x, left_x - 29, - 1):
+            self.actions.press(el, i, caret3_y).release().perform()
+
+        # Drag the left caret back to the initial selection, the first word.
+        self.actions.flick(el, caret3_x, caret3_y, caret1_x, caret1_y).perform()
+
+        assertFunc(target_content, sel.selected_content)
+
     ########################################################################
     # <input> test cases with selection carets enabled
     ########################################################################
     def test_input_long_press_to_select_a_word(self):
         self.openTestHtml(enabled=True)
         self._test_long_press_to_select_a_word(self._input, self.assertEqual)
 
     def test_input_move_selection_carets(self):
         self.openTestHtml(enabled=True)
         self._test_move_selection_carets(self._input, self.assertEqual)
 
-    def test_input_minimum_select_one_caracter(self):
+    def test_input_minimum_select_one_character(self):
         self.openTestHtml(enabled=True)
         self._test_minimum_select_one_character(self._input, self.assertEqual)
 
     def test_input_focus_obtained_by_long_press_from_textarea(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._textarea, self._input)
 
     def test_input_focus_obtained_by_long_press_from_contenteditable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._contenteditable, self._input)
 
     def test_input_focus_obtained_by_long_press_from_content_non_editable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._content, self._input)
 
+    def test_input_handle_tilt_when_carets_overlap_to_each_other(self):
+        self.openTestHtml(enabled=True)
+        self._test_handle_tilt_when_carets_overlap_to_each_other(self._input, self.assertEqual)
+
     ########################################################################
     # <input> test cases with selection carets disabled
     ########################################################################
     def test_input_long_press_to_select_a_word_disabled(self):
         self.openTestHtml(enabled=False)
         self._test_long_press_to_select_a_word(self._input, self.assertNotEqual)
 
     def test_input_move_selection_carets_disabled(self):
@@ -206,32 +250,36 @@ class SelectionCaretsTest(MarionetteTest
     def test_textarea_long_press_to_select_a_word(self):
         self.openTestHtml(enabled=True)
         self._test_long_press_to_select_a_word(self._textarea, self.assertEqual)
 
     def test_textarea_move_selection_carets(self):
         self.openTestHtml(enabled=True)
         self._test_move_selection_carets(self._textarea, self.assertEqual)
 
-    def test_textarea_minimum_select_one_caracter(self):
+    def test_textarea_minimum_select_one_character(self):
         self.openTestHtml(enabled=True)
         self._test_minimum_select_one_character(self._textarea, self.assertEqual)
 
     def test_textarea_focus_obtained_by_long_press_from_input(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._input, self._textarea)
 
     def test_textarea_focus_obtained_by_long_press_from_contenteditable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._contenteditable, self._textarea)
 
     def test_textarea_focus_obtained_by_long_press_from_content_non_editable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._content, self._textarea)
 
+    def test_textarea_handle_tilt_when_carets_overlap_to_each_other(self):
+        self.openTestHtml(enabled=True)
+        self._test_handle_tilt_when_carets_overlap_to_each_other(self._textarea, self.assertEqual)
+
     ########################################################################
     # <textarea> test cases with selection carets disabled
     ########################################################################
     def test_textarea_long_press_to_select_a_word_disabled(self):
         self.openTestHtml(enabled=False)
         self._test_long_press_to_select_a_word(self._textarea, self.assertNotEqual)
 
     def test_textarea_move_selection_carets_disable(self):
@@ -244,17 +292,17 @@ class SelectionCaretsTest(MarionetteTest
     def test_textarea_rtl_long_press_to_select_a_word(self):
         self.openTestHtml(enabled=True)
         self._test_long_press_to_select_a_word(self._textarea_rtl, self.assertEqual)
 
     def test_textarea_rtl_move_selection_carets(self):
         self.openTestHtml(enabled=True)
         self._test_move_selection_carets(self._textarea_rtl, self.assertEqual)
 
-    def test_textarea_rtl_minimum_select_one_caracter(self):
+    def test_textarea_rtl_minimum_select_one_character(self):
         self.openTestHtml(enabled=True)
         self._test_minimum_select_one_character(self._textarea_rtl, self.assertEqual)
 
     ########################################################################
     # <textarea> right-to-left test cases with selection carets disabled
     ########################################################################
     def test_textarea_rtl_long_press_to_select_a_word_disabled(self):
         self.openTestHtml(enabled=False)
@@ -286,16 +334,20 @@ class SelectionCaretsTest(MarionetteTest
     def test_contenteditable_focus_obtained_by_long_press_from_textarea(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._textarea, self._contenteditable)
 
     def test_contenteditable_focus_obtained_by_long_press_from_content_non_editable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._content, self._contenteditable)
 
+    def test_contenteditable_handle_tilt_when_carets_overlap_to_each_other(self):
+        self.openTestHtml(enabled=True)
+        self._test_handle_tilt_when_carets_overlap_to_each_other(self._contenteditable, self.assertEqual)
+
     ########################################################################
     # <div> contenteditable test cases with selection carets disabled
     ########################################################################
     def test_contenteditable_long_press_to_select_a_word_disabled(self):
         self.openTestHtml(enabled=False)
         self._test_long_press_to_select_a_word(self._contenteditable, self.assertNotEqual)
 
     def test_contenteditable_move_selection_carets_disabled(self):
@@ -316,16 +368,20 @@ class SelectionCaretsTest(MarionetteTest
     def test_content_non_editable_focus_obtained_by_long_press_from_textarea(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._textarea, self._content)
 
     def test_content_non_editable_focus_obtained_by_long_press_from_contenteditable(self):
         self.openTestHtml(enabled=True)
         self._test_focus_obtained_by_long_press(self._contenteditable, self._content)
 
+    def test_content_non_editable_handle_tilt_when_carets_overlap_to_each_other(self):
+        self.openTestHtml(enabled=True)
+        self._test_handle_tilt_when_carets_overlap_to_each_other(self._content, self.assertEqual)
+
     ########################################################################
     # <div> contenteditable2 test cases with selection carets enabled
     ########################################################################
     def test_contenteditable_minimum_select_one_character(self):
         self.openTestHtml(enabled=True)
         self._test_minimum_select_one_character(self._contenteditable2, self.assertEqual)
 
 
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -428,72 +428,74 @@ nsFieldSetFrame::Reflow(nsPresContext*  
   NS_ASSERTION(!legend ||
       nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
                                            legend,
                                            nsLayoutUtils::MIN_ISIZE) <=
                legendAvailSize.ISize(legendWM),
                "Bogus availSize.ISize; should be bigger");
 
   // get our border and padding
-  nsMargin border = aReflowState.ComputedPhysicalBorderPadding() -
-                      aReflowState.ComputedPhysicalPadding();
-  LogicalMargin logBorder(wm, border);
+  LogicalMargin border = aReflowState.ComputedLogicalBorderPadding() -
+                         aReflowState.ComputedLogicalPadding();
 
   // Figure out how big the legend is if there is one.
   // get the legend's margin
   LogicalMargin legendMargin(wm);
   // reflow the legend only if needed
   Maybe<nsHTMLReflowState> legendReflowState;
   if (legend) {
     legendReflowState.emplace(aPresContext, aReflowState, legend,
                                 legendAvailSize);
   }
   if (reflowLegend) {
     nsHTMLReflowMetrics legendDesiredSize(aReflowState);
 
     ReflowChild(legend, aPresContext, legendDesiredSize, *legendReflowState,
-                0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
+                wm, LogicalPoint(wm), 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
 #ifdef NOISY_REFLOW
     printf("  returned (%d, %d)\n",
            legendDesiredSize.Width(), legendDesiredSize.Height());
 #endif
     // figure out the legend's rectangle
     legendMargin = legend->GetLogicalUsedMargin(wm);
     mLegendRect =
       LogicalRect(wm, 0, 0,
                   legendDesiredSize.ISize(wm) + legendMargin.IStartEnd(wm),
                   legendDesiredSize.BSize(wm) + legendMargin.BStartEnd(wm));
     nscoord oldSpace = mLegendSpace;
     mLegendSpace = 0;
-    if (mLegendRect.BSize(wm) > logBorder.BStart(wm)) {
+    if (mLegendRect.BSize(wm) > border.BStart(wm)) {
       // center the border on the legend
-      mLegendSpace = mLegendRect.BSize(wm) - logBorder.BStart(wm);
+      mLegendSpace = mLegendRect.BSize(wm) - border.BStart(wm);
     } else {
       mLegendRect.BStart(wm) =
-        (logBorder.BStart(wm) - mLegendRect.BSize(wm)) / 2;
+        (border.BStart(wm) - mLegendRect.BSize(wm)) / 2;
     }
 
     // if the legend space changes then we need to reflow the
     // content area as well.
     if (mLegendSpace != oldSpace && inner) {
       reflowInner = true;
     }
 
     // We'll move the legend to its proper place later.
     FinishReflowChild(legend, aPresContext, legendDesiredSize,
-                      legendReflowState.ptr(), 0, 0, NS_FRAME_NO_MOVE_FRAME);
+                      legendReflowState.ptr(), wm, LogicalPoint(wm), 0,
+                      NS_FRAME_NO_MOVE_FRAME);
   } else if (!legend) {
     mLegendRect.SetEmpty();
     mLegendSpace = 0;
   } else {
     // mLegendSpace and mLegendRect haven't changed, but we need
     // the used margin when placing the legend.
     legendMargin = legend->GetLogicalUsedMargin(wm);
   }
 
+  nscoord containerWidth = (wm.IsVertical() ? mLegendSpace : 0) +
+                            border.LeftRight(wm);
   // reflow the content frame only if needed
   if (reflowInner) {
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, inner,
                                      innerAvailSize, -1, -1,
                                      nsHTMLReflowState::CALLER_WILL_INIT);
     // Override computed padding, in case it's percentage padding
     kidReflowState.Init(aPresContext, -1, -1, nullptr,
                         &aReflowState.ComputedPhysicalPadding());
@@ -515,33 +517,31 @@ nsFieldSetFrame::Reflow(nsPresContext*  
         std::max(0, aReflowState.ComputedMaxBSize() - mLegendSpace);
     }
 
     nsHTMLReflowMetrics kidDesiredSize(kidReflowState,
                                        aDesiredSize.mFlags);
     // Reflow the frame
     NS_ASSERTION(kidReflowState.ComputedPhysicalMargin() == nsMargin(0,0,0,0),
                  "Margins on anonymous fieldset child not supported!");
-    nsPoint pt(border.left, border.top);
-    if (wm.IsVerticalLR()) {
-      pt.x += mLegendSpace;
-    } else if (!wm.IsVertical()) {
-      pt.y += mLegendSpace;
-    }
+    LogicalPoint pt(wm, border.IStart(wm), border.BStart(wm) + mLegendSpace);
+
     ReflowChild(inner, aPresContext, kidDesiredSize, kidReflowState,
-                pt.x, pt.y, 0, aStatus);
+                wm, pt, containerWidth, 0, aStatus);
 
+    // update the container width after reflowing the inner frame
     FinishReflowChild(inner, aPresContext, kidDesiredSize,
-                      &kidReflowState, pt.x, pt.y, 0);
+                      &kidReflowState, wm, pt,
+                      containerWidth + kidDesiredSize.Width(), 0);
     NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
   }
 
-  nscoord containerWidth =
-    (wm.IsVertical() ? mLegendSpace : 0) +
-    logBorder.LeftRight(wm) + (inner ? inner->GetSize().width : 0);
+  if (inner) {
+    containerWidth += inner->GetSize().width;
+  }
 
   LogicalRect contentRect(wm);
   if (inner) {
     // We don't support margins on inner, so our content rect is just the
     // inner's border-box. We don't care about container-width at this point,
     // as we'll figure out the actual positioning later.
     contentRect = inner->GetLogicalRect(wm, containerWidth);
   }
@@ -600,19 +600,19 @@ nsFieldSetFrame::Reflow(nsPresContext*  
     LogicalPoint actualLegendPos(actualLegendRect.Origin(wm));
     legendReflowState->ApplyRelativePositioning(&actualLegendPos, containerWidth);
     legend->SetPosition(wm, actualLegendPos, containerWidth);
     nsContainerFrame::PositionFrameView(legend);
     nsContainerFrame::PositionChildViews(legend);
   }
 
   // Return our size and our result.
-  LogicalSize finalSize(wm, contentRect.ISize(wm) + logBorder.IStartEnd(wm),
-                        mLegendSpace + logBorder.BStartEnd(wm) +
-                        (inner ? inner->GetLogicalSize(wm).BSize(wm) : 0));
+  LogicalSize finalSize(wm, contentRect.ISize(wm) + border.IStartEnd(wm),
+                        mLegendSpace + border.BStartEnd(wm) +
+                        (inner ? inner->BSize(wm) : 0));
   aDesiredSize.SetSize(wm, finalSize);
   aDesiredSize.SetOverflowAreasToDesiredBounds();
 
   if (legend) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, legend);
   }
   if (inner) {
     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, inner);
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -1136,16 +1136,26 @@ nsBlockFrame::Reflow(nsPresContext*     
 
   // If we're not dirty (which means we'll mark everything dirty later)
   // and our inline-size has changed, mark the lines dirty that we need to
   // mark dirty for a resize reflow.
   if (!(GetStateBits() & NS_FRAME_IS_DIRTY) && reflowState->IsIResize()) {
     PrepareResizeReflow(state);
   }
 
+  // The same for percentage text-indent, except conditioned on the
+  // parent resizing.
+  if (!(GetStateBits() & NS_FRAME_IS_DIRTY) &&
+      reflowState->mCBReflowState &&
+      reflowState->mCBReflowState->IsIResize() &&
+      reflowState->mStyleText->mTextIndent.HasPercent() &&
+      !mLines.empty()) {
+    mLines.front()->MarkDirty();
+  }
+
   LazyMarkLinesDirty();
 
   mState &= ~NS_FRAME_FIRST_REFLOW;
 
   // Now reflow...
   ReflowDirtyLines(state);
 
   // If we have a next-in-flow, and that next-in-flow has pushed floats from
@@ -1257,17 +1267,17 @@ nsBlockFrame::Reflow(nsPresContext*     
   //
   // Note that writing-mode:vertical-rl is the only case where the block
   // logical direction progresses in a negative physical direction, and
   // therefore block-dir coordinate conversion depends on knowing the width
   // of the coordinate space in order to translate between the logical and
   // physical origins.
   if (wm.IsVerticalRL()) {
     nscoord containerWidth = aMetrics.Width();
-    nscoord deltaX = containerWidth - state.mContainerWidth;
+    nscoord deltaX = containerWidth - state.ContainerWidth();
     if (deltaX) {
       for (line_iterator line = begin_lines(), end = end_lines();
            line != end; line++) {
         UpdateLineContainerWidth(line, containerWidth);
       }
       for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) {
         nsPoint physicalDelta(deltaX, 0);
         f->MovePositionBy(physicalDelta);
@@ -1918,17 +1928,17 @@ nsBlockFrame::PropagateFloatDamage(nsBlo
   if (floatManager->HasFloatDamage()) {
     // Need to check mBounds *and* mCombinedArea to find intersections 
     // with aLine's floats
     nscoord lineBCoordBefore = aLine->BStart() + aDeltaBCoord;
     nscoord lineBCoordAfter = lineBCoordBefore + aLine->BSize();
     // Scrollable overflow should be sufficient for things that affect
     // layout.
     WritingMode wm = aState.mReflowState.GetWritingMode();
-    nscoord containerWidth = aState.mContainerWidth;
+    nscoord containerWidth = aState.ContainerWidth();
     LogicalRect overflow = aLine->GetOverflowArea(eScrollableOverflow, wm,
                                                   containerWidth);
     nscoord lineBCoordCombinedBefore = overflow.BStart(wm) + aDeltaBCoord;
     nscoord lineBCoordCombinedAfter = lineBCoordCombinedBefore +
                                       overflow.BSize(wm);
 
     // "Translate" the float manager with an offset of (0, 0) in order to
     // set the origin to our writing mode
@@ -2169,18 +2179,18 @@ nsBlockFrame::ReflowDirtyLines(nsBlockRe
       // See if there's any reflow damage that requires that we mark the
       // line dirty.
       PropagateFloatDamage(aState, line, deltaBCoord);
     }
 
     // If the container width has changed reset the container width. If the
     // line's writing mode is not ltr, or if the line is not left-aligned, also
     // mark the line dirty.
-    if (aState.mContainerWidth != line->mContainerWidth) {
-      line->mContainerWidth = aState.mContainerWidth;
+    if (aState.ContainerWidth() != line->mContainerWidth) {
+      line->mContainerWidth = aState.ContainerWidth();
 
       bool isLastLine = line == mLines.back() &&
                         !GetNextInFlow() &&
                         NS_STYLE_TEXT_ALIGN_AUTO == StyleText()->mTextAlignLast;
       uint8_t align = isLastLine ?
         StyleText()->mTextAlign : StyleText()->mTextAlignLast;
 
       if (line->mWritingMode.IsVertical() ||
@@ -2807,17 +2817,17 @@ nsBlockFrame::PullFrameFrom(nsLineBox*  
 
 void
 nsBlockFrame::SlideLine(nsBlockReflowState& aState,
                         nsLineBox* aLine, nscoord aDeltaBCoord)
 {
   NS_PRECONDITION(aDeltaBCoord != 0, "why slide a line nowhere?");
 
   // Adjust line state
-  aLine->SlideBy(aDeltaBCoord, aState.mContainerWidth);
+  aLine->SlideBy(aDeltaBCoord, aState.ContainerWidth());
 
   // Adjust the frames in the line
   MoveChildFramesOfLine(aLine, aDeltaBCoord);
 }
 
 void
 nsBlockFrame::UpdateLineContainerWidth(nsLineBox* aLine,
                                        nscoord aNewContainerWidth)
@@ -3694,17 +3704,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
   printf("nsBlockFrame::DoReflowInlineFrames %p impacted = %d\n",
          this, aFloatAvailableSpace.mHasFloats);
 #endif
 
   WritingMode outerWM = aState.mReflowState.GetWritingMode();
   WritingMode lineWM = GetWritingMode(aLine->mFirstChild);
   LogicalRect lineRect =
     aFloatAvailableSpace.mRect.ConvertTo(lineWM, outerWM,
-                                         aState.mContainerWidth);
+                                         aState.ContainerWidth());
 
   nscoord iStart = lineRect.IStart(lineWM);
   nscoord availISize = lineRect.ISize(lineWM);
   nscoord availBSize;
   if (aState.GetFlag(BRS_UNCONSTRAINEDBSIZE)) {
     availBSize = NS_UNCONSTRAINEDSIZE;
   }
   else {
@@ -3715,17 +3725,17 @@ nsBlockFrame::DoReflowInlineFrames(nsBlo
   // Make sure to enable resize optimization before we call BeginLineReflow
   // because it might get disabled there
   aLine->EnableResizeReflowOptimization();
 
   aLineLayout.BeginLineReflow(iStart, aState.mBCoord,
                               availISize, availBSize,
                               aFloatAvailableSpace.mHasFloats,
                               false, /*XXX isTopOfPage*/
-                              lineWM, aState.mContainerWidth);
+                              lineWM, aState.mContainerSize);
 
   aState.SetFlag(BRS_LINE_LAYOUT_EMPTY, false);
 
   // XXX Unfortunately we need to know this before reflowing the first
   // inline frame in the line. FIX ME.
   if ((0 == aLineLayout.GetLineNumber()) &&
       (NS_BLOCK_HAS_FIRST_LETTER_CHILD & mState) &&
       (NS_BLOCK_HAS_FIRST_LETTER_STYLE & mState)) {
@@ -7040,17 +7050,17 @@ nsBlockFrame::ReflowBullet(nsIFrame* aBu
 
   // Approximate the bullets position; vertical alignment will provide
   // the final vertical location. We pass our writing-mode here, because
   // it may be different from the bullet frame's mode.
   nscoord bStart = floatAvailSpace.BStart(wm);
   aBulletFrame->SetRect(wm, LogicalRect(wm, iStart, bStart,
                                         aMetrics.ISize(wm),
                                         aMetrics.BSize(wm)),
-                        aState.mContainerWidth);
+                        aState.ContainerWidth());
   aBulletFrame->DidReflow(aState.mPresContext, &aState.mReflowState,
                           nsDidReflowStatus::FINISHED);
 }
 
 // This is used to scan frames for any float placeholders, add their
 // floats to the list represented by aList, and remove the
 // floats from whatever list they might be in. We don't search descendants
 // that are float containing blocks.  Floats that or not children of 'this'
--- a/layout/generic/nsBlockReflowContext.cpp
+++ b/layout/generic/nsBlockReflowContext.cpp
@@ -223,17 +223,17 @@ nsBlockReflowContext::ReflowBlock(const 
                                   bool                aIsAdjacentWithBStart,
                                   nsLineBox*          aLine,
                                   nsHTMLReflowState&  aFrameRS,
                                   nsReflowStatus&     aFrameReflowStatus,
                                   nsBlockReflowState& aState)
 {
   mFrame = aFrameRS.frame;
   mWritingMode = aState.mReflowState.GetWritingMode();
-  mContainerWidth = aState.mContainerWidth;
+  mContainerWidth = aState.ContainerWidth();
   mSpace = aSpace;
 
   if (!aIsAdjacentWithBStart) {
     aFrameRS.mFlags.mIsTopOfPage = false;  // make sure this is cleared
   }
 
   if (aApplyBStartMargin) {
     mBStartMargin = aPrevMargin;
--- a/layout/generic/nsBlockReflowState.cpp
+++ b/layout/generic/nsBlockReflowState.cpp
@@ -60,29 +60,37 @@ nsBlockReflowState::nsBlockReflowState(c
   WritingMode wm = aReflowState.GetWritingMode();
   SetFlag(BRS_ISFIRSTINFLOW, aFrame->GetPrevInFlow() == nullptr);
   SetFlag(BRS_ISOVERFLOWCONTAINER, IS_TRUE_OVERFLOW_CONTAINER(aFrame));
 
   nsIFrame::LogicalSides logicalSkipSides =
     aFrame->GetLogicalSkipSides(&aReflowState);
   mBorderPadding.ApplySkipSides(logicalSkipSides);
 
-  // Note that mContainerWidth is the physical width, needed to convert
-  // logical block-coordinates in vertical-rl writing mode (measured from a
-  // RHS origin) to physical coordinates within the containing block.
-  // If aReflowState doesn't have a constrained ComputedWidth(), we set it to
-  // zero, which means lines will be positioned (physically) incorrectly;
-  // we will fix them up at the end of nsBlockFrame::Reflow, after we know
-  // the total block-size of the frame.
-  mContainerWidth = aReflowState.ComputedWidth();
-  if (mContainerWidth == NS_UNCONSTRAINEDSIZE) {
-    mContainerWidth = 0;
+  // Note that mContainerSize is the physical size, needed to
+  // convert logical block-coordinates in vertical-rl writing mode
+  // (measured from a RHS origin) to physical coordinates within the
+  // containing block.
+  // If aReflowState doesn't have a constrained ComputedWidth(), we set
+  // mContainerSize.width to zero, which means lines will be positioned
+  // (physically) incorrectly; we will fix them up at the end of
+  // nsBlockFrame::Reflow, after we know the total block-size of the
+  // frame.
+  mContainerSize.width = aReflowState.ComputedWidth();
+  if (mContainerSize.width == NS_UNCONSTRAINEDSIZE) {
+    mContainerSize.width = 0;
   }
 
-  mContainerWidth += mBorderPadding.LeftRight(wm);
+  mContainerSize.width += mBorderPadding.LeftRight(wm);
+
+  // For now at least, we don't do that fix-up for mContainerHeight.
+  // It's only used in nsBidiUtils::ReorderFrames for vertical rtl
+  // writing modes, which aren't fully supported for the time being.
+  mContainerSize.height = aReflowState.ComputedHeight() +
+                          mBorderPadding.TopBottom(wm);
 
   if ((aBStartMarginRoot && !logicalSkipSides.BStart()) ||
       0 != mBorderPadding.BStart(wm)) {
     SetFlag(BRS_ISBSTARTMARGINROOT, true);
     SetFlag(BRS_APPLYBSTARTMARGIN, true);
   }
   if ((aBEndMarginRoot && !logicalSkipSides.BEnd()) ||
       0 != mBorderPadding.BEnd(wm)) {
@@ -315,17 +323,17 @@ nsBlockReflowState::GetFloatAvailableSpa
   }
 #endif
 
   nscoord blockSize = (mContentArea.BSize(wm) == nscoord_MAX)
     ? nscoord_MAX : std::max(mContentArea.BEnd(wm) - aBCoord, 0);
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::BAND_FROM_POINT,
                                blockSize, mContentArea, aState,
-                               mContainerWidth);
+                               ContainerWidth());
   // Keep the inline size >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.ISize(wm) < 0) {
     result.mRect.ISize(wm) = 0;
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
@@ -352,17 +360,17 @@ nsBlockReflowState::GetFloatAvailableSpa
     NS_ASSERTION(wPt == mFloatManagerOrigin, "bad coord system");
   } else {
     //XXX if the writing modes are different we can't easily assert that
     //    the origin is the same.
   }
 #endif
   nsFlowAreaRect result =
     mFloatManager->GetFlowArea(wm, aBCoord, nsFloatManager::WIDTH_WITHIN_HEIGHT,
-                               aBSize, mContentArea, aState, mContainerWidth);
+                               aBSize, mContentArea, aState, ContainerWidth());
   // Keep the width >= 0 for compatibility with nsSpaceManager.
   if (result.mRect.ISize(wm) < 0) {
     result.mRect.ISize(wm) = 0;
   }
 
 #ifdef DEBUG
   if (nsBlockFrame::gNoisyReflow) {
     nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
@@ -483,31 +491,31 @@ nsBlockReflowState::RecoverFloats(nsLine
         mFloatManager->GetTranslation(tWM, tPt);
         nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
         printf("RecoverFloats: txy=%d,%d (%d,%d) ",
                tPt.I(tWM), tPt.B(tWM),
                mFloatManagerOrigin.I(mFloatManagerWM),
                mFloatManagerOrigin.B(mFloatManagerWM));
         nsFrame::ListTag(stdout, floatFrame);
         LogicalRect region = nsFloatManager::GetRegionFor(wm, floatFrame,
-                                                          mContainerWidth);
+                                                          ContainerWidth());
         printf(" aDeltaBCoord=%d region={%d,%d,%d,%d}\n",
                aDeltaBCoord, region.IStart(wm), region.BStart(wm),
                region.ISize(wm), region.BSize(wm));
       }
 #endif
       mFloatManager->AddFloat(floatFrame,
                               nsFloatManager::GetRegionFor(wm, floatFrame,
-                                                           mContainerWidth),
-                              wm, mContainerWidth);
+                                                           ContainerWidth()),
+                              wm, ContainerWidth());
       fc = fc->Next();
     }
   } else if (aLine->IsBlock()) {
     nsBlockFrame::RecoverFloatsFor(aLine->mFirstChild, *mFloatManager, wm,
-                                   mContainerWidth);
+                                   ContainerWidth());
   }
   mFloatManager->Untranslate(oldWM, oPt);
 }
 
 /**
  * Everything done in this function is done O(N) times for each pass of
  * reflow so it is O(N*M) where M is the number of incremental reflow
  * passes.  That's bad.  Don't do stuff here.
@@ -691,25 +699,25 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // FIXME: Should give AutoRestore a getter for the value to avoid this.
   const nscoord saveBCoord = mBCoord;
 
   // Grab the float's display information
   const nsStyleDisplay* floatDisplay = aFloat->StyleDisplay();
 
   // The float's old region, so we can propagate damage.
   LogicalRect oldRegion = nsFloatManager::GetRegionFor(wm, aFloat,
-                                                       mContainerWidth);
+                                                       ContainerWidth());
 
   // Enforce CSS2 9.5.1 rule [2], i.e., make sure that a float isn't
   // ``above'' another float that preceded it in the flow.
   // "Translate" the float manager with an offset of (0, 0) in order to
   // set the origin to our writing mode
   LogicalPoint oPt(wm);
   WritingMode oldWM = mFloatManager->Translate(wm, oPt);
-  mBCoord = std::max(mFloatManager->GetLowestFloatTop(wm, mContainerWidth),
+  mBCoord = std::max(mFloatManager->GetLowestFloatTop(wm, ContainerWidth()),
                      mBCoord);
 
   // See if the float should clear any preceding floats...
   // XXX We need to mark this float somehow so that it gets reflowed
   // when floats are inserted before it.
   if (NS_STYLE_CLEAR_NONE != floatDisplay->mBreakType) {
     // XXXldb Does this handle vertical margins correctly?
     mBCoord = ClearFloats(mBCoord, floatDisplay->mBreakType);
@@ -913,49 +921,49 @@ nsBlockReflowState::FlowAndPlaceFloat(ns
   // Calculate the actual origin of the float frame's border rect
   // relative to the parent block; the margin must be added in
   // to get the border rect
   LogicalPoint origin(wm, floatMargin.IStart(wm) + floatPos.I(wm),
                       floatMargin.BStart(wm) + floatPos.B(wm));
 
   // If float is relatively positioned, factor that in as well
   nsHTMLReflowState::ApplyRelativePositioning(aFloat, wm, floatOffsets,
-                                              &origin, mContainerWidth);
+                                              &origin, ContainerWidth());
 
   // Position the float and make sure and views are properly
   // positioned. We need to explicitly position its child views as
   // well, since we're moving the float after flowing it.
-  bool moved = aFloat->GetLogicalPosition(wm, mContainerWidth) != origin;
+  bool moved = aFloat->GetLogicalPosition(wm, ContainerWidth()) != origin;
   if (moved) {
-    aFloat->SetPosition(wm, origin, mContainerWidth);
+    aFloat->SetPosition(wm, origin, ContainerWidth());
     nsContainerFrame::PositionFrameView(aFloat);
     nsContainerFrame::PositionChildViews(aFloat);
   }
 
   // Update the float combined area state
   // XXX Floats should really just get invalidated here if necessary
   mFloatOverflowAreas.UnionWith(aFloat->GetOverflowAreas() +
                                 aFloat->GetPosition());
 
   // Place the float in the float manager
   // calculate region
   LogicalRect region =
     nsFloatManager::CalculateRegionFor(wm, aFloat, floatMargin,
-                                       mContainerWidth);
+                                       ContainerWidth());
   // if the float split, then take up all of the vertical height
   if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus) &&
       (NS_UNCONSTRAINEDSIZE != ContentBSize())) {
     region.BSize(wm) = std::max(region.BSize(wm),
                                 ContentBSize() - floatPos.B(wm));
   }
   DebugOnly<nsresult> rv = mFloatManager->AddFloat(aFloat, region, wm,
-                                                   mContainerWidth);
+                                                   ContainerWidth());
   MOZ_ASSERT(NS_SUCCEEDED(rv), "bad float placement");
   // store region
-  nsFloatManager::StoreRegionFor(wm, aFloat, region, mContainerWidth);
+  nsFloatManager::StoreRegionFor(wm, aFloat, region, ContainerWidth());
 
   // If the float's dimensions have changed, note the damage in the
   // float manager.
   if (!region.IsEqualEdges(oldRegion)) {
     // XXXwaterson conservative: we could probably get away with noting
     // less damage; e.g., if only height has changed, then only note the
     // area into which the float has grown or from which the float has
     // shrunk.
@@ -1073,17 +1081,17 @@ nsBlockReflowState::ClearFloats(nscoord 
     return aBCoord;
   }
 
   nscoord newBCoord = aBCoord;
   WritingMode wm = mReflowState.GetWritingMode();
 
   if (aBreakType != NS_STYLE_CLEAR_NONE) {
     newBCoord = mFloatManager->ClearFloats(wm, newBCoord, aBreakType,
-                                           mContainerWidth, aFlags);
+                                           ContainerWidth(), aFlags);
   }
 
   if (aReplacedBlock) {
     for (;;) {
       nsFlowAreaRect floatAvailableSpace = GetFloatAvailableSpace(newBCoord);
       if (!floatAvailableSpace.mHasFloats) {
         // If there aren't any floats here, then we always fit.
         // We check this before calling ISizeToClearPastFloats, which is
--- a/layout/generic/nsBlockReflowState.h
+++ b/layout/generic/nsBlockReflowState.h
@@ -201,18 +201,20 @@ public:
   nscoord ContentBEnd() const {
     return mContentArea.BEnd(mReflowState.GetWritingMode());
   }
   mozilla::LogicalSize ContentSize(mozilla::WritingMode aWM) const {
     mozilla::WritingMode wm = mReflowState.GetWritingMode();
     return mContentArea.Size(wm).ConvertTo(aWM, wm);
   }
 
-  // Physical width. Use only for physical <-> logical coordinate conversion.
-  nscoord mContainerWidth;
+  // Physical size. Use only for physical <-> logical coordinate conversion.
+  nsSize mContainerSize;
+  nscoord ContainerWidth() const { return mContainerSize.width; }
+  nscoord ContainerHeight() const { return mContainerSize.height; }
 
   // Continuation out-of-flow float frames that need to move to our
   // next in flow are placed here during reflow.  It's a pointer to
   // a frame list stored in the block's property table.
   nsFrameList *mPushedFloats;
   // This method makes sure pushed floats are accessible to
   // StealFrame. Call it before adding any frames to mPushedFloats.
   void SetupPushedFloatList();
--- a/layout/generic/nsBulletFrame.cpp
+++ b/layout/generic/nsBulletFrame.cpp
@@ -415,23 +415,29 @@ nsBulletFrame::PaintBullet(nsRenderingCo
       nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
                                             GetFontSizeInflation());
       nsAutoString text;
       GetListItemText(text);
       WritingMode wm = GetWritingMode();
       nscoord ascent = wm.IsLineInverted()
                          ? fm->MaxDescent() : fm->MaxAscent();
       aPt.MoveBy(padding.left, padding.top);
+      gfxContext *ctx = aRenderingContext.ThebesContext();
       if (wm.IsVertical()) {
-        // XXX what about baseline snapping?
-        aPt.x += (wm.IsVerticalLR() ? ascent
-                                    : mRect.width - ascent);
+        if (wm.IsVerticalLR()) {
+          aPt.x = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineX(
+                                   this, ctx, aPt.x, ascent));
+        } else {
+          aPt.x = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineX(
+                                   this, ctx, aPt.x + mRect.width,
+                                   -ascent));
+        }
       } else {
         aPt.y = NSToCoordRound(nsLayoutUtils::GetSnappedBaselineY(
-                this, aRenderingContext.ThebesContext(), aPt.y, ascent));
+                                 this, ctx, aPt.y, ascent));
       }
       nsPresContext* presContext = PresContext();
       if (!presContext->BidiEnabled() && HasRTLChars(text)) {
         presContext->SetBidiEnabled();
       }
       nsLayoutUtils::DrawString(this, *fm, &aRenderingContext,
                                 text.get(), text.Length(), aPt);
     }
--- a/layout/generic/nsFirstLetterFrame.cpp
+++ b/layout/generic/nsFirstLetterFrame.cpp
@@ -194,17 +194,18 @@ nsFirstLetterFrame::Reflow(nsPresContext
     WritingMode kidWritingMode = GetWritingMode(kid);
     LogicalSize kidAvailSize = availSize.ConvertTo(kidWritingMode, wm);
     nsHTMLReflowState rs(aPresContext, aReflowState, kid, kidAvailSize);
     nsLineLayout ll(aPresContext, nullptr, &aReflowState, nullptr, nullptr);
 
     ll.BeginLineReflow(bp.IStart(wm), bp.BStart(wm),
                        availSize.ISize(wm), NS_UNCONSTRAINEDSIZE,
                        false, true, kidWritingMode,
-                       aReflowState.AvailableWidth());
+                       nsSize(aReflowState.AvailableWidth(),
+                              aReflowState.AvailableHeight()));
     rs.mLineLayout = &ll;
     ll.SetInFirstLetter(true);
     ll.SetFirstLetterStyleOK(true);
 
     kid->WillReflow(aPresContext);
     kid->Reflow(aPresContext, kidMetrics, rs, aReflowStatus);
 
     ll.EndLineReflow();
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5175,51 +5175,62 @@ nsIFrame::SchedulePaint(PaintType aType)
   if (shell) {
     shell->AddInvalidateHiddenPresShellObserver(pres->RefreshDriver());
   }
 }
 
 Layer*
 nsIFrame::InvalidateLayer(uint32_t aDisplayItemKey,
                           const nsIntRect* aDamageRect,
+                          const nsRect* aFrameDamageRect,
                           uint32_t aFlags /* = 0 */)
 {
   NS_ASSERTION(aDisplayItemKey > 0, "Need a key");
 
   Layer* layer = FrameLayerBuilder::GetDedicatedLayer(this, aDisplayItemKey);
 
   // If the layer is being updated asynchronously, and it's being forwarded
   // to a compositor, then we don't need to invalidate.
   if ((aFlags & UPDATE_IS_ASYNC) && layer &&
       layer->Manager()->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
     return layer;
   }
 
-  if (aDamageRect && aDamageRect->IsEmpty()) {
-    return layer;
-  }
-
   if (!layer) {
+    if (aFrameDamageRect && aFrameDamageRect->IsEmpty()) {
+      return nullptr;
+    }
+
     // Plugins can transition from not rendering anything to rendering,
     // and still only call this. So always invalidate, with specifying
     // the display item type just in case.
     //
     // In the bug 930056, dialer app startup but not shown on the
     // screen because sometimes we don't have any retainned data
     // for remote type displayitem and thus Repaint event is not
     // triggered. So, always invalidate here as well.
+    uint32_t displayItemKey = aDisplayItemKey;
     if (aDisplayItemKey == nsDisplayItem::TYPE_PLUGIN ||
         aDisplayItemKey == nsDisplayItem::TYPE_REMOTE) {
-      InvalidateFrame();
+      displayItemKey = 0;
+    }
+
+    if (aFrameDamageRect) {
+      InvalidateFrameWithRect(*aFrameDamageRect, displayItemKey);
     } else {
-      InvalidateFrame(aDisplayItemKey);
-    }
+      InvalidateFrame(displayItemKey);
+    }
+
     return nullptr;
   }
 
+  if (aDamageRect && aDamageRect->IsEmpty()) {
+    return layer;
+  }
+
   if (aDamageRect) {
     layer->AddInvalidRect(*aDamageRect);
   } else {
     layer->SetInvalidRectToVisibleRegion();
   }
 
   SchedulePaint(PAINT_COMPOSITE_ONLY);
   return layer;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -2219,26 +2219,32 @@ public:
   /**
    * Checks if the layer tree includes a dedicated layer for this 
    * frame/display item key pair, and invalidates at least aDamageRect
    * area within that layer.
    *
    * If no layer is found, calls InvalidateFrame() instead.
    *
    * @param aDamageRect Area of the layer to invalidate.
+   * @param aFrameDamageRect If no layer is found, the area of the frame to
+   *                         invalidate. If null, the entire frame will be
+   *                         invalidated.
    * @param aDisplayItemKey Display item type.
    * @param aFlags UPDATE_IS_ASYNC : Will skip the invalidation
    * if the found layer is being composited by a remote
    * compositor.
    * @return Layer, if found, nullptr otherwise.
    */
   enum {
     UPDATE_IS_ASYNC = 1 << 0
   };
-  Layer* InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect = nullptr, uint32_t aFlags = 0);
+  Layer* InvalidateLayer(uint32_t aDisplayItemKey,
+                         const nsIntRect* aDamageRect = nullptr,
+                         const nsRect* aFrameDamageRect = nullptr,
+                         uint32_t aFlags = 0);
 
   /**
    * Returns a rect that encompasses everything that might be painted by
    * this frame.  This includes this frame, all its descendent frames, this
    * frame's outline, and descentant frames' outline, but does not include
    * areas clipped out by the CSS "overflow" and "clip" properties.
    *
    * HasOverflowRects() (below) will return true when this overflow
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -380,63 +380,31 @@ nsImageFrame::GetSourceToDestTransform(n
                         float(destRect.height) /
                         float(mIntrinsicSize.height.GetCoordValue()));
     return true;
   }
 
   return false;
 }
 
-/*
- * These two functions basically do the same check.  The first one
- * checks that the given request is the current request for our
- * mContent.  The second checks that the given image container the
- * same as the image container on the current request for our
- * mContent.
- */
+// This function checks whether the given request is the current request for our
+// mContent.
 bool
 nsImageFrame::IsPendingLoad(imgIRequest* aRequest) const
 {
   // Default to pending load in case of errors
   nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
   NS_ASSERTION(imageLoader, "No image loading content?");
 
   int32_t requestType = nsIImageLoadingContent::UNKNOWN_REQUEST;
   imageLoader->GetRequestType(aRequest, &requestType);
 
   return requestType != nsIImageLoadingContent::CURRENT_REQUEST;
 }
 
-bool
-nsImageFrame::IsPendingLoad(imgIContainer* aContainer) const
-{
-  //  default to pending load in case of errors
-  if (!aContainer) {
-    NS_ERROR("No image container!");
-    return true;
-  }
-
-  nsCOMPtr<nsIImageLoadingContent> imageLoader(do_QueryInterface(mContent));
-  NS_ASSERTION(imageLoader, "No image loading content?");
-  
-  nsCOMPtr<imgIRequest> currentRequest;
-  imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
-                          getter_AddRefs(currentRequest));
-  if (!currentRequest) {
-    NS_ERROR("No current request");
-    return true;
-  }
-
-  nsCOMPtr<imgIContainer> currentContainer;
-  currentRequest->GetImage(getter_AddRefs(currentContainer));
-
-  return currentContainer != aContainer;
-  
-}
-
 nsRect
 nsImageFrame::SourceRectToDest(const nsIntRect& aRect)
 {
   // When scaling the image, row N of the source image may (depending on
   // the scaling function) be used to draw any row in the destination image
   // between floor(F * (N-1)) and ceil(F * (N+1)), where F is the
   // floating-point scaling factor.  The same holds true for columns.
   // So, we start by computing that bound without the floor and ceiling.
@@ -628,57 +596,62 @@ nsImageFrame::OnSizeAvailable(imgIReques
   }
 
   return NS_OK;
 }
 
 nsresult
 nsImageFrame::OnFrameUpdate(imgIRequest* aRequest, const nsIntRect* aRect)
 {
-  if (mFirstFrameComplete) {
-    nsCOMPtr<imgIContainer> container;
-    aRequest->GetImage(getter_AddRefs(container));
-    return FrameChanged(aRequest, container);
-  }
-
-  // XXX do we need to make sure that the reflow from the OnSizeAvailable has
-  // been processed before we start calling invalidate?
-
   NS_ENSURE_ARG_POINTER(aRect);
 
   if (!(mState & IMAGE_GOTINITIALREFLOW)) {
     // Don't bother to do anything; we have a reflow coming up!
     return NS_OK;
   }
   
+  if (mFirstFrameComplete && !StyleVisibility()->IsVisible()) {
+    return NS_OK;
+  }
+
   if (IsPendingLoad(aRequest)) {
     // We don't care
     return NS_OK;
   }
 
-  nsIntRect rect = mImage ? mImage->GetImageSpaceInvalidationRect(*aRect)
-                          : *aRect;
-
-#ifdef DEBUG_decode
-  printf("Source rect (%d,%d,%d,%d)\n",
-         aRect->x, aRect->y, aRect->width, aRect->height);
-#endif
+  nsIntRect layerInvalidRect = mImage
+                             ? mImage->GetImageSpaceInvalidationRect(*aRect)
+                             : *aRect;
 
-  if (rect.IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
-    InvalidateFrame(nsDisplayItem::TYPE_IMAGE);
-    InvalidateFrame(nsDisplayItem::TYPE_ALT_FEEDBACK);
-  } else {
-    nsRect invalid = SourceRectToDest(rect);
-    InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_IMAGE);
-    InvalidateFrameWithRect(invalid, nsDisplayItem::TYPE_ALT_FEEDBACK);
+  if (layerInvalidRect.IsEqualInterior(nsIntRect::GetMaxSizedIntRect())) {
+    // Invalidate our entire area.
+    InvalidateSelf(nullptr, nullptr);
+    return NS_OK;
   }
 
+  nsRect frameInvalidRect = SourceRectToDest(layerInvalidRect);
+  InvalidateSelf(&layerInvalidRect, &frameInvalidRect);
   return NS_OK;
 }
 
+void
+nsImageFrame::InvalidateSelf(const nsIntRect* aLayerInvalidRect,
+                             const nsRect* aFrameInvalidRect)
+{
+  InvalidateLayer(nsDisplayItem::TYPE_IMAGE,
+                  aLayerInvalidRect,
+                  aFrameInvalidRect);
+
+  if (!mFirstFrameComplete) {
+    InvalidateLayer(nsDisplayItem::TYPE_ALT_FEEDBACK,
+                    aLayerInvalidRect,
+                    aFrameInvalidRect);
+  }
+}
+
 nsresult
 nsImageFrame::OnLoadComplete(imgIRequest* aRequest, nsresult aStatus)
 {
   // Check what request type we're dealing with
   nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
   NS_ASSERTION(imageLoader, "Who's notifying us??");
   int32_t loadType = nsIImageLoadingContent::UNKNOWN_REQUEST;
   imageLoader->GetRequestType(aRequest, &loadType);
@@ -725,33 +698,16 @@ nsImageFrame::NotifyNewCurrentRequest(im
                                     NS_FRAME_IS_DIRTY);
       }
     }
     // Update border+content to account for image change
     InvalidateFrame();
   }
 }
 
-nsresult
-nsImageFrame::FrameChanged(imgIRequest *aRequest,
-                           imgIContainer *aContainer)
-{
-  if (!StyleVisibility()->IsVisible()) {
-    return NS_OK;
-  }
-
-  if (IsPendingLoad(aContainer)) {
-    // We don't care about it
-    return NS_OK;
-  }
-
-  InvalidateLayer(nsDisplayItem::TYPE_IMAGE);
-  return NS_OK;
-}
-
 void
 nsImageFrame::EnsureIntrinsicSizeAndRatio()
 {
   // If mIntrinsicSize.width and height are 0, then we need to update from the
   // image container.
   if (mIntrinsicSize.width.GetUnit() == eStyleUnit_Coord &&
       mIntrinsicSize.width.GetCoordValue() == 0 &&
       mIntrinsicSize.height.GetUnit() == eStyleUnit_Coord &&
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -221,18 +221,17 @@ protected:
 
 protected:
   friend class nsImageListener;
   friend class nsImageLoadingContent;
 
   nsresult OnSizeAvailable(imgIRequest* aRequest, imgIContainer* aImage);
   nsresult OnFrameUpdate(imgIRequest* aRequest, const nsIntRect* aRect);
   nsresult OnLoadComplete(imgIRequest* aRequest, nsresult aStatus);
-  nsresult FrameChanged(imgIRequest *aRequest,
-                        imgIContainer *aContainer);
+
   /**
    * Notification that aRequest will now be the current request.
    */
   void NotifyNewCurrentRequest(imgIRequest *aRequest, nsresult aStatus);
 
 private:
   // random helpers
   inline void SpecToURI(const nsAString& aSpec, nsIIOService *aIOService,
@@ -267,29 +266,40 @@ private:
    *
    * @param aTransform The transform object to populate.
    *
    * @return whether we succeeded in creating the transform.
    */
   bool GetSourceToDestTransform(nsTransform2D& aTransform);
 
   /**
-   * Helper functions to check whether the request or image container
-   * corresponds to a load we don't care about.  Most of the decoder
-   * observer methods will bail early if these return true.
+   * Helper function to check whether the request corresponds to a load we don't
+   * care about.  Most of the decoder observer methods will bail early if this
+   * returns true.
    */
   bool IsPendingLoad(imgIRequest* aRequest) const;
-  bool IsPendingLoad(imgIContainer* aContainer) const;
 
   /**
    * Function to convert a dirty rect in the source image to a dirty
    * rect for the image frame.
    */
   nsRect SourceRectToDest(const nsIntRect & aRect);
 
+  /**
+   * Triggers invalidation for both our image display item and, if appropriate,
+   * our alt-feedback display item.
+   *
+   * @param aLayerInvalidRect The area to invalidate in layer space. If null, the
+   *                          entire layer will be invalidated.
+   * @param aFrameInvalidRect The area to invalidate in frame space. If null, the
+   *                          entire frame will be invalidated.
+   */
+  void InvalidateSelf(const nsIntRect* aLayerInvalidRect,
+                      const nsRect* aFrameInvalidRect);
+
   nsImageMap*         mImageMap;
 
   nsCOMPtr<imgINotificationObserver> mListener;
 
   nsCOMPtr<imgIContainer> mImage;
   nsSize mComputedSize;
   mozilla::IntrinsicSize mIntrinsicSize;
   nsSize mIntrinsicRatio;
--- a/layout/generic/nsLineLayout.cpp
+++ b/layout/generic/nsLineLayout.cpp
@@ -147,17 +147,17 @@ HasPrevInFlow(nsIFrame *aFrame)
 }
 
 void
 nsLineLayout::BeginLineReflow(nscoord aICoord, nscoord aBCoord,
                               nscoord aISize, nscoord aBSize,
                               bool aImpactedByFloats,
                               bool aIsTopOfPage,
                               WritingMode aWritingMode,
-                              nscoord aContainerWidth)
+                              const nsSize& aContainerSize)
 {
   NS_ASSERTION(nullptr == mRootSpan, "bad linelayout user");
   NS_WARN_IF_FALSE(aISize != NS_UNCONSTRAINEDSIZE,
                    "have unconstrained width; this should only result from "
                    "very large sizes, not attempts at intrinsic width "
                    "calculation");
 #ifdef DEBUG
   if ((aISize != NS_UNCONSTRAINEDSIZE) && CRAZY_SIZE(aISize)) {
@@ -202,17 +202,17 @@ nsLineLayout::BeginLineReflow(nscoord aI
   }
 
   PerSpanData* psd = NewPerSpanData();
   mCurrentSpan = mRootSpan = psd;
   psd->mReflowState = mBlockReflowState;
   psd->mIStart = aICoord;
   psd->mICoord = aICoord;
   psd->mIEnd = aICoord + aISize;
-  mContainerWidth = aContainerWidth;
+  mContainerSize = aContainerSize;
 
   // If we're in a constrained height frame, then we don't allow a
   // max line box width to take effect.
   if (!(LineContainerFrame()->GetStateBits() &
         NS_FRAME_IN_CONSTRAINED_HEIGHT)) {
 
     // If the available size is greater than the maximum line box width (if
     // specified), then we need to adjust the line box width to be at the max
@@ -236,20 +236,16 @@ nsLineLayout::BeginLineReflow(nscoord aI
   // property amounts to anything.
 
   if (0 == mLineNumber && !HasPrevInFlow(mBlockReflowState->frame)) {
     const nsStyleCoord &textIndent = mStyleText->mTextIndent;
     nscoord pctBasis = 0;
     if (textIndent.HasPercent()) {
       pctBasis =
         nsHTMLReflowState::GetContainingBlockContentWidth(mBlockReflowState);
-
-      if (mGotLineBox) {
-        mLineBox->DisableResizeReflowOptimization();
-      }
     }
     nscoord indent = nsRuleNode::ComputeCoordPercentCalc(textIndent, pctBasis);
 
     mTextIndent = indent;
 
     psd->mICoord += indent;
   }
 
@@ -316,17 +312,17 @@ void
 nsLineLayout::UpdateBand(WritingMode aWM,
                          const LogicalRect& aNewAvailSpace,
                          nsIFrame* aFloatFrame)
 {
   WritingMode lineWM = mRootSpan->mWritingMode;
   // need to convert to our writing mode, because we might have a different
   // mode from the caller due to dir: auto
   LogicalRect availSpace = aNewAvailSpace.ConvertTo(lineWM, aWM,
-                                                    mContainerWidth);
+                                                    ContainerWidth());
 #ifdef REALLY_NOISY_REFLOW
   printf("nsLL::UpdateBand %d, %d, %d, %d, (converted to %d, %d, %d, %d); frame=%p\n  will set mImpacted to true\n",
          aNewAvailSpace.x, aNewAvailSpace.y,
          aNewAvailSpace.width, aNewAvailSpace.height,
          availSpace.IStart(lineWM), availSpace.BStart(lineWM),
          availSpace.ISize(lineWM), availSpace.BSize(lineWM),
          aFloatFrame);
 #endif
@@ -1483,33 +1479,33 @@ nsLineLayout::AddBulletFrame(nsIFrame* a
   pfd->mIsBullet = true;
   if (aMetrics.BlockStartAscent() == nsHTMLReflowMetrics::ASK_FOR_BASELINE) {
     pfd->mAscent = aFrame->GetLogicalBaseline(lineWM);
   } else {
     pfd->mAscent = aMetrics.BlockStartAscent();
   }
 
   // Note: block-coord value will be updated during block-direction alignment
-  pfd->mBounds = LogicalRect(lineWM, aFrame->GetRect(), mContainerWidth);
+  pfd->mBounds = LogicalRect(lineWM, aFrame->GetRect(), ContainerWidth());
   pfd->mOverflowAreas = aMetrics.mOverflowAreas;
 }
 
 #ifdef DEBUG
 void
 nsLineLayout::DumpPerSpanData(PerSpanData* psd, int32_t aIndent)
 {
   nsFrame::IndentBy(stdout, aIndent);
   printf("%p: left=%d x=%d right=%d\n", static_cast<void*>(psd),
          psd->mIStart, psd->mICoord, psd->mIEnd);
   PerFrameData* pfd = psd->mFirstFrame;
   while (nullptr != pfd) {
     nsFrame::IndentBy(stdout, aIndent+1);
     nsFrame::ListTag(stdout, pfd->mFrame);
     nsRect rect = pfd->mBounds.GetPhysicalRect(psd->mWritingMode,
-                                               mContainerWidth);
+                                               ContainerWidth());
     printf(" %d,%d,%d,%d\n", rect.x, rect.y, rect.width, rect.height);
     if (pfd->mSpan) {
       DumpPerSpanData(pfd->mSpan, aIndent + 1);
     }
     pfd = pfd->mNext;
   }
 }
 #endif
@@ -1588,28 +1584,28 @@ nsLineLayout::VerticalAlignLine()
   // recurse over the child spans and place any frames we find with
   // vertical-align: top or bottom.
   // XXX PERFORMANCE: set a bit per-span to avoid the extra work
   // (propagate it upward too)
   WritingMode lineWM = psd->mWritingMode;
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     if (pfd->mBlockDirAlign == VALIGN_OTHER) {
       pfd->mBounds.BStart(lineWM) += baselineBCoord;
-      pfd->mFrame->SetRect(lineWM, pfd->mBounds, mContainerWidth);
+      pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidth());
     }
   }
   PlaceTopBottomFrames(psd, -mBStartEdge, lineBSize);
 
   mFinalLineBSize = lineBSize;
   if (mGotLineBox) {
     // Fill in returned line-box and max-element-width data
     mLineBox->SetBounds(lineWM,
                         psd->mIStart, mBStartEdge,
                         psd->mICoord - psd->mIStart, lineBSize,
-                        mContainerWidth);
+                        ContainerWidth());
 
     mLineBox->SetLogicalAscent(baselineBCoord - mBStartEdge);
 #ifdef NOISY_BLOCKDIR_ALIGN
     printf(
       "  [line]==> bounds{x,y,w,h}={%d,%d,%d,%d} lh=%d a=%d\n",
       mLineBox->GetBounds().IStart(lineWM), mLineBox->GetBounds().BStart(lineWM),
       mLineBox->GetBounds().ISize(lineWM), mLineBox->GetBounds().BSize(lineWM),
       mFinalLineBSize, mLineBox->GetLogicalAscent());
@@ -3032,47 +3028,47 @@ nsLineLayout::TextAlignLine(nsLineBox* a
   if (mHasRuby) {
     ExpandInlineRubyBoxes(mRootSpan);
   }
 
   if (mPresContext->BidiEnabled() &&
       (!mPresContext->IsVisualMode() || !lineWM.IsBidiLTR())) {
     nsBidiPresUtils::ReorderFrames(psd->mFirstFrame->mFrame,
                                    aLine->GetChildCount(),
-                                   lineWM, mContainerWidth,
+                                   lineWM, mContainerSize,
                                    psd->mIStart + mTextIndent + dx);
     if (dx) {
-      aLine->IndentBy(dx, mContainerWidth);
+      aLine->IndentBy(dx, ContainerWidth());
     }
   } else if (dx) {
     for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
       pfd->mBounds.IStart(lineWM) += dx;
       pfd->mFrame->SetRect(lineWM, pfd->mBounds, ContainerWidthForSpan(psd));
     }
-    aLine->IndentBy(dx, mContainerWidth);
+    aLine->IndentBy(dx, ContainerWidth());
   }
 }
 
 // This method applies any relative positioning to the given frame.
 void
 nsLineLayout::ApplyRelativePositioning(PerFrameData* aPFD)
 {
   if (!aPFD->mRelativePos) {
     return;
   }
 
   nsIFrame* frame = aPFD->mFrame;
   WritingMode frameWM = frame->GetWritingMode();
-  LogicalPoint origin = frame->GetLogicalPosition(mContainerWidth);
+  LogicalPoint origin = frame->GetLogicalPosition(ContainerWidth());
   // right and bottom are handled by
   // nsHTMLReflowState::ComputeRelativeOffsets
   nsHTMLReflowState::ApplyRelativePositioning(frame, frameWM,
                                               aPFD->mOffsets, &origin,
-                                              mContainerWidth);
-  frame->SetPosition(frameWM, origin, mContainerWidth);
+                                              ContainerWidth());
+  frame->SetPosition(frameWM, origin, ContainerWidth());
 }
 
 // This method do relative positioning for ruby annotations.
 void
 nsLineLayout::RelativePositionAnnotations(PerSpanData* aRubyPSD,
                                           nsOverflowAreas& aOverflowAreas)
 {
   MOZ_ASSERT(aRubyPSD->mFrame->mFrame->GetType() == nsGkAtoms::rubyFrame);
@@ -3115,17 +3111,17 @@ nsLineLayout::RelativePositionFrames(Per
   }
   else {
     LogicalRect rect(wm, psd->mIStart, mBStartEdge,
                      psd->mICoord - psd->mIStart, mFinalLineBSize);
     // The minimum combined area for the frames that are direct
     // children of the block starts at the upper left corner of the
     // line and is sized to match the size of the line's bounding box
     // (the same size as the values returned from VerticalAlignFrames)
-    overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, mContainerWidth);
+    overflowAreas.VisualOverflow() = rect.GetPhysicalRect(wm, ContainerWidth());
     overflowAreas.ScrollableOverflow() = overflowAreas.VisualOverflow();
   }
 
   for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
     nsIFrame* frame = pfd->mFrame;
 
     // Adjust the origin of the frame
     ApplyRelativePositioning(pfd);
--- a/layout/generic/nsLineLayout.h
+++ b/layout/generic/nsLineLayout.h
@@ -51,17 +51,17 @@ public:
     return mLineNumber;
   }
 
   void BeginLineReflow(nscoord aICoord, nscoord aBCoord,
                        nscoord aISize, nscoord aBSize,
                        bool aImpactedByFloats,
                        bool aIsTopOfPage,
                        mozilla::WritingMode aWritingMode,
-                       nscoord aContainerWidth);
+                       const nsSize& aContainerSize);
 
   void EndLineReflow();
 
   /**
    * Called when a float has been placed. This method updates the
    * inline frame and span data to account for any change in positions
    * due to available space for the line boxes changing.
    * @param aX/aY/aWidth/aHeight are the new available
@@ -544,21 +544,21 @@ protected:
     }
   };
   PerSpanData* mSpanFreeList;
   PerSpanData* mRootSpan;
   PerSpanData* mCurrentSpan;
 
   // The container width to use when converting between logical and
   // physical coordinates for frames in this span. For the root span
-  // this is the width of the block cached in mContainerWidth; for
+  // this is the width of the block cached in mContainerSize.width; for
   // child spans it's the width of the root span
   nscoord ContainerWidthForSpan(PerSpanData* aPSD) {
     return (aPSD == mRootSpan)
-      ? mContainerWidth
+      ? ContainerWidth()
       : aPSD->mFrame->mBounds.Width(mRootSpan->mWritingMode);
   }
 
   gfxBreakPriority mLastOptionalBreakPriority;
   int32_t     mLastOptionalBreakFrameOffset;
   int32_t     mForceBreakFrameOffset;
 
   nscoord mMinLineBSize;
@@ -583,18 +583,20 @@ protected:
   // Final computed line-bSize value after VerticalAlignFrames for
   // the block has been called.
   nscoord mFinalLineBSize;
   
   // Amount of trimmable whitespace inline size for the trailing text
   // frame, if any
   nscoord mTrimmableISize;
 
-  // Physical width. Use only for physical <-> logical coordinate conversion.
-  nscoord mContainerWidth;
+  // Physical size. Use only for physical <-> logical coordinate conversion.
+  nsSize mContainerSize;
+  nscoord ContainerWidth() const { return mContainerSize.width; }
+  nscoord ContainerHeight() const { return mContainerSize.height; }
 
   bool mFirstLetterStyleOK      : 1;
   bool mIsTopOfPage             : 1;
   bool mImpactedByFloats        : 1;
   bool mLastFloatWasLetterFrame : 1;
   bool mLineIsEmpty             : 1;
   bool mLineEndsInBR            : 1;
   bool mNeedBackup              : 1;
--- a/layout/generic/nsRubyBaseContainerFrame.cpp
+++ b/layout/generic/nsRubyBaseContainerFrame.cpp
@@ -382,20 +382,20 @@ nsRubyBaseContainerFrame::Reflow(nsPresC
     // XXX nullptr here may cause problem, see comments for
     //     nsLineLayout::mBlockRS and nsLineLayout::AddFloat
     lineLayout->Init(nullptr, reflowState->CalcLineHeight(), -1);
     reflowState->mLineLayout = lineLayout;
 
     // Border and padding are suppressed on ruby text containers.
     // If the writing mode is vertical-rl, the horizontal position of
     // rt frames will be updated when reflowing this text container,
-    // hence leave container width 0 here for now.
+    // hence leave container size 0 here for now.
     lineLayout->BeginLineReflow(0, 0, reflowState->ComputedISize(),
                                 NS_UNCONSTRAINEDSIZE,
-                                false, false, lineWM, 0);
+                                false, false, lineWM, nsSize(0, 0));
     lineLayout->AttachRootFrameToBaseLineLayout();
   }
 
   aReflowState.mLineLayout->BeginSpan(this, &aReflowState,
                                       0, aReflowState.AvailableISize(),
                                       &mBaseline);
 
   nsIFrame* parent = GetParent();
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -6123,19 +6123,25 @@ nsTextFrame::PaintText(nsRenderingContex
   gfxContext* ctx = aRenderingContext->ThebesContext();
   const bool rtl = mTextRun->IsRightToLeft();
   const bool verticalRun = mTextRun->IsVertical();
   WritingMode wm = GetWritingMode();
   const nscoord frameWidth = GetSize().width;
   gfxPoint framePt(aPt.x, aPt.y);
   gfxPoint textBaselinePt;
   if (verticalRun) {
-    textBaselinePt = // XXX sideways-left will need different handling here
-      gfxPoint(aPt.x + (wm.IsVerticalLR() ? mAscent : frameWidth - mAscent),
-               rtl ? aPt.y + GetSize().height : aPt.y);
+    if (wm.IsVerticalLR()) {
+      textBaselinePt.x =
+        nsLayoutUtils::GetSnappedBaselineX(this, ctx, aPt.x, mAscent);
+    } else {
+      textBaselinePt.x =
+        nsLayoutUtils::GetSnappedBaselineX(this, ctx, aPt.x + frameWidth,
+                                           -mAscent);
+    }
+    textBaselinePt.y = rtl ? aPt.y + GetSize().height : aPt.y;
   } else {
     textBaselinePt = gfxPoint(rtl ? gfxFloat(aPt.x + frameWidth) : framePt.x,
              nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent));
   }
   uint32_t startOffset = provider.GetStart().GetSkippedOffset();
   uint32_t maxLength = ComputeTransformedLength(provider);
   nscoord snappedLeftEdge, snappedRightEdge;
   if (!MeasureCharClippedText(provider, aItem.mLeftEdge, aItem.mRightEdge,
--- a/layout/reftests/text-indent/reftest.list
+++ b/layout/reftests/text-indent/reftest.list
@@ -11,8 +11,9 @@
 == text-indent-single-line-indent-inline.html text-indent-single-line-indent-inline-ref-inline-margin.html
 == text-indent-multiple-line.html text-indent-multiple-line-ref-inline-margin.html
 == text-indent-multiple-line.html text-indent-multiple-line-ref-float.html
 != text-indent-multiple-line.html text-indent-multiple-line-notref-block-margin.html
 == text-indent-intrinsic-pref.html text-indent-intrinsic-pref-ref.html
 == text-indent-intrinsic-min.html text-indent-intrinsic-min-ref.html
 == text-indent-negative-intrinsic-pref.html text-indent-negative-intrinsic-pref-ref.html
 == text-indent-negative-intrinsic-min.html text-indent-negative-intrinsic-min-ref.html
+== text-indent-parent-dynamic.html text-indent-parent-dynamic-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-indent/text-indent-parent-dynamic-ref.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<div id="x" style="background: lightgreen; height: 3em; width: 500px; padding: 4px;">
+  <div style="text-indent: 200px; width: 200px; background: yellow;">X</div>
+</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text-indent/text-indent-parent-dynamic.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<div id="x" style="background: lightgreen; height: 3em; width: 400px; padding: 4px;">
+  <div style="text-indent: 40%; width: 200px; background: yellow;">X</div>
+</div>
+
+<script>
+var x = document.getElementById('x');
+x.offsetWidth;
+x.style.width = '500px';
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1117210-1-vertical-baseline-snap-ref.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style>
+@font-face {
+  font-family: ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+
+div {
+  font-family: ahem;
+  font-size: 10px;
+}
+
+.lr {
+  writing-mode: vertical-lr;
+  text-orientation: sideways-right;
+  height: 40px;
+}
+.rl {
+  writing-mode: vertical-lr;
+  text-orientation: sideways-right;
+  height: 40px;
+}
+
+.c { position: relative; top: 10px; left: 10px; }
+</style>
+</head>
+
+<body>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+
+<br>
+
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1117210-1-vertical-baseline-snap.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<style>
+@font-face {
+  font-family: ahem;
+  src: url(../fonts/Ahem.ttf);
+}
+
+div {
+  font-family: ahem;
+  font-size: 10px;
+}
+
+.lr {
+  writing-mode: vertical-lr;
+  text-orientation: sideways-right;
+  height: 40px;
+}
+.rl {
+  writing-mode: vertical-rl;
+  text-orientation: sideways-right;
+  height: 40px;
+}
+
+.a { position: relative; top: 10px; left: 10px; }
+.b { position: relative; top: 10px; left: 10px; }
+.c { position: relative; top: 10px; left: 10px; }
+.d { position: relative; top: 10px; left: 10px; }
+.e { position: relative; top: 10px; left: 10px; }
+
+/* resolution-dependent offsets: we want CSS px values that will correspond
+   to less that 0.5 device pixels either side of where 10px falls, so they
+   all snap to the same device-pixel value */
+
+/* XXX For higher-than-retina density, we punt; the test becomes a no-op */
+
+@media (max-resolution: 2dppx) {
+  .a { left: 9.8px; }
+  .b { left: 9.9px; }
+  .c { left: 10px; }
+  .d { left: 10.1px; }
+  .e { left: 10.2px; }
+}
+
+@media (max-resolution: 1.5dppx) {
+  .a { left: 9.7px; }
+  .b { left: 9.85px; }
+  .c { left: 10px; }
+  .d { left: 10.15px; }
+  .e { left: 10.3px; }
+}
+
+@media (max-resolution: 1dppx) {
+  .a { left: 9.6px; }
+  .b { left: 9.8px; }
+  .c { left: 10px; }
+  .d { left: 10.2px; }
+  .e { left: 10.4px; }
+}
+
+</style>
+</head>
+
+<body>
+<div class="lr a">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr b">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr d">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="lr e">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+
+<br>
+
+<div class="rl a">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl b">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl c">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl d">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+<div class="rl e">abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc<br>abc</div>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-bottom-left-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div {
+    position: absolute;
+    left: 0px;
+    top: 200px;
+  }
+  </style>
+ </head>
+ <body>
+   <div><img src="green-100x100.png" width="100" height="100" alt="Image download support must be enabled"></img></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-bottom-right-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div {
+    position: absolute;
+    left: 200px;
+    top: 200px;
+  }
+  </style>
+ </head>
+ <body>
+   <div><img src="green-100x100.png" width="100" height="100" alt="Image download support must be enabled"></img></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-horizontal-tb-ltr.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: horizontal-tb;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-horizontal-tb-rtl.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: horizontal-tb;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-vertical-lr-ltr.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: vertical-lr;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-vertical-lr-rtl.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: vertical-lr;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-vertical-rl-ltr.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: vertical-rl;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-default-vertical-rl-rtl.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    writing-mode: vertical-rl;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-horizontal-tb-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: horizontal-tb;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-horizontal-tb-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: horizontal-tb;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-vertical-lr-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: vertical-lr;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-vertical-lr-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: vertical-lr;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-vertical-rl-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: vertical-rl;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-end-vertical-rl-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: end;
+    writing-mode: vertical-rl;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-horizontal-tb-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: horizontal-tb;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-horizontal-tb-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: horizontal-tb;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-vertical-lr-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: vertical-lr;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-vertical-lr-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: vertical-lr;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-vertical-rl-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: vertical-rl;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-left-vertical-rl-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: left;
+    writing-mode: vertical-rl;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-horizontal-tb-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: horizontal-tb;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-horizontal-tb-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: horizontal-tb;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-vertical-lr-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: vertical-lr;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-vertical-lr-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: vertical-lr;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-vertical-rl-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: vertical-rl;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-right-vertical-rl-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: right;
+    writing-mode: vertical-rl;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-horizontal-tb-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: horizontal-tb;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-horizontal-tb-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: horizontal-tb;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-vertical-lr-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: vertical-lr;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-vertical-lr-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("left-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: vertical-lr;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-vertical-rl-ltr.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-top-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: vertical-rl;
+    direction: ltr;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-start-vertical-rl-rtl.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+ <head>
+   <meta charset="UTF-8">
+   <title>CSS Writing Modes</title>
+   <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/">
+   <link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#vertical-layout" title="7.1 Principles of Layout in Vertical Writing Modes">
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div.outer {
+    background: red url("right-bottom-300x300.png");
+    height: 300px;
+    width: 300px;
+    text-align: start;
+    writing-mode: vertical-rl;
+    direction: rtl;
+  }
+  div.inner {
+    display: inline-block;
+    background-color: green;
+    height: 100px;
+    width: 100px;
+  }
+  </style>
+ </head>
+ <body>
+  <div class="outer"><div class="inner"></div></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-top-left-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div {
+    position: absolute;
+    left: 0px;
+    top: 0px;
+  }
+  </style>
+ </head>
+ <body>
+   <div><img src="green-100x100.png" width="100" height="100" alt="Image download support must be enabled"></img></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1127488-align-top-right-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+ <head>
+  <title>CSS Reftest Reference</title>
+  <link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
+  <style type="text/css">
+  body {
+    margin: 0;
+  }
+  div {
+    position: absolute;
+    left: 200px;
+    top: 0px;
+  }
+  </style>
+ </head>
+ <body>
+   <div><img src="green-100x100.png" width="100" height="100" alt="Image download support must be enabled"></img></div>
+ </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1131013-vertical-bidi-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>vertical bidi</title>
+    <style type="text/css">
+div {
+  writing-mode: vertical-rl;
+  height:       150px;
+  width:        100px;
+  text-align:   end;
+  background:   yellow;
+}
+    </style>
+  </head>
+  <body>
+    <div><b>ג bar</b> ב foo א</b></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/writing-mode/1131013-vertical-bidi.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>vertical bidi</title>
+    <style type="text/css">
+div {
+  writing-mode: vertical-rl;
+  height:       150px;
+  width:        100px;
+  text-align:   start;
+  background:   yellow;
+}
+    </style>
+  </head>
+  <body>
+    <div dir="rtl">א foo ב <b>bar ג</b></div>
+  </body>
+</html>
new file mode 100644
index 0000000000000000000000000000000000000000..0aa79b0c86bd72c2220ecce39b9553e2cd3605b9
GIT binary patch
literal 84
zc%17D@N?(olHy`uVBq!ia0vp^{2<K83?vyP*g1g|bAV5XD?<aroS#c40=Yb%E{-7;
dw~`YS7=b)p2FBl7!dgHUgQu&X%Q~loCIBjB50U@?
new file mode 100644
index 0000000000000000000000000000000000000000..cd565a8b82cfce9b0c4c57fb85886791862b6f55
GIT binary patch
literal 914
zc%17D@N?(olHy`uVBq!ia0y~yVAKI&4mO}jWo=(6kYY>nc6VX;4}uH!E}sk(;Vkfo
zEM{QfI|9OtQ?>b|fr9KMp1!W^_nA2POqueoPE!C1NtU=qlsM<-=BDPAFgO>bCYGe8
zD3oWGWGJ|M`UZqI@`*DrF#Ym$aSW-r_4ZmLCxZeH^T8{B%lm>ky2_Q8d?>kP#=sw;
z#=yeuuz}$qlYkD80JB-R!E6B?Fq;@jq7{ysLT^*f%~Ufz?D|UP!C`C~Np%W#$w6q!
b183<AOSt^knDE>OW)%icS3j3^P6<r__C?S!
new file mode 100644
index 0000000000000000000000000000000000000000..68961d9d0a9cf5b802b0e644d56f0b2262d6a33d
GIT binary patch
literal 773
zc%17D@N?(olHy`uVBq!ia0y~yVAKI&4kn<;H+e}VAjMhW5n0T@z;^_M8K-LVNdpDh
zOFVsD+3z#43iB~ndmIx53Q3l@MwB?`=jNv7l`uFLr6!i7rYMwWmSiZnd-?{1H}Z)y
zFfi47x;TbZ+<JTUA}50akMlvTyY)|ZG|4N8ymRBQ*%TDhy|p5LHiHX?63akhK_-fE
z%gJ3r+70T|Fp50f#No>@KvpB1z&OCzv84eCAIN9VZD0?5_OSz)&>0v!UHx3vIVCg!
E02X;{)&Kwi
--- a/layout/reftests/writing-mode/reftest.list
+++ b/layout/reftests/writing-mode/reftest.list
@@ -29,11 +29,43 @@ fails == 1102175-1a.html 1102175-1-ref.h
 == 1102175-1b.html 1102175-1-ref.html
 == 1103613-1.html 1103613-1-ref.html
 == 1105268-1-min-max-dimensions.html 1105268-1-min-max-dimensions-ref.html
 == 1105268-2-min-max-dimensions.html 1105268-2-min-max-dimensions-ref.html
 == 1106669-1-intrinsic-for-container.html 1106669-1-intrinsic-for-container-ref.html
 == 1108923-1-percentage-margins.html 1108923-1-percentage-margins-ref.html
 == 1111944-1-list-marker.html 1111944-1-list-marker-ref.html
 fuzzy(116,64) HTTP(..) == 1115916-1-vertical-metrics.html 1115916-1-vertical-metrics-ref.html
+== 1117210-1-vertical-baseline-snap.html 1117210-1-vertical-baseline-snap-ref.html
 == 1122366-1-margin-collapse.html 1122366-1-margin-collapse-ref.html
 == 1124636-1-fieldset-max-height.html 1124636-1-fieldset-max-height-ref.html
 == 1124636-2-fieldset-min-height.html 1124636-2-fieldset-min-height-ref.html
+HTTP(..) == 1127488-align-default-horizontal-tb-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-start-horizontal-tb-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-end-horizontal-tb-ltr.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-left-horizontal-tb-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-right-horizontal-tb-ltr.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-default-horizontal-tb-rtl.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-start-horizontal-tb-rtl.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-end-horizontal-tb-rtl.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-left-horizontal-tb-rtl.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-right-horizontal-tb-rtl.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-default-vertical-rl-rtl.html 1127488-align-bottom-right-ref.html
+HTTP(..) == 1127488-align-start-vertical-rl-rtl.html 1127488-align-bottom-right-ref.html
+HTTP(..) == 1127488-align-end-vertical-rl-rtl.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-left-vertical-rl-rtl.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-right-vertical-rl-rtl.html 1127488-align-bottom-right-ref.html
+HTTP(..) == 1127488-align-default-vertical-rl-ltr.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-start-vertical-rl-ltr.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-end-vertical-rl-ltr.html 1127488-align-bottom-right-ref.html
+HTTP(..) == 1127488-align-left-vertical-rl-ltr.html 1127488-align-top-right-ref.html
+HTTP(..) == 1127488-align-right-vertical-rl-ltr.html 1127488-align-bottom-right-ref.html
+HTTP(..) == 1127488-align-default-vertical-lr-rtl.html 1127488-align-bottom-left-ref.html
+HTTP(..) == 1127488-align-start-vertical-lr-rtl.html 1127488-align-bottom-left-ref.html
+HTTP(..) == 1127488-align-end-vertical-lr-rtl.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-left-vertical-lr-rtl.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-right-vertical-lr-rtl.html 1127488-align-bottom-left-ref.html
+HTTP(..) == 1127488-align-default-vertical-lr-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-start-vertical-lr-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-end-vertical-lr-ltr.html 1127488-align-bottom-left-ref.html
+HTTP(..) == 1127488-align-left-vertical-lr-ltr.html 1127488-align-top-left-ref.html
+HTTP(..) == 1127488-align-right-vertical-lr-ltr.html 1127488-align-bottom-left-ref.html
+== 1131013-vertical-bidi.html 1131013-vertical-bidi-ref.html
new file mode 100644
index 0000000000000000000000000000000000000000..1182ceefcc0ba372e8a6806902aef3cac6b8e17f
GIT binary patch
literal 914
zc%17D@N?(olHy`uVBq!ia0y~yVAKI&4mO}jWo=(6kYY>nc6VX;4}uH!E}sk(;Vkfo
zEM{QfI|9OtQ?>b|fr9KMp1!W^_nA2P%mr`6Zmj_dNtU=qlsM<-=BDPAFgO>bCYGe8
zD3oWGWGJ|M`UZqI@`*DrF#Ym$aSW-r_4e99P6h=AW<%|F`-|=#nBO#^=fd%eTi!DK
zIAFr45W&#I$|2T}z{nv6W-CO1*+2rsCQ6cMg`=j>*_49wMvO8lW*;^%uy70LFdSqO
t&~X5<fdq&RB*1J`Num`FR#P6d@)oUPi&(~5r4P(144$rjF6*2UngBnL&;bAd
new file mode 100644
index 0000000000000000000000000000000000000000..0387861a2f3c3180f66b5f910ae0b22f408fc47d
GIT binary patch
literal 919
zc%17D@N?(olHy`uVBq!ia0y~yVAKI&4mO}jWo=(6kYY>nc6VX;4}uH!E}sk(;Vkfo
zEM{QfI|9OtQ?>b|fr9KMp1!W^_nA2PtYlMM+oga)k|nMYCC>S|xv6<249-QVi6yBi
z3gww484B*6z5(HleBulYO#eMy978H@y}fpjmqCGt*|6(I{nHH$ucRAoo#d8>OyYU4
z<`kRwOf?1;ZifvF2blzPfCQM$!VP8%=z!V8ND{4ZpiOxYdz$5fN6v#pMh-EB2!<wB
zg@}d(AR9=4*gyd=8&#5Mg`=j>-xQ8%oY<oM-v-7ztQ=vHFE-2p<`)J}S3j3^P6<r_
DVHnaB
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -239,23 +239,21 @@ RuleHash_CSMatchEntry(PLDHashTable *tabl
   nsIAtom *match_atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>
                                               (key));
   // Use our extra |getKey| callback to avoid code duplication.
   nsIAtom *entry_atom = ToLocalOps(table->Ops())->getKey(table, hdr);
 
   return match_atom == entry_atom;
 }
 
-static bool
-RuleHash_InitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                   const void *key)
+static void
+RuleHash_InitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   RuleHashTableEntry* entry = static_cast<RuleHashTableEntry*>(hdr);
   new (entry) RuleHashTableEntry();
-  return true;
 }
 
 static void
 RuleHash_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   RuleHashTableEntry* entry = static_cast<RuleHashTableEntry*>(hdr);
   entry->~RuleHashTableEntry();
 }
@@ -279,24 +277,22 @@ RuleHash_TagTable_MatchEntry(PLDHashTabl
 {
   nsIAtom *match_atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>
                                               (key));
   nsIAtom *entry_atom = static_cast<const RuleHashTagTableEntry*>(hdr)->mTag;
 
   return match_atom == entry_atom;
 }
 
-static bool
-RuleHash_TagTable_InitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                            const void *key)
+static void
+RuleHash_TagTable_InitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>(hdr);
   new (entry) RuleHashTagTableEntry();
   entry->mTag = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(key));
-  return true;
 }
 
 static void
 RuleHash_TagTable_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>(hdr);
   entry->~RuleHashTagTableEntry();
 }
@@ -831,24 +827,22 @@ struct AtomSelectorEntry : public PLDHas
 };
 
 static void
 AtomSelector_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   (static_cast<AtomSelectorEntry*>(hdr))->~AtomSelectorEntry();
 }
 
-static bool
-AtomSelector_InitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                       const void *key)
+static void
+AtomSelector_InitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   AtomSelectorEntry *entry = static_cast<AtomSelectorEntry*>(hdr);
   new (entry) AtomSelectorEntry();
   entry->mAtom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(key));
-  return true;
 }
 
 static void
 AtomSelector_MoveEntry(PLDHashTable *table, const PLDHashEntryHdr *from,
                        PLDHashEntryHdr *to)
 {
   NS_PRECONDITION(from != to, "This is not going to work!");
   AtomSelectorEntry *oldEntry =
@@ -3315,23 +3309,21 @@ HashIntKey(PLDHashTable *table, const vo
 static bool
 MatchWeightEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                  const void *key)
 {
   const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
   return entry->data.mWeight == NS_PTR_TO_INT32(key);
 }
 
-static bool
-InitWeightEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                const void *key)
+static void
+InitWeightEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   RuleByWeightEntry* entry = static_cast<RuleByWeightEntry*>(hdr);
   new (entry) RuleByWeightEntry();
-  return true;
 }
 
 static const PLDHashTableOps gRulesByWeightOps = {
     HashIntKey,
     MatchWeightEntry,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     InitWeightEntry
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -203,28 +203,25 @@ LangRuleTable_MatchEntry(PLDHashTable *t
                          const void *key)
 {
   const nsString *lang = static_cast<const nsString*>(key);
   const LangRuleTableEntry *entry = static_cast<const LangRuleTableEntry*>(hdr);
 
   return entry->mRule->mLang == *lang;
 }
 
-static bool
-LangRuleTable_InitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                        const void *key)
+static void
+LangRuleTable_InitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   const nsString *lang = static_cast<const nsString*>(key);
 
   LangRuleTableEntry *entry = new (hdr) LangRuleTableEntry();
 
   // Create the unique rule for this language
   entry->mRule = new nsHTMLStyleSheet::LangRule(*lang);
-
-  return true;
 }
 
 static const PLDHashTableOps LangRuleTable_Ops = {
   LangRuleTable_HashKey,
   LangRuleTable_MatchEntry,
   PL_DHashMoveEntryStub,
   LangRuleTable_ClearEntry,
   LangRuleTable_InitEntry
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -73,26 +73,24 @@ static void
 RequestHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
 {
     RequestMapEntry *e = static_cast<RequestMapEntry *>(entry);
 
     // An entry is being cleared, let the entry do its own cleanup.
     e->~RequestMapEntry();
 }
 
-static bool
-RequestHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
-                     const void *key)
+static void
+RequestHashInitEntry(PLDHashEntryHdr *entry, const void *key)
 {
     const nsIRequest *const_request = static_cast<const nsIRequest *>(key);
     nsIRequest *request = const_cast<nsIRequest *>(const_request);
 
     // Initialize the entry with placement new
     new (entry) RequestMapEntry(request);
-    return true;
 }
 
 
 static void
 RescheduleRequest(nsIRequest *aRequest, int32_t delta)
 {
     nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aRequest);
     if (p)
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -454,24 +454,22 @@ HostDB_ClearEntry(PLDHashTable *table,
             }
             while (addrElement);
         }
     }
 #endif
     NS_RELEASE(he->rec);
 }
 
-static bool
-HostDB_InitEntry(PLDHashTable *table,
-                 PLDHashEntryHdr *entry,
+static void
+HostDB_InitEntry(PLDHashEntryHdr *entry,
                  const void *key)
 {
     nsHostDBEnt *he = static_cast<nsHostDBEnt *>(entry);
     nsHostRecord::Create(static_cast<const nsHostKey *>(key), &he->rec);
-    return true;
 }
 
 static const PLDHashTableOps gHostDB_ops =
 {
     HostDB_HashKey,
     HostDB_MatchEntry,
     HostDB_MoveEntry,
     HostDB_ClearEntry,
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -271,16 +271,17 @@ class RecursiveMakeBackend(CommonBackend
     However, as long as there are Makefile.in files in the tree, we are tied to
     recursive make and thus will need this backend.
     """
 
     def _init(self):
         CommonBackend._init(self)
 
         self._backend_files = {}
+        self._idl_dirs = set()
 
         def detailed(summary):
             s = '{:d} total backend files; ' \
                 '{:d} created; {:d} updated; {:d} unchanged; ' \
                 '{:d} deleted; {:d} -> {:d} Makefile'.format(
                 summary.created_count + summary.updated_count +
                 summary.unchanged_count,
                 summary.created_count,
@@ -342,16 +343,17 @@ class RecursiveMakeBackend(CommonBackend
 
         CommonBackend.consume_object(self, obj)
 
         # CommonBackend handles XPIDLFile and TestManifest, but we want to do
         # some extra things for them.
         if isinstance(obj, XPIDLFile):
             backend_file.idls.append(obj)
             backend_file.xpt_name = '%s.xpt' % obj.module
+            self._idl_dirs.add(obj.relobjdir)
 
         elif isinstance(obj, TestManifest):
             self._process_test_manifest(obj, backend_file)
 
         # If CommonBackend acknowledged the object, we're done with it.
         if obj._ack:
             return
 
@@ -571,19 +573,23 @@ class RecursiveMakeBackend(CommonBackend
 
         root_deps_mk = Makefile()
 
         # Fill the dependencies for traversal of each tier.
         for tier, filter in filters:
             main, all_deps = \
                 self._traversal.compute_dependencies(filter)
             for dir, deps in all_deps.items():
-                if deps is not None:
+                if deps is not None or (dir in self._idl_dirs \
+                                        and tier == 'export'):
                     rule = root_deps_mk.create_rule(['%s/%s' % (dir, tier)])
+                if deps:
                     rule.add_dependencies('%s/%s' % (d, tier) for d in deps if d)
+                if dir in self._idl_dirs and tier == 'export':
+                    rule.add_dependencies(['xpcom/xpidl/%s' % tier])
             rule = root_deps_mk.create_rule(['recurse_%s' % tier])
             if main:
                 rule.add_dependencies('%s/%s' % (d, tier) for d in main)
 
         all_compile_deps = reduce(lambda x,y: x|y,
             self._compile_graph.values()) if self._compile_graph else set()
         compile_roots = set(self._compile_graph.keys()) - all_compile_deps
 
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -891,17 +891,17 @@ VARIABLES = {
 
     # IDL Generation.
     'XPIDL_SOURCES': (StrictOrderingOnAppendList, list,
         """XPCOM Interface Definition Files (xpidl).
 
         This is a list of files that define XPCOM interface definitions.
         Entries must be files that exist. Entries are almost certainly ``.idl``
         files.
-        """, 'misc'),
+        """, 'export'),
 
     'XPIDL_MODULE': (unicode, unicode,
         """XPCOM Interface Definition Module Name.
 
         This is the name of the ``.xpt`` file that is created by linking
         ``XPIDL_SOURCES`` together. If unspecified, it defaults to be the same
         as ``MODULE``.
         """, None),
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -58,23 +58,21 @@ struct RequestHashEntry : PLDHashEntryHd
 static bool
 RequestMapMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                          const void *key)
 {
   const RequestHashEntry *entry = static_cast<const RequestHashEntry*>(hdr);
   return entry->r == key;
 }
 
-static bool
-RequestMapInitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                     const void *key)
+static void
+RequestMapInitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   RequestHashEntry *entry = static_cast<RequestHashEntry*>(hdr);
   entry->r = (void*)key;
-  return true;
 }
 
 static const PLDHashTableOps gMapOps = {
   PL_DHashVoidPtrKeyStub,
   RequestMapMatchEntry,
   PL_DHashMoveEntryStub,
   PL_DHashClearEntryStub,
   RequestMapInitEntry
--- a/security/manager/ssl/src/nsCertTree.cpp
+++ b/security/manager/ssl/src/nsCertTree.cpp
@@ -66,27 +66,22 @@ CompareCacheHashEntry::CompareCacheHashE
 static bool
 CompareCacheMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                          const void *key)
 {
   const CompareCacheHashEntryPtr *entryPtr = static_cast<const CompareCacheHashEntryPtr*>(hdr);
   return entryPtr->entry->key == key;
 }
 
-static bool
-CompareCacheInitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                     const void *key)
+static void
+CompareCacheInitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   new (hdr) CompareCacheHashEntryPtr();
   CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
-  if (!entryPtr->entry) {
-    return false;
-  }
   entryPtr->entry->key = (void*)key;
-  return true;
 }
 
 static void
 CompareCacheClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>(hdr);
   entryPtr->~CompareCacheHashEntryPtr();
 }
--- a/security/manager/ssl/src/nsNSSShutDown.cpp
+++ b/security/manager/ssl/src/nsNSSShutDown.cpp
@@ -18,23 +18,21 @@ struct ObjectHashEntry : PLDHashEntryHdr
 static bool
 ObjectSetMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
                          const void *key)
 {
   const ObjectHashEntry *entry = static_cast<const ObjectHashEntry*>(hdr);
   return entry->obj == static_cast<const nsNSSShutDownObject*>(key);
 }
 
-static bool
-ObjectSetInitEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
-                     const void *key)
+static void
+ObjectSetInitEntry(PLDHashEntryHdr *hdr, const void *key)
 {
   ObjectHashEntry *entry = static_cast<ObjectHashEntry*>(hdr);
   entry->obj = const_cast<nsNSSShutDownObject*>(static_cast<const nsNSSShutDownObject*>(key));
-  return true;
 }
 
 static const PLDHashTableOps gSetOps = {
   PL_DHashVoidPtrKeyStub,
   ObjectSetMatchEntry,
   PL_DHashMoveEntryStub,
   PL_DHashClearEntryStub,
   ObjectSetInitEntry
--- a/security/sandbox/chromium-shim/base/logging.cpp
+++ b/security/sandbox/chromium-shim/base/logging.cpp
@@ -37,30 +37,27 @@ int min_log_level = 0;
 int GetMinLogLevel() {
   return min_log_level;
 }
 
 int GetVlogLevelHelper(const char* file, size_t N) {
   return 0;
 }
 
-// MSVC doesn't like complex extern templates and DLLs.
-#if !defined(COMPILER_MSVC)
 // Explicit instantiations for commonly used comparisons.
 template std::string* MakeCheckOpString<int, int>(
     const int&, const int&, const char* names);
 template std::string* MakeCheckOpString<unsigned long, unsigned long>(
     const unsigned long&, const unsigned long&, const char* names);
 template std::string* MakeCheckOpString<unsigned long, unsigned int>(
     const unsigned long&, const unsigned int&, const char* names);
 template std::string* MakeCheckOpString<unsigned int, unsigned long>(
     const unsigned int&, const unsigned long&, const char* names);
 template std::string* MakeCheckOpString<std::string, std::string>(
     const std::string&, const std::string&, const char* name);
-#endif
 
 #if defined(OS_WIN)
 LogMessage::SaveLastError::SaveLastError() : last_error_(::GetLastError()) {
 }
 
 LogMessage::SaveLastError::~SaveLastError() {
   ::SetLastError(last_error_);
 }
@@ -100,16 +97,27 @@ Win32ErrorLogMessage::Win32ErrorLogMessa
                                            LogSeverity severity,
                                            SystemErrorCode err)
     : err_(err),
       log_message_(file, line, severity) {
 }
 
 Win32ErrorLogMessage::~Win32ErrorLogMessage() {
 }
+#elif defined(OS_POSIX)
+ErrnoLogMessage::ErrnoLogMessage(const char* file,
+                                 int line,
+                                 LogSeverity severity,
+                                 SystemErrorCode err)
+    : err_(err),
+      log_message_(file, line, severity) {
+}
+
+ErrnoLogMessage::~ErrnoLogMessage() {
+}
 #endif  // OS_WIN
 
 void RawLog(int level, const char* message) {
 }
 
 } // namespace logging
 
 #if defined(OS_WIN)
deleted file mode 100644
--- a/security/sandbox/chromium-shim/base/threading/thread_local_storage.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-// Blank header file as thread_local.h includes a file that should only be
-// included on Android.
-// Chromium issue 431339 raised.
-// https://code.google.com/p/chromium/issues/detail?id=431339
--- a/security/sandbox/chromium/base/atomic_ref_count.h
+++ b/security/sandbox/chromium/base/atomic_ref_count.h
@@ -7,17 +7,16 @@
 //
 // The implementation includes annotations to avoid some false positives
 // when using data race detection tools.
 
 #ifndef BASE_ATOMIC_REF_COUNT_H_
 #define BASE_ATOMIC_REF_COUNT_H_
 
 #include "base/atomicops.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
 
 namespace base {
 
 typedef subtle::Atomic32 AtomicRefCount;
 
 // Increment a reference count by "increment", which must exceed 0.
 inline void AtomicRefCountIncN(volatile AtomicRefCount *ptr,
                                AtomicRefCount increment) {
@@ -25,21 +24,17 @@ inline void AtomicRefCountIncN(volatile 
 }
 
 // Decrement a reference count by "decrement", which must exceed 0,
 // and return whether the result is non-zero.
 // Insert barriers to ensure that state written before the reference count
 // became zero will be visible to a thread that has just made the count zero.
 inline bool AtomicRefCountDecN(volatile AtomicRefCount *ptr,
                                AtomicRefCount decrement) {
-  ANNOTATE_HAPPENS_BEFORE(ptr);
   bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0);
-  if (!res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
-  }
   return res;
 }
 
 // Increment a reference count by 1.
 inline void AtomicRefCountInc(volatile AtomicRefCount *ptr) {
   base::AtomicRefCountIncN(ptr, 1);
 }
 
@@ -53,28 +48,22 @@ inline bool AtomicRefCountDec(volatile A
 // Return whether the reference count is one.  If the reference count is used
 // in the conventional way, a refrerence count of 1 implies that the current
 // thread owns the reference and no other thread shares it.  This call performs
 // the test for a reference count of one, and performs the memory barrier
 // needed for the owning thread to act on the object, knowing that it has
 // exclusive access to the object.
 inline bool AtomicRefCountIsOne(volatile AtomicRefCount *ptr) {
   bool res = (subtle::Acquire_Load(ptr) == 1);
-  if (res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
-  }
   return res;
 }
 
 // Return whether the reference count is zero.  With conventional object
 // referencing counting, the object will be destroyed, so the reference count
 // should never be zero.  Hence this is generally used for a debug check.
 inline bool AtomicRefCountIsZero(volatile AtomicRefCount *ptr) {
   bool res = (subtle::Acquire_Load(ptr) == 0);
-  if (res) {
-    ANNOTATE_HAPPENS_AFTER(ptr);
-  }
   return res;
 }
 
 }  // namespace base
 
 #endif  // BASE_ATOMIC_REF_COUNT_H_
--- a/security/sandbox/chromium/base/atomicops.h
+++ b/security/sandbox/chromium/base/atomicops.h
@@ -23,18 +23,21 @@
 //   NoBarrier_Load()
 // Although there are currently no compiler enforcement, you are encouraged
 // to use these.
 //
 
 #ifndef BASE_ATOMICOPS_H_
 #define BASE_ATOMICOPS_H_
 
+#include <cassert>  // Small C++ header which defines implementation specific
+                    // macros used to identify the STL implementation.
 #include <stdint.h>
 
+#include "base/base_export.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
 // windows.h #defines this (only on x64). This causes problems because the
 // public API also uses MemoryBarrier at the public name for this fence. So, on
 // X64, undef it, and call its documented
 // (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx)
 // implementation directly.
@@ -132,36 +135,75 @@ void Release_Store(volatile Atomic64* pt
 Atomic64 NoBarrier_Load(volatile const Atomic64* ptr);
 Atomic64 Acquire_Load(volatile const Atomic64* ptr);
 Atomic64 Release_Load(volatile const Atomic64* ptr);
 #endif  // ARCH_CPU_64_BITS
 
 }  // namespace subtle
 }  // namespace base
 
-// Include our platform specific implementation.
-#if defined(THREAD_SANITIZER)
-#include "base/atomicops_internals_tsan.h"
-#elif defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY)
-#include "base/atomicops_internals_x86_msvc.h"
-#elif defined(OS_MACOSX)
-#include "base/atomicops_internals_mac.h"
-#elif defined(OS_NACL)
-#include "base/atomicops_internals_gcc.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL)
-#include "base/atomicops_internals_arm_gcc.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64)
-#include "base/atomicops_internals_arm64_gcc.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
-#include "base/atomicops_internals_x86_gcc.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY)
-#include "base/atomicops_internals_mips_gcc.h"
-#else
-#error "Atomic operations are not supported on your platform"
+// The following x86 CPU features are used in atomicops_internals_x86_gcc.h, but
+// this file is duplicated inside of Chrome: protobuf and tcmalloc rely on the
+// struct being present at link time. Some parts of Chrome can currently use the
+// portable interface whereas others still use GCC one. The include guards are
+// the same as in atomicops_internals_x86_gcc.cc.
+#if defined(__i386__) || defined(__x86_64__)
+// This struct is not part of the public API of this module; clients may not
+// use it.  (However, it's exported via BASE_EXPORT because clients implicitly
+// do use it at link time by inlining these functions.)
+// Features of this x86.  Values may not be correct before main() is run,
+// but are set conservatively.
+struct AtomicOps_x86CPUFeatureStruct {
+  bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
+                            // after acquire compare-and-swap.
+  // The following fields are unused by Chrome's base implementation but are
+  // still used by copies of the same code in other parts of the code base. This
+  // causes an ODR violation, and the other code is likely reading invalid
+  // memory.
+  // TODO(jfb) Delete these fields once the rest of the Chrome code base doesn't
+  //           depend on them.
+  bool has_sse2;            // Processor has SSE2.
+  bool has_cmpxchg16b;      // Processor supports cmpxchg16b instruction.
+};
+BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
+    AtomicOps_Internalx86CPUFeatures;
 #endif
 
+// Try to use a portable implementation based on C++11 atomics.
+//
+// Some toolchains support C++11 language features without supporting library
+// features (recent compiler, older STL). Whitelist libstdc++ and libc++ that we
+// know will have <atomic> when compiling C++11.
+#if ((__cplusplus >= 201103L) &&                            \
+     ((defined(__GLIBCXX__) && (__GLIBCXX__ > 20110216)) || \
+      (defined(_LIBCPP_VERSION) && (_LIBCPP_STD_VER >= 11))))
+#  include "base/atomicops_internals_portable.h"
+#else  // Otherwise use a platform specific implementation.
+#  if defined(THREAD_SANITIZER)
+#    error "Thread sanitizer must use the portable atomic operations"
+#  elif (defined(OS_WIN) && defined(COMPILER_MSVC) && \
+         defined(ARCH_CPU_X86_FAMILY))
+#    include "base/atomicops_internals_x86_msvc.h"
+#  elif defined(OS_MACOSX)
+#    include "base/atomicops_internals_mac.h"
+#  elif defined(OS_NACL)
+#    include "base/atomicops_internals_gcc.h"
+#  elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL)
+#    include "base/atomicops_internals_arm_gcc.h"
+#  elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64)
+#    include "base/atomicops_internals_arm64_gcc.h"
+#  elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
+#    include "base/atomicops_internals_x86_gcc.h"
+#  elif (defined(COMPILER_GCC) && \
+         (defined(ARCH_CPU_MIPS_FAMILY) || defined(ARCH_CPU_MIPS64_FAMILY)))
+#    include "base/atomicops_internals_mips_gcc.h"
+#  else
+#    error "Atomic operations are not supported on your platform"
+#  endif
+#endif   // Portable / non-portable includes.
+
 // On some platforms we need additional declarations to make
 // AtomicWord compatible with our other Atomic* types.
 #if defined(OS_MACOSX) || defined(OS_OPENBSD)
 #include "base/atomicops_internals_atomicword_compat.h"
 #endif
 
 #endif  // BASE_ATOMICOPS_H_
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium/base/atomicops_internals_arm_gcc.h
@@ -0,0 +1,294 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+//
+// LinuxKernelCmpxchg and Barrier_AtomicIncrement are from Google Gears.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
+
+#if defined(OS_QNX)
+#include <sys/cpuinline.h>
+#endif
+
+namespace base {
+namespace subtle {
+
+// Memory barriers on ARM are funky, but the kernel is here to help:
+//
+// * ARMv5 didn't support SMP, there is no memory barrier instruction at
+//   all on this architecture, or when targeting its machine code.
+//
+// * Some ARMv6 CPUs support SMP. A full memory barrier can be produced by
+//   writing a random value to a very specific coprocessor register.
+//
+// * On ARMv7, the "dmb" instruction is used to perform a full memory
+//   barrier (though writing to the co-processor will still work).
+//   However, on single core devices (e.g. Nexus One, or Nexus S),
+//   this instruction will take up to 200 ns, which is huge, even though
+//   it's completely un-needed on these devices.
+//
+// * There is no easy way to determine at runtime if the device is
+//   single or multi-core. However, the kernel provides a useful helper
+//   function at a fixed memory address (0xffff0fa0), which will always
+//   perform a memory barrier in the most efficient way. I.e. on single
+//   core devices, this is an empty function that exits immediately.
+//   On multi-core devices, it implements a full memory barrier.
+//
+// * This source could be compiled to ARMv5 machine code that runs on a
+//   multi-core ARMv6 or ARMv7 device. In this case, memory barriers
+//   are needed for correct execution. Always call the kernel helper, even
+//   when targeting ARMv5TE.
+//
+
+inline void MemoryBarrier() {
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+  // Note: This is a function call, which is also an implicit compiler barrier.
+  typedef void (*KernelMemoryBarrierFunc)();
+  ((KernelMemoryBarrierFunc)0xffff0fa0)();
+#elif defined(OS_QNX)
+  __cpu_membarrier();
+#else
+#error MemoryBarrier() is not implemented on this platform.
+#endif
+}
+
+// An ARM toolchain would only define one of these depending on which
+// variant of the target architecture is being used. This tests against
+// any known ARMv6 or ARMv7 variant, where it is possible to directly
+// use ldrex/strex instructions to implement fast atomic operations.
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
+    defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \
+    defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+    defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
+    defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value;
+  int reloop;
+  do {
+    // The following is equivalent to:
+    //
+    //   prev_value = LDREX(ptr)
+    //   reloop = 0
+    //   if (prev_value != old_value)
+    //      reloop = STREX(ptr, new_value)
+    __asm__ __volatile__("    ldrex %0, [%3]\n"
+                         "    mov %1, #0\n"
+                         "    cmp %0, %4\n"
+#ifdef __thumb2__
+                         "    it eq\n"
+#endif
+                         "    strexeq %1, %5, [%3]\n"
+                         : "=&r"(prev_value), "=&r"(reloop), "+m"(*ptr)
+                         : "r"(ptr), "r"(old_value), "r"(new_value)
+                         : "cc", "memory");
+  } while (reloop != 0);
+  return prev_value;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 result = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+  MemoryBarrier();
+  return result;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  MemoryBarrier();
+  return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 value;
+  int reloop;
+  do {
+    // Equivalent to:
+    //
+    //  value = LDREX(ptr)
+    //  value += increment
+    //  reloop = STREX(ptr, value)
+    //
+    __asm__ __volatile__("    ldrex %0, [%3]\n"
+                         "    add %0, %0, %4\n"
+                         "    strex %1, %0, [%3]\n"
+                         : "=&r"(value), "=&r"(reloop), "+m"(*ptr)
+                         : "r"(ptr), "r"(increment)
+                         : "cc", "memory");
+  } while (reloop);
+  return value;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  // TODO(digit): Investigate if it's possible to implement this with
+  // a single MemoryBarrier() operation between the LDREX and STREX.
+  // See http://crbug.com/246514
+  MemoryBarrier();
+  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  int reloop;
+  do {
+    // old_value = LDREX(ptr)
+    // reloop = STREX(ptr, new_value)
+    __asm__ __volatile__("   ldrex %0, [%3]\n"
+                         "   strex %1, %4, [%3]\n"
+                         : "=&r"(old_value), "=&r"(reloop), "+m"(*ptr)
+                         : "r"(ptr), "r"(new_value)
+                         : "cc", "memory");
+  } while (reloop != 0);
+  return old_value;
+}
+
+// This tests against any known ARMv5 variant.
+#elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
+      defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__)
+
+// The kernel also provides a helper function to perform an atomic
+// compare-and-swap operation at the hard-wired address 0xffff0fc0.
+// On ARMv5, this is implemented by a special code path that the kernel
+// detects and treats specially when thread pre-emption happens.
+// On ARMv6 and higher, it uses LDREX/STREX instructions instead.
+//
+// Note that this always perform a full memory barrier, there is no
+// need to add calls MemoryBarrier() before or after it. It also
+// returns 0 on success, and 1 on exit.
+//
+// Available and reliable since Linux 2.6.24. Both Android and ChromeOS
+// use newer kernel revisions, so this should not be a concern.
+namespace {
+
+inline int LinuxKernelCmpxchg(Atomic32 old_value,
+                              Atomic32 new_value,
+                              volatile Atomic32* ptr) {
+  typedef int (*KernelCmpxchgFunc)(Atomic32, Atomic32, volatile Atomic32*);
+  return ((KernelCmpxchgFunc)0xffff0fc0)(old_value, new_value, ptr);
+}
+
+}  // namespace
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev_value;
+  for (;;) {
+    prev_value = *ptr;
+    if (prev_value != old_value)
+      return prev_value;
+    if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
+      return old_value;
+  }
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 old_value;
+  do {
+    old_value = *ptr;
+  } while (LinuxKernelCmpxchg(old_value, new_value, ptr));
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  for (;;) {
+    // Atomic exchange the old value with an incremented one.
+    Atomic32 old_value = *ptr;
+    Atomic32 new_value = old_value + increment;
+    if (!LinuxKernelCmpxchg(old_value, new_value, ptr)) {
+      // The exchange took place as expected.
+      return new_value;
+    }
+    // Otherwise, *ptr changed mid-loop and we need to retry.
+  }
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev_value;
+  for (;;) {
+    prev_value = *ptr;
+    if (prev_value != old_value) {
+      // Always ensure acquire semantics.
+      MemoryBarrier();
+      return prev_value;
+    }
+    if (!LinuxKernelCmpxchg(old_value, new_value, ptr))
+      return old_value;
+  }
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  // This could be implemented as:
+  //    MemoryBarrier();
+  //    return NoBarrier_CompareAndSwap();
+  //
+  // But would use 3 barriers per succesful CAS. To save performance,
+  // use Acquire_CompareAndSwap(). Its implementation guarantees that:
+  // - A succesful swap uses only 2 barriers (in the kernel helper).
+  // - An early return due to (prev_value != old_value) performs
+  //   a memory barrier with no store, which is equivalent to the
+  //   generic implementation above.
+  return Acquire_CompareAndSwap(ptr, old_value, new_value);
+}
+
+#else
+#  error "Your CPU's ARM architecture is not supported yet"
+#endif
+
+// NOTE: Atomicity of the following load and store operations is only
+// guaranteed in case of 32-bit alignement of |ptr| values.
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; }
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace base::subtle
+}  // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
new file mode 100644
--- /dev/null
+++ b/security/sandbox/chromium/base/atomicops_internals_portable.h
@@ -0,0 +1,227 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+//
+// This implementation uses C++11 atomics' member functions. The code base is
+// currently written assuming atomicity revolves around accesses instead of
+// C++11's memory locations. The burden is on the programmer to ensure that all
+// memory locations accessed atomically are never accessed non-atomically (tsan
+// should help with this).
+//
+// TODO(jfb) Modify the atomicops.h API and user code to declare atomic
+//           locations as truly atomic. See the static_assert below.
+//
+// Of note in this implementation:
+//  * All NoBarrier variants are implemented as relaxed.
+//  * All Barrier variants are implemented as sequentially-consistent.
+//  * Compare exchange's failure ordering is always the same as the success one
+//    (except for release, which fails as relaxed): using a weaker ordering is
+//    only valid under certain uses of compare exchange.
+//  * Acquire store doesn't exist in the C11 memory model, it is instead
+//    implemented as a relaxed store followed by a sequentially consistent
+//    fence.
+//  * Release load doesn't exist in the C11 memory model, it is instead
+//    implemented as sequentially consistent fence followed by a relaxed load.
+//  * Atomic increment is expected to return the post-incremented value, whereas
+//    C11 fetch add returns the previous value. The implementation therefore
+//    needs to increment twice (which the compiler should be able to detect and
+//    optimize).
+
+#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
+#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
+
+#include <atomic>
+
+namespace base {
+namespace subtle {
+
+// This implementation is transitional and maintains the original API for
+// atomicops.h. This requires casting memory locations to the atomic types, and
+// assumes that the API and the C++11 implementation are layout-compatible,
+// which isn't true for all implementations or hardware platforms. The static
+// assertion should detect this issue, were it to fire then this header
+// shouldn't be used.
+//
+// TODO(jfb) If this header manages to stay committed then the API should be
+//           modified, and all call sites updated.
+typedef volatile std::atomic<Atomic32>* AtomicLocation32;
+static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
+              "incompatible 32-bit atomic layout");
+
+inline void MemoryBarrier() {
+#if defined(__GLIBCXX__)
+  // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
+  // not defined, leading to the linker complaining about undefined references.
+  __atomic_thread_fence(std::memory_order_seq_cst);
+#else
+  std::atomic_thread_fence(std::memory_order_seq_cst);
+#endif
+}
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_relaxed,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  return ((AtomicLocation32)ptr)
+      ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  return increment +
+         ((AtomicLocation32)ptr)
+             ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_acquire,
+                                std::memory_order_acquire);
+  return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  ((AtomicLocation32)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_release,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+#if defined(ARCH_CPU_64_BITS)
+
+typedef volatile std::atomic<Atomic64>* AtomicLocation64;
+static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
+              "incompatible 64-bit atomic layout");
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_relaxed,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  return ((AtomicLocation64)ptr)
+      ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  return increment +
+         ((AtomicLocation64)ptr)
+             ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_acquire,
+                                std::memory_order_acquire);
+  return old_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  ((AtomicLocation64)ptr)
+      ->compare_exchange_strong(old_value,
+                                new_value,
+                                std::memory_order_release,
+                                std::memory_order_relaxed);
+  return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+#endif  // defined(ARCH_CPU_64_BITS)
+}
+}  // namespace base::subtle
+
+#endif  // BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
deleted file mode 100644
--- a/security/sandbox/chromium/base/atomicops_internals_tsan.h
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is an internal atomic implementation for compiler-based
-// ThreadSanitizer. Use base/atomicops.h instead.
-
-#ifndef BASE_ATOMICOPS_INTERNALS_TSAN_H_
-#define BASE_ATOMICOPS_INTERNALS_TSAN_H_
-
-#include <sanitizer/tsan_interface_atomic.h>
-
-namespace base {
-namespace subtle {
-
-inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
-                                         Atomic32 old_value,
-                                         Atomic32 new_value) {
-  Atomic32 cmp = old_value;
-  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
-  return cmp;
-}
-
-inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
-                                         Atomic32 new_value) {
-  return __tsan_atomic32_exchange(ptr, new_value,
-      __tsan_memory_order_relaxed);
-}
-
-inline Atomic32 Acquire_AtomicExchange(volatile Atomic32* ptr,
-                                       Atomic32 new_value) {
-  return __tsan_atomic32_exchange(ptr, new_value,
-      __tsan_memory_order_acquire);
-}
-
-inline Atomic32 Release_AtomicExchange(volatile Atomic32* ptr,
-                                       Atomic32 new_value) {
-  return __tsan_atomic32_exchange(ptr, new_value,
-      __tsan_memory_order_release);
-}
-
-inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
-                                          Atomic32 increment) {
-  return increment + __tsan_atomic32_fetch_add(ptr, increment,
-      __tsan_memory_order_relaxed);
-}
-
-inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
-                                        Atomic32 increment) {
-  return increment + __tsan_atomic32_fetch_add(ptr, increment,
-      __tsan_memory_order_acq_rel);
-}
-
-inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 cmp = old_value;
-  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
-  return cmp;
-}
-
-inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
-                                       Atomic32 old_value,
-                                       Atomic32 new_value) {
-  Atomic32 cmp = old_value;
-  __tsan_atomic32_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_release, __tsan_memory_order_relaxed);
-  return cmp;
-}
-
-inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
-  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
-}
-
-inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
-  __tsan_atomic32_store(ptr, value, __tsan_memory_order_relaxed);
-  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
-}
-
-inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
-  __tsan_atomic32_store(ptr, value, __tsan_memory_order_release);
-}
-
-inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
-  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
-}
-
-inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
-  return __tsan_atomic32_load(ptr, __tsan_memory_order_acquire);
-}
-
-inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
-  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
-  return __tsan_atomic32_load(ptr, __tsan_memory_order_relaxed);
-}
-
-inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
-                                         Atomic64 old_value,
-                                         Atomic64 new_value) {
-  Atomic64 cmp = old_value;
-  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_relaxed, __tsan_memory_order_relaxed);
-  return cmp;
-}
-
-inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
-                                         Atomic64 new_value) {
-  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_relaxed);
-}
-
-inline Atomic64 Acquire_AtomicExchange(volatile Atomic64* ptr,
-                                       Atomic64 new_value) {
-  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_acquire);
-}
-
-inline Atomic64 Release_AtomicExchange(volatile Atomic64* ptr,
-                                       Atomic64 new_value) {
-  return __tsan_atomic64_exchange(ptr, new_value, __tsan_memory_order_release);
-}
-
-inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
-                                          Atomic64 increment) {
-  return increment + __tsan_atomic64_fetch_add(ptr, increment,
-      __tsan_memory_order_relaxed);
-}
-
-inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
-                                        Atomic64 increment) {
-  return increment + __tsan_atomic64_fetch_add(ptr, increment,
-      __tsan_memory_order_acq_rel);
-}
-
-inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
-  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
-}
-
-inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
-  __tsan_atomic64_store(ptr, value, __tsan_memory_order_relaxed);
-  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
-}
-
-inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
-  __tsan_atomic64_store(ptr, value, __tsan_memory_order_release);
-}
-
-inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
-  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
-}
-
-inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
-  return __tsan_atomic64_load(ptr, __tsan_memory_order_acquire);
-}
-
-inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
-  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
-  return __tsan_atomic64_load(ptr, __tsan_memory_order_relaxed);
-}
-
-inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 cmp = old_value;
-  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_acquire, __tsan_memory_order_acquire);
-  return cmp;
-}
-
-inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
-                                       Atomic64 old_value,
-                                       Atomic64 new_value) {
-  Atomic64 cmp = old_value;
-  __tsan_atomic64_compare_exchange_strong(ptr, &cmp, new_value,
-      __tsan_memory_order_release, __tsan_memory_order_relaxed);
-  return cmp;
-}
-
-inline void MemoryBarrier() {
-  __tsan_atomic_thread_fence(__tsan_memory_order_seq_cst);
-}
-
-}  // namespace base::subtle
-}  // namespace base
-
-#endif  // BASE_ATOMICOPS_INTERNALS_TSAN_H_
--- a/security/sandbox/chromium/base/atomicops_internals_x86_gcc.h
+++ b/security/sandbox/chromium/base/atomicops_internals_x86_gcc.h
@@ -2,30 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // This file is an internal atomic implementation, use base/atomicops.h instead.
 
 #ifndef BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
 #define BASE_ATOMICOPS_INTERNALS_X86_GCC_H_
 
-#include "base/base_export.h"
-
-// This struct is not part of the public API of this module; clients may not
-// use it.  (However, it's exported via BASE_EXPORT because clients implicitly
-// do use it at link time by inlining these functions.)
-// Features of this x86.  Values may not be correct before main() is run,
-// but are set conservatively.
-struct AtomicOps_x86CPUFeatureStruct {
-  bool has_amd_lock_mb_bug; // Processor has AMD memory-barrier bug; do lfence
-                            // after acquire compare-and-swap.
-};
-BASE_EXPORT extern struct AtomicOps_x86CPUFeatureStruct
-    AtomicOps_Internalx86CPUFeatures;
-
 #define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
 
 namespace base {
 namespace subtle {
 
 // 32-bit low-level operations on any platform.
 
 inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
--- a/security/sandbox/chromium/base/base_paths_win.h
+++ b/security/sandbox/chromium/base/base_paths_win.h
@@ -20,30 +20,27 @@ enum {
   DIR_PROGRAM_FILESX86,   // Usually c:\program files or c:\program files (x86)
 
   DIR_IE_INTERNET_CACHE,  // Temporary Internet Files directory.
   DIR_COMMON_START_MENU,  // Usually "C:\Documents and Settings\All Users\
                           // Start Menu\Programs"
   DIR_START_MENU,         // Usually "C:\Documents and Settings\<user>\
                           // Start Menu\Programs"
   DIR_APP_DATA,           // Application Data directory under the user profile.
-  DIR_LOCAL_APP_DATA_LOW, // Local AppData directory for low integrity level.
   DIR_LOCAL_APP_DATA,     // "Local Settings\Application Data" directory under
                           // the user profile.
   DIR_COMMON_APP_DATA,    // W2K, XP, W2K3: "C:\Documents and Settings\
                           // All Users\Application Data".
                           // Vista, W2K8 and above: "C:\ProgramData".
   DIR_APP_SHORTCUTS,      // Where tiles on the start screen are stored, only
                           // for Windows 8. Maps to "Local\AppData\Microsoft\
                           // Windows\Application Shortcuts\".
   DIR_COMMON_DESKTOP,     // Directory for the common desktop (visible
                           // on all user's Desktop).
   DIR_USER_QUICK_LAUNCH,  // Directory for the quick launch shortcuts.
-  DIR_DEFAULT_USER_QUICK_LAUNCH,  // Directory for the quick launch shortcuts
-                                  // of the Default user.
   DIR_TASKBAR_PINS,       // Directory for the shortcuts pinned to taskbar via
                           // base::win::TaskbarPinShortcutLink().
   DIR_WINDOWS_FONTS,      // Usually C:\Windows\Fonts.
 
   PATH_WIN_END
 };
 
 }  // namespace base
--- a/security/sandbox/chromium/base/base_switches.cc
+++ b/security/sandbox/chromium/base/base_switches.cc
@@ -45,16 +45,24 @@ const char kV[]                         
 const char kVModule[]                       = "vmodule";
 
 // Will wait for 60 seconds for a debugger to come to attach to the process.
 const char kWaitForDebugger[]               = "wait-for-debugger";
 
 // Sends a pretty-printed version of tracing info to the console.
 const char kTraceToConsole[]                = "trace-to-console";
 
+// Sends trace events from these categories to a file.
+// --trace-to-file on its own sends to default categories.
+const char kTraceToFile[]                   = "trace-to-file";
+
+// Specifies the file name for --trace-to-file. If unspecified, it will
+// go to a default file name.
+const char kTraceToFileName[]               = "trace-to-file-name";
+
 // Configure whether chrome://profiler will contain timing information. This
 // option is enabled by default. A value of "0" will disable profiler timing,
 // while all other values will enable it.
 const char kProfilerTiming[]                = "profiler-timing";
 // Value of the --profiler-timing flag that will disable timing information for
 // chrome://profiler.
 const char kProfilerTimingDisabledValue[]   = "0";
 
--- a/security/sandbox/chromium/base/base_switches.h
+++ b/security/sandbox/chromium/base/base_switches.h
@@ -15,16 +15,18 @@ extern const char kDisableBreakpad[];
 extern const char kEnableCrashReporter[];
 extern const char kFullMemoryCrashReport[];
 extern const char kLowEndDeviceMode[];
 extern const char kNoErrorDialogs[];
 extern const char kProfilerTiming[];
 extern const char kProfilerTimingDisabledValue[];
 extern const char kTestChildProcess[];
 extern const char kTraceToConsole[];
+extern const char kTraceToFile[];
+extern const char kTraceToFileName[];
 extern const char kV[];
 extern const char kVModule[];
 extern const char kWaitForDebugger[];
 
 #if defined(OS_POSIX)
 extern const char kEnableCrashReporterForTesting[];
 #endif
 
--- a/security/sandbox/chromium/base/basictypes.h
+++ b/security/sandbox/chromium/base/basictypes.h
@@ -17,34 +17,21 @@
 
 #include "base/macros.h"
 #include "base/port.h"  // Types that only need exist on certain systems.
 
 // DEPRECATED: Please use (u)int{8,16,32,64}_t instead (and include <stdint.h>).
 typedef int8_t int8;
 typedef uint8_t uint8;
 typedef int16_t int16;
+typedef uint16_t uint16;
 typedef int32_t int32;
-typedef uint16_t uint16;
 typedef uint32_t uint32;
-
-// TODO(vtl): Figure what's up with the 64-bit types. Can we just define them as
-// |int64_t|/|uint64_t|?
-// The NSPR system headers define 64-bit as |long| when possible, except on
-// Mac OS X.  In order to not have typedef mismatches, we do the same on LP64.
-//
-// On Mac OS X, |long long| is used for 64-bit types for compatibility with
-// <inttypes.h> format macros even in the LP64 model.
-#if defined(__LP64__) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
-typedef long int64;
-typedef unsigned long uint64;
-#else
-typedef long long int64;
-typedef unsigned long long uint64;
-#endif
+typedef int64_t int64;
+typedef uint64_t uint64;
 
 // DEPRECATED: Please use std::numeric_limits (from <limits>) instead.
 const uint8  kuint8max  =  0xFF;
 const uint16 kuint16max =  0xFFFF;
 const uint32 kuint32max =  0xFFFFFFFF;
 const uint64 kuint64max =  0xFFFFFFFFFFFFFFFFULL;
 const  int8  kint8min   = -0x7F - 1;
 const  int8  kint8max   =  0x7F;
--- a/security/sandbox/chromium/base/bind_helpers.h
+++ b/security/sandbox/chromium/base/bind_helpers.h
@@ -246,17 +246,17 @@ class SupportsAddRefAndRelease {
 
   template <typename C>
   static No& Check(Helper<&C::AddRef>*);
 
   template <typename >
   static Yes& Check(...);
 
  public:
-  static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes);
+  enum { value = sizeof(Check<Base>(0)) == sizeof(Yes) };
 };
 
 // Helpers to assert that arguments of a recounted type are bound with a
 // scoped_refptr.
 template <bool IsClasstype, typename T>
 struct UnsafeBindtoRefCountedArgHelper : false_type {
 };
 
@@ -281,17 +281,17 @@ class HasIsMethodTag {
 
   template <typename U>
   static Yes& Check(typename U::IsMethod*);
 
   template <typename U>
   static No& Check(...);
 
  public:
-  static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
+  enum { value = sizeof(Check<T>(0)) == sizeof(Yes) };
 };
 
 template <typename T>
 class UnretainedWrapper {
  public:
   explicit UnretainedWrapper(T* o) : ptr_(o) {}
   T* get() const { return ptr_; }
  private:
--- a/security/sandbox/chromium/base/bind_internal_win.h
+++ b/security/sandbox/chromium/base/bind_internal_win.h
@@ -1,13 +1,8 @@
-// This file was GENERATED by command:
-//     pump.py bind_internal_win.h.pump
-// DO NOT EDIT BY HAND!!!
-
-
 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 // Specializations of RunnableAdapter<> for Windows specific calling
 // conventions.  Please see base/bind_internal.h for more info.
 
 #ifndef BASE_BIND_INTERNAL_WIN_H_
@@ -19,350 +14,50 @@
 #if !defined(ARCH_CPU_X86_64)
 
 namespace base {
 namespace internal {
 
 template <typename Functor>
 class RunnableAdapter;
 
-// __stdcall Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R(__stdcall *)()> {
- public:
-  typedef R (RunType)();
-
-  explicit RunnableAdapter(R(__stdcall *function)())
-      : function_(function) {
-  }
-
-  R Run() {
-    return function_();
-  }
-
- private:
-  R (__stdcall *function_)();
-};
-
-// __fastcall Function: Arity 0.
-template <typename R>
-class RunnableAdapter<R(__fastcall *)()> {
+// __stdcall Function.
+template <typename R, typename... Args>
+class RunnableAdapter<R(__stdcall *)(Args...)> {
  public:
-  typedef R (RunType)();
-
-  explicit RunnableAdapter(R(__fastcall *function)())
-      : function_(function) {
-  }
-
-  R Run() {
-    return function_();
-  }
-
- private:
-  R (__fastcall *function_)();
-};
-
-// __stdcall Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R(__stdcall *)(A1)> {
- public:
-  typedef R (RunType)(A1);
-
-  explicit RunnableAdapter(R(__stdcall *function)(A1))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(a1);
-  }
-
- private:
-  R (__stdcall *function_)(A1);
-};
-
-// __fastcall Function: Arity 1.
-template <typename R, typename A1>
-class RunnableAdapter<R(__fastcall *)(A1)> {
- public:
-  typedef R (RunType)(A1);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1) {
-    return function_(a1);
-  }
-
- private:
-  R (__fastcall *function_)(A1);
-};
-
-// __stdcall Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R(__stdcall *)(A1, A2)> {
- public:
-  typedef R (RunType)(A1, A2);
+  typedef R (RunType)(Args...);
 
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(a1, a2);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2);
-};
-
-// __fastcall Function: Arity 2.
-template <typename R, typename A1, typename A2>
-class RunnableAdapter<R(__fastcall *)(A1, A2)> {
- public:
-  typedef R (RunType)(A1, A2);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2) {
-    return function_(a1, a2);
-  }
-
- private:
-  R (__fastcall *function_)(A1, A2);
-};
-
-// __stdcall Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(__stdcall *)(A1, A2, A3)> {
- public:
-  typedef R (RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(a1, a2, a3);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2, A3);
-};
-
-// __fastcall Function: Arity 3.
-template <typename R, typename A1, typename A2, typename A3>
-class RunnableAdapter<R(__fastcall *)(A1, A2, A3)> {
- public:
-  typedef R (RunType)(A1, A2, A3);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3) {
-    return function_(a1, a2, a3);
-  }
-
- private:
-  R (__fastcall *function_)(A1, A2, A3);
-};
-
-// __stdcall Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4))
+  explicit RunnableAdapter(R(__stdcall *function)(Args...))
       : function_(function) {
   }
 
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(a1, a2, a3, a4);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2, A3, A4);
-};
-
-// __fastcall Function: Arity 4.
-template <typename R, typename A1, typename A2, typename A3, typename A4>
-class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4) {
-    return function_(a1, a2, a3, a4);
-  }
-
- private:
-  R (__fastcall *function_)(A1, A2, A3, A4);
-};
-
-// __stdcall Function: Arity 5.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(a1, a2, a3, a4, a5);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2, A3, A4, A5);
-};
-
-// __fastcall Function: Arity 5.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5>
-class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5) {
-    return function_(a1, a2, a3, a4, a5);
+  R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
+    return function_(args...);
   }
 
  private:
-  R (__fastcall *function_)(A1, A2, A3, A4, A5);
+  R (__stdcall *function_)(Args...);
 };
 
-// __stdcall Function: Arity 6.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6)> {
+// __fastcall Function.
+template <typename R, typename... Args>
+class RunnableAdapter<R(__fastcall *)(Args...)> {
  public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6);
+  typedef R (RunType)(Args...);
 
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6))
+  explicit RunnableAdapter(R(__fastcall *function)(Args...))
       : function_(function) {
   }
 
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(a1, a2, a3, a4, a5, a6);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// __fastcall Function: Arity 6.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6>
-class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6) {
-    return function_(a1, a2, a3, a4, a5, a6);
+  R Run(typename CallbackParamTraits<Args>::ForwardType... args) {
+    return function_(args...);
   }
 
  private:
-  R (__fastcall *function_)(A1, A2, A3, A4, A5, A6);
-};
-
-// __stdcall Function: Arity 7.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-class RunnableAdapter<R(__stdcall *)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R(__stdcall *function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6,
-      typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(a1, a2, a3, a4, a5, a6, a7);
-  }
-
- private:
-  R (__stdcall *function_)(A1, A2, A3, A4, A5, A6, A7);
-};
-
-// __fastcall Function: Arity 7.
-template <typename R, typename A1, typename A2, typename A3, typename A4,
-    typename A5, typename A6, typename A7>
-class RunnableAdapter<R(__fastcall *)(A1, A2, A3, A4, A5, A6, A7)> {
- public:
-  typedef R (RunType)(A1, A2, A3, A4, A5, A6, A7);
-
-  explicit RunnableAdapter(R(__fastcall *function)(A1, A2, A3, A4, A5, A6, A7))
-      : function_(function) {
-  }
-
-  R Run(typename CallbackParamTraits<A1>::ForwardType a1,
-      typename CallbackParamTraits<A2>::ForwardType a2,
-      typename CallbackParamTraits<A3>::ForwardType a3,
-      typename CallbackParamTraits<A4>::ForwardType a4,
-      typename CallbackParamTraits<A5>::ForwardType a5,
-      typename CallbackParamTraits<A6>::ForwardType a6,
-      typename CallbackParamTraits<A7>::ForwardType a7) {
-    return function_(a1, a2, a3, a4, a5, a6, a7);
-  }
-
- private:
-  R (__fastcall *function_)(A1, A2, A3, A4, A5, A6, A7);
+  R (__fastcall *function_)(Args...);
 };
 
 }  // namespace internal
 }  // namespace base
 
 #endif  // !defined(ARCH_CPU_X86_64)
 
 #endif  // BASE_BIND_INTERNAL_WIN_H_
--- a/security/sandbox/chromium/base/callback_internal.cc
+++ b/security/sandbox/chromium/base/callback_internal.cc
@@ -4,20 +4,16 @@
 
 #include "base/callback_internal.h"
 
 #include "base/logging.h"
 
 namespace base {
 namespace internal {
 
-bool CallbackBase::is_null() const {
-  return bind_state_.get() == NULL;
-}
-
 void CallbackBase::Reset() {
   polymorphic_invoke_ = NULL;
   // NULL the bind_state_ last, since it may be holding the last ref to whatever
   // object owns us, and we may be deleted after that.
   bind_state_ = NULL;
 }
 
 bool CallbackBase::Equals(const CallbackBase& other) const {
--- a/security/sandbox/chromium/base/callback_internal.h
+++ b/security/sandbox/chromium/base/callback_internal.h
@@ -32,17 +32,17 @@ class BindStateBase : public RefCountedT
   virtual ~BindStateBase() {}
 };
 
 // Holds the Callback methods that don't require specialization to reduce
 // template bloat.
 class BASE_EXPORT CallbackBase {
  public:
   // Returns true if Callback is null (doesn't refer to anything).
-  bool is_null() const;
+  bool is_null() const { return bind_state_.get() == NULL; }
 
   // Returns the Callback into an uninitialized state.
   void Reset();
 
  protected:
   // In C++, it is safe to cast function pointers to function pointers of
   // another type. It is not okay to use void*. We create a InvokeFuncStorage
   // that that can store our function pointer, and then cast it back to
@@ -72,17 +72,17 @@ class BASE_EXPORT CallbackBase {
 // destructive way.
 template <typename T> struct IsMoveOnlyType {
   template <typename U>
   static YesType Test(const typename U::MoveOnlyTypeForCPP03*);
 
   template <typename U>
   static NoType Test(...);
 
-  static const bool value = sizeof(Test<T>(0)) == sizeof(YesType) &&
+  static const bool value = sizeof((Test<T>(0))) == sizeof(YesType) &&
                             !is_const<T>::value;
 };
 
 // This is a typetraits object that's used to take an argument type, and
 // extract a suitable type for storing and forwarding arguments.
 //
 // In particular, it strips off references, and converts arrays to
 // pointers for storage; and it avoids accidentally trying to create a
--- a/security/sandbox/chromium/base/compiler_specific.h
+++ b/security/sandbox/chromium/base/compiler_specific.h
@@ -89,21 +89,27 @@
 #else
 #define STATIC_CONST_MEMBER_DEFINITION
 #endif
 
 // Annotate a variable indicating it's ok if the variable is not used.
 // (Typically used to silence a compiler warning when the assignment
 // is important for some other reason.)
 // Use like:
-//   int x ALLOW_UNUSED = ...;
+//   int x = ...;
+//   ALLOW_UNUSED_LOCAL(x);
+#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0
+
+// Annotate a typedef or function indicating it's ok if it's not used.
+// Use like:
+//   typedef Foo Bar ALLOW_UNUSED_TYPE;
 #if defined(COMPILER_GCC)
-#define ALLOW_UNUSED __attribute__((unused))
+#define ALLOW_UNUSED_TYPE __attribute__((unused))
 #else
-#define ALLOW_UNUSED
+#define ALLOW_UNUSED_TYPE
 #endif
 
 // Annotate a function indicating it should not be inlined.
 // Use like:
 //   NOINLINE void DoStuff() { ... }
 #if defined(COMPILER_GCC)
 #define NOINLINE __attribute__((noinline))
 #elif defined(COMPILER_MSVC)
@@ -128,50 +134,16 @@
 // Use like:
 //   ALIGNOF(int32)  // this would be 4
 #if defined(COMPILER_MSVC)
 #define ALIGNOF(type) (sizeof(type) - sizeof(type) + __alignof(type))
 #elif defined(COMPILER_GCC)
 #define ALIGNOF(type) __alignof__(type)
 #endif
 
-// Annotate a virtual method indicating it must be overriding a virtual
-// method in the parent class.
-// Use like:
-//   virtual void foo() OVERRIDE;
-#if defined(COMPILER_MSVC)
-#define OVERRIDE override
-#elif defined(__clang__)
-#define OVERRIDE override
-#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \
-      (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
-// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
-#define OVERRIDE override
-#else
-#define OVERRIDE
-#endif
-
-// Annotate a virtual method indicating that subclasses must not override it,
-// or annotate a class to indicate that it cannot be subclassed.
-// Use like:
-//   virtual void foo() FINAL;
-//   class B FINAL : public A {};
-#if defined(__clang__)
-#define FINAL final
-#elif defined(COMPILER_MSVC)
-// TODO(jered): Change this to "final" when chromium no longer uses MSVC 2010.
-#define FINAL sealed
-#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \
-      (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700
-// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled.
-#define FINAL final
-#else
-#define FINAL
-#endif
-
 // Annotate a function indicating the caller must examine the return value.
 // Use like:
 //   int foo() WARN_UNUSED_RESULT;
 // To explicitly ignore a result, see |ignore_result()| in <base/basictypes.h>.
 #if defined(COMPILER_GCC)
 #define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
 #else
 #define WARN_UNUSED_RESULT
--- a/security/sandbox/chromium/base/containers/hash_tables.h
+++ b/security/sandbox/chromium/base/containers/hash_tables.h
@@ -23,57 +23,72 @@
 
 #include <utility>
 
 #include "base/basictypes.h"
 #include "base/strings/string16.h"
 #include "build/build_config.h"
 
 #if defined(COMPILER_MSVC)
+#include <unordered_map>
+#include <unordered_set>
 
-#pragma push_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
-#define _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
-#include <hash_map>
-#include <hash_set>
-#pragma pop_macro("_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS")
-
-#define BASE_HASH_NAMESPACE stdext
+#define BASE_HASH_NAMESPACE std
 
 #elif defined(COMPILER_GCC)
-#if defined(OS_ANDROID)
-#define BASE_HASH_NAMESPACE std
-#else
-#define BASE_HASH_NAMESPACE __gnu_cxx
-#endif
+
+#define BASE_HASH_NAMESPACE base_hash
 
 // This is a hack to disable the gcc 4.4 warning about hash_map and hash_set
 // being deprecated.  We can get rid of this when we upgrade to VS2008 and we
 // can use <tr1/unordered_map> and <tr1/unordered_set>.
 #ifdef __DEPRECATED
 #define CHROME_OLD__DEPRECATED __DEPRECATED
 #undef __DEPRECATED
 #endif
 
 #if defined(OS_ANDROID)
 #include <hash_map>
 #include <hash_set>
+#define BASE_HASH_IMPL_NAMESPACE std
 #else
 #include <ext/hash_map>
 #include <ext/hash_set>
+#define BASE_HASH_IMPL_NAMESPACE __gnu_cxx
 #endif
 
 #include <string>
 
 #ifdef CHROME_OLD__DEPRECATED
 #define __DEPRECATED CHROME_OLD__DEPRECATED
 #undef CHROME_OLD__DEPRECATED
 #endif
 
 namespace BASE_HASH_NAMESPACE {
 
+// The pre-standard hash behaves like C++11's std::hash, except around pointers.
+// const char* is specialized to hash the C string and hash functions for
+// general T* are missing. Define a BASE_HASH_NAMESPACE::hash which aligns with
+// the C++11 behavior.
+
+template<typename T>
+struct hash {
+  std::size_t operator()(const T& value) const {
+    return BASE_HASH_IMPL_NAMESPACE::hash<T>()(value);
+  }
+};
+
+template<typename T>
+struct hash<T*> {
+  std::size_t operator()(T* value) const {
+    return BASE_HASH_IMPL_NAMESPACE::hash<uintptr_t>()(
+        reinterpret_cast<uintptr_t>(value));
+  }
+};
+
 #if !defined(OS_ANDROID)
 // The GNU C++ library provides identity hash functions for many integral types,
 // but not for |long long|.  This hash function will truncate if |size_t| is
 // narrower than |long long|.  This is probably good enough for what we will
 // use it for.
 
 #define DEFINE_TRIVIAL_HASH(integral_type) \
     template<> \
@@ -113,20 +128,77 @@ DEFINE_STRING_HASH(base::string16);
 
 }  // namespace BASE_HASH_NAMESPACE
 
 #else  // COMPILER
 #error define BASE_HASH_NAMESPACE for your compiler
 #endif  // COMPILER
 
 namespace base {
-using BASE_HASH_NAMESPACE::hash_map;
-using BASE_HASH_NAMESPACE::hash_multimap;
-using BASE_HASH_NAMESPACE::hash_multiset;
-using BASE_HASH_NAMESPACE::hash_set;
+
+// On MSVC, use the C++11 containers.
+#if defined(COMPILER_MSVC)
+
+template<class Key, class T,
+         class Hash = std::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<std::pair<const Key, T>>>
+using hash_map = std::unordered_map<Key, T, Hash, Pred, Alloc>;
+
+template<class Key, class T,
+         class Hash = std::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<std::pair<const Key, T>>>
+using hash_multimap = std::unordered_multimap<Key, T, Hash, Pred, Alloc>;
+
+template<class Key,
+         class Hash = std::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<Key>>
+using hash_multiset = std::unordered_multiset<Key, Hash, Pred, Alloc>;
+
+template<class Key,
+         class Hash = std::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<Key>>
+using hash_set = std::unordered_set<Key, Hash, Pred, Alloc>;
+
+#else  // !COMPILER_MSVC
+
+// Otherwise, use the pre-standard ones, but override the default hash to match
+// C++11.
+template<class Key, class T,
+         class Hash = BASE_HASH_NAMESPACE::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<std::pair<const Key, T>>>
+using hash_map = BASE_HASH_IMPL_NAMESPACE::hash_map<Key, T, Hash, Pred, Alloc>;
+
+template<class Key, class T,
+         class Hash = BASE_HASH_NAMESPACE::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<std::pair<const Key, T>>>
+using hash_multimap =
+    BASE_HASH_IMPL_NAMESPACE::hash_multimap<Key, T, Hash, Pred, Alloc>;
+
+template<class Key,
+         class Hash = BASE_HASH_NAMESPACE::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<Key>>
+using hash_multiset =
+    BASE_HASH_IMPL_NAMESPACE::hash_multiset<Key, Hash, Pred, Alloc>;
+
+template<class Key,
+         class Hash = BASE_HASH_NAMESPACE::hash<Key>,
+         class Pred = std::equal_to<Key>,
+         class Alloc = std::allocator<Key>>
+using hash_set = BASE_HASH_IMPL_NAMESPACE::hash_set<Key, Hash, Pred, Alloc>;
+
+#undef BASE_HASH_IMPL_NAMESPACE
+
+#endif  // COMPILER_MSVC
 
 // Implement hashing for pairs of at-most 32 bit integer values.
 // When size_t is 32 bits, we turn the 64-bit hash code into 32 bits by using
 // multiply-add hashing. This algorithm, as described in
 // Theorem 4.3.3 of the thesis "Über die Komplexität der Multiplikation in
 // eingeschränkten Branchingprogrammmodellen" by Woelfel, is:
 //
 //   h32(x32, y32) = (h64(x32, y32) * rand_odd64 + rand16 * 2^16) % 2^64 / 2^32
@@ -236,33 +308,21 @@ DEFINE_64BIT_PAIR_HASH(uint64, uint64);
 #undef DEFINE_64BIT_PAIR_HASH
 }  // namespace base
 
 namespace BASE_HASH_NAMESPACE {
 
 // Implement methods for hashing a pair of integers, so they can be used as
 // keys in STL containers.
 
-#if defined(COMPILER_MSVC)
-
-template<typename Type1, typename Type2>
-inline std::size_t hash_value(const std::pair<Type1, Type2>& value) {
-  return base::HashPair(value.first, value.second);
-}
-
-#elif defined(COMPILER_GCC)
 template<typename Type1, typename Type2>
 struct hash<std::pair<Type1, Type2> > {
   std::size_t operator()(std::pair<Type1, Type2> value) const {
     return base::HashPair(value.first, value.second);
   }
 };
 
-#else
-#error define hash<std::pair<Type1, Type2> > for your compiler
-#endif  // COMPILER
-
 }
 
 #undef DEFINE_PAIR_HASH_FUNCTION_START
 #undef DEFINE_PAIR_HASH_FUNCTION_END
 
 #endif  // BASE_CONTAINERS_HASH_TABLES_H_
--- a/security/sandbox/chromium/base/cpu.cc
+++ b/security/sandbox/chromium/base/cpu.cc
@@ -1,23 +1,25 @@
 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #include "base/cpu.h"
 
+#include <stdlib.h>
 #include <string.h>
 
 #include <algorithm>
 
 #include "base/basictypes.h"
+#include "base/strings/string_piece.h"
 #include "build/build_config.h"
 
 #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
-#include "base/file_util.h"
+#include "base/files/file_util.h"
 #include "base/lazy_instance.h"
 #endif
 
 #if defined(ARCH_CPU_X86_FAMILY)
 #if defined(_MSC_VER)
 #include <intrin.h>
 #include <immintrin.h>  // For _xgetbv()
 #endif
@@ -39,33 +41,24 @@ CPU::CPU()
     has_sse3_(false),
     has_ssse3_(false),
     has_sse41_(false),
     has_sse42_(false),
     has_avx_(false),
     has_avx_hardware_(false),
     has_aesni_(false),
     has_non_stop_time_stamp_counter_(false),
+    has_broken_neon_(false),
     cpu_vendor_("unknown") {
   Initialize();
 }
 
 namespace {
 
 #if defined(ARCH_CPU_X86_FAMILY)
-#if defined(_MSC_VER) && (_MSC_FULL_VER < 160040219)
-// Prior to VS2010 SP1, _xgetbv is not defined in immintrin.h, so we need to
-// define our own version using the assembly operation.
-// By using __fastcall we ensure that xcr is already in register ecx for xgetbv
-// and xgetbv populates the correct registers (eax edx) for our return value.
-uint64_t __fastcall _xgetbv(uint32_t xcr) {
-  __asm xgetbv;
-}
-#endif
-
 #ifndef _MSC_VER
 
 #if defined(__pic__) && defined(__i386__)
 
 void __cpuid(int cpu_info[4], int info_type) {
   __asm__ volatile (
     "mov %%ebx, %%edi\n"
     "cpuid\n"
@@ -95,62 +88,109 @@ uint64 _xgetbv(uint32 xcr) {
   __asm__ volatile ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (xcr));
   return (static_cast<uint64>(edx) << 32) | eax;
 }
 
 #endif  // !_MSC_VER
 #endif  // ARCH_CPU_X86_FAMILY
 
 #if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
+class LazyCpuInfoValue {
+ public:
+  LazyCpuInfoValue() : has_broken_neon_(false) {
+    // This function finds the value from /proc/cpuinfo under the key "model
+    // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7
+    // and later for arm64) and is shown once per CPU. "Processor" is used in
+    // earler versions and is shown only once at the top of /proc/cpuinfo
+    // regardless of the number CPUs.
+    const char kModelNamePrefix[] = "model name\t: ";
+    const char kProcessorPrefix[] = "Processor\t: ";
 
-// Returns the string found in /proc/cpuinfo unde