Merge m-c to fx-team a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 19 Nov 2014 19:08:27 -0800
changeset 240872 f04a2780f2530802a8d87309829aa5f7ce6ea8f7
parent 240871 c276e2d77d27f551cd85c2aa14103abcf13c24d0 (current diff)
parent 240855 d1adecc7adad0beee45eeea0d7f774adbfe03dee (diff)
child 240873 94e9fc62355f9698506678269d25a83fdf5f757e
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team a=merge
build/pgo/js-input/3d-cube.html
build/pgo/js-input/3d-morph.html
build/pgo/js-input/3d-raytrace.html
build/pgo/js-input/access-binary-trees.html
build/pgo/js-input/access-fannkuch.html
build/pgo/js-input/access-nbody.html
build/pgo/js-input/access-nsieve.html
build/pgo/js-input/bitops-3bit-bits-in-byte.html
build/pgo/js-input/bitops-bits-in-byte.html
build/pgo/js-input/bitops-bitwise-and.html
build/pgo/js-input/bitops-nsieve-bits.html
build/pgo/js-input/controlflow-recursive.html
build/pgo/js-input/crypto-aes.html
build/pgo/js-input/crypto-md5.html
build/pgo/js-input/crypto-sha1.html
build/pgo/js-input/date-format-tofte.html
build/pgo/js-input/date-format-xparb.html
build/pgo/js-input/math-cordic.html
build/pgo/js-input/math-partial-sums.html
build/pgo/js-input/math-spectral-norm.html
build/pgo/js-input/regexp-dna.html
build/pgo/js-input/string-base64.html
build/pgo/js-input/string-fasta.html
build/pgo/js-input/string-tagcloud.html
build/pgo/js-input/string-unpack-code.html
build/pgo/js-input/string-validate-input.html
--- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <!-- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
--- 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="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d5d3f93914558b6f168447b805cd799c8233e300"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="a47dd04f8f66e42fd331711140f2c3e2fed0767d"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <!-- 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="3ab0d9c70f0b2e1ededc679112c392303f037361">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <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="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
--- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <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": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "f155f8ab67a65c066730976e0b7cef0d39579a24", 
+    "revision": "db25ffb7b2e825b20123fc11ccc8a5ebe597f378", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- 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="0e94c080bee081a50aa2097527b0b40852f9143f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <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/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="df362ace56338da8173d30d3e09e08c42c1accfa">
     <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="e64428c5b2dce5db90b75a5055077a04f4bd4819"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="8e09627d75acd4abced0ab81983b5b5de6d15881"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="45c54a55e31758f7e54e5eafe0d01d387f35897a"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="b6f8267794b8c7f2a33236d46a857a84388b8485"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js
+++ b/browser/base/content/test/plugins/browser_globalplugin_crashinfobar.js
@@ -1,19 +1,21 @@
 /* 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/. */
 
 let gTestBrowser = null;
 
-let propBagProperties = {
+let crashedEventProperties = {
   pluginName: "GlobalTestPlugin",
   pluginDumpID: "1234",
   browserDumpID: "5678",
-  submittedCrashReport: false
+  submittedCrashReport: false,
+  bubbles: true,
+  cancelable: true
 }
 
 // Test that plugin crash submissions still work properly after
 // click-to-play activation.
 
 function test() {
   waitForExplicitFinish();
   let tab = gBrowser.loadOneTab("about:blank", { inBackground: false });
@@ -29,39 +31,30 @@ function test() {
 }
 
 function onPageLoad() {
   executeSoon(generateCrashEvent);
 }
 
 function generateCrashEvent() {
   let window = gTestBrowser.contentWindow;
-  let propBag = Cc["@mozilla.org/hash-property-bag;1"]
-                  .createInstance(Ci.nsIWritablePropertyBag);
-  for (let [name, val] of Iterator(propBagProperties)) {
-    propBag.setProperty(name, val);
-  }
+  let crashedEvent = new window.PluginCrashedEvent("PluginCrashed", crashedEventProperties);
 
-  let event = window.document.createEvent("CustomEvent");
-  event.initCustomEvent("PluginCrashed", true, true, propBag);
-  window.dispatchEvent(event);
+  window.dispatchEvent(crashedEvent);
 }
 
 
 function onCrash(event) {
   let target = event.target;
   is (target, gTestBrowser.contentWindow, "Event target is the window.");
 
-  let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
-  for (let [name, val] of Iterator(propBagProperties)) {
-    let type = typeof val;
-    let propVal = type == "string"
-                  ? propBag.getPropertyAsAString(name)
-                  : propBag.getPropertyAsBool(name);
-    is (propVal, val, "Correct property in detail propBag: " + name + ".");
+  for (let [name, val] of Iterator(crashedEventProperties)) {
+    let propVal = event[name];
+
+    is (propVal, val, "Correct property: " + name + ".");
   }
 
   waitForNotificationBar("plugin-crashed", gTestBrowser, (notification) => {
     let notificationBox = gBrowser.getNotificationBox(gTestBrowser);
     ok(notification, "Infobar was shown.");
     is(notification.priority, notificationBox.PRIORITY_WARNING_MEDIUM, "Correct priority.");
     is(notification.getAttribute("label"), "The GlobalTestPlugin plugin has crashed.", "Correct message.");
     finish();
--- a/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js
+++ b/browser/base/content/test/plugins/browser_pluginCrashCommentAndURL.js
@@ -52,20 +52,18 @@ function frameScript() {
       let style = content.getComputedStyle(getUI("pleaseSubmit"));
       if (style.display != message.data.pleaseSubmitStyle) {
         fail("Submission UI visibility is not correct. Expected " +
              `${message.data.pleaseSubmitStyle} and got ${style.display}`);
         return;
       }
 
       if (message.data.sendCrashMessage) {
-        let propBag = event.detail.QueryInterface(Ci.nsIPropertyBag2);
-        let crashID = propBag.getPropertyAsAString("pluginDumpID");
         sendAsyncMessage("test:crash-plugin:crashed", {
-          crashID: crashID,
+          crashID: event.pluginDumpID,
         });
         return;
       }
 
       if (message.data.submitComment) {
         getUI("submitComment").value = message.data.submitComment;
       }
       getUI("submitURLOptIn").checked = message.data.urlOptIn;
--- a/browser/components/customizableui/test/browser.ini
+++ b/browser/components/customizableui/test/browser.ini
@@ -125,16 +125,17 @@ skip-if = os == "linux"
 
 [browser_984455_bookmarks_items_reparenting.js]
 skip-if = os == "linux"
 
 [browser_985815_propagate_setToolbarVisibility.js]
 skip-if = e10s # bug 1090635
 [browser_981305_separator_insertion.js]
 [browser_988072_sidebar_events.js]
+skip-if = e10s # bug 1101482 - fails in --run-by-dir
 [browser_989338_saved_placements_not_resaved.js]
 [browser_989751_subviewbutton_class.js]
 [browser_987177_destroyWidget_xul.js]
 [browser_987177_xul_wrapper_updating.js]
 [browser_987185_syncButton.js]
 [browser_987492_window_api.js]
 [browser_987640_charEncoding.js]
 skip-if = e10s # Bug 1088710
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -403,29 +403,29 @@ skip-if = e10s # Bug 1093535
 skip-if = e10s
 [browser_dbg_sources-labels.js]
 skip-if = e10s
 [browser_dbg_sources-sorting.js]
 skip-if = e10s
 [browser_dbg_split-console-paused-reload.js]
 skip-if = e10s
 [browser_dbg_stack-01.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_stack-02.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_stack-03.js]
-skip-if = e10s
+skip-if = e10s # TODO
 [browser_dbg_stack-04.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_stack-05.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_stack-06.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_stack-07.js]
-skip-if = e10s
+skip-if = e10s && debug
 [browser_dbg_step-out.js]
 skip-if = e10s
 [browser_dbg_tabactor-01.js]
 skip-if = e10s
 [browser_dbg_tabactor-02.js]
 skip-if = e10s
 [browser_dbg_terminate-on-tab-close.js]
 skip-if = e10s
--- a/browser/devtools/debugger/test/browser_dbg_stack-01.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-01.js
@@ -2,44 +2,42 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Test that stackframes are added when debugger is paused.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gFrames, gClassicFrames;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
 
     waitForSourceAndCaretAndScopes(gPanel, ".html", 14).then(performTest);
-    gDebuggee.simpleCall();
+    callInTab(gTab, "simpleCall");
   });
 }
 
 function performTest() {
   is(gDebugger.gThreadClient.state, "paused",
     "Should only be getting stack frames while paused.");
   is(gFrames.itemCount, 1,
     "Should have only one frame.");
   is(gClassicFrames.itemCount, 1,
     "Should also have only one frame in the mirrored view.");
 
   resumeDebuggerThenCloseAndFinish(gPanel);
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gClassicFrames = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_stack-02.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-02.js
@@ -2,30 +2,29 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Test that stackframes are added when debugger is paused in eval calls.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gFrames, gClassicFrames;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
 
     waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest);
-    gDebuggee.evalCall();
+    callInTab(gTab, "evalCall");
   });
 }
 
 function performTest() {
   is(gDebugger.gThreadClient.state, "paused",
     "Should only be getting stack frames while paused.");
   is(gFrames.itemCount, 2,
     "Should have two frames.");
@@ -98,14 +97,13 @@ function performTest() {
   is(gClassicFrames.selectedIndex, 1,
     "Oldest frame in the mirrored view should be selected.");
 
   resumeDebuggerThenCloseAndFinish(gPanel);
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gClassicFrames = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_stack-04.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-04.js
@@ -2,30 +2,29 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Test that stackframes are cleared after resume.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_recursion-stack.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gFrames, gClassicFrames;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
 
     waitForSourceAndCaretAndScopes(gPanel, ".html", 1).then(performTest);
-    gDebuggee.evalCall();
+    callInTab(gTab, "evalCall");
   });
 }
 
 function performTest() {
   is(gDebugger.gThreadClient.state, "paused",
     "Should only be getting stack frames while paused.");
   is(gFrames.itemCount, 2,
     "Should have two frames.");
@@ -41,14 +40,13 @@ function performTest() {
     closeDebuggerAndFinish(gPanel);
   }, true);
 
   gDebugger.gThreadClient.resume();
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gFrames = null;
   gClassicFrames = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_stack-05.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-05.js
@@ -3,23 +3,22 @@
 
 /**
  * Test that switching between stack frames properly sets the current debugger
  * location in the source editor.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources, gFrames, gClassicFrames;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1)
@@ -27,17 +26,17 @@ function test() {
       .then(testNewestTwoFrames)
       .then(testOldestTwoFrames)
       .then(testAfterResume)
       .then(() => closeDebuggerAndFinish(gPanel))
       .then(null, aError => {
         ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
       });
 
-    gDebuggee.firstCall();
+    callInTab(gTab, "firstCall");
   });
 }
 
 function initialChecks() {
   is(gDebugger.gThreadClient.state, "paused",
     "Should only be getting stack frames while paused.");
   is(gFrames.itemCount, 4,
     "Should have four frames.");
@@ -153,17 +152,16 @@ function testAfterResume() {
 
   gDebugger.gThreadClient.resume();
 
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
   gFrames = null;
   gClassicFrames = null;
 });
 
--- a/browser/devtools/debugger/test/browser_dbg_stack-06.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-06.js
@@ -3,32 +3,31 @@
 
 /**
  * Make sure that selecting a stack frame loads the right source in the editor
  * pane and highlights the proper line.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources, gFrames, gClassicFrames;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest);
-    gDebuggee.firstCall();
+    callInTab(gTab, "firstCall");
   });
 }
 
 function performTest() {
   is(gFrames.selectedIndex, 3,
     "Newest frame should be selected by default.");
   is(gClassicFrames.selectedIndex, 0,
     "Newest frame should also be selected in the mirrored view.");
@@ -73,16 +72,15 @@ function performTest() {
 
   EventUtils.sendMouseEvent({ type: "mousedown" },
     gDebugger.document.querySelector("#stackframe-3"),
     gDebugger);
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
   gFrames = null;
   gClassicFrames = null;
 });
--- a/browser/devtools/debugger/test/browser_dbg_stack-07.js
+++ b/browser/devtools/debugger/test/browser_dbg_stack-07.js
@@ -4,33 +4,32 @@
 /**
  * Make sure that after selecting a different stack frame, resuming reselects
  * the topmost stackframe, loads the right source in the editor pane and
  * highlights the proper line.
  */
 
 const TAB_URL = EXAMPLE_URL + "doc_script-switching-01.html";
 
-let gTab, gDebuggee, gPanel, gDebugger;
+let gTab, gPanel, gDebugger;
 let gEditor, gSources, gFrames, gClassicFrames, gToolbar;
 
 function test() {
-  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+  initDebugger(TAB_URL).then(([aTab,, aPanel]) => {
     gTab = aTab;
-    gDebuggee = aDebuggee;
     gPanel = aPanel;
     gDebugger = gPanel.panelWin;
     gEditor = gDebugger.DebuggerView.editor;
     gSources = gDebugger.DebuggerView.Sources;
     gFrames = gDebugger.DebuggerView.StackFrames;
     gClassicFrames = gDebugger.DebuggerView.StackFramesClassicList;
     gToolbar = gDebugger.DebuggerView.Toolbar;
 
     waitForSourceAndCaretAndScopes(gPanel, "-02.js", 1).then(performTest);
-    gDebuggee.firstCall();
+    callInTab(gTab, "firstCall");
   });
 }
 
 function performTest() {
   return Task.spawn(function() {
     yield selectBottomFrame();
     testBottomFrame(0);
 
@@ -93,17 +92,16 @@ function performTest() {
       "The second source is displayed.");
     is(gEditor.getText().search(/debugger/), 172,
       "The first source is not displayed.");
   }
 }
 
 registerCleanupFunction(function() {
   gTab = null;
-  gDebuggee = null;
   gPanel = null;
   gDebugger = null;
   gEditor = null;
   gSources = null;
   gFrames = null;
   gClassicFrames = null;
   gToolbar = null;
 });
--- a/browser/modules/PluginContent.jsm
+++ b/browser/modules/PluginContent.jsm
@@ -844,40 +844,26 @@ PluginContent.prototype = {
 
   hideNotificationBar: function (name) {
     this.global.sendAsyncMessage("PluginContent:HideNotificationBar", { name: name });
   },
 
   // Crashed-plugin event listener. Called for every instance of a
   // plugin in content.
   pluginInstanceCrashed: function (target, aEvent) {
-    // Ensure the plugin and event are of the right type.
-    if (!(aEvent instanceof Ci.nsIDOMCustomEvent))
+    if (!(aEvent instanceof this.content.PluginCrashedEvent))
       return;
 
-    let propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2);
-    let submittedReport = propBag.getPropertyAsBool("submittedCrashReport");
-    let doPrompt        = true; // XXX followup for .getPropertyAsBool("doPrompt");
-    let submitReports   = true; // XXX followup for .getPropertyAsBool("submitReports");
-    let pluginName      = propBag.getPropertyAsAString("pluginName");
-    let pluginDumpID    = propBag.getPropertyAsAString("pluginDumpID");
-    let browserDumpID   = null;
-    let gmpPlugin       = false;
-
-    try {
-      browserDumpID = propBag.getPropertyAsAString("browserDumpID");
-    } catch (e) {
-      // For GMP crashes we don't get a browser dump.
-    }
-
-    try {
-      gmpPlugin = propBag.getPropertyAsBool("gmpPlugin");
-    } catch (e) {
-      // This property is only set for GMP plugins.
-    }
+    let submittedReport = aEvent.submittedCrashReport;
+    let doPrompt        = true; // XXX followup for aEvent.doPrompt;
+    let submitReports   = true; // XXX followup for aEvent.submitReports;
+    let pluginName      = aEvent.pluginName;
+    let pluginDumpID    = aEvent.pluginDumpID;
+    let browserDumpID   = aEvent.browserDumpID;
+    let gmpPlugin       = aEvent.gmpPlugin;
 
     // For non-GMP plugins, remap the plugin name to a more user-presentable form.
     if (!gmpPlugin) {
       pluginName = BrowserUtils.makeNicePluginName(pluginName);
     }
 
     let messageString = gNavigatorBundle.formatStringFromName("crashedpluginsMessage.title", [pluginName], 1);
 
--- a/build/pgo/index.html
+++ b/build/pgo/index.html
@@ -1,64 +1,80 @@
 <script>
 /* 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/. */
 
- var list = 
-     [
+ var list = [
   "blueprint/sample.html",
   "blueprint/forms.html",
   "blueprint/grid.html",
   "blueprint/elements.html",
-  "js-input/3d-cube.html",
-  "js-input/3d-morph.html",
-  "js-input/3d-raytrace.html",
   "js-input/3d-thingy.html",
-  "js-input/access-binary-trees.html",
-  "js-input/access-fannkuch.html",
-  "js-input/access-nbody.html",
-  "js-input/access-nsieve.html",
-  "js-input/bitops-3bit-bits-in-byte.html",
-  "js-input/bitops-bits-in-byte.html",
-  "js-input/bitops-bitwise-and.html",
-  "js-input/bitops-nsieve-bits.html",
-  "js-input/controlflow-recursive.html",
-  "js-input/crypto-aes.html",
-  "js-input/crypto-md5.html",
-  "js-input/crypto-sha1.html",
   "js-input/crypto-otp.html",
-  "js-input/date-format-tofte.html",
-  "js-input/date-format-xparb.html",
-  "js-input/math-cordic.html",
-  "js-input/math-partial-sums.html",
-  "js-input/math-spectral-norm.html",
-  "js-input/regexp-dna.html",
-  "js-input/string-base64.html",
-  "js-input/string-fasta.html",
-  "js-input/string-tagcloud.html",
-  "js-input/string-unpack-code.html",
-  "js-input/string-validate-input.html"
+
+  "js-input/sunspider/3d-cube.html",
+  "js-input/sunspider/3d-morph.html",
+  "js-input/sunspider/3d-raytrace.html",
+  "js-input/sunspider/access-binary-trees.html",
+  "js-input/sunspider/access-fannkuch.html",
+  "js-input/sunspider/access-nbody.html",
+  "js-input/sunspider/access-nsieve.html",
+  "js-input/sunspider/bitops-3bit-bits-in-byte.html",
+  "js-input/sunspider/bitops-bits-in-byte.html",
+  "js-input/sunspider/bitops-bitwise-and.html",
+  "js-input/sunspider/bitops-nsieve-bits.html",
+  "js-input/sunspider/controlflow-recursive.html",
+  "js-input/sunspider/crypto-aes.html",
+  "js-input/sunspider/crypto-md5.html",
+  "js-input/sunspider/crypto-sha1.html",
+  "js-input/sunspider/date-format-tofte.html",
+  "js-input/sunspider/date-format-xparb.html",
+  "js-input/sunspider/math-cordic.html",
+  "js-input/sunspider/math-partial-sums.html",
+  "js-input/sunspider/math-spectral-norm.html",
+  "js-input/sunspider/regexp-dna.html",
+  "js-input/sunspider/string-base64.html",
+  "js-input/sunspider/string-fasta.html",
+  "js-input/sunspider/string-tagcloud.html",
+  "js-input/sunspider/string-unpack-code.html",
+  "js-input/sunspider/string-validate-input.html",
+
+  "js-input/octane/box2d.html",
+  "js-input/octane/code-load.html",
+  "js-input/octane/crypto.html",
+  "js-input/octane/deltablue.html",
+  "js-input/octane/earley-boyer.html",
+  "js-input/octane/gbemu.html",
+  "js-input/octane/mandreel.html",
+  "js-input/octane/navier-stokes.html",
+  "js-input/octane/pdfjs.html",
+  "js-input/octane/raytrace.html",
+  "js-input/octane/regexp.html",
+  "js-input/octane/richards.html",
+  "js-input/octane/splay.html",
+  "js-input/octane/typescript.html",
+  "js-input/octane/zlib.html"
      ];
- var interval = 3000; // 15000
+ var interval = 1000;
  var idx = 0;
  var w;
- 
+
  window.onload = function () {
      w = window.open("about:blank");
-     window.setTimeout(loadURL, interval); 
+     window.setTimeout(loadURL, interval);
  };
  function loadURL () {
      w.close();
      w = window.open(list[idx++]);
      if (idx < list.length) {
      window.setTimeout(loadURL, interval);
      } else {
          window.setTimeout(Quitter.quit, interval);
      }
  }
  var i;
- 
+
  for(i=0; i < list.length;i++) {
      document.write(list[i]);
      document.write("<br>");
  }
   </script>
copy from js/src/octane/base.js
copy to build/pgo/js-input/octane/base.js
--- a/js/src/octane/base.js
+++ b/build/pgo/js-input/octane/base.js
@@ -152,17 +152,20 @@ BenchmarkSuite.RunSuites = function(runn
         var suite = suites[index++];
         if (runner.NotifyStart) runner.NotifyStart(suite.name);
         if (skipBenchmarks.indexOf(suite.name) > -1) {
           suite.NotifySkipped(runner);
         } else {
           continuation = suite.RunStep(runner);
         }
       }
-      if (continuation && typeof window != 'undefined' && window.setTimeout) {
+
+      // Don't use setTimeout during the PGO run, it could interfere with
+      // the setTimeout in the index.html script.
+      if (continuation && 0) {//XXX && typeof window != 'undefined' && window.setTimeout) {
         window.setTimeout(RunStep, 25);
         return;
       }
     }
 
     // show final result
     if (runner.NotifyScore) {
       var score = BenchmarkSuite.GeometricMean(BenchmarkSuite.scores);
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/box2d.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="box2d.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/box2d.js
copy to build/pgo/js-input/octane/box2d.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/code-load.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="code-load.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/code-load.js
copy to build/pgo/js-input/octane/code-load.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/crypto.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="crypto.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/crypto.js
copy to build/pgo/js-input/octane/crypto.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/deltablue.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="deltablue.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/deltablue.js
copy to build/pgo/js-input/octane/deltablue.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/earley-boyer.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="earley-boyer.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/earley-boyer.js
copy to build/pgo/js-input/octane/earley-boyer.js
copy from js/src/octane/gbemu-part1.js
copy to build/pgo/js-input/octane/gbemu-part1.js
copy from js/src/octane/gbemu-part2.js
copy to build/pgo/js-input/octane/gbemu-part2.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/gbemu.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="gbemu-part1.js"></script>
+<script src="gbemu-part2.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/mandreel.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="mandreel.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/mandreel.js
copy to build/pgo/js-input/octane/mandreel.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/navier-stokes.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="navier-stokes.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/navier-stokes.js
copy to build/pgo/js-input/octane/navier-stokes.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/pdfjs.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="pdfjs.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/pdfjs.js
copy to build/pgo/js-input/octane/pdfjs.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/raytrace.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="raytrace.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/raytrace.js
copy to build/pgo/js-input/octane/raytrace.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/regexp.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="regexp.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/regexp.js
copy to build/pgo/js-input/octane/regexp.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/richards.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="richards.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/richards.js
copy to build/pgo/js-input/octane/richards.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/run.js
@@ -0,0 +1,33 @@
+print = function(s) {
+    document.getElementById("console").innerHTML += "\n<br>" + s;
+};
+
+var success = true;
+
+function PrintResult(name, result) {
+  print(name + ': ' + result);
+}
+
+
+function PrintError(name, error) {
+  PrintResult(name, error);
+  success = false;
+}
+
+
+function PrintScore(score) {
+  if (success) {
+    print('----');
+    print('Score (version ' + BenchmarkSuite.version + '): ' + score);
+  }
+}
+
+
+BenchmarkSuite.config.doWarmup = undefined;
+BenchmarkSuite.config.doDeterministic = undefined;
+
+BenchmarkSuite.RunSuites({ NotifyResult: PrintResult,
+                           NotifyError: PrintError,
+                           NotifyScore: PrintScore });
+
+print((Date.now() - __startTime) + " ms");
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/splay.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="splay.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/splay.js
copy to build/pgo/js-input/octane/splay.js
copy from js/src/octane/typescript-compiler.js
copy to build/pgo/js-input/octane/typescript-compiler.js
copy from js/src/octane/typescript-input.js
copy to build/pgo/js-input/octane/typescript-input.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/typescript.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="typescript.js"></script>
+<script src="typescript-input.js"></script>
+<script src="typescript-compiler.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/typescript.js
copy to build/pgo/js-input/octane/typescript.js
copy from js/src/octane/zlib-data.js
copy to build/pgo/js-input/octane/zlib-data.js
new file mode 100644
--- /dev/null
+++ b/build/pgo/js-input/octane/zlib.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<head>
+<title>Octane</title>
+
+</head>
+
+<body>
+<h3>Octane</h3>
+<div id="console">
+</div>
+
+<script type="text/javascript">var __startTime = Date.now();</script>
+
+<script src="base.js"></script>
+<script src="zlib.js"></script>
+<script src="zlib-data.js"></script>
+<script src="run.js"></script>
+
+</body>
+</html>
copy from js/src/octane/zlib.js
copy to build/pgo/js-input/octane/zlib.js
rename from build/pgo/js-input/3d-cube.html
rename to build/pgo/js-input/sunspider/3d-cube.html
rename from build/pgo/js-input/3d-morph.html
rename to build/pgo/js-input/sunspider/3d-morph.html
rename from build/pgo/js-input/3d-raytrace.html
rename to build/pgo/js-input/sunspider/3d-raytrace.html
rename from build/pgo/js-input/access-binary-trees.html
rename to build/pgo/js-input/sunspider/access-binary-trees.html
rename from build/pgo/js-input/access-fannkuch.html
rename to build/pgo/js-input/sunspider/access-fannkuch.html
rename from build/pgo/js-input/access-nbody.html
rename to build/pgo/js-input/sunspider/access-nbody.html
rename from build/pgo/js-input/access-nsieve.html
rename to build/pgo/js-input/sunspider/access-nsieve.html
rename from build/pgo/js-input/bitops-3bit-bits-in-byte.html
rename to build/pgo/js-input/sunspider/bitops-3bit-bits-in-byte.html
rename from build/pgo/js-input/bitops-bits-in-byte.html
rename to build/pgo/js-input/sunspider/bitops-bits-in-byte.html
rename from build/pgo/js-input/bitops-bitwise-and.html
rename to build/pgo/js-input/sunspider/bitops-bitwise-and.html
rename from build/pgo/js-input/bitops-nsieve-bits.html
rename to build/pgo/js-input/sunspider/bitops-nsieve-bits.html
rename from build/pgo/js-input/controlflow-recursive.html
rename to build/pgo/js-input/sunspider/controlflow-recursive.html
rename from build/pgo/js-input/crypto-aes.html
rename to build/pgo/js-input/sunspider/crypto-aes.html
rename from build/pgo/js-input/crypto-md5.html
rename to build/pgo/js-input/sunspider/crypto-md5.html
rename from build/pgo/js-input/crypto-sha1.html
rename to build/pgo/js-input/sunspider/crypto-sha1.html
rename from build/pgo/js-input/date-format-tofte.html
rename to build/pgo/js-input/sunspider/date-format-tofte.html
rename from build/pgo/js-input/date-format-xparb.html
rename to build/pgo/js-input/sunspider/date-format-xparb.html
rename from build/pgo/js-input/math-cordic.html
rename to build/pgo/js-input/sunspider/math-cordic.html
rename from build/pgo/js-input/math-partial-sums.html
rename to build/pgo/js-input/sunspider/math-partial-sums.html
rename from build/pgo/js-input/math-spectral-norm.html
rename to build/pgo/js-input/sunspider/math-spectral-norm.html
rename from build/pgo/js-input/regexp-dna.html
rename to build/pgo/js-input/sunspider/regexp-dna.html
rename from build/pgo/js-input/string-base64.html
rename to build/pgo/js-input/sunspider/string-base64.html
rename from build/pgo/js-input/string-fasta.html
rename to build/pgo/js-input/sunspider/string-fasta.html
rename from build/pgo/js-input/string-tagcloud.html
rename to build/pgo/js-input/sunspider/string-tagcloud.html
rename from build/pgo/js-input/string-unpack-code.html
rename to build/pgo/js-input/sunspider/string-unpack-code.html
rename from build/pgo/js-input/string-validate-input.html
rename to build/pgo/js-input/sunspider/string-validate-input.html
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1156,20 +1156,21 @@ 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
 _XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
 _XPT_NAME_DEST := $(FINAL_TARGET)/components
+_XPT_NAME_TARGET := misc
 INSTALL_TARGETS += _XPT_NAME
 
 ifndef NO_INTERFACES_MANIFEST
-libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
+misc:: $(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/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -185,16 +185,17 @@
 #include "nsIAppsService.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/AnimationTimeline.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
+#include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/NodeFilterBinding.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/UndoManager.h"
 #include "mozilla/dom/WebComponentsBinding.h"
 #include "nsFrame.h"
 #include "nsDOMCaretPosition.h"
 #include "nsIDOMHTMLTextAreaElement.h"
@@ -1555,16 +1556,18 @@ nsIDocument::nsIDocument()
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
     mIsBeingUsedAsImage(false),
     mHasLinksToUpdate(false),
     mPartID(0),
     mDidFireDOMContentLoaded(true)
 {
   SetInDocument();
+
+  PR_INIT_CLIST(&mDOMMediaQueryLists);  
 }
 
 // NOTE! nsDocument::operator new() zeroes out all members, so don't
 // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(true)
@@ -1600,16 +1603,19 @@ ClearAllBoxObjects(nsIContent* aKey, nsP
   if (aBoxObject) {
     aBoxObject->Clear();
   }
   return PL_DHASH_NEXT;
 }
 
 nsIDocument::~nsIDocument()
 {
+  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
+                    "must not have media query lists left");
+
   if (mNodeInfoManager) {
     mNodeInfoManager->DropDocumentReference();
   }
 }
 
 
 nsDocument::~nsDocument()
 {
@@ -2013,16 +2019,28 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
 
   for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
     nsHostObjectProtocolHandler::Traverse(tmp->mHostObjectURIs[i], cb);
   }
+
+  // We own only the items in mDOMMediaQueryLists that have listeners;
+  // this reference is managed by their AddListener and RemoveListener
+  // methods.
+  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
+       l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+    if (mql->HasListeners()) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
+      cb.NoteXPCOMChild(mql);
+    }
+  }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
   if (tmp->PreservingWrapper()) {
     NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando);
   }
@@ -2115,16 +2133,27 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     tmp->mCSSLoader->DropDocumentReference();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
   }
 
   for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
     nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i]);
   }
 
+  // We own only the items in mDOMMediaQueryLists that have listeners;
+  // this reference is managed by their AddListener and RemoveListener
+  // methods.
+  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
+       l != &tmp->mDOMMediaQueryLists; ) {
+    PRCList *next = PR_NEXT_LINK(l);
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+    mql->RemoveAllListeners();
+    l = next;
+  }
+
   tmp->mInUnlinkOrDeletion = false;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 static bool sPrefsInitialized = false;
 static uint32_t sOnloadDecodeLimit = 0;
 
 nsresult
 nsDocument::Init()
@@ -7134,16 +7163,27 @@ nsDocument::ClearBoxObjectFor(nsIContent
     nsPIBoxObject *boxObject = mBoxObjectTable->GetWeak(aContent);
     if (boxObject) {
       boxObject->Clear();
       mBoxObjectTable->Remove(aContent);
     }
   }
 }
 
+already_AddRefed<MediaQueryList>
+nsIDocument::MatchMedia(const nsAString& aMediaQueryList)
+{
+  nsRefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
+
+  // Insert the new item at the end of the linked list.
+  PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
+
+  return result.forget();
+}
+
 void
 nsDocument::FlushSkinBindings()
 {
   BindingManager()->FlushSkinBindings();
 }
 
 nsresult
 nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5351,36 +5351,21 @@ nsGlobalWindow::MatchMedia(const nsAStri
 {
   // FIXME: This whole forward-to-outer and then get a pres
   // shell/context off the docshell dance is sort of silly; it'd make
   // more sense to forward to the inner, but it's what everyone else
   // (GetSelection, GetScrollXY, etc.) does around here.
   FORWARD_TO_OUTER_OR_THROW(MatchMedia, (aMediaQueryList, aError), aError,
                             nullptr);
 
-  // We need this now to ensure that we have a non-null |presContext|
-  // when we ought to.
-  // This is similar to EnsureSizeUpToDate, but only flushes frames.
-  nsGlobalWindow *parent = static_cast<nsGlobalWindow*>(GetPrivateParent());
-  if (parent) {
-    parent->FlushPendingNotifications(Flush_Frames);
-  }
-
-  if (!mDocShell) {
+  if (!mDoc) {
     return nullptr;
   }
 
-  nsRefPtr<nsPresContext> presContext;
-  mDocShell->GetPresContext(getter_AddRefs(presContext));
-
-  if (!presContext) {
-    return nullptr;
-  }
-
-  return presContext->MatchMedia(aMediaQueryList);
+  return mDoc->MatchMedia(aMediaQueryList);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
                            nsISupports** aResult)
 {
   ErrorResult rv;
   nsRefPtr<MediaQueryList> mediaQueryList = MatchMedia(aMediaQueryList, rv);
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -21,16 +21,17 @@
 #include "nsTHashtable.h"                // for member
 #include "mozilla/net/ReferrerPolicy.h"  // for member
 #include "nsWeakReference.h"
 #include "mozilla/dom/DocumentBinding.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
+#include "prclist.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
@@ -109,16 +110,17 @@ class Event;
 class EventTarget;
 class FontFaceSet;
 class FrameRequestCallback;
 class ImportManager;
 class OverfillCallback;
 class HTMLBodyElement;
 struct LifecycleCallbackArgs;
 class Link;
+class MediaQueryList;
 class GlobalObject;
 class NodeFilter;
 class NodeIterator;
 class ProcessingInstruction;
 class StyleSheetList;
 class SVGDocument;
 class Touch;
 class TouchList;
@@ -1521,16 +1523,27 @@ public:
    * Get the box object for an element. This is not exposed through a
    * scriptable interface except for XUL documents.
    */
   virtual already_AddRefed<mozilla::dom::BoxObject>
     GetBoxObjectFor(mozilla::dom::Element* aElement,
                     mozilla::ErrorResult& aRv) = 0;
 
   /**
+   * Support for window.matchMedia()
+   */
+
+  already_AddRefed<mozilla::dom::MediaQueryList>
+    MatchMedia(const nsAString& aMediaQueryList);
+
+  const PRCList* MediaQueryLists() const {
+    return &mDOMMediaQueryLists;
+  }
+
+  /**
    * Get the compatibility mode for this document
    */
   nsCompatibility GetCompatibilityMode() const {
     return mCompatMode;
   }
   
   /**
    * Check whether we've ever fired a DOMTitleChanged event for this
@@ -2772,16 +2785,19 @@ protected:
   uint32_t mInSyncOperationCount;
 
   nsRefPtr<mozilla::dom::XPathEvaluator> mXPathEvaluator;
 
   nsTArray<nsRefPtr<mozilla::dom::AnonymousContent>> mAnonymousContents;
 
   uint32_t mBlockDOMContentLoaded;
   bool mDidFireDOMContentLoaded:1;
+
+  // Our live MediaQueryLists
+  PRCList mDOMMediaQueryLists;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
 
 /**
  * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
  * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
  * object is deleted.
--- a/dom/base/nsObjectLoadingContent.cpp
+++ b/dom/base/nsObjectLoadingContent.cpp
@@ -73,16 +73,17 @@
 
 #include "nsWidgetsCID.h"
 #include "nsContentCID.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/PluginCrashedEvent.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/EventStates.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/dom/HTMLObjectElementBinding.h"
 
 #ifdef XP_WIN
 // Thanks so much, Microsoft! :(
 #ifdef CreateEvent
@@ -321,65 +322,31 @@ nsPluginCrashedEvent::Run()
        mContent.get()));
 
   nsCOMPtr<nsIDocument> doc = mContent->GetComposedDoc();
   if (!doc) {
     NS_WARNING("Couldn't get document for PluginCrashed event!");
     return NS_OK;
   }
 
-  ErrorResult rv;
-  nsRefPtr<Event> event =
-    doc->CreateEvent(NS_LITERAL_STRING("customevent"), rv);
-  nsCOMPtr<nsIDOMCustomEvent> customEvent(do_QueryObject(event));
-  if (!customEvent) {
-    NS_WARNING("Couldn't QI event for PluginCrashed event!");
-    return NS_OK;
-  }
-
-  nsCOMPtr<nsIWritableVariant> variant;
-  variant = do_CreateInstance("@mozilla.org/variant;1");
-  if (!variant) {
-    NS_WARNING("Couldn't create detail variant for PluginCrashed event!");
-    return NS_OK;
-  }
-  customEvent->InitCustomEvent(NS_LITERAL_STRING("PluginCrashed"),
-                               true, true, variant);
+  PluginCrashedEventInit init;
+  init.mPluginDumpID = mPluginDumpID;
+  init.mBrowserDumpID = mBrowserDumpID;
+  init.mPluginName = mPluginName;
+  init.mPluginFilename = mPluginFilename;
+  init.mSubmittedCrashReport = mSubmittedCrashReport;
+  init.mBubbles = true;
+  init.mCancelable = true;
+
+  nsRefPtr<PluginCrashedEvent> event =
+    PluginCrashedEvent::Constructor(doc, NS_LITERAL_STRING("PluginCrashed"), init);
+
   event->SetTrusted(true);
   event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
 
-  nsCOMPtr<nsIWritablePropertyBag2> propBag;
-  propBag = do_CreateInstance("@mozilla.org/hash-property-bag;1");
-  if (!propBag) {
-    NS_WARNING("Couldn't create a property bag for PluginCrashed event!");
-    return NS_OK;
-  }
-
-  // add a "pluginDumpID" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("pluginDumpID"),
-                                mPluginDumpID);
-
-  // add a "browserDumpID" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("browserDumpID"),
-                                mBrowserDumpID);
-
-  // add a "pluginName" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("pluginName"),
-                                mPluginName);
-
-  // add a "pluginFilename" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("pluginFilename"),
-                                mPluginFilename);
-
-  // add a "submittedCrashReport" property to this event
-  propBag->SetPropertyAsBool(NS_LITERAL_STRING("submittedCrashReport"),
-                             mSubmittedCrashReport);
-
-  variant->SetAsISupports(propBag);
-
   EventDispatcher::DispatchDOMEvent(mContent, nullptr, event, nullptr, nullptr);
   return NS_OK;
 }
 
 class nsStopPluginRunnable : public nsRunnable, public nsITimerCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -2193,17 +2193,23 @@ SetDefaultPragmas(mozIStorageConnection*
 #endif
     // We use foreign keys in lots of places.
     "PRAGMA foreign_keys = ON; "
     // The "INSERT OR REPLACE" statement doesn't fire the update trigger,
     // instead it fires only the insert trigger. This confuses the update
     // refcount function. This behavior changes with enabled recursive triggers,
     // so the statement fires the delete trigger first and then the insert
     // trigger.
-    "PRAGMA recursive_triggers = ON;";
+    "PRAGMA recursive_triggers = ON;"
+    // We don't need SQLite's table locks because we manage transaction ordering
+    // ourselves and we know we will never allow a write transaction to modify
+    // an object store that a read transaction is in the process of using.
+    "PRAGMA read_uncommitted = TRUE;"
+    // No more PRAGMAs.
+    ;
 
   nsresult rv = aConnection->ExecuteSimpleSQL(NS_LITERAL_CSTRING(query));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (IndexedDatabaseManager::FullSynchronous()) {
     rv = aConnection->ExecuteSimpleSQL(
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -73,16 +73,18 @@ support-files =
   unit/test_remove_index.js
   unit/test_remove_objectStore.js
   unit/test_request_readyState.js
   unit/test_setVersion.js
   unit/test_setVersion_abort.js
   unit/test_setVersion_events.js
   unit/test_setVersion_exclusion.js
   unit/test_success_events_after_abort.js
+  unit/test_table_locks.js
+  unit/test_table_rollback.js
   unit/test_temporary_storage.js
   unit/test_traffic_jam.js
   unit/test_transaction_abort.js
   unit/test_transaction_abort_hang.js
   unit/test_transaction_duplicate_store_names.js
   unit/test_transaction_error.js
   unit/test_transaction_lifetimes.js
   unit/test_transaction_lifetimes_nested.js
@@ -334,16 +336,20 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_setVersion_abort.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_setVersion_events.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_setVersion_exclusion.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_success_events_after_abort.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
+[test_table_locks.html]
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
+[test_table_rollback.html]
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_third_party.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_traffic_jam.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_transaction_abort.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_transaction_abort_hang.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_table_locks.html
@@ -0,0 +1,18 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>IndexedDB Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7" src="unit/test_table_locks.js"></script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_table_rollback.html
@@ -0,0 +1,19 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7" src="unit/test_table_rollback.js"></script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_table_locks.js
@@ -0,0 +1,116 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const dbName = ("window" in this) ? window.location.pathname : "test";
+const dbVersion = 1;
+const objName1 = "o1";
+const objName2 = "o2";
+const idxName1 = "i1";
+const idxName2 = "i2";
+const idxKeyPathProp = "idx";
+const objDataProp = "data";
+const objData = "1234567890";
+const objDataCount = 5;
+const loopCount = 100;
+
+let testGenerator = testSteps();
+
+function testSteps()
+{
+  let req = indexedDB.open(dbName, dbVersion);
+  req.onerror = errorHandler;
+  req.onupgradeneeded = grabEventAndContinueHandler;
+  req.onsuccess = grabEventAndContinueHandler;
+
+  let event = yield undefined;
+
+  is(event.type, "upgradeneeded", "Got upgradeneeded event");
+
+  let db = event.target.result;
+
+  let objectStore1 = db.createObjectStore(objName1);
+  objectStore1.createIndex(idxName1, idxKeyPathProp);
+
+  let objectStore2 = db.createObjectStore(objName2);
+  objectStore2.createIndex(idxName2, idxKeyPathProp);
+
+  for (let i = 0; i < objDataCount; i++) {
+    var data = { };
+    data[objDataProp] = objData;
+    data[idxKeyPathProp] = objDataCount - i - 1;
+
+    objectStore1.add(data, i);
+    objectStore2.add(data, i);
+  }
+
+  event = yield undefined;
+
+  is(event.type, "success", "Got success event");
+
+  doReadOnlyTransaction(db, 0, loopCount);
+  doReadWriteTransaction(db, 0, loopCount);
+
+  // Wait for readonly and readwrite transaction loops to complete.
+  yield undefined;
+  yield undefined;
+
+  finishTest();
+  yield undefined;
+}
+
+function doReadOnlyTransaction(db, key, remaining)
+{
+  if (!remaining) {
+    info("Finished all readonly transactions");
+    continueToNextStep();
+    return;
+  }
+
+  info("Starting readonly transaction for key " + key + ", " + remaining +
+       " loops left");
+
+  let objectStore = db.transaction(objName1, "readonly").objectStore(objName1);
+  let index = objectStore.index(idxName1);
+
+  index.openKeyCursor(key, "prev").onsuccess = function(event) {
+    let cursor = event.target.result;
+    ok(cursor, "Got readonly cursor");
+
+    objectStore.get(cursor.primaryKey).onsuccess = function(event) {
+      if (++key == objDataCount) {
+        key = 0;
+      }
+      doReadOnlyTransaction(db, key, remaining - 1);
+    }
+  };
+}
+
+function doReadWriteTransaction(db, key, remaining)
+{
+  if (!remaining) {
+    info("Finished all readwrite transactions");
+    continueToNextStep();
+    return;
+  }
+
+  info("Starting readwrite transaction for key " + key + ", " + remaining +
+       " loops left");
+
+  let objectStore = db.transaction(objName2, "readwrite").objectStore(objName2);
+  objectStore.openCursor(key).onsuccess = function(event) {
+    let cursor = event.target.result;
+    ok(cursor, "Got readwrite cursor");
+
+    let value = cursor.value;
+    value[idxKeyPathProp]++;
+
+    cursor.update(value).onsuccess = function(event) {
+      if (++key == objDataCount) {
+        key = 0;
+      }
+      doReadWriteTransaction(db, key, remaining - 1);
+    }
+  };
+}
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_table_rollback.js
@@ -0,0 +1,115 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+let testGenerator = testSteps();
+
+function testSteps()
+{
+  const dbName = ("window" in this) ? window.location.pathname : "test";
+  const objName1 = "foo";
+  const objName2 = "bar";
+  const data1 = "1234567890";
+  const data2 = "0987654321";
+  const dataCount = 500;
+
+  let request = indexedDB.open(dbName, 1);
+  request.onerror = errorHandler;
+  request.onupgradeneeded = grabEventAndContinueHandler;
+
+  let event = yield undefined;
+
+  is(event.type, "upgradeneeded", "Got upgradeneeded");
+
+  request.onupgradeneeded = errorHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+
+  let db = request.result;
+
+  let objectStore1 = db.createObjectStore(objName1, { autoIncrement: true });
+  let objectStore2 = db.createObjectStore(objName2, { autoIncrement: true });
+
+  info("Created object stores, adding data");
+
+  for (let i = 0; i < dataCount; i++) {
+    objectStore1.add(data1);
+    objectStore2.add(data2);
+  }
+
+  info("Done adding data");
+
+  event = yield undefined;
+
+  is(event.type, "success", "Got success");
+
+  let readResult = null;
+  let readError = null;
+  let writeAborted = false;
+
+  info("Creating readwrite transaction");
+
+  objectStore1 = db.transaction(objName1, "readwrite").objectStore(objName1);
+  objectStore1.openCursor().onsuccess = grabEventAndContinueHandler;
+
+  event = yield undefined;
+
+  let cursor = event.target.result;
+  is(cursor.value, data1, "Got correct data for readwrite transaction");
+
+  info("Modifying object store on readwrite transaction");
+
+  cursor.update(data2);
+  cursor.continue();
+
+  event = yield undefined;
+
+  info("Done modifying object store on readwrite transaction, creating " +
+       "readonly transaction");
+
+  objectStore2 = db.transaction(objName2, "readonly").objectStore(objName2);
+  request = objectStore2.getAll();
+  request.onsuccess = function(event) {
+    readResult = event.target.result;
+    is(readResult.length,
+       dataCount,
+       "Got correct number of results on readonly transaction");
+    for (let i = 0; i < readResult.length; i++) {
+      is(readResult[i], data2, "Got correct data for readonly transaction");
+    }
+    if (writeAborted) {
+      continueToNextStep();
+    }
+  };
+  request.onerror = function(event) {
+    readResult = null;
+    readError = event.target.error;
+
+    ok(false, "Got read error: " + readError.name);
+    event.preventDefault();
+
+    if (writeAborted) {
+      continueToNextStep();
+    }
+  }
+
+  cursor = event.target.result;
+  is(cursor.value, data1, "Got correct data for readwrite transaction");
+
+  info("Aborting readwrite transaction");
+
+  cursor.source.transaction.abort();
+  writeAborted = true;
+
+  if (!readError && !readResult) {
+    info("Waiting for readonly transaction to complete");
+    yield undefined;
+  }
+
+  ok(readResult, "Got result from readonly transaction");
+  is(readError, null, "No read error");
+  is(writeAborted, true, "Aborted readwrite transaction");
+
+  finishTest();
+  yield undefined;
+}
--- a/dom/indexedDB/test/unit/xpcshell-shared.ini
+++ b/dom/indexedDB/test/unit/xpcshell-shared.ini
@@ -59,16 +59,18 @@ skip-if = toolkit == 'android' # bug 107
 [test_remove_index.js]
 [test_remove_objectStore.js]
 [test_request_readyState.js]
 [test_setVersion.js]
 [test_setVersion_abort.js]
 [test_setVersion_events.js]
 [test_setVersion_exclusion.js]
 [test_success_events_after_abort.js]
+[test_table_locks.js]
+[test_table_rollback.js]
 [test_traffic_jam.js]
 [test_transaction_abort.js]
 [test_transaction_abort_hang.js]
 [test_transaction_duplicate_store_names.js]
 [test_transaction_error.js]
 [test_transaction_lifetimes.js]
 [test_transaction_lifetimes_nested.js]
 [test_transaction_ordering.js]
--- a/dom/media/AudioSink.cpp
+++ b/dom/media/AudioSink.cpp
@@ -311,17 +311,17 @@ AudioSink::PlaySilence(uint32_t aFrames)
   return frames;
 }
 
 uint32_t
 AudioSink::PlayFromAudioQueue()
 {
   AssertOnAudioThread();
   NS_ASSERTION(!mAudioStream->IsPaused(), "Don't play when paused");
-  nsAutoPtr<AudioData> audio(AudioQueue().PopFront());
+  nsRefPtr<AudioData> audio(AudioQueue().PopFront());
 
   SINK_LOG_V("playing %u frames of audio at time %lld",
              audio->mFrames, audio->mTime);
   mAudioStream->Write(audio->mAudioData, audio->mFrames);
 
   StartAudioStreamPlaybackIfNeeded();
 
   if (audio->mOffset != -1) {
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -83,39 +83,36 @@ IsInEmulator()
 #endif
 
 VideoData::VideoData(int64_t aOffset, int64_t aTime, int64_t aDuration, int64_t aTimecode)
   : MediaData(VIDEO_DATA, aOffset, aTime, aDuration),
     mTimecode(aTimecode),
     mDuplicate(true),
     mKeyframe(false)
 {
-  MOZ_COUNT_CTOR(VideoData);
   NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
 }
 
 VideoData::VideoData(int64_t aOffset,
                      int64_t aTime,
                      int64_t aDuration,
                      bool aKeyframe,
                      int64_t aTimecode,
                      IntSize aDisplay)
   : MediaData(VIDEO_DATA, aOffset, aTime, aDuration),
     mDisplay(aDisplay),
     mTimecode(aTimecode),
     mDuplicate(false),
     mKeyframe(aKeyframe)
 {
-  MOZ_COUNT_CTOR(VideoData);
   NS_ASSERTION(mDuration >= 0, "Frame must have non-negative duration.");
 }
 
 VideoData::~VideoData()
 {
-  MOZ_COUNT_DTOR(VideoData);
 }
 
 size_t
 VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t size = aMallocSizeOf(this);
 
   // Currently only PLANAR_YCBCR has a well defined function for determining
@@ -125,58 +122,61 @@ VideoData::SizeOfIncludingThis(MallocSiz
         static_cast<const mozilla::layers::PlanarYCbCrImage*>(mImage.get());
     size += img->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   return size;
 }
 
 /* static */
-VideoData* VideoData::ShallowCopyUpdateDuration(VideoData* aOther,
-                                                int64_t aDuration)
+already_AddRefed<VideoData>
+VideoData::ShallowCopyUpdateDuration(VideoData* aOther,
+                                     int64_t aDuration)
 {
-  VideoData* v = new VideoData(aOther->mOffset,
-                               aOther->mTime,
-                               aDuration,
-                               aOther->mKeyframe,
-                               aOther->mTimecode,
-                               aOther->mDisplay);
+  nsRefPtr<VideoData> v = new VideoData(aOther->mOffset,
+                                        aOther->mTime,
+                                        aDuration,
+                                        aOther->mKeyframe,
+                                        aOther->mTimecode,
+                                        aOther->mDisplay);
   v->mImage = aOther->mImage;
-  return v;
+  return v.forget();
 }
 
 /* static */
-VideoData* VideoData::ShallowCopyUpdateTimestamp(VideoData* aOther,
-                                                 int64_t aTimestamp)
+already_AddRefed<VideoData>
+VideoData::ShallowCopyUpdateTimestamp(VideoData* aOther,
+                                      int64_t aTimestamp)
 {
   NS_ENSURE_TRUE(aOther, nullptr);
-  VideoData* v = new VideoData(aOther->mOffset,
-                               aTimestamp,
-                               aOther->GetEndTime() - aTimestamp,
-                               aOther->mKeyframe,
-                               aOther->mTimecode,
-                               aOther->mDisplay);
+  nsRefPtr<VideoData> v = new VideoData(aOther->mOffset,
+                                        aTimestamp,
+                                        aOther->GetEndTime() - aTimestamp,
+                                        aOther->mKeyframe,
+                                        aOther->mTimecode,
+                                        aOther->mDisplay);
   v->mImage = aOther->mImage;
-  return v;
+  return v.forget();
 }
 
 /* static */
-VideoData* VideoData::ShallowCopyUpdateTimestampAndDuration(VideoData* aOther,
-                                                            int64_t aTimestamp,
-                                                            int64_t aDuration)
+already_AddRefed<VideoData>
+VideoData::ShallowCopyUpdateTimestampAndDuration(VideoData* aOther,
+                                                 int64_t aTimestamp,
+                                                 int64_t aDuration)
 {
   NS_ENSURE_TRUE(aOther, nullptr);
-  VideoData* v = new VideoData(aOther->mOffset,
-                               aTimestamp,
-                               aDuration,
-                               aOther->mKeyframe,
-                               aOther->mTimecode,
-                               aOther->mDisplay);
+  nsRefPtr<VideoData> v = new VideoData(aOther->mOffset,
+                                        aTimestamp,
+                                        aDuration,
+                                        aOther->mKeyframe,
+                                        aOther->mTimecode,
+                                        aOther->mDisplay);
   v->mImage = aOther->mImage;
-  return v;
+  return v.forget();
 }
 
 /* static */
 void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                     VideoInfo& aInfo,
                                     const YCbCrBuffer &aBuffer,
                                     const IntRect& aPicture,
                                     bool aCopyData)
@@ -208,36 +208,37 @@ void VideoData::SetVideoDataToImage(Plan
   if (aCopyData) {
     aVideoImage->SetData(data);
   } else {
     aVideoImage->SetDataNoCopy(data);
   }
 }
 
 /* static */
-VideoData* VideoData::Create(VideoInfo& aInfo,
-                             ImageContainer* aContainer,
-                             Image* aImage,
-                             int64_t aOffset,
-                             int64_t aTime,
-                             int64_t aDuration,
-                             const YCbCrBuffer& aBuffer,
-                             bool aKeyframe,
-                             int64_t aTimecode,
-                             const IntRect& aPicture)
+already_AddRefed<VideoData>
+VideoData::Create(VideoInfo& aInfo,
+                  ImageContainer* aContainer,
+                  Image* aImage,
+                  int64_t aOffset,
+                  int64_t aTime,
+                  int64_t aDuration,
+                  const YCbCrBuffer& aBuffer,
+                  bool aKeyframe,
+                  int64_t aTimecode,
+                  const IntRect& aPicture)
 {
   if (!aImage && !aContainer) {
     // Create a dummy VideoData with no image. This gives us something to
     // send to media streams if necessary.
-    nsAutoPtr<VideoData> v(new VideoData(aOffset,
-                                         aTime,
-                                         aDuration,
-                                         aKeyframe,
-                                         aTimecode,
-                                         aInfo.mDisplay.ToIntSize()));
+    nsRefPtr<VideoData> v(new VideoData(aOffset,
+                                        aTime,
+                                        aDuration,
+                                        aKeyframe,
+                                        aTimecode,
+                                        aInfo.mDisplay.ToIntSize()));
     return v.forget();
   }
 
   // The following situation should never happen unless there is a bug
   // in the decoder
   if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
       aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
     NS_ERROR("C planes with different sizes");
@@ -264,22 +265,22 @@ VideoData* VideoData::Create(VideoInfo& 
       !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
   {
     // The specified picture dimensions can't be contained inside the video
     // frame, we'll stomp memory if we try to copy it. Fail.
     NS_WARNING("Overflowing picture rect");
     return nullptr;
   }
 
-  nsAutoPtr<VideoData> v(new VideoData(aOffset,
-                                       aTime,
-                                       aDuration,
-                                       aKeyframe,
-                                       aTimecode,
-                                       aInfo.mDisplay.ToIntSize()));
+  nsRefPtr<VideoData> v(new VideoData(aOffset,
+                                      aTime,
+                                      aDuration,
+                                      aKeyframe,
+                                      aTimecode,
+                                      aInfo.mDisplay.ToIntSize()));
 #ifdef MOZ_WIDGET_GONK
   const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
   const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
   const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
 #endif
 
   if (!aImage) {
     // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
@@ -323,87 +324,91 @@ VideoData* VideoData::Create(VideoInfo& 
     VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
                                    true /* aCopyData */);
   }
 #endif
   return v.forget();
 }
 
 /* static */
-VideoData* VideoData::Create(VideoInfo& aInfo,
-                             ImageContainer* aContainer,
-                             int64_t aOffset,
-                             int64_t aTime,
-                             int64_t aDuration,
-                             const YCbCrBuffer& aBuffer,
-                             bool aKeyframe,
-                             int64_t aTimecode,
-                             const IntRect& aPicture)
+already_AddRefed<VideoData>
+VideoData::Create(VideoInfo& aInfo,
+                  ImageContainer* aContainer,
+                  int64_t aOffset,
+                  int64_t aTime,
+                  int64_t aDuration,
+                  const YCbCrBuffer& aBuffer,
+                  bool aKeyframe,
+                  int64_t aTimecode,
+                  const IntRect& aPicture)
 {
   return Create(aInfo, aContainer, nullptr, aOffset, aTime, aDuration, aBuffer,
                 aKeyframe, aTimecode, aPicture);
 }
 
 /* static */
-VideoData* VideoData::Create(VideoInfo& aInfo,
-                             Image* aImage,
-                             int64_t aOffset,
-                             int64_t aTime,
-                             int64_t aDuration,
-                             const YCbCrBuffer& aBuffer,
-                             bool aKeyframe,
-                             int64_t aTimecode,
-                             const IntRect& aPicture)
+already_AddRefed<VideoData>
+VideoData::Create(VideoInfo& aInfo,
+                  Image* aImage,
+                  int64_t aOffset,
+                  int64_t aTime,
+                  int64_t aDuration,
+                  const YCbCrBuffer& aBuffer,
+                  bool aKeyframe,
+                  int64_t aTimecode,
+                  const IntRect& aPicture)
 {
   return Create(aInfo, nullptr, aImage, aOffset, aTime, aDuration, aBuffer,
                 aKeyframe, aTimecode, aPicture);
 }
 
 /* static */
-VideoData* VideoData::CreateFromImage(VideoInfo& aInfo,
-                                      ImageContainer* aContainer,
-                                      int64_t aOffset,
-                                      int64_t aTime,
-                                      int64_t aDuration,
-                                      const nsRefPtr<Image>& aImage,
-                                      bool aKeyframe,
-                                      int64_t aTimecode,
-                                      const IntRect& aPicture)
+already_AddRefed<VideoData>
+VideoData::CreateFromImage(VideoInfo& aInfo,
+                           ImageContainer* aContainer,
+                           int64_t aOffset,
+                           int64_t aTime,
+                           int64_t aDuration,
+                           const nsRefPtr<Image>& aImage,
+                           bool aKeyframe,
+                           int64_t aTimecode,
+                           const IntRect& aPicture)
 {
-  nsAutoPtr<VideoData> v(new VideoData(aOffset,
-                                       aTime,
-                                       aDuration,
-                                       aKeyframe,
-                                       aTimecode,
-                                       aInfo.mDisplay.ToIntSize()));
+  nsRefPtr<VideoData> v(new VideoData(aOffset,
+                                      aTime,
+                                      aDuration,
+                                      aKeyframe,
+                                      aTimecode,
+                                      aInfo.mDisplay.ToIntSize()));
   v->mImage = aImage;
   return v.forget();
 }
 
 #ifdef MOZ_OMX_DECODER
 /* static */
-VideoData* VideoData::Create(VideoInfo& aInfo,
-                             ImageContainer* aContainer,
-                             int64_t aOffset,
-                             int64_t aTime,
-                             int64_t aDuration,
-                             mozilla::layers::TextureClient* aBuffer,
-                             bool aKeyframe,
-                             int64_t aTimecode,
-                             const IntRect& aPicture)
+already_AddRefed<VideoData>
+VideoData::Create(VideoInfo& aInfo,
+                  ImageContainer* aContainer,
+                  int64_t aOffset,
+                  int64_t aTime,
+                  int64_t aDuration,
+                  mozilla::layers::TextureClient* aBuffer,
+                  bool aKeyframe,
+                  int64_t aTimecode,
+                  const IntRect& aPicture)
 {
   if (!aContainer) {
     // Create a dummy VideoData with no image. This gives us something to
     // send to media streams if necessary.
-    nsAutoPtr<VideoData> v(new VideoData(aOffset,
-                                         aTime,
-                                         aDuration,
-                                         aKeyframe,
-                                         aTimecode,
-                                         aInfo.mDisplay.ToIntSize()));
+    nsRefPtr<VideoData> v(new VideoData(aOffset,
+                                        aTime,
+                                        aDuration,
+                                        aKeyframe,
+                                        aTimecode,
+                                        aInfo.mDisplay.ToIntSize()));
     return v.forget();
   }
 
   // The following situations could be triggered by invalid input
   if (aPicture.width <= 0 || aPicture.height <= 0) {
     NS_WARNING("Empty picture rect");
     return nullptr;
   }
@@ -415,22 +420,22 @@ VideoData* VideoData::Create(VideoInfo& 
   if (!xLimit.isValid() || !yLimit.isValid())
   {
     // The specified picture dimensions can't be contained inside the video
     // frame, we'll stomp memory if we try to copy it. Fail.
     NS_WARNING("Overflowing picture rect");
     return nullptr;
   }
 
-  nsAutoPtr<VideoData> v(new VideoData(aOffset,
-                                       aTime,
-                                       aDuration,
-                                       aKeyframe,
-                                       aTimecode,
-                                       aInfo.mDisplay.ToIntSize()));
+  nsRefPtr<VideoData> v(new VideoData(aOffset,
+                                      aTime,
+                                      aDuration,
+                                      aKeyframe,
+                                      aTimecode,
+                                      aInfo.mDisplay.ToIntSize()));
 
   v->mImage = aContainer->CreateImage(ImageFormat::GRALLOC_PLANAR_YCBCR);
   if (!v->mImage) {
     return nullptr;
   }
   NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::GRALLOC_PLANAR_YCBCR,
                "Wrong format?");
   typedef mozilla::layers::GrallocImage GrallocImage;
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -19,34 +19,34 @@ namespace layers {
 class Image;
 class ImageContainer;
 }
 
 // Container that holds media samples.
 class MediaData {
 public:
 
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaData)
+
   enum Type {
     AUDIO_DATA = 0,
     VIDEO_DATA
   };
 
   MediaData(Type aType,
             int64_t aOffset,
             int64_t aTimestamp,
             int64_t aDuration)
     : mType(aType)
     , mOffset(aOffset)
     , mTime(aTimestamp)
     , mDuration(aDuration)
     , mDiscontinuity(false)
   {}
 
-  virtual ~MediaData() {}
-
   // Type of contained data.
   const Type mType;
 
   // Approximate byte offset where this data was demuxed from its media.
   const int64_t mOffset;
 
   // Start time of sample, in microseconds.
   const int64_t mTime;
@@ -55,16 +55,19 @@ public:
   const int64_t mDuration;
 
   // True if this is the first sample after a gap or discontinuity in
   // the stream. This is true for the first sample in a stream after a seek.
   bool mDiscontinuity;
 
   int64_t GetEndTime() const { return mTime + mDuration; }
 
+protected:
+  virtual ~MediaData() {}
+
 };
 
 // Holds chunk a decoded audio frames.
 class AudioData : public MediaData {
 public:
 
   AudioData(int64_t aOffset,
             int64_t aTime,
@@ -72,39 +75,34 @@ public:
             uint32_t aFrames,
             AudioDataValue* aData,
             uint32_t aChannels,
             uint32_t aRate)
     : MediaData(AUDIO_DATA, aOffset, aTime, aDuration)
     , mFrames(aFrames)
     , mChannels(aChannels)
     , mRate(aRate)
-    , mAudioData(aData)
-  {
-    MOZ_COUNT_CTOR(AudioData);
-  }
-
-  ~AudioData()
-  {
-    MOZ_COUNT_DTOR(AudioData);
-  }
+    , mAudioData(aData) {}
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   // If mAudioBuffer is null, creates it from mAudioData.
   void EnsureAudioBuffer();
 
   const uint32_t mFrames;
   const uint32_t mChannels;
   const uint32_t mRate;
   // At least one of mAudioBuffer/mAudioData must be non-null.
   // mChannels channels, each with mFrames frames
   nsRefPtr<SharedBuffer> mAudioBuffer;
   // mFrames frames, each with mChannels values
   nsAutoArrayPtr<AudioDataValue> mAudioData;
+
+protected:
+  ~AudioData() {}
 };
 
 namespace layers {
 class TextureClient;
 class PlanarYCbCrImage;
 }
 
 class VideoInfo;
@@ -138,113 +136,112 @@ public:
   // Constructs a VideoData object. If aImage is nullptr, creates a new Image
   // holding a copy of the YCbCr data passed in aBuffer. If aImage is not
   // nullptr, it's stored as the underlying video image and aBuffer is assumed
   // to point to memory within aImage so no copy is made. aTimecode is a codec
   // specific number representing the timestamp of the frame of video data.
   // Returns nsnull if an error occurs. This may indicate that memory couldn't
   // be allocated to create the VideoData object, or it may indicate some
   // problem with the input data (e.g. negative stride).
-  static VideoData* Create(VideoInfo& aInfo,
-                           ImageContainer* aContainer,
-                           Image* aImage,
-                           int64_t aOffset,
-                           int64_t aTime,
-                           int64_t aDuration,
-                           const YCbCrBuffer &aBuffer,
-                           bool aKeyframe,
-                           int64_t aTimecode,
-                           const IntRect& aPicture);
+  static already_AddRefed<VideoData> Create(VideoInfo& aInfo,
+                                            ImageContainer* aContainer,
+                                            Image* aImage,
+                                            int64_t aOffset,
+                                            int64_t aTime,
+                                            int64_t aDuration,
+                                            const YCbCrBuffer &aBuffer,
+                                            bool aKeyframe,
+                                            int64_t aTimecode,
+                                            const IntRect& aPicture);
 
   // Variant that always makes a copy of aBuffer
-  static VideoData* Create(VideoInfo& aInfo,
-                           ImageContainer* aContainer,
-                           int64_t aOffset,
-                           int64_t aTime,
-                           int64_t aDuration,
-                           const YCbCrBuffer &aBuffer,
-                           bool aKeyframe,
-                           int64_t aTimecode,
-                           const IntRect& aPicture);
+  static already_AddRefed<VideoData> Create(VideoInfo& aInfo,
+                                            ImageContainer* aContainer,
+                                            int64_t aOffset,
+                                            int64_t aTime,
+                                            int64_t aDuration,
+                                            const YCbCrBuffer &aBuffer,
+                                            bool aKeyframe,
+                                            int64_t aTimecode,
+                                            const IntRect& aPicture);
 
   // Variant to create a VideoData instance given an existing aImage
-  static VideoData* Create(VideoInfo& aInfo,
-                           Image* aImage,
-                           int64_t aOffset,
-                           int64_t aTime,
-                           int64_t aDuration,
-                           const YCbCrBuffer &aBuffer,
-                           bool aKeyframe,
-                           int64_t aTimecode,
-                           const IntRect& aPicture);
+  static already_AddRefed<VideoData> Create(VideoInfo& aInfo,
+                                            Image* aImage,
+                                            int64_t aOffset,
+                                            int64_t aTime,
+                                            int64_t aDuration,
+                                            const YCbCrBuffer &aBuffer,
+                                            bool aKeyframe,
+                                            int64_t aTimecode,
+                                            const IntRect& aPicture);
 
-  static VideoData* Create(VideoInfo& aInfo,
-                           ImageContainer* aContainer,
-                           int64_t aOffset,
-                           int64_t aTime,
-                           int64_t aDuration,
-                           layers::TextureClient* aBuffer,
-                           bool aKeyframe,
-                           int64_t aTimecode,
-                           const IntRect& aPicture);
+  static already_AddRefed<VideoData> Create(VideoInfo& aInfo,
+                                             ImageContainer* aContainer,
+                                             int64_t aOffset,
+                                             int64_t aTime,
+                                             int64_t aDuration,
+                                             layers::TextureClient* aBuffer,
+                                             bool aKeyframe,
+                                             int64_t aTimecode,
+                                             const IntRect& aPicture);
 
-  static VideoData* CreateFromImage(VideoInfo& aInfo,
-                                    ImageContainer* aContainer,
-                                    int64_t aOffset,
-                                    int64_t aTime,
-                                    int64_t aDuration,
-                                    const nsRefPtr<Image>& aImage,
-                                    bool aKeyframe,
-                                    int64_t aTimecode,
-                                    const IntRect& aPicture);
+  static already_AddRefed<VideoData> CreateFromImage(VideoInfo& aInfo,
+                                                     ImageContainer* aContainer,
+                                                     int64_t aOffset,
+                                                     int64_t aTime,
+                                                     int64_t aDuration,
+                                                     const nsRefPtr<Image>& aImage,
+                                                     bool aKeyframe,
+                                                     int64_t aTimecode,
+                                                     const IntRect& aPicture);
 
   // Creates a new VideoData identical to aOther, but with a different
   // specified duration. All data from aOther is copied into the new
   // VideoData. The new VideoData's mImage field holds a reference to
   // aOther's mImage, i.e. the Image is not copied. This function is useful
   // in reader backends that can't determine the duration of a VideoData
   // until the next frame is decoded, i.e. it's a way to change the const
   // duration field on a VideoData.
-  static VideoData* ShallowCopyUpdateDuration(VideoData* aOther,
-                                              int64_t aDuration);
+  static already_AddRefed<VideoData> ShallowCopyUpdateDuration(VideoData* aOther,
+                                                               int64_t aDuration);
 
   // Creates a new VideoData identical to aOther, but with a different
   // specified timestamp. All data from aOther is copied into the new
   // VideoData, as ShallowCopyUpdateDuration() does.
-  static VideoData* ShallowCopyUpdateTimestamp(VideoData* aOther,
-                                               int64_t aTimestamp);
+  static already_AddRefed<VideoData> ShallowCopyUpdateTimestamp(VideoData* aOther,
+                                                                int64_t aTimestamp);
 
   // Creates a new VideoData identical to aOther, but with a different
   // specified timestamp and duration. All data from aOther is copied
   // into the new VideoData, as ShallowCopyUpdateDuration() does.
-  static VideoData* ShallowCopyUpdateTimestampAndDuration(VideoData* aOther,
-                                                          int64_t aTimestamp,
-                                                          int64_t aDuration);
+  static already_AddRefed<VideoData>
+  ShallowCopyUpdateTimestampAndDuration(VideoData* aOther, int64_t aTimestamp,
+                                        int64_t aDuration);
 
   // Initialize PlanarYCbCrImage. Only When aCopyData is true,
   // video data is copied to PlanarYCbCrImage.
   static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                   VideoInfo& aInfo,
                                   const YCbCrBuffer &aBuffer,
                                   const IntRect& aPicture,
                                   bool aCopyData);
 
   // Constructs a duplicate VideoData object. This intrinsically tells the
   // player that it does not need to update the displayed frame when this
   // frame is played; this frame is identical to the previous.
-  static VideoData* CreateDuplicate(int64_t aOffset,
-                                    int64_t aTime,
-                                    int64_t aDuration,
-                                    int64_t aTimecode)
+  static already_AddRefed<VideoData> CreateDuplicate(int64_t aOffset,
+                                                     int64_t aTime,
+                                                     int64_t aDuration,
+                                                     int64_t aTimecode)
   {
-    return new VideoData(aOffset, aTime, aDuration, aTimecode);
+    nsRefPtr<VideoData> rv = new VideoData(aOffset, aTime, aDuration, aTimecode);
+    return rv.forget();
   }
 
-  ~VideoData();
-
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   // Dimensions at which to display the video frame. The picture region
   // will be scaled to this size. This is should be the picture region's
   // dimensions scaled with respect to its aspect ratio.
   const IntSize mDisplay;
 
   // Codec specific internal time code. For Ogg based codecs this is the
@@ -254,26 +251,27 @@ public:
   // This frame's image.
   nsRefPtr<Image> mImage;
 
   // When true, denotes that this frame is identical to the frame that
   // came before; it's a duplicate. mBuffer will be empty.
   const bool mDuplicate;
   const bool mKeyframe;
 
-public:
   VideoData(int64_t aOffset,
             int64_t aTime,
             int64_t aDuration,
             int64_t aTimecode);
 
   VideoData(int64_t aOffset,
             int64_t aTime,
             int64_t aDuration,
             bool aKeyframe,
             int64_t aTimecode,
             IntSize aDisplay);
 
+protected:
+  ~VideoData();
 };
 
 } // namespace mozilla
 
 #endif // MediaData_h
--- a/dom/media/MediaDataDecodedListener.h
+++ b/dom/media/MediaDataDecodedListener.h
@@ -29,33 +29,31 @@ public:
     , mTarget(aTarget)
   {
     MOZ_ASSERT(aTarget);
     MOZ_ASSERT(aTaskQueue);
   }
 
   virtual void OnAudioDecoded(AudioData* aSample) MOZ_OVERRIDE {
     MonitorAutoLock lock(mMonitor);
-    nsAutoPtr<AudioData> sample(aSample);
     if (!mTarget || !mTaskQueue) {
       // We've been shutdown, abort.
       return;
     }
-    RefPtr<nsIRunnable> task(new DeliverAudioTask(sample.forget(), mTarget));
+    RefPtr<nsIRunnable> task(new DeliverAudioTask(aSample, mTarget));
     mTaskQueue->Dispatch(task);
   }
 
   virtual void OnVideoDecoded(VideoData* aSample) MOZ_OVERRIDE {
     MonitorAutoLock lock(mMonitor);
-    nsAutoPtr<VideoData> sample(aSample);
     if (!mTarget || !mTaskQueue) {
       // We've been shutdown, abort.
       return;
     }
-    RefPtr<nsIRunnable> task(new DeliverVideoTask(sample.forget(), mTarget));
+    RefPtr<nsIRunnable> task(new DeliverVideoTask(aSample, mTarget));
     mTaskQueue->Dispatch(task);
   }
 
   virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE {
     MonitorAutoLock lock(mMonitor);
     if (!mTarget || !mTaskQueue) {
       // We've been shutdown, abort.
       return;
@@ -96,21 +94,21 @@ private:
     }
   protected:
     ~DeliverAudioTask()
     {
       MOZ_COUNT_DTOR(DeliverAudioTask);
     }
   public:
     NS_METHOD Run() {
-      mTarget->OnAudioDecoded(mSample.forget());
+      mTarget->OnAudioDecoded(mSample);
       return NS_OK;
     }
   private:
-    nsAutoPtr<AudioData> mSample;
+    nsRefPtr<AudioData> mSample;
     RefPtr<Target> mTarget;
   };
 
   class DeliverVideoTask : public nsRunnable {
   public:
     DeliverVideoTask(VideoData* aSample, Target* aTarget)
       : mSample(aSample)
       , mTarget(aTarget)
@@ -119,21 +117,21 @@ private:
     }
   protected:
     ~DeliverVideoTask()
     {
       MOZ_COUNT_DTOR(DeliverVideoTask);
     }
   public:
     NS_METHOD Run() {
-      mTarget->OnVideoDecoded(mSample.forget());
+      mTarget->OnVideoDecoded(mSample);
       return NS_OK;
     }
   private:
-    nsAutoPtr<VideoData> mSample;
+    nsRefPtr<VideoData> mSample;
     RefPtr<Target> mTarget;
   };
 
   class DeliverNotDecodedTask : public nsRunnable {
   public:
     DeliverNotDecodedTask(MediaData::Type aType,
                           RequestSampleCallback::NotDecodedReason aReason,
                           Target* aTarget)
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -189,17 +189,17 @@ MediaDecoderReader::RequestVideoData(boo
       // again. We don't just decode straight in a loop here, as that
       // would hog the decode task queue.
       RefPtr<nsIRunnable> task(new RequestVideoWithSkipTask(this, aTimeThreshold));
       mTaskQueue->Dispatch(task);
       return;
     }
   }
   if (VideoQueue().GetSize() > 0) {
-    VideoData* v = VideoQueue().PopFront();
+    nsRefPtr<VideoData> v = VideoQueue().PopFront();
     if (v && mVideoDiscontinuity) {
       v->mDiscontinuity = true;
       mVideoDiscontinuity = false;
     }
     GetCallback()->OnVideoDecoded(v);
   } else if (VideoQueue().IsFinished()) {
     GetCallback()->OnNotDecoded(MediaData::VIDEO_DATA, RequestSampleCallback::END_OF_STREAM);
   }
@@ -221,17 +221,17 @@ MediaDecoderReader::RequestAudioData()
     if (AudioQueue().GetSize() == 0 && mTaskQueue) {
       RefPtr<nsIRunnable> task(NS_NewRunnableMethod(
           this, &MediaDecoderReader::RequestAudioData));
       mTaskQueue->Dispatch(task.forget());
       return;
     }
   }
   if (AudioQueue().GetSize() > 0) {
-    AudioData* a = AudioQueue().PopFront();
+    nsRefPtr<AudioData> a = AudioQueue().PopFront();
     if (mAudioDiscontinuity) {
       a->mDiscontinuity = true;
       mAudioDiscontinuity = false;
     }
     GetCallback()->OnAudioDecoded(a);
     return;
   } else if (AudioQueue().IsFinished()) {
     GetCallback()->OnNotDecoded(MediaData::AUDIO_DATA, RequestSampleCallback::END_OF_STREAM);
@@ -303,17 +303,17 @@ AudioDecodeRendezvous::Reset()
 {
   MonitorAutoLock mon(mMonitor);
   mHaveResult = false;
   mStatus = NS_OK;
   mSample = nullptr;
 }
 
 nsresult
-AudioDecodeRendezvous::Await(nsAutoPtr<AudioData>& aSample)
+AudioDecodeRendezvous::Await(nsRefPtr<AudioData>& aSample)
 {
   MonitorAutoLock mon(mMonitor);
   while (!mHaveResult) {
     mon.Wait();
   }
   mHaveResult = false;
   aSample = mSample;
   return mStatus;
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -317,23 +317,23 @@ public:
   virtual void OnVideoDecoded(VideoData* aSample) MOZ_OVERRIDE {}
   virtual void OnNotDecoded(MediaData::Type aType, NotDecodedReason aReason) MOZ_OVERRIDE;
   virtual void OnSeekCompleted(nsresult aResult) MOZ_OVERRIDE {};
   virtual void BreakCycles() MOZ_OVERRIDE {};
   void Reset();
 
   // Returns failure on error, or NS_OK.
   // If *aSample is null, EOS has been reached.
-  nsresult Await(nsAutoPtr<AudioData>& aSample);
+  nsresult Await(nsRefPtr<AudioData>& aSample);
 
   // Interrupts a call to Wait().
   void Cancel();
 
 private:
   Monitor mMonitor;
   nsresult mStatus;
-  nsAutoPtr<AudioData> mSample;
+  nsRefPtr<AudioData> mSample;
   bool mHaveResult;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -398,17 +398,17 @@ void MediaDecoderStateMachine::SendStrea
         mediaStream->AddTrack(TRACK_VIDEO, RATE_VIDEO, 0, video);
         stream->mStream->DispatchWhenNotEnoughBuffered(TRACK_VIDEO,
             GetStateMachineThread(), GetWakeDecoderRunnable());
       }
       stream->mStreamInitialized = true;
     }
 
     if (mInfo.HasAudio()) {
-      nsAutoTArray<AudioData*,10> audio;
+      nsAutoTArray<nsRefPtr<AudioData>,10> audio;
       // It's OK to hold references to the AudioData because while audio
       // is captured, only the decoder thread pops from the queue (see below).
       AudioQueue().GetElementsAfter(stream->mLastAudioPacketTime, &audio);
       AudioSegment output;
       for (uint32_t i = 0; i < audio.Length(); ++i) {
         SendStreamAudio(audio[i], stream, &output);
       }
       if (output.GetDuration() > 0) {
@@ -420,17 +420,17 @@ void MediaDecoderStateMachine::SendStrea
       }
       minLastAudioPacketTime = std::min(minLastAudioPacketTime, stream->mLastAudioPacketTime);
       endPosition = std::max(endPosition,
           mediaStream->TicksToTimeRoundDown(mInfo.mAudio.mRate,
                                             stream->mAudioFramesWritten));
     }
 
     if (mInfo.HasVideo()) {
-      nsAutoTArray<VideoData*,10> video;
+      nsAutoTArray<nsRefPtr<VideoData>,10> video;
       // It's OK to hold references to the VideoData only the decoder thread
       // pops from the queue.
       VideoQueue().GetElementsAfter(stream->mNextVideoTime, &video);
       VideoSegment output;
       for (uint32_t i = 0; i < video.Length(); ++i) {
         VideoData* v = video[i];
         if (stream->mNextVideoTime < v->mTime) {
           VERBOSE_LOG("writing last video to MediaStream %p for %lldus",
@@ -485,17 +485,17 @@ void MediaDecoderStateMachine::SendStrea
       // actually contain data for mCurrentFrameTime. This means if someone might
       // create a new output stream and we actually don't have the audio for the
       // very start. That's OK, we'll play silence instead for a brief moment.
       // That's OK. Seeking to this time would have a similar issue for such
       // badly muxed resources.
       if (!a || a->GetEndTime() >= minLastAudioPacketTime)
         break;
       OnAudioEndTimeUpdate(std::max(mAudioEndTime, a->GetEndTime()));
-      delete AudioQueue().PopFront();
+      nsRefPtr<AudioData> releaseMe = AudioQueue().PopFront();
     }
 
     if (finished) {
       mAudioCompleted = true;
       UpdateReadyState();
     }
   }
 }
@@ -686,36 +686,36 @@ MediaDecoderStateMachine::IsVideoSeekCom
      !mDropVideoUntilNextDiscontinuity &&
      (VideoQueue().IsFinished() || VideoQueue().GetSize() > 0));
 }
 
 void
 MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  nsAutoPtr<AudioData> audio(aAudioSample);
+  nsRefPtr<AudioData> audio(aAudioSample);
   MOZ_ASSERT(audio);
   mAudioRequestPending = false;
 
   SAMPLE_LOG("OnAudioDecoded [%lld,%lld] disc=%d",
              (audio ? audio->mTime : -1),
              (audio ? audio->GetEndTime() : -1),
              (audio ? audio->mDiscontinuity : 0));
 
   switch (mState) {
     case DECODER_STATE_DECODING_FIRSTFRAME: {
-      Push(audio.forget());
+      Push(audio);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_BUFFERING:
     case DECODER_STATE_DECODING: {
       // In buffering and decoding state, we simply enqueue samples.
-      Push(audio.forget());
+      Push(audio);
       return;
     }
 
     case DECODER_STATE_SEEKING: {
       if (!mCurrentSeekTarget.IsValid()) {
         // We've received a sample from a previous decode. Discard it.
         return;
       }
@@ -733,21 +733,21 @@ MediaDecoderStateMachine::OnAudioDecoded
           // seek and decode to the seek target. This is not conformant to the
           // spec, fastSeek should always be fast, but until we get the time to
           // change all Readers to seek to the keyframe after the currentTime
           // in this case, we'll just decode forward. Bug 1026330.
           mCurrentSeekTarget.mType = SeekTarget::Accurate;
         }
         if (mCurrentSeekTarget.mType == SeekTarget::PrevSyncPoint) {
           // Non-precise seek; we can stop the seek at the first sample.
-          AudioQueue().Push(audio.forget());
+          AudioQueue().Push(audio);
         } else {
           // We're doing an accurate seek. We must discard
           // MediaData up to the one containing exact seek target.
-          if (NS_FAILED(DropAudioUpToSeekTarget(audio.forget()))) {
+          if (NS_FAILED(DropAudioUpToSeekTarget(audio))) {
             DecodeError();
             return;
           }
         }
       }
       CheckIfSeekComplete();
       return;
     }
@@ -832,17 +832,18 @@ MediaDecoderStateMachine::OnNotDecoded(M
   // state.
   MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
   if (!isAudio && mState == DECODER_STATE_SEEKING &&
       mCurrentSeekTarget.IsValid() && mFirstVideoFrameAfterSeek) {
     // Null sample. Hit end of stream. If we have decoded a frame,
     // insert it into the queue so that we have something to display.
     // We make sure to do this before invoking VideoQueue().Finish()
     // below.
-    VideoQueue().Push(mFirstVideoFrameAfterSeek.forget());
+    VideoQueue().Push(mFirstVideoFrameAfterSeek);
+    mFirstVideoFrameAfterSeek = nullptr;
   }
   isAudio ? AudioQueue().Finish() : VideoQueue().Finish();
   switch (mState) {
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
@@ -896,34 +897,34 @@ MediaDecoderStateMachine::MaybeFinishDec
     DecodeError();
   }
 }
 
 void
 MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-  nsAutoPtr<VideoData> video(aVideoSample);
+  nsRefPtr<VideoData> video(aVideoSample);
   mVideoRequestPending = false;
 
   SAMPLE_LOG("OnVideoDecoded [%lld,%lld] disc=%d",
              (video ? video->mTime : -1),
              (video ? video->GetEndTime() : -1),
              (video ? video->mDiscontinuity : 0));
 
   switch (mState) {
     case DECODER_STATE_DECODING_FIRSTFRAME: {
-      Push(video.forget());
+      Push(video);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_BUFFERING:
     case DECODER_STATE_DECODING: {
-      Push(video.forget());
+      Push(video);
       // If the requested video sample was slow to arrive, increase the
       // amount of audio we buffer to ensure that we don't run out of audio.
       // TODO: Detect when we're truly async, and don't do this if so, as
       // it's not necessary.
       TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime;
       if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
           !HasLowUndecodedData())
       {
@@ -957,21 +958,21 @@ MediaDecoderStateMachine::OnVideoDecoded
           // seek and decode to the seek target. This is not conformant to the
           // spec, fastSeek should always be fast, but until we get the time to
           // change all Readers to seek to the keyframe after the currentTime
           // in this case, we'll just decode forward. Bug 1026330.
           mCurrentSeekTarget.mType = SeekTarget::Accurate;
         }
         if (mCurrentSeekTarget.mType == SeekTarget::PrevSyncPoint) {
           // Non-precise seek; we can stop the seek at the first sample.
-          VideoQueue().Push(video.forget());
+          VideoQueue().Push(video);
         } else {
           // We're doing an accurate seek. We still need to discard
           // MediaData up to the one containing exact seek target.
-          if (NS_FAILED(DropVideoUpToSeekTarget(video.forget()))) {
+          if (NS_FAILED(DropVideoUpToSeekTarget(video))) {
             DecodeError();
             return;
           }
         }
       }
       CheckIfSeekComplete();
       return;
     }
@@ -2790,32 +2791,32 @@ void MediaDecoderStateMachine::AdvanceFr
   }
 
   const int64_t clock_time = GetClock();
   TimeStamp nowTime = TimeStamp::Now();
   // Skip frames up to the frame at the playback position, and figure out
   // the time remaining until it's time to display the next frame.
   int64_t remainingTime = AUDIO_DURATION_USECS;
   NS_ASSERTION(clock_time >= mStartTime, "Should have positive clock time.");
-  nsAutoPtr<VideoData> currentFrame;
+  nsRefPtr<VideoData> currentFrame;
   if (VideoQueue().GetSize() > 0) {
     VideoData* frame = VideoQueue().PeekFront();
 #ifdef PR_LOGGING
     int32_t droppedFrames = 0;
 #endif
     while (mScheduler->IsRealTime() || clock_time >= frame->mTime) {
       mVideoFrameEndTime = frame->GetEndTime();
 #ifdef PR_LOGGING
       if (currentFrame) {
         VERBOSE_LOG("discarding video frame mTime=%lld clock_time=%lld (%d so far)",
                     currentFrame->mTime, clock_time, ++droppedFrames);
       }
 #endif
       currentFrame = frame;
-      VideoQueue().PopFront();
+      nsRefPtr<VideoData> releaseMe = VideoQueue().PopFront();
       // Notify the decode thread that the video queue's buffers may have
       // free'd up space for more frames.
       mDecoder->GetReentrantMonitor().NotifyAll();
       OnPlaybackOffsetUpdate(frame->mOffset);
       if (VideoQueue().GetSize() == 0)
         break;
       frame = VideoQueue().PeekFront();
     }
@@ -2831,17 +2832,17 @@ void MediaDecoderStateMachine::AdvanceFr
   // Check to see if we don't have enough data to play up to the next frame.
   // If we don't, switch to buffering mode.
   if (mState == DECODER_STATE_DECODING &&
       mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
       HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
       mDecoder->IsExpectingMoreData()) {
     if (JustExitedQuickBuffering() || HasLowUndecodedData()) {
       if (currentFrame) {
-        VideoQueue().PushFront(currentFrame.forget());
+        VideoQueue().PushFront(currentFrame);
       }
       StartBuffering();
       // Don't go straight back to the state machine loop since that might
       // cause us to start decoding again and we could flip-flop between
       // decoding and quick-buffering.
       ScheduleStateMachine(USECS_PER_S);
       return;
     }
@@ -2901,32 +2902,32 @@ void MediaDecoderStateMachine::AdvanceFr
   UpdateReadyState();
 
   ScheduleStateMachine(remainingTime / mPlaybackRate);
 }
 
 nsresult
 MediaDecoderStateMachine::DropVideoUpToSeekTarget(VideoData* aSample)
 {
-  nsAutoPtr<VideoData> video(aSample);
+  nsRefPtr<VideoData> video(aSample);
   MOZ_ASSERT(video);
   DECODER_LOG("DropVideoUpToSeekTarget() frame [%lld, %lld] dup=%d",
               video->mTime, video->GetEndTime(), video->mDuplicate);
   const int64_t target = mCurrentSeekTarget.mTime;
 
   // Duplicate handling: if we're dropping frames up the seek target, we must
   // be wary of Theora duplicate frames. They don't have an image, so if the
   // target frame is in a run of duplicates, we won't have an image to draw
   // after the seek. So store the last frame encountered while dropping, and
   // copy its Image forward onto duplicate frames, so that every frame has
   // an Image.
   if (video->mDuplicate &&
       mFirstVideoFrameAfterSeek &&
       !mFirstVideoFrameAfterSeek->mDuplicate) {
-    VideoData* temp =
+    nsRefPtr<VideoData> temp =
       VideoData::ShallowCopyUpdateTimestampAndDuration(mFirstVideoFrameAfterSeek,
                                                        video->mTime,
                                                        video->mDuration);
     video = temp;
   }
 
   // If the frame end time is less than the seek target, we won't want
   // to display this frame after the seek, so discard it.
@@ -2934,34 +2935,34 @@ MediaDecoderStateMachine::DropVideoUpToS
     DECODER_LOG("DropVideoUpToSeekTarget() pop video frame [%lld, %lld] target=%lld",
                 video->mTime, video->GetEndTime(), target);
     mFirstVideoFrameAfterSeek = video;
   } else {
     if (target >= video->mTime && video->GetEndTime() >= target) {
       // The seek target lies inside this frame's time slice. Adjust the frame's
       // start time to match the seek target. We do this by replacing the
       // first frame with a shallow copy which has the new timestamp.
-      VideoData* temp = VideoData::ShallowCopyUpdateTimestamp(video, target);
+      nsRefPtr<VideoData> temp = VideoData::ShallowCopyUpdateTimestamp(video, target);
       video = temp;
     }
     mFirstVideoFrameAfterSeek = nullptr;
 
     DECODER_LOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
                 video->mTime, video->GetEndTime(), target);
 
-    VideoQueue().PushFront(video.forget());
-
+    VideoQueue().PushFront(video);
   }
+
   return NS_OK;
 }
 
 nsresult
 MediaDecoderStateMachine::DropAudioUpToSeekTarget(AudioData* aSample)
 {
-  nsAutoPtr<AudioData> audio(aSample);
+  nsRefPtr<AudioData> audio(aSample);
   MOZ_ASSERT(audio &&
              mCurrentSeekTarget.IsValid() &&
              mCurrentSeekTarget.mType == SeekTarget::Accurate);
 
   CheckedInt64 startFrame = UsecsToFrames(audio->mTime,
                                           mInfo.mAudio.mRate);
   CheckedInt64 targetFrame = UsecsToFrames(mCurrentSeekTarget.mTime,
                                            mInfo.mAudio.mRate);
@@ -2977,17 +2978,17 @@ MediaDecoderStateMachine::DropAudioUpToS
     // The seek target doesn't lie in the audio block just after the last
     // audio frames we've seen which were before the seek target. This
     // could have been the first audio data we've seen after seek, i.e. the
     // seek terminated after the seek target in the audio stream. Just
     // abort the audio decode-to-target, the state machine will play
     // silence to cover the gap. Typically this happens in poorly muxed
     // files.
     DECODER_WARN("Audio not synced after seek, maybe a poorly muxed file?");
-    AudioQueue().Push(audio.forget());
+    AudioQueue().Push(audio);
     return NS_OK;
   }
 
   // The seek target lies somewhere in this AudioData's frames, strip off
   // any frames which lie before the seek target, so we'll begin playback
   // exactly at the seek target.
   NS_ASSERTION(targetFrame.value() >= startFrame.value(),
                "Target must at or be after data start.");
@@ -3006,24 +3007,24 @@ MediaDecoderStateMachine::DropAudioUpToS
   nsAutoArrayPtr<AudioDataValue> audioData(new AudioDataValue[frames * channels]);
   memcpy(audioData.get(),
          audio->mAudioData.get() + (framesToPrune * channels),
          frames * channels * sizeof(AudioDataValue));
   CheckedInt64 duration = FramesToUsecs(frames, mInfo.mAudio.mRate);
   if (!duration.isValid()) {
     return NS_ERROR_FAILURE;
   }
-  nsAutoPtr<AudioData> data(new AudioData(audio->mOffset,
-                                          mCurrentSeekTarget.mTime,
-                                          duration.value(),
-                                          frames,
-                                          audioData.forget(),
-                                          channels,
-                                          audio->mRate));
-  AudioQueue().PushFront(data.forget());
+  nsRefPtr<AudioData> data(new AudioData(audio->mOffset,
+                                         mCurrentSeekTarget.mTime,
+                                         duration.value(),
+                                         frames,
+                                         audioData.forget(),
+                                         channels,
+                                         audio->mRate));
+  AudioQueue().PushFront(data);
 
   return NS_OK;
 }
 
 void MediaDecoderStateMachine::SetStartTime(int64_t aStartTimeUsecs)
 {
   AssertCurrentThreadInMonitor();
   DECODER_LOG("SetStartTime(%lld)", aStartTimeUsecs);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -872,17 +872,17 @@ protected:
   // samples we must consume before are considered to be finished prerolling.
   uint32_t mAudioPrerollUsecs;
   uint32_t mVideoPrerollFrames;
 
   // This temporarily stores the first frame we decode after we seek.
   // This is so that if we hit end of stream while we're decoding to reach
   // the seek target, we will still have a frame that we can display as the
   // last frame in the media.
-  nsAutoPtr<VideoData> mFirstVideoFrameAfterSeek;
+  nsRefPtr<VideoData> mFirstVideoFrameAfterSeek;
 
   // When we start decoding (either for the first time, or after a pause)
   // we may be low on decoded data. We don't want our "low data" logic to
   // kick in and decide that we're low on decoded data because the download
   // can't keep up with the decode, and cause us to pause playback. So we
   // have a "preroll" stage, where we ignore the results of our "low data"
   // logic during the first few frames of our decode. This occurs during
   // playback. The flags below are true when the corresponding stream is
--- a/dom/media/MediaQueue.h
+++ b/dom/media/MediaQueue.h
@@ -13,17 +13,17 @@
 #include "MediaTaskQueue.h"
 
 namespace mozilla {
 
 // Thread and type safe wrapper around nsDeque.
 template <class T>
 class MediaQueueDeallocator : public nsDequeFunctor {
   virtual void* operator() (void* aObject) {
-    delete static_cast<T*>(aObject);
+    nsRefPtr<T> releaseMe = dont_AddRef(static_cast<T*>(aObject));
     return nullptr;
   }
 };
 
 template <class T> class MediaQueue : private nsDeque {
  public:
 
    MediaQueue()
@@ -39,32 +39,34 @@ template <class T> class MediaQueue : pr
   inline int32_t GetSize() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return nsDeque::GetSize();
   }
 
   inline void Push(T* aItem) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     MOZ_ASSERT(aItem);
+    NS_ADDREF(aItem);
     nsDeque::Push(aItem);
   }
 
   inline void PushFront(T* aItem) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     MOZ_ASSERT(aItem);
+    NS_ADDREF(aItem);
     nsDeque::PushFront(aItem);
   }
 
-  inline T* PopFront() {
+  inline already_AddRefed<T> PopFront() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    T* rv = static_cast<T*>(nsDeque::PopFront());
+    nsRefPtr<T> rv = dont_AddRef(static_cast<T*>(nsDeque::PopFront()));
     if (rv) {
       NotifyPopListeners();
     }
-    return rv;
+    return rv.forget();
   }
 
   inline T* Peek() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return static_cast<T*>(nsDeque::Peek());
   }
 
   inline T* PeekFront() {
@@ -75,18 +77,17 @@ template <class T> class MediaQueue : pr
   inline void Empty() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     nsDeque::Empty();
   }
 
   void Reset() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     while (GetSize() > 0) {
-      T* x = PopFront();
-      delete x;
+      nsRefPtr<T> x = PopFront();
     }
     mEndOfStream = false;
   }
 
   bool AtEndOfStream() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     return GetSize() == 0 && mEndOfStream;
   }
@@ -118,30 +119,31 @@ template <class T> class MediaQueue : pr
 
   void LockedForEach(nsDequeFunctor& aFunctor) const {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     ForEach(aFunctor);
   }
 
   // Extracts elements from the queue into aResult, in order.
   // Elements whose start time is before aTime are ignored.
-  void GetElementsAfter(int64_t aTime, nsTArray<T*>* aResult) {
+  void GetElementsAfter(int64_t aTime, nsTArray<nsRefPtr<T>>* aResult) {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     if (!GetSize())
       return;
     int32_t i;
     for (i = GetSize() - 1; i > 0; --i) {
       T* v = static_cast<T*>(ObjectAt(i));
       if (v->GetEndTime() < aTime)
         break;
     }
     // Elements less than i have a end time before aTime. It's also possible
     // that the element at i has a end time before aTime, but that's OK.
     for (; i < GetSize(); ++i) {
-      aResult->AppendElement(static_cast<T*>(ObjectAt(i)));
+      nsRefPtr<T> elem = static_cast<T*>(ObjectAt(i));
+      aResult->AppendElement(elem);
     }
   }
 
   uint32_t FrameCount() {
     ReentrantMonitorAutoEnter mon(mReentrantMonitor);
     uint32_t frames = 0;
     for (int32_t i = 0; i < GetSize(); ++i) {
       T* v = static_cast<T*>(ObjectAt(i));
--- a/dom/media/android/AndroidMediaReader.cpp
+++ b/dom/media/android/AndroidMediaReader.cpp
@@ -139,18 +139,19 @@ bool AndroidMediaReader::DecodeVideoFram
     if (!mPlugin->ReadVideo(mPlugin, &frame, mVideoSeekTimeUs, &bufferCallback)) {
       // We reached the end of the video stream. If we have a buffered
       // video frame, push it the video queue using the total duration
       // of the video as the end time.
       if (mLastVideoFrame) {
         int64_t durationUs;
         mPlugin->GetDuration(mPlugin, &durationUs);
         durationUs = std::max<int64_t>(durationUs - mLastVideoFrame->mTime, 0);
-        mVideoQueue.Push(VideoData::ShallowCopyUpdateDuration(mLastVideoFrame,
-                                                              durationUs));
+        nsRefPtr<VideoData> data = VideoData::ShallowCopyUpdateDuration(mLastVideoFrame,
+                                                                        durationUs);
+        mVideoQueue.Push(data);
         mLastVideoFrame = nullptr;
       }
       return false;
     }
     mVideoSeekTimeUs = -1;
 
     if (aKeyframeSkip) {
       // Disable keyframe skipping for now as
@@ -167,17 +168,17 @@ bool AndroidMediaReader::DecodeVideoFram
 
     if (frame.mSize == 0)
       return true;
 
     currentImage = bufferCallback.GetImage();
     int64_t pos = mDecoder->GetResource()->Tell();
     IntRect picture = ToIntRect(mPicture);
 
-    nsAutoPtr<VideoData> v;
+    nsRefPtr<VideoData> v;
     if (currentImage) {
       gfx::IntSize frameSize = currentImage->GetSize();
       if (frameSize.width != mInitialFrame.width ||
           frameSize.height != mInitialFrame.height) {
         // Frame size is different from what the container reports. This is legal,
         // and we will preserve the ratio of the crop rectangle as it
         // was reported relative to the picture size reported by the container.
         picture.x = (mPicture.x * frameSize.width) / mInitialFrame.width;
@@ -268,19 +269,18 @@ bool AndroidMediaReader::DecodeVideoFram
     // We have the start time of the next frame, so we can push the previous
     // frame into the queue, except if the end time is below the threshold,
     // in which case it wouldn't be displayed anyway.
     if (mLastVideoFrame->GetEndTime() < aTimeThreshold) {
       mLastVideoFrame = nullptr;
       continue;
     }
 
-    mVideoQueue.Push(mLastVideoFrame.forget());
-
     // Buffer the current frame we just decoded.
+    mVideoQueue.Push(mLastVideoFrame);
     mLastVideoFrame = v;
 
     break;
   }
 
   return true;
 }
 
--- a/dom/media/android/AndroidMediaReader.h
+++ b/dom/media/android/AndroidMediaReader.h
@@ -34,17 +34,17 @@ class AndroidMediaReader : public MediaD
   nsCString mType;
   MPAPI::Decoder *mPlugin;
   bool mHasAudio;
   bool mHasVideo;
   nsIntRect mPicture;
   nsIntSize mInitialFrame;
   int64_t mVideoSeekTimeUs;
   int64_t mAudioSeekTimeUs;
-  nsAutoPtr<VideoData> mLastVideoFrame;
+  nsRefPtr<VideoData> mLastVideoFrame;
 public:
   AndroidMediaReader(AbstractMediaDecoder* aDecoder,
                      const nsACString& aContentType);
 
   virtual nsresult Init(MediaDecoderReader* aCloneDonor);
   virtual nsresult ResetDecode();
 
   virtual bool DecodeAudioData();
--- a/dom/media/fmp4/BlankDecoderModule.cpp
+++ b/dom/media/fmp4/BlankDecoderModule.cpp
@@ -46,19 +46,20 @@ public:
                 BlankMediaDataCreator* aCreator)
       : mSample(aSample)
       , mCreator(aCreator)
       , mCallback(aCallback)
     {
     }
     NS_IMETHOD Run() MOZ_OVERRIDE
     {
-      mCallback->Output(mCreator->Create(mSample->composition_timestamp,
-                                         mSample->duration,
-                                         mSample->byte_offset));
+      nsRefPtr<MediaData> data = mCreator->Create(mSample->composition_timestamp,
+                                                  mSample->duration,
+                                                  mSample->byte_offset);
+      mCallback->Output(data);
       return NS_OK;
     }
   private:
     nsAutoPtr<mp4_demuxer::MP4Sample> mSample;
     BlankMediaDataCreator* mCreator;
     MediaDataDecoderCallback* mCallback;
   };
 
@@ -79,17 +80,16 @@ public:
 
   virtual nsresult Drain() MOZ_OVERRIDE {
     mCallback->DrainComplete();
     return NS_OK;
   }
 
 private:
   nsAutoPtr<BlankMediaDataCreator> mCreator;
-  nsAutoPtr<MediaData> mOutput;
   RefPtr<MediaTaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
 };
 
 class BlankVideoDataCreator {
 public:
   BlankVideoDataCreator(uint32_t aFrameWidth,
                         uint32_t aFrameHeight,
@@ -97,19 +97,18 @@ public:
     : mFrameWidth(aFrameWidth)
     , mFrameHeight(aFrameHeight)
     , mImageContainer(aImageContainer)
   {
     mInfo.mDisplay = nsIntSize(mFrameWidth, mFrameHeight);
     mPicture = gfx::IntRect(0, 0, mFrameWidth, mFrameHeight);
   }
 
-  MediaData* Create(Microseconds aDTS,
-                    Microseconds aDuration,
-                    int64_t aOffsetInStream)
+  already_AddRefed<MediaData>
+  Create(Microseconds aDTS, Microseconds aDuration, int64_t aOffsetInStream)
   {
     // Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane,
     // with a U and V plane that are half the size of the Y plane, i.e 8 bit,
     // 2x2 subsampled. Have the data pointers of each frame point to the
     // first plane, they'll always be zero'd memory anyway.
     nsAutoArrayPtr<uint8_t> frame(new uint8_t[mFrameWidth * mFrameHeight]);
     memset(frame, 0, mFrameWidth * mFrameHeight);
     VideoData::YCbCrBuffer buffer;
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -619,17 +619,16 @@ MP4Reader::Output(TrackType aTrack, Medi
     Error(aTrack);
     return;
   }
 
   DecoderData& data = GetDecoderData(aTrack);
   // Don't accept output while we're flushing.
   MonitorAutoLock mon(data.mMonitor);
   if (data.mIsFlushing) {
-    delete aSample;
     LOG("MP4Reader produced output while flushing, discarding.");
     mon.NotifyAll();
     return;
   }
 
   switch (aTrack) {
     case kAudio: {
       MOZ_ASSERT(aSample->mType == MediaData::AUDIO_DATA);
--- a/dom/media/fmp4/PlatformDecoderModule.h
+++ b/dom/media/fmp4/PlatformDecoderModule.h
@@ -136,18 +136,17 @@ protected:
 };
 
 // A callback used by MediaDataDecoder to return output/errors to the
 // MP4Reader. Implementation is threadsafe, and can be called on any thread.
 class MediaDataDecoderCallback {
 public:
   virtual ~MediaDataDecoderCallback() {}
 
-  // Called by MediaDataDecoder when a sample has been decoded. Callee is
-  // responsibile for deleting aData.
+  // Called by MediaDataDecoder when a sample has been decoded.
   virtual void Output(MediaData* aData) = 0;
 
   // Denotes an error in the decoding process. The reader will stop calling
   // the decoder.
   virtual void Error() = 0;
 
   // Denotes that the last input sample has been inserted into the decoder,
   // and no more output can be produced unless more input is sent.
--- a/dom/media/fmp4/android/AndroidDecoderModule.cpp
+++ b/dom/media/fmp4/android/AndroidDecoderModule.cpp
@@ -74,24 +74,25 @@ public:
     layers::SurfaceTextureImage::Data data;
     data.mSurfTex = mSurfaceTexture.get();
     data.mSize = gfx::IntSize(mConfig.display_width, mConfig.display_height);
     data.mInverted = true;
 
     layers::SurfaceTextureImage* typedImg = static_cast<layers::SurfaceTextureImage*>(img.get());
     typedImg->SetData(data);
 
-    mCallback->Output(VideoData::CreateFromImage(videoInfo, mImageContainer, aInfo->getOffset(),
-                                                 aInfo->getPresentationTimeUs(),
-                                                 aDuration,
-                                                 img, isSync,
-                                                 aInfo->getPresentationTimeUs(),
-                                                 gfx::IntRect(0, 0,
-                                                   mConfig.display_width,
-                                                   mConfig.display_height)));
+    nsRefPtr<VideoData> v = VideoData::CreateFromImage(videoInfo, mImageContainer, aInfo->getOffset(),
+                                                       aInfo->getPresentationTimeUs(),
+                                                       aDuration,
+                                                       img, isSync,
+                                                       aInfo->getPresentationTimeUs(),
+                                                       gfx::IntRect(0, 0,
+                                                         mConfig.display_width,
+                                                         mConfig.display_height));
+    mCallback->Output(v);
     return NS_OK;
   }
 
 protected:
   layers::ImageContainer* mImageContainer;
   const mp4_demuxer::VideoDecoderConfig& mConfig;
   RefPtr<AndroidSurfaceTexture> mSurfaceTexture;
 };
--- a/dom/media/fmp4/apple/AppleVDADecoder.cpp
+++ b/dom/media/fmp4/apple/AppleVDADecoder.cpp
@@ -209,17 +209,17 @@ AppleVDADecoder::DrainReorderedFrames()
     mCallback->Output(mReorderQueue.Pop());
   }
 }
 
 void
 AppleVDADecoder::ClearReorderedFrames()
 {
   while (!mReorderQueue.IsEmpty()) {
-    delete mReorderQueue.Pop();
+    mReorderQueue.Pop();
   }
 }
 
 // Copy and return a decoded frame.
 nsresult
 AppleVDADecoder::OutputFrame(CVPixelBufferRef aImage,
                              nsAutoPtr<AppleVDADecoder::AppleFrameRef> aFrameRef)
 {
@@ -245,17 +245,17 @@ AppleVDADecoder::OutputFrame(CVPixelBuff
                                       mConfig.display_height);
 
   nsRefPtr<layers::Image> image =
     mImageContainer->CreateImage(ImageFormat::MAC_IOSURFACE);
   layers::MacIOSurfaceImage* videoImage =
     static_cast<layers::MacIOSurfaceImage*>(image.get());
   videoImage->SetSurface(macSurface);
 
-  nsAutoPtr<VideoData> data;
+  nsRefPtr<VideoData> data;
   data = VideoData::CreateFromImage(info,
                                     mImageContainer,
                                     aFrameRef->byte_offset,
                                     aFrameRef->composition_timestamp,
                                     aFrameRef->duration, image.forget(),
                                     aFrameRef->is_sync_point,
                                     aFrameRef->decode_timestamp,
                                     visible);
@@ -263,20 +263,20 @@ AppleVDADecoder::OutputFrame(CVPixelBuff
   if (!data) {
     NS_ERROR("Couldn't create VideoData for frame");
     mCallback->Error();
     return NS_ERROR_FAILURE;
   }
 
   // Frames come out in DTS order but we need to output them
   // in composition order.
-  mReorderQueue.Push(data.forget());
+  mReorderQueue.Push(data);
   // Assume a frame with a PTS <= current DTS is ready.
   while (mReorderQueue.Length() > 0) {
-    VideoData* readyData = mReorderQueue.Pop();
+    nsRefPtr<VideoData> readyData = mReorderQueue.Pop();
     if (readyData->mTime <= aFrameRef->decode_timestamp) {
       LOG("returning queued frame with pts %lld", readyData->mTime);
       mCallback->Output(readyData);
     } else {
       LOG("requeued frame with pts %lld > %lld",
           readyData->mTime, aFrameRef->decode_timestamp);
       mReorderQueue.Push(readyData);
       break;
--- a/dom/media/fmp4/apple/ReorderQueue.h
+++ b/dom/media/fmp4/apple/ReorderQueue.h
@@ -17,13 +17,13 @@ namespace mozilla {
 struct ReorderQueueComparator
 {
   bool LessThan(VideoData* const& a, VideoData* const& b) const
   {
     return a->mTime < b->mTime;
   }
 };
 
-typedef nsTPriorityQueue<VideoData*, ReorderQueueComparator> ReorderQueue;
+typedef nsTPriorityQueue<nsRefPtr<VideoData>, ReorderQueueComparator> ReorderQueue;
 
 } // namespace mozilla
 
 #endif // mozilla_ReorderQueue_h
--- a/dom/media/fmp4/eme/EMEAudioDecoder.cpp
+++ b/dom/media/fmp4/eme/EMEAudioDecoder.cpp
@@ -170,30 +170,30 @@ EMEAudioDecoder::Decoded(const nsTArray<
 
   auto duration = FramesToUsecs(numFrames, aRate);
   if (!duration.isValid()) {
     NS_WARNING("Invalid duration on audio samples");
     mCallback->Error();
     return;
   }
 
-  nsAutoPtr<AudioData> audio(new AudioData(mStreamOffset,
-                                           timestamp.value(),
-                                           duration.value(),
-                                           numFrames,
-                                           audioData.forget(),
-                                           aChannels,
-                                           aRate));
+  nsRefPtr<AudioData> audio(new AudioData(mStreamOffset,
+                                          timestamp.value(),
+                                          duration.value(),
+                                          numFrames,
+                                          audioData.forget(),
+                                          aChannels,
+                                          aRate));
 
   #ifdef LOG_SAMPLE_DECODE
   LOG("Decoded audio sample! timestamp=%lld duration=%lld currentLength=%u",
       timestamp, duration, currentLength);
   #endif
 
-  mCallback->Output(audio.forget());
+  mCallback->Output(audio);
 }
 
 void
 EMEAudioDecoder::InputDataExhausted()
 {
   MOZ_ASSERT(IsOnGMPThread());
   mCallback->InputExhausted();
 }
--- a/dom/media/fmp4/eme/EMEH264Decoder.cpp
+++ b/dom/media/fmp4/eme/EMEH264Decoder.cpp
@@ -152,25 +152,25 @@ EMEH264Decoder::Decoded(GMPVideoi420Fram
   b.mPlanes[2].mData = aDecodedFrame->Buffer(kGMPVPlane);
   b.mPlanes[2].mStride = aDecodedFrame->Stride(kGMPVPlane);
   b.mPlanes[2].mHeight = height / 2;
   b.mPlanes[2].mWidth = width / 2;
   b.mPlanes[2].mOffset = 0;
   b.mPlanes[2].mSkip = 0;
 
   gfx::IntRect pictureRegion(0, 0, width, height);
-  VideoData *v = VideoData::Create(mVideoInfo,
-                                   mImageContainer,
-                                   mLastStreamOffset,
-                                   aDecodedFrame->Timestamp(),
-                                   aDecodedFrame->Duration(),
-                                   b,
-                                   false,
-                                   -1,
-                                   pictureRegion);
+  nsRefPtr<VideoData> v = VideoData::Create(mVideoInfo,
+                                            mImageContainer,
+                                            mLastStreamOffset,
+                                            aDecodedFrame->Timestamp(),
+                                            aDecodedFrame->Duration(),
+                                            b,
+                                            false,
+                                            -1,
+                                            pictureRegion);
   aDecodedFrame->Destroy();
   mCallback->Output(v);
 }
 
 void
 EMEH264Decoder::ReceivedDecodedReferenceFrame(const uint64_t aPictureId)
 {
   // Ignore.
--- a/dom/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
+++ b/dom/media/fmp4/ffmpeg/FFmpegH264Decoder.cpp
@@ -98,25 +98,25 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFr
     b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
 
     b.mPlanes[2].mData = mFrame->data[2];
     b.mPlanes[2].mStride = mFrame->linesize[2];
     b.mPlanes[2].mHeight = (mFrame->height + 1) >> 1;
     b.mPlanes[2].mWidth = (mFrame->width + 1) >> 1;
     b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
 
-    VideoData *v = VideoData::Create(info,
-                                     mImageContainer,
-                                     aSample->byte_offset,
-                                     mFrame->pkt_pts,
-                                     aSample->duration,
-                                     b,
-                                     aSample->is_sync_point,
-                                     -1,
-                                     gfx::IntRect(0, 0, mCodecContext->width, mCodecContext->height));
+    nsRefPtr<VideoData> v = VideoData::Create(info,
+                                              mImageContainer,
+                                              aSample->byte_offset,
+                                              mFrame->pkt_pts,
+                                              aSample->duration,
+                                              b,
+                                              aSample->is_sync_point,
+                                              -1,
+                                              gfx::IntRect(0, 0, mCodecContext->width, mCodecContext->height));
     if (!v) {
       NS_WARNING("image allocation error.");
       mCallback->Error();
       return DecodeResult::DECODE_ERROR;
     }
     mCallback->Output(v);
     return DecodeResult::DECODE_FRAME;
   }
--- a/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.cpp
+++ b/dom/media/fmp4/ffmpeg/FFmpegRuntimeLinker.cpp
@@ -27,16 +27,17 @@ struct AvFormatLib
 
 template <int V> class FFmpegDecoderModule
 {
 public:
   static PlatformDecoderModule* Create();
 };
 
 static const AvFormatLib sLibs[] = {
+  { "libavformat.so.56", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.55", FFmpegDecoderModule<55>::Create, 55 },
   { "libavformat.so.54", FFmpegDecoderModule<54>::Create, 54 },
   { "libavformat.so.53", FFmpegDecoderModule<53>::Create, 53 },
 };
 
 void* FFmpegRuntimeLinker::sLinkedLib = nullptr;
 const AvFormatLib* FFmpegRuntimeLinker::sLib = nullptr;
 
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.cpp
@@ -124,40 +124,41 @@ GonkAudioDecoderManager::CreateAudioData
   nsAutoArrayPtr<AudioDataValue> buffer(new AudioDataValue[size/2]);
   memcpy(buffer.get(), data+dataOffset, size);
   uint32_t frames = size / (2 * mAudioChannels);
 
   CheckedInt64 duration = FramesToUsecs(frames, mAudioRate);
   if (!duration.isValid()) {
     return NS_ERROR_UNEXPECTED;
   }
-  *v = new AudioData(aStreamOffset,
-                     timeUs,
-                     duration.value(),
-                     frames,
-                     buffer.forget(),
-                     mAudioChannels,
-                     mAudioRate);
+  nsRefPtr<AudioData> audioData = new AudioData(aStreamOffset,
+                                                timeUs,
+                                                duration.value(),
+                                                frames,
+                                                buffer.forget(),
+                                                mAudioChannels,
+                                                mAudioRate);
   ReleaseAudioBuffer();
+  audioData.forget(v);
   return NS_OK;
 }
 
 nsresult
 GonkAudioDecoderManager::Output(int64_t aStreamOffset,
-                                nsAutoPtr<MediaData>& aOutData)
+                                nsRefPtr<MediaData>& aOutData)
 {
   aOutData = nullptr;
   status_t err;
   err = mDecoder->Output(&mAudioBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
 
   switch (err) {
     case OK:
     {
-      AudioData* data = nullptr;
-      nsresult rv = CreateAudioData(aStreamOffset, &data);
+      nsRefPtr<AudioData> data;
+      nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data));
       if (rv == NS_ERROR_NOT_AVAILABLE) {
         // Decoder outputs an empty video buffer, try again
         return NS_ERROR_NOT_AVAILABLE;
       } else if (rv != NS_OK || data == nullptr) {
         return NS_ERROR_UNEXPECTED;
       }
       aOutData = data;
       return NS_OK;
@@ -171,18 +172,18 @@ GonkAudioDecoderManager::Output(int64_t 
     }
     case -EAGAIN:
     {
       return NS_ERROR_NOT_AVAILABLE;
     }
     case android::ERROR_END_OF_STREAM:
     {
       ALOG("Got EOS frame!");
-      AudioData* data = nullptr;
-      nsresult rv = CreateAudioData(aStreamOffset, &data);
+      nsRefPtr<AudioData> data;
+      nsresult rv = CreateAudioData(aStreamOffset, getter_AddRefs(data));
       if (rv == NS_ERROR_NOT_AVAILABLE) {
         // For EOS, no need to do any thing.
         return NS_ERROR_ABORT;
       } else if (rv != NS_OK || data == nullptr) {
         ALOG("Failed to create audio data!");
         return NS_ERROR_UNEXPECTED;
       }
       aOutData = data;
--- a/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkAudioDecoderManager.h
@@ -26,17 +26,17 @@ public:
   GonkAudioDecoderManager(const mp4_demuxer::AudioDecoderConfig& aConfig);
   ~GonkAudioDecoderManager();
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual nsresult Output(int64_t aStreamOffset,
-                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+                          nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 private:
 
   nsresult CreateAudioData(int64_t aStreamOffset,
                               AudioData** aOutData);
 
   void ReleaseAudioBuffer();
   // MediaCodedc's wrapper that performs the decoding.
   android::sp<MediaCodecProxy> mDecoder;
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.cpp
@@ -84,22 +84,22 @@ GonkMediaDataDecoder::ProcessDecode(mp4_
     mLastStreamOffset = aSample->byte_offset;
   }
   ProcessOutput();
 }
 
 void
 GonkMediaDataDecoder::ProcessOutput()
 {
-  nsAutoPtr<MediaData> output;
+  nsRefPtr<MediaData> output;
   nsresult rv;
   while (true && !mDrainComplete) {
     rv = mManager->Output(mLastStreamOffset, output);
     if (rv == NS_OK) {
-      mCallback->Output(output.forget());
+      mCallback->Output(output);
       continue;
     } else if (rv == NS_ERROR_NOT_AVAILABLE && mSignaledEOS) {
       // Try to get more frames before getting EOS frame
       continue;
     }
     else {
       break;
     }
@@ -109,18 +109,18 @@ GonkMediaDataDecoder::ProcessOutput()
     mCallback->InputExhausted();
     return;
   }
   if (rv != NS_OK) {
     NS_WARNING("GonkMediaDataDecoder failed to output data");
     ALOG("Failed to output data");
     // GonkDecoderManangers report NS_ERROR_ABORT when EOS is reached.
     if (rv == NS_ERROR_ABORT) {
-      if (output.get() != nullptr) {
-        mCallback->Output(output.forget());
+      if (output) {
+        mCallback->Output(output);
       }
       mCallback->DrainComplete();
       mSignaledEOS = false;
       mDrainComplete = true;
       return;
     }
     mCallback->Error();
   }
--- a/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
+++ b/dom/media/fmp4/gonk/GonkMediaDataDecoder.h
@@ -27,17 +27,17 @@ public:
 
   // Produces decoded output, it blocks until output can be produced or a timeout
   // is expired or until EOS. Returns NS_OK on success, or NS_ERROR_NOT_AVAILABLE
   // if there's not enough data to produce more output. If this returns a failure
   // code other than NS_ERROR_NOT_AVAILABLE, an error will be reported to the
   // MP4Reader.
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) = 0;
   virtual nsresult Output(int64_t aStreamOffset,
-                          nsAutoPtr<MediaData>& aOutput) = 0;
+                          nsRefPtr<MediaData>& aOutput) = 0;
 
 };
 
 // Samples are decoded using the GonkDecoder (MediaCodec)
 // created by the GonkDecoderManager. This class implements
 // the higher-level logic that drives mapping the Gonk to the async
 // MediaDataDecoder interface. The specifics of decoding the exact stream
 // type are handled by GonkDecoderManager and the GonkDecoder it creates.
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -120,16 +120,17 @@ GonkVideoDecoderManager::Init(MediaDataD
 
   return mDecoder;
 }
 
 nsresult
 GonkVideoDecoderManager::CreateVideoData(int64_t aStreamOffset, VideoData **v)
 {
   *v = nullptr;
+  nsRefPtr<VideoData> data;
   int64_t timeUs;
   int32_t keyFrame;
 
   if (mVideoBuffer == nullptr) {
     ALOG("Video Buffer is not valid!");
     return NS_ERROR_UNEXPECTED;
   }
 
@@ -168,26 +169,25 @@ GonkVideoDecoderManager::CreateVideoData
     textureClient = mNativeWindow->getTextureClientFromBuffer(mVideoBuffer->graphicBuffer().get());
   }
 
   if (textureClient) {
     GrallocTextureClientOGL* grallocClient = static_cast<GrallocTextureClientOGL*>(textureClient.get());
     grallocClient->SetMediaBuffer(mVideoBuffer);
     textureClient->SetRecycleCallback(GonkVideoDecoderManager::RecycleCallback, this);
 
-    *v = VideoData::Create(mInfo.mVideo,
-                          mImageContainer,
-                          aStreamOffset,
-                          timeUs,
-                          1, // We don't know the duration.
-                          textureClient,
-                          keyFrame,
-                          -1,
-                          picture);
-
+    data = VideoData::Create(mInfo.mVideo,
+                             mImageContainer,
+                             aStreamOffset,
+                             timeUs,
+                             1, // We don't know the duration.
+                             textureClient,
+                             keyFrame,
+                             -1,
+                             picture);
   } else {
     if (!mVideoBuffer->data()) {
       ALOG("No data in Video Buffer!");
       return NS_ERROR_UNEXPECTED;
     }
     uint8_t *yuv420p_buffer = (uint8_t *)mVideoBuffer->data();
     int32_t stride = mFrameInfo.mStride;
     int32_t slice_height = mFrameInfo.mSliceHeight;
@@ -236,28 +236,30 @@ GonkVideoDecoderManager::CreateVideoData
 
     b.mPlanes[2].mData = yuv420p_v;
     b.mPlanes[2].mWidth =(mFrameInfo.mWidth + 1) / 2;
     b.mPlanes[2].mHeight = (mFrameInfo.mHeight + 1) / 2;
     b.mPlanes[2].mStride = (stride + 1) / 2;
     b.mPlanes[2].mOffset = 0;
     b.mPlanes[2].mSkip = 0;
 
-    *v = VideoData::Create(
+    data = VideoData::Create(
         mInfo.mVideo,
         mImageContainer,
         pos,
         timeUs,
         1, // We don't know the duration.
         b,
         keyFrame,
         -1,
         picture);
     ReleaseVideoBuffer();
   }
+
+  data.forget(v);
   return NS_OK;
 }
 
 bool
 GonkVideoDecoderManager::SetVideoFormat()
 {
   // read video metadata from MediaCodec
   sp<AMessage> codecFormat;
@@ -297,31 +299,31 @@ GonkVideoDecoderManager::SetVideoFormat(
   }
   ALOG("Fail to get output format");
   return false;
 }
 
 // Blocks until decoded sample is produced by the deoder.
 nsresult
 GonkVideoDecoderManager::Output(int64_t aStreamOffset,
-                                nsAutoPtr<MediaData>& aOutData)
+                                nsRefPtr<MediaData>& aOutData)
 {
   aOutData = nullptr;
   status_t err;
   if (mDecoder == nullptr) {
     ALOG("Decoder is not inited");
     return NS_ERROR_UNEXPECTED;
   }
   err = mDecoder->Output(&mVideoBuffer, READ_OUTPUT_BUFFER_TIMEOUT_US);
 
   switch (err) {
     case OK:
     {
-      VideoData* data = nullptr;
-      nsresult rv = CreateVideoData(aStreamOffset, &data);
+      nsRefPtr<VideoData> data;
+      nsresult rv = CreateVideoData(aStreamOffset, getter_AddRefs(data));
       if (rv == NS_ERROR_NOT_AVAILABLE) {
 	// Decoder outputs a empty video buffer, try again
         return NS_ERROR_NOT_AVAILABLE;
       } else if (rv != NS_OK || data == nullptr) {
         ALOG("Failed to create VideoData");
         return NS_ERROR_UNEXPECTED;
       }
       aOutData = data;
@@ -345,18 +347,18 @@ GonkVideoDecoderManager::Output(int64_t 
     }
     case -EAGAIN:
     {
       return NS_ERROR_NOT_AVAILABLE;
     }
     case android::ERROR_END_OF_STREAM:
     {
       ALOG("Got the EOS frame!");
-      VideoData* data = nullptr;
-      nsresult rv = CreateVideoData(aStreamOffset, &data);
+      nsRefPtr<VideoData> data;
+      nsresult rv = CreateVideoData(aStreamOffset, getter_AddRefs(data));
       if (rv == NS_ERROR_NOT_AVAILABLE) {
 	// For EOS, no need to do any thing.
         return NS_ERROR_ABORT;
       }
       if (rv != NS_OK || data == nullptr) {
         ALOG("Failed to create video data");
         return NS_ERROR_UNEXPECTED;
       }
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.h
@@ -43,17 +43,17 @@ public:
 
   ~GonkVideoDecoderManager();
 
   virtual android::sp<MediaCodecProxy> Init(MediaDataDecoderCallback* aCallback) MOZ_OVERRIDE;
 
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual nsresult Output(int64_t aStreamOffset,
-                          nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+                          nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
   static void RecycleCallback(TextureClient* aClient, void* aClosure);
 private:
   struct FrameInfo
   {
     int32_t mWidth = 0;
     int32_t mHeight = 0;
     int32_t mStride = 0;
--- a/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFAudioMFTManager.cpp
@@ -187,17 +187,17 @@ WMFAudioMFTManager::UpdateOutputType()
   hr = type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &mAudioChannels);
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
   return S_OK;
 }
 
 HRESULT
 WMFAudioMFTManager::Output(int64_t aStreamOffset,
-                           nsAutoPtr<MediaData>& aOutData)
+                           nsRefPtr<MediaData>& aOutData)
 {
   aOutData = nullptr;
   RefPtr<IMFSample> sample;
   HRESULT hr;
   while (true) {
     hr = mDecoder->Output(&sample);
     if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
       return hr;
--- a/dom/media/fmp4/wmf/WMFAudioMFTManager.h
+++ b/dom/media/fmp4/wmf/WMFAudioMFTManager.h
@@ -23,17 +23,17 @@ public:
   virtual TemporaryRef<MFTDecoder> Init() MOZ_OVERRIDE;
 
   virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   // Note WMF's AAC decoder sometimes output negatively timestamped samples,
   // presumably they're the preroll samples, and we strip them. We may return
   // a null aOutput in this case.
   virtual HRESULT Output(int64_t aStreamOffset,
-                         nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+                         nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
 private:
 
   HRESULT UpdateOutputType();
 
   // IMFTransform wrapper that performs the decoding.
--- a/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -85,21 +85,21 @@ WMFMediaDataDecoder::ProcessDecode(mp4_d
   mLastStreamOffset = aSample->byte_offset;
 
   ProcessOutput();
 }
 
 void
 WMFMediaDataDecoder::ProcessOutput()
 {
-  nsAutoPtr<MediaData> output;
+  nsRefPtr<MediaData> output;
   HRESULT hr = S_OK;
   while (SUCCEEDED(hr = mMFTManager->Output(mLastStreamOffset, output)) &&
          output) {
-    mCallback->Output(output.forget());
+    mCallback->Output(output);
   }
   if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
     if (mTaskQueue->IsEmpty()) {
       mCallback->InputExhausted();
     }
   } else if (FAILED(hr)) {
     NS_WARNING("WMFMediaDataDecoder failed to output data");
     mCallback->Error();
--- a/dom/media/fmp4/wmf/WMFMediaDataDecoder.h
+++ b/dom/media/fmp4/wmf/WMFMediaDataDecoder.h
@@ -37,17 +37,17 @@ public:
 
   // Produces decoded output, if possible. Blocks until output can be produced,
   // or until no more is able to be produced.
   // Returns S_OK on success, or MF_E_TRANSFORM_NEED_MORE_INPUT if there's not
   // enough data to produce more output. If this returns a failure code other
   // than MF_E_TRANSFORM_NEED_MORE_INPUT, an error will be reported to the
   // MP4Reader.
   virtual HRESULT Output(int64_t aStreamOffset,
-                         nsAutoPtr<MediaData>& aOutput) = 0;
+                         nsRefPtr<MediaData>& aOutput) = 0;
 
   // Destroys all resources.
   virtual void Shutdown() = 0;
 };
 
 // Decodes audio and video using Windows Media Foundation. Samples are decoded
 // using the MFTDecoder created by the MFTManager. This class implements
 // the higher-level logic that drives mapping the MFT to the async
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -284,33 +284,32 @@ WMFVideoMFTManager::CreateBasicVideoFram
   b.mPlanes[2].mStride = halfStride;
   b.mPlanes[2].mHeight = halfHeight;
   b.mPlanes[2].mWidth = halfWidth;
   b.mPlanes[2].mOffset = 0;
   b.mPlanes[2].mSkip = 0;
 
   Microseconds pts = GetSampleTime(aSample);
   Microseconds duration = GetSampleDuration(aSample);
-  VideoData *v = VideoData::Create(mVideoInfo,
-                                   mImageContainer,
-                                   aStreamOffset,
-                                   pts,
-                                   duration,
-                                   b,
-                                   false,
-                                   -1,
-                                   ToIntRect(mPictureRegion));
+  nsRefPtr<VideoData> v = VideoData::Create(mVideoInfo,
+                                            mImageContainer,
+                                            aStreamOffset,
+                                            pts,
+                                            duration,
+                                            b,
+                                            false,
+                                            -1,
+                                            ToIntRect(mPictureRegion));
   if (twoDBuffer) {
     twoDBuffer->Unlock2D();
   } else {
     buffer->Unlock();
   }
 
-  *aOutVideoData = v;
-
+  v.forget(aOutVideoData);
   return S_OK;
 }
 
 HRESULT
 WMFVideoMFTManager::CreateD3DVideoFrame(IMFSample* aSample,
                                         int64_t aStreamOffset,
                                         VideoData** aOutVideoData)
 {
@@ -327,36 +326,36 @@ WMFVideoMFTManager::CreateD3DVideoFrame(
                                   mPictureRegion,
                                   mImageContainer,
                                   getter_AddRefs(image));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   NS_ENSURE_TRUE(image, E_FAIL);
 
   Microseconds pts = GetSampleTime(aSample);
   Microseconds duration = GetSampleDuration(aSample);
-  VideoData *v = VideoData::CreateFromImage(mVideoInfo,
-                                            mImageContainer,
-                                            aStreamOffset,
-                                            pts,
-                                            duration,
-                                            image.forget(),
-                                            false,
-                                            -1,
-                                            ToIntRect(mPictureRegion));
+  nsRefPtr<VideoData> v = VideoData::CreateFromImage(mVideoInfo,
+                                                     mImageContainer,
+                                                     aStreamOffset,
+                                                     pts,
+                                                     duration,
+                                                     image.forget(),
+                                                     false,
+                                                     -1,
+                                                     ToIntRect(mPictureRegion));
 
   NS_ENSURE_TRUE(v, E_FAIL);
-  *aOutVideoData = v;
+  v.forget(aOutVideoData);
 
   return S_OK;
 }
 
 // Blocks until decoded sample is produced by the deoder.
 HRESULT
 WMFVideoMFTManager::Output(int64_t aStreamOffset,
-                           nsAutoPtr<MediaData>& aOutData)
+                           nsRefPtr<MediaData>& aOutData)
 {
   RefPtr<IMFSample> sample;
   HRESULT hr;
   aOutData = nullptr;
 
   // Loop until we decode a sample, or an unexpected error that we can't
   // handle occurs.
   while (true) {
@@ -377,21 +376,21 @@ WMFVideoMFTManager::Output(int64_t aStre
     if (SUCCEEDED(hr)) {
       break;
     }
     // Else unexpected error, assert, and bail.
     NS_WARNING("WMFVideoMFTManager::Output() unexpected error");
     return E_FAIL;
   }
 
-  VideoData* frame = nullptr;
+  nsRefPtr<VideoData> frame;
   if (mUseHwAccel) {
-    hr = CreateD3DVideoFrame(sample, aStreamOffset, &frame);
+    hr = CreateD3DVideoFrame(sample, aStreamOffset, getter_AddRefs(frame));
   } else {
-    hr = CreateBasicVideoFrame(sample, aStreamOffset, &frame);
+    hr = CreateBasicVideoFrame(sample, aStreamOffset, getter_AddRefs(frame));
   }
   // Frame should be non null only when we succeeded.
   MOZ_ASSERT((frame != nullptr) == SUCCEEDED(hr));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   NS_ENSURE_TRUE(frame, E_FAIL);
 
   aOutData = frame;
 
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.h
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.h
@@ -26,17 +26,17 @@ public:
                      bool aDXVAEnabled);
   ~WMFVideoMFTManager();
 
   virtual TemporaryRef<MFTDecoder> Init() MOZ_OVERRIDE;
 
   virtual HRESULT Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   virtual HRESULT Output(int64_t aStreamOffset,
-                         nsAutoPtr<MediaData>& aOutput) MOZ_OVERRIDE;
+                         nsRefPtr<MediaData>& aOutput) MOZ_OVERRIDE;
 
   virtual void Shutdown() MOZ_OVERRIDE;
 
 private:
 
   bool InitializeDXVA();
 
   HRESULT ConfigureVideoFrameGeometry();
--- a/dom/media/gmp/GMPLoader.cpp
+++ b/dom/media/gmp/GMPLoader.cpp
@@ -67,17 +67,17 @@ private:
   GMPGetAPIFunc mGetAPIFunc;
   SandboxStarter* mSandboxStarter;
 };
 
 GMPLoader* CreateGMPLoader(SandboxStarter* aStarter) {
   return static_cast<GMPLoader*>(new GMPLoaderImpl(aStarter));
 }
 
-#if defined(XP_WIN)
+#if defined(XP_WIN) && defined(HASH_NODE_ID_WITH_DEVICE_ID)
 MOZ_NEVER_INLINE
 static bool
 GetStackAfterCurrentFrame(uint8_t** aOutTop, uint8_t** aOutBottom)
 {
   // "Top" of the free space on the stack is directly after the memory
   // holding our return address.
   uint8_t* top = (uint8_t*)_AddressOfReturnAddress();
 
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -770,21 +770,21 @@ bool GStreamerReader::DecodeVideoFrame(b
      */
     GstBuffer* tmp = nullptr;
     CopyIntoImageBuffer(buffer, &tmp, image);
     gst_buffer_unref(buffer);
     buffer = tmp;
   }
 
   int64_t offset = mDecoder->GetResource()->Tell(); // Estimate location in media.
-  VideoData* video = VideoData::CreateFromImage(mInfo.mVideo,
-                                                mDecoder->GetImageContainer(),
-                                                offset, timestamp, duration,
-                                                static_cast<Image*>(image.get()),
-                                                isKeyframe, -1, mPicture);
+  nsRefPtr<VideoData> video = VideoData::CreateFromImage(mInfo.mVideo,
+                                                         mDecoder->GetImageContainer(),
+                                                         offset, timestamp, duration,
+                                                         static_cast<Image*>(image.get()),
+                                                         isKeyframe, -1, mPicture);
   mVideoQueue.Push(video);
 
   gst_buffer_unref(buffer);
 
   return true;
 }
 
 void GStreamerReader::Seek(int64_t aTarget,
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -110,17 +110,16 @@ void
 MediaSourceReader::OnAudioDecoded(AudioData* aSample)
 {
   MSE_DEBUGV("MediaSourceReader(%p)::OnAudioDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
              this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
   if (mDropAudioBeforeThreshold) {
     if (aSample->mTime < mTimeThreshold) {
       MSE_DEBUG("MediaSourceReader(%p)::OnAudioDecoded mTime=%lld < mTimeThreshold=%lld",
                 this, aSample->mTime, mTimeThreshold);
-      delete aSample;
       mAudioReader->RequestAudioData();
       return;
     }
     mDropAudioBeforeThreshold = false;
   }
 
   // Any OnAudioDecoded callbacks received while mAudioIsSeeking must be not
   // update our last used timestamp, as these are emitted by the reader we're
@@ -155,17 +154,16 @@ void
 MediaSourceReader::OnVideoDecoded(VideoData* aSample)
 {
   MSE_DEBUGV("MediaSourceReader(%p)::OnVideoDecoded [mTime=%lld mDuration=%lld mDiscontinuity=%d]",
              this, aSample->mTime, aSample->mDuration, aSample->mDiscontinuity);
   if (mDropVideoBeforeThreshold) {
     if (aSample->mTime < mTimeThreshold) {
       MSE_DEBUG("MediaSourceReader(%p)::OnVideoDecoded mTime=%lld < mTimeThreshold=%lld",
                 this, aSample->mTime, mTimeThreshold);
-      delete aSample;
       mVideoReader->RequestVideoData(false, 0);
       return;
     }
     mDropVideoBeforeThreshold = false;
   }
 
   // Any OnVideoDecoded callbacks received while mVideoIsSeeking must be not
   // update our last used timestamp, as these are emitted by the reader we're
@@ -638,16 +636,39 @@ MediaSourceReader::ReadMetadata(MediaInf
 
   *aInfo = mInfo;
   *aTags = nullptr; // TODO: Handle metadata.
 
   return NS_OK;
 }
 
 void
+MediaSourceReader::ReadUpdatedMetadata(MediaInfo* aInfo)
+{
+  if (mAudioTrack) {
+    MOZ_ASSERT(mAudioTrack->IsReady());
+    mAudioReader = mAudioTrack->Decoders()[0]->GetReader();
+
+    const MediaInfo& info = mAudioReader->GetMediaInfo();
+    MOZ_ASSERT(info.HasAudio());
+    mInfo.mAudio = info.mAudio;
+  }
+
+  if (mVideoTrack) {
+    MOZ_ASSERT(mVideoTrack->IsReady());
+    mVideoReader = mVideoTrack->Decoders()[0]->GetReader();
+
+    const MediaInfo& info = mVideoReader->GetMediaInfo();
+    MOZ_ASSERT(info.HasVideo());
+    mInfo.mVideo = info.mVideo;
+  }
+  *aInfo = mInfo;
+}
+
+void
 MediaSourceReader::Ended()
 {
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mEnded = true;
 }
 
 bool
 MediaSourceReader::IsEnded()
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -79,16 +79,17 @@ public:
   // "don't have enough") don't really make sense for MSE. The delay is
   // essentially a streaming heuristic, but JS is supposed to take care of that
   // in the MSE world. Avoid injecting inexplicable delays.
   virtual uint32_t GetBufferingWait() { return 0; }
 
   bool IsMediaSeekable() { return true; }
 
   nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
+  void ReadUpdatedMetadata(MediaInfo* aInfo) MOZ_OVERRIDE;
   void Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
             int64_t aCurrentTime) MOZ_OVERRIDE;
 
   // Acquires the decoder monitor, and is thus callable on any thread.
   nsresult GetBuffered(dom::TimeRanges* aBuffered) MOZ_OVERRIDE;
 
   already_AddRefed<SourceBufferDecoder> CreateSubDecoder(const nsACString& aType);
 
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -876,44 +876,44 @@ nsresult OggReader::DecodeTheora(ogg_pac
   int64_t endTime = mTheoraState->Time(aPacket->granulepos);
   if (endTime < aTimeThreshold) {
     // The end time of this frame is already before the current playback
     // position. It will never be displayed, don't bother enqueing it.
     return NS_OK;
   }
 
   if (ret == TH_DUPFRAME) {
-    VideoData* v = VideoData::CreateDuplicate(mDecoder->GetResource()->Tell(),
-                                              time,
-                                              endTime - time,
-                                              aPacket->granulepos);
+    nsRefPtr<VideoData> v = VideoData::CreateDuplicate(mDecoder->GetResource()->Tell(),
+                                                       time,
+                                                       endTime - time,
+                                                       aPacket->granulepos);
     mVideoQueue.Push(v);
   } else if (ret == 0) {
     th_ycbcr_buffer buffer;
     ret = th_decode_ycbcr_out(mTheoraState->mCtx, buffer);
     NS_ASSERTION(ret == 0, "th_decode_ycbcr_out failed");
     bool isKeyframe = th_packet_iskeyframe(aPacket) == 1;
     VideoData::YCbCrBuffer b;
     for (uint32_t i=0; i < 3; ++i) {
       b.mPlanes[i].mData = buffer[i].data;
       b.mPlanes[i].mHeight = buffer[i].height;
       b.mPlanes[i].mWidth = buffer[i].width;
       b.mPlanes[i].mStride = buffer[i].stride;
       b.mPlanes[i].mOffset = b.mPlanes[i].mSkip = 0;
     }
 
-    VideoData *v = VideoData::Create(mInfo.mVideo,
-                                     mDecoder->GetImageContainer(),
-                                     mDecoder->GetResource()->Tell(),
-                                     time,
-                                     endTime - time,
-                                     b,
-                                     isKeyframe,
-                                     aPacket->granulepos,
-                                     ToIntRect(mPicture));
+    nsRefPtr<VideoData> v = VideoData::Create(mInfo.mVideo,
+                                              mDecoder->GetImageContainer(),
+                                              mDecoder->GetResource()->Tell(),
+                                              time,
+                                              endTime - time,
+                                              b,
+                                              isKeyframe,
+                                              aPacket->granulepos,
+                                              ToIntRect(mPicture));
     if (!v) {
       // There may be other reasons for this error, but for
       // simplicity just assume the worst case: out of memory.
       NS_WARNING("Failed to allocate memory for video frame");
       return NS_ERROR_OUT_OF_MEMORY;
     }
     mVideoQueue.Push(v);
   }
@@ -1535,17 +1535,17 @@ nsresult OggReader::SeekInternal(int64_t
     // When doing fastSeek we display the first frame after the seek, so
     // we need to advance the decode to the keyframe otherwise we'll get
     // visual artifacts in the first frame output after the seek.
     // First, we must check to see if there's already a keyframe in the frames
     // that we may have already decoded, and discard frames up to the
     // keyframe.
     VideoData* v;
     while ((v = mVideoQueue.PeekFront()) && !v->mKeyframe) {
-      delete mVideoQueue.PopFront();
+      nsRefPtr<VideoData> releaseMe = mVideoQueue.PopFront();
     }
     if (mVideoQueue.GetSize() == 0) {
       // We didn't find a keyframe in the frames already here, so decode
       // forwards until we find a keyframe.
       bool skip = true;
       while (DecodeVideoFrame(skip, 0) && skip) {
         ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
         if (mDecoder->IsShutdown()) {
--- a/dom/media/omx/MediaCodecReader.cpp
+++ b/dom/media/omx/MediaCodecReader.cpp
@@ -472,17 +472,17 @@ MediaCodecReader::DecodeAudioDataSync()
   return result;
 }
 
 bool
 MediaCodecReader::DecodeAudioDataTask()
 {
   bool result = DecodeAudioDataSync();
   if (AudioQueue().GetSize() > 0) {
-    AudioData* a = AudioQueue().PopFront();
+    nsRefPtr<AudioData> a = AudioQueue().PopFront();
     if (a) {
       if (mAudioTrack.mDiscontinuity) {
         a->mDiscontinuity = true;
         mAudioTrack.mDiscontinuity = false;
       }
       GetCallback()->OnAudioDecoded(a);
     }
   }
@@ -492,17 +492,17 @@ MediaCodecReader::DecodeAudioDataTask()
   return result;
 }
 
 bool
 MediaCodecReader::DecodeVideoFrameTask(int64_t aTimeThreshold)
 {
   bool result = DecodeVideoFrameSync(aTimeThreshold);
   if (VideoQueue().GetSize() > 0) {
-    VideoData* v = VideoQueue().PopFront();
+    nsRefPtr<VideoData> v = VideoQueue().PopFront();
     if (v) {
       if (mVideoTrack.mDiscontinuity) {
         v->mDiscontinuity = true;
         mVideoTrack.mDiscontinuity = false;
       }
       GetCallback()->OnVideoDecoded(v);
     }
   }
@@ -873,17 +873,17 @@ MediaCodecReader::DecodeVideoFrameSync(i
         return false;
       }
     } else {
       return false;
     }
   }
 
   bool result = false;
-  VideoData *v = nullptr;
+  nsRefPtr<VideoData> v;
   RefPtr<TextureClient> textureClient;
   sp<GraphicBuffer> graphicBuffer;
   if (bufferInfo.mBuffer != nullptr) {
     // This is the approximate byte position in the stream.
     int64_t pos = mDecoder->GetResource()->Tell();
 
     if (mVideoTrack.mNativeWindow != nullptr &&
         mVideoTrack.mCodec->getOutputGraphicBufferFromIndex(bufferInfo.mIndex, &graphicBuffer) == OK &&
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -415,17 +415,17 @@ bool MediaOmxReader::DecodeVideoFrame(bo
       picture.y = (mPicture.y * frame.Y.mHeight) / mInitialFrame.height;
       picture.width = (frame.Y.mWidth * mPicture.width) / mInitialFrame.width;
       picture.height = (frame.Y.mHeight * mPicture.height) / mInitialFrame.height;
     }
 
     // This is the approximate byte position in the stream.
     int64_t pos = mDecoder->GetResource()->Tell();
 
-    VideoData *v;
+    nsRefPtr<VideoData> v;
     if (!frame.mGraphicBuffer) {
 
       VideoData::YCbCrBuffer b;
       b.mPlanes[0].mData = static_cast<uint8_t *>(frame.Y.mData);
       b.mPlanes[0].mStride = frame.Y.mStride;
       b.mPlanes[0].mHeight = frame.Y.mHeight;
       b.mPlanes[0].mWidth = frame.Y.mWidth;
       b.mPlanes[0].mOffset = frame.Y.mOffset;
--- a/dom/media/raw/RawReader.cpp
+++ b/dom/media/raw/RawReader.cpp
@@ -210,25 +210,25 @@ bool RawReader::DecodeVideoFrame(bool &a
   b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
 
   b.mPlanes[2].mData = b.mPlanes[1].mData + mMetadata.frameHeight * cbcrStride / 2;
   b.mPlanes[2].mStride = cbcrStride;
   b.mPlanes[2].mHeight = mMetadata.frameHeight / 2;
   b.mPlanes[2].mWidth = mMetadata.frameWidth / 2;
   b.mPlanes[2].mOffset = b.mPlanes[2].mSkip = 0;
 
-  VideoData *v = VideoData::Create(mInfo.mVideo,
-                                   mDecoder->GetImageContainer(),
-                                   -1,
-                                   currentFrameTime,
-                                   (USECS_PER_S / mFrameRate),
-                                   b,
-                                   1, // In raw video every frame is a keyframe
-                                   -1,
-                                   ToIntRect(mPicture));
+  nsRefPtr<VideoData> v = VideoData::Create(mInfo.mVideo,
+                                            mDecoder->GetImageContainer(),
+                                            -1,
+                                            currentFrameTime,
+                                            (USECS_PER_S / mFrameRate),
+                                            b,
+                                            1, // In raw video every frame is a keyframe
+                                            -1,
+                                            ToIntRect(mPicture));
   if (!v)
     return false;
 
   mVideoQueue.Push(v);
   mCurrentFrame++;
   decoded++;
   currentFrameTime += USECS_PER_S / mFrameRate;
 
@@ -273,22 +273,18 @@ nsresult RawReader::SeekInternal(int64_t
     {
       ReentrantMonitorAutoEnter autoMonitor(mDecoder->GetReentrantMonitor());
       if (mDecoder->IsShutdown()) {
         mCurrentFrame = frame;
         return NS_ERROR_FAILURE;
       }
     }
 
-    nsAutoPtr<VideoData> video(mVideoQueue.PeekFront());
-    if (video && video->GetEndTime() < aTime) {
-      mVideoQueue.PopFront();
-      video = nullptr;
-    } else {
-      video.forget();
+    if (mVideoQueue.PeekFront() && mVideoQueue.PeekFront()->GetEndTime() < aTime) {
+      nsRefPtr<VideoData> releaseMe = mVideoQueue.PopFront();
     }
   }
 
   return NS_OK;
 }
 
 nsresult RawReader::GetBuffered(dom::TimeRanges* aBuffered)
 {
--- a/dom/media/webaudio/MediaBufferDecoder.cpp
+++ b/dom/media/webaudio/MediaBufferDecoder.cpp
@@ -257,26 +257,26 @@ MediaDecodeTask::Decode()
     return;
   }
 
   MediaQueue<AudioData> audioQueue;
   nsRefPtr<AudioDecodeRendezvous> barrier(new AudioDecodeRendezvous());
   mDecoderReader->SetCallback(barrier);
   while (1) {
     mDecoderReader->RequestAudioData();
-    nsAutoPtr<AudioData> audio;
+    nsRefPtr<AudioData> audio;
     if (NS_FAILED(barrier->Await(audio))) {
       ReportFailureOnMainThread(WebAudioDecodeJob::InvalidContent);
       return;
     }
     if (!audio) {
       // End of stream.
       break;
     }
-    audioQueue.Push(audio.forget());
+    audioQueue.Push(audio);
   }
   mDecoderReader->Shutdown();
   mDecoderReader->BreakCycles();
 
   uint32_t frameCount = audioQueue.FrameCount();
   uint32_t channelCount = mediaInfo.mAudio.mChannels;
   uint32_t sampleRate = mediaInfo.mAudio.mRate;
 
@@ -320,17 +320,17 @@ MediaDecodeTask::Decode()
       }
     }
   }
   if (!memoryAllocationSuccess) {
     ReportFailureOnMainThread(WebAudioDecodeJob::UnknownError);
     return;
   }
 
-  nsAutoPtr<AudioData> audioData;
+  nsRefPtr<AudioData> audioData;
   while ((audioData = audioQueue.PopFront())) {
     audioData->EnsureAudioBuffer(); // could lead to a copy :(
     AudioDataValue* bufferData = static_cast<AudioDataValue*>
       (audioData->mAudioBuffer->Data());
 
     if (sampleRate != destSampleRate) {
       const uint32_t maxOutSamples = resampledFrames - mDecodeJob.mWriteIndex;
 
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -1013,25 +1013,25 @@ bool WebMReader::DecodeVideoFrame(bool &
         // as it was reported relative to the picture size reported by the
         // container.
         picture.x = (mPicture.x * img->d_w) / mInitialFrame.width;
         picture.y = (mPicture.y * img->d_h) / mInitialFrame.height;
         picture.width = (img->d_w * mPicture.width) / mInitialFrame.width;
         picture.height = (img->d_h * mPicture.height) / mInitialFrame.height;
       }
 
-      VideoData *v = VideoData::Create(mInfo.mVideo,
-                                       mDecoder->GetImageContainer(),
-                                       holder->mOffset,
-                                       tstamp_usecs,
-                                       (next_tstamp / NS_PER_USEC)-tstamp_usecs,
-                                       b,
-                                       si.is_kf,
-                                       -1,
-                                       picture);
+      nsRefPtr<VideoData> v = VideoData::Create(mInfo.mVideo,
+                                                mDecoder->GetImageContainer(),
+                                                holder->mOffset,
+                                                tstamp_usecs,
+                                                (next_tstamp / NS_PER_USEC)-tstamp_usecs,
+                                                b,
+                                                si.is_kf,
+                                                -1,
+                                                picture);
       if (!v) {
         return false;
       }
       parsed++;
       decoded++;
       NS_ASSERTION(decoded <= parsed,
         "Expect only 1 frame per chunk per packet in WebM...");
       VideoQueue().Push(v);
--- a/dom/media/wmf/WMFReader.cpp
+++ b/dom/media/wmf/WMFReader.cpp
@@ -731,33 +731,32 @@ WMFReader::CreateBasicVideoFrame(IMFSamp
   // V plane (Cr)
   b.mPlanes[2].mData = data + y_size;
   b.mPlanes[2].mStride = halfStride;
   b.mPlanes[2].mHeight = halfHeight;
   b.mPlanes[2].mWidth = halfWidth;
   b.mPlanes[2].mOffset = 0;
   b.mPlanes[2].mSkip = 0;
 
-  VideoData *v = VideoData::Create(mInfo.mVideo,
-                                   mDecoder->GetImageContainer(),
-                                   aOffsetBytes,
-                                   aTimestampUsecs,
-                                   aDurationUsecs,
-                                   b,
-                                   false,
-                                   -1,
-                                   ToIntRect(mPictureRegion));
+  nsRefPtr<VideoData> v = VideoData::Create(mInfo.mVideo,
+                                            mDecoder->GetImageContainer(),
+                                            aOffsetBytes,
+                                            aTimestampUsecs,
+                                            aDurationUsecs,
+                                            b,
+                                            false,
+                                            -1,
+                                            ToIntRect(mPictureRegion));
   if (twoDBuffer) {
     twoDBuffer->Unlock2D();
   } else {
     buffer->Unlock();
   }
 
-  *aOutVideoData = v;
-
+  v.forget(aOutVideoData);
   return S_OK;
 }
 
 HRESULT
 WMFReader::CreateD3DVideoFrame(IMFSample* aSample,
                                int64_t aTimestampUsecs,
                                int64_t aDurationUsecs,
                                int64_t aOffsetBytes,
@@ -774,28 +773,28 @@ WMFReader::CreateD3DVideoFrame(IMFSample
   nsRefPtr<Image> image;
   hr = mDXVA2Manager->CopyToImage(aSample,
                                   mPictureRegion,
                                   mDecoder->GetImageContainer(),
                                   getter_AddRefs(image));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
   NS_ENSURE_TRUE(image, E_FAIL);
 
-  VideoData *v = VideoData::CreateFromImage(mInfo.mVideo,
-                                            mDecoder->GetImageContainer(),
-                                            aOffsetBytes,
-                                            aTimestampUsecs,
-                                            aDurationUsecs,
-                                            image.forget(),
-                                            false,
-                                            -1,
-                                            ToIntRect(mPictureRegion));
+  nsRefPtr<VideoData> v = VideoData::CreateFromImage(mInfo.mVideo,
+                                                     mDecoder->GetImageContainer(),
+                                                     aOffsetBytes,
+                                                     aTimestampUsecs,
+                                                     aDurationUsecs,
+                                                     image.forget(),
+                                                     false,
+                                                     -1,
+                                                     ToIntRect(mPictureRegion));
 
   NS_ENSURE_TRUE(v, E_FAIL);
-  *aOutVideoData = v;
+  v.forget(aOutVideoData);
 
   return S_OK;
 }
 
 bool
 WMFReader::DecodeVideoFrame(bool &aKeyframeSkip,
                             int64_t aTimeThreshold)
 {
--- a/dom/plugins/test/mochitest/hang_test.js
+++ b/dom/plugins/test/mochitest/hang_test.js
@@ -87,29 +87,28 @@ var testObserver = {
 function onPluginCrashed(aEvent) {
   ok(true, "Plugin crashed notification received");
   ok(observerFired, "Observer should have fired first");
   is(aEvent.type, "PluginCrashed", "event is correct type");
 
   var pluginElement = document.getElementById("plugin1");
   is (pluginElement, aEvent.target, "Plugin crashed event target is plugin element");
 
-  ok(aEvent instanceof Ci.nsIDOMCustomEvent,
+  ok(aEvent instanceof PluginCrashedEvent,
      "plugin crashed event has the right interface");
 
-  var propBag = aEvent.detail.QueryInterface(Ci.nsIPropertyBag2);
-  var pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
-  isnot(pluginDumpID, "", "got a non-empty dump ID");
-  var pluginName = propBag.getPropertyAsAString("pluginName");
-  is(pluginName, "Test Plug-in", "got correct plugin name");
-  var pluginFilename = propBag.getPropertyAsAString("pluginFilename");
-  isnot(pluginFilename, "", "got a non-empty filename");
-  var didReport = propBag.getPropertyAsBool("submittedCrashReport");
+  is(typeof aEvent.pluginDumpID, "string", "pluginDumpID is correct type");
+  isnot(aEvent.pluginDumpID, "", "got a non-empty dump ID");
+  is(typeof aEvent.pluginName, "string", "pluginName is correct type");
+  is(aEvent.pluginName, "Test Plug-in", "got correct plugin name");
+  is(typeof aEvent.pluginFilename, "string", "pluginFilename is correct type");
+  isnot(aEvent.pluginFilename, "", "got a non-empty filename");
   // The app itself may or may not have decided to submit the report, so
   // allow either true or false here.
-  ok((didReport == true || didReport == false), "event said crash report was submitted");
+  ok("submittedCrashReport" in aEvent, "submittedCrashReport is a property of event");
+  is(typeof aEvent.submittedCrashReport, "boolean", "submittedCrashReport is correct type");
 
   var os = Cc["@mozilla.org/observer-service;1"].
            getService(Ci.nsIObserverService);
   os.removeObserver(testObserver, "plugin-crashed");
 
   SimpleTest.finish();
 }
--- a/dom/plugins/test/mochitest/test_crash_notify.xul
+++ b/dom/plugins/test/mochitest/test_crash_notify.xul
@@ -61,30 +61,29 @@ var testObserver = {
 function onPluginCrashed(aEvent) {
   ok(true, "Plugin crashed notification received");
   ok(observerFired, "Observer should have fired first");
   is(aEvent.type, "PluginCrashed", "event is correct type");
 
   var pluginElement = document.getElementById("plugin1");
   is (pluginElement, aEvent.target, "Plugin crashed event target is plugin element");
 
-  ok(aEvent instanceof Components.interfaces.nsIDOMCustomEvent,
+  ok(aEvent instanceof PluginCrashedEvent,
      "plugin crashed event has the right interface");
 
-  var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
-  var pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
-  isnot(pluginDumpID, "", "got a non-empty dump ID");
-  var pluginName = propBag.getPropertyAsAString("pluginName");
-  is(pluginName, "Test Plug-in", "got correct plugin name");
-  var pluginFilename = propBag.getPropertyAsAString("pluginFilename");
-  isnot(pluginFilename, "", "got a non-empty filename");
-  var didReport = propBag.getPropertyAsBool("submittedCrashReport");
+  is(typeof aEvent.pluginDumpID, "string", "pluginDumpID is correct type");
+  isnot(aEvent.pluginDumpID, "", "got a non-empty dump ID");
+  is(typeof aEvent.pluginName, "string", "pluginName is correct type");
+  is(aEvent.pluginName, "Test Plug-in", "got correct plugin name");
+  is(typeof aEvent.pluginFilename, "string", "pluginFilename is correct type");
+  isnot(aEvent.pluginFilename, "", "got a non-empty filename");
   // The app itself may or may not have decided to submit the report, so
   // allow either true or false here.
-  ok((didReport == true || didReport == false), "event said crash report was submitted");
+  ok("submittedCrashReport" in aEvent, "submittedCrashReport is a property of event");
+  is(typeof aEvent.submittedCrashReport, "boolean", "submittedCrashReport is correct type");
 
   var os = Components.classes["@mozilla.org/observer-service;1"].
            getService(Components.interfaces.nsIObserverService);
   os.removeObserver(testObserver, "plugin-crashed");
 
   SimpleTest.finish();
 }
 
--- a/dom/plugins/test/mochitest/test_crash_notify_no_report.xul
+++ b/dom/plugins/test/mochitest/test_crash_notify_no_report.xul
@@ -64,25 +64,25 @@ var testObserver = {
 function onPluginCrashed(aEvent) {
   ok(true, "Plugin crashed notification received");
   ok(observerFired, "Observer should have fired first");
   is(aEvent.type, "PluginCrashed", "event is correct type");
 
   var pluginElement = document.getElementById("plugin1");
   is (pluginElement, aEvent.target, "Plugin crashed event target is plugin element");
 
-  ok(aEvent instanceof Components.interfaces.nsIDOMCustomEvent,
+  ok(aEvent instanceof PluginCrashedEvent,
      "plugin crashed event has the right interface");
-  var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
-  var pluginName = propBag.getPropertyAsAString("pluginName");
-  is(pluginName, "Test Plug-in");
-  var didReport = propBag.getPropertyAsBool("submittedCrashReport");
+
+  is(typeof aEvent.pluginName, "string", "pluginName is correct type");
+  is(aEvent.pluginName, "Test Plug-in");
   // The app itself may or may not have decided to submit the report, so
   // allow either true or false here.
-  ok((didReport == true || didReport == false), "event said crash report was submitted");
+  ok("submittedCrashReport" in aEvent, "submittedCrashReport is a property of event");
+  is(typeof aEvent.submittedCrashReport, "boolean", "submittedCrashReport is correct type");
 
   var os = Components.classes["@mozilla.org/observer-service;1"].
            getService(Components.interfaces.nsIObserverService);
   os.removeObserver(testObserver, "plugin-crashed");
 
   // re-set MOZ_CRASHREPORTER_NO_REPORT
   let env = Components.classes["@mozilla.org/process/environment;1"]
                       .getService(Components.interfaces.nsIEnvironment);
--- a/dom/plugins/test/mochitest/test_hangui.xul
+++ b/dom/plugins/test/mochitest/test_hangui.xul
@@ -112,30 +112,30 @@ window.frameLoaded = runTests;
 var obsCount = 0;
 
 function onPluginCrashedHangUI(aEvent) {
   ok(true, "Plugin crashed notification received");
   is(aEvent.type, "PluginCrashed", "event is correct type");
 
   is(p, aEvent.target, "Plugin crashed event target is plugin element");
 
-  ok(aEvent instanceof Components.interfaces.nsIDOMCustomEvent,
+  ok(aEvent instanceof PluginCrashedEvent,
      "plugin crashed event has the right interface");
 
-  var propBag = aEvent.detail.QueryInterface(Components.interfaces.nsIPropertyBag2);
-  var pluginDumpID = propBag.getPropertyAsAString("pluginDumpID");
-  isnot(pluginDumpID, "", "got a non-empty dump ID");
-  var pluginName = propBag.getPropertyAsAString("pluginName");
-  is(pluginName, "Test Plug-in", "got correct plugin name");
-  var pluginFilename = propBag.getPropertyAsAString("pluginFilename");
-  isnot(pluginFilename, "", "got a non-empty filename");
-  var didReport = propBag.getPropertyAsBool("submittedCrashReport");
+  is(typeof aEvent.pluginDumpID, "string", "pluginDumpID is correct type");
+  isnot(aEvent.pluginDumpID, "", "got a non-empty dump ID");
+  is(typeof aEvent.pluginName, "string", "pluginName is correct type");
+  is(aEvent.pluginName, "Test Plug-in", "got correct plugin name");
+  is(typeof aEvent.pluginFilename, "string", "pluginFilename is correct type");
+  isnot(aEvent.pluginFilename, "", "got a non-empty filename");
   // The app itself may or may not have decided to submit the report, so
   // allow either true or false here.
-  ok((didReport == true || didReport == false), "event said crash report was submitted");
+  ok("submittedCrashReport" in aEvent, "submittedCrashReport is a property of event");
+  is(typeof aEvent.submittedCrashReport, "boolean", "submittedCrashReport is correct type");
+
   os.removeObserver(testObserver, "plugin-crashed");
   --obsCount;
 }
 
 function resetVars() {
   iframe = document.getElementById('iframe1');
   p = iframe.contentDocument.getElementById("plugin1");
   if (obsCount == 0) {
new file mode 100644
--- /dev/null
+++ b/dom/webidl/PluginCrashedEvent.webidl
@@ -0,0 +1,26 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 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/.
+ */
+
+[Constructor(DOMString type, optional PluginCrashedEventInit eventInitDict), ChromeOnly]
+interface PluginCrashedEvent : Event
+{
+  readonly attribute DOMString pluginDumpID;
+  readonly attribute DOMString pluginName;
+  readonly attribute DOMString? browserDumpID;
+  readonly attribute DOMString? pluginFilename;
+  readonly attribute boolean submittedCrashReport;
+  readonly attribute boolean gmpPlugin;
+};
+
+dictionary PluginCrashedEventInit : EventInit
+{
+  DOMString pluginDumpID = "";
+  DOMString pluginName = "";
+  DOMString? browserDumpID = null;
+  DOMString? pluginFilename = null;
+  boolean submittedCrashReport = false;
+  boolean gmpPlugin = false;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -709,16 +709,17 @@ GENERATED_EVENTS_WEBIDL_FILES = [
     'MozMmsEvent.webidl',
     'MozOtaStatusEvent.webidl',
     'MozSettingsEvent.webidl',
     'MozSettingsTransactionEvent.webidl',
     'MozSmsEvent.webidl',
     'MozStkCommandEvent.webidl',
     'MozVoicemailEvent.webidl',
     'PageTransitionEvent.webidl',
+    'PluginCrashedEvent.webidl',
     'PopStateEvent.webidl',
     'PopupBlockedEvent.webidl',
     'ProgressEvent.webidl',
     'RecordErrorEvent.webidl',
     'RTCDataChannelEvent.webidl',
     'RTCPeerConnectionIceEvent.webidl',
     'RTCPeerConnectionIdentityErrorEvent.webidl',
     'RTCPeerConnectionIdentityEvent.webidl',
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -1475,18 +1475,19 @@ TemporaryRef<DrawTarget>
 DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
 {
   cairo_surface_t* similar = cairo_surface_create_similar(mSurface,
                                                           GfxFormatToCairoContent(aFormat),
                                                           aSize.width, aSize.height);
 
   if (!cairo_surface_status(similar)) {
     RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-    target->InitAlreadyReferenced(similar, aSize);
-    return target.forget();
+    if (target->InitAlreadyReferenced(similar, aSize)) {
+      return target.forget();
+    }
   }
 
   gfxCriticalError() << "Failed to create similar cairo surface! Size: " << aSize << " Status: " << cairo_surface_status(similar);
 
   return nullptr;
 }
 
 bool
@@ -1532,18 +1533,21 @@ DrawTargetCairo::CreateShadowDrawTarget(
   if (cairo_surface_status(similar)) {
     return nullptr;
   }
 
   // If we don't have a blur then we can use the RGBA mask and keep all the
   // operations in graphics memory.
   if (aSigma == 0.0F) {
     RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-    target->InitAlreadyReferenced(similar, aSize);
-    return target.forget();
+    if (target->InitAlreadyReferenced(similar, aSize)) {
+      return target.forget();
+    } else {
+      return nullptr;
+    }
   }
 
   cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8,
                                                          aSize.width,
                                                          aSize.height);
 
   if (cairo_surface_status(blursurf)) {
     return nullptr;
@@ -1555,18 +1559,20 @@ DrawTargetCairo::CreateShadowDrawTarget(
     cairo_surface_destroy(similar);
     return nullptr;
   }
 
   cairo_tee_surface_add(tee, similar);
   cairo_surface_destroy(similar);
 
   RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-  target->InitAlreadyReferenced(tee, aSize);
-  return target.forget();
+  if (target->InitAlreadyReferenced(tee, aSize)) {
+    return target.forget();
+  }
+  return nullptr;
 }
 
 bool
 DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
 {
   cairo_surface_reference(aSurface);
   return InitAlreadyReferenced(aSurface, aSize, aFormat);
 }
--- a/gfx/2d/DrawTargetD2D.cpp
+++ b/gfx/2d/DrawTargetD2D.cpp
@@ -2370,17 +2370,18 @@ DrawTargetD2D::CreateBrushForPattern(con
     if (!pat->mSamplingRect.IsEmpty() &&
         (source->GetType() == SurfaceType::D2D1_BITMAP ||
          source->GetType() == SurfaceType::D2D1_DRAWTARGET)) {
       IntRect samplingRect = pat->mSamplingRect;
 
       RefPtr<DrawTargetD2D> dt = new DrawTargetD2D();
       if (!dt->Init(samplingRect.Size(),
                     source->GetFormat())) {
-        MOZ_ASSERT("Invalid sampling rect size!");
+        // FIXME: Uncomment assertion, bug 1068195
+        // MOZ_ASSERT(false, "Invalid sampling rect size!");
         return nullptr;
       }
 
       dt->CopySurface(source, samplingRect, IntPoint());
       source = dt->Snapshot();
 
       mat.PreTranslate(samplingRect.x, samplingRect.y);
     }
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -706,17 +706,17 @@ BufferTextureClient::GetAllocator() cons
   return mAllocator;
 }
 
 bool
 BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
 {
   MOZ_ASSERT(IsValid());
   MOZ_ASSERT(mFormat != gfx::SurfaceFormat::YUV, "This textureClient cannot use YCbCr data");
-  MOZ_ASSERT(aSize.width * aSize.height);
+  MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
 
   int bufSize
     = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
   if (!Allocate(bufSize)) {
     return false;
   }
 
   if (aFlags & ALLOC_CLEAR_BUFFER) {
--- a/gfx/layers/composite/AsyncCompositionManager.cpp
+++ b/gfx/layers/composite/AsyncCompositionManager.cpp
@@ -262,17 +262,20 @@ IntervalOverlap(gfxFloat aTranslation, g
 void
 AsyncCompositionManager::AlignFixedAndStickyLayers(Layer* aLayer,
                                                    Layer* aTransformedSubtreeRoot,
                                                    FrameMetrics::ViewID aTransformScrollId,
                                                    const Matrix4x4& aPreviousTransformForRoot,
                                                    const Matrix4x4& aCurrentTransformForRoot,
                                                    const LayerMargin& aFixedLayerMargins)
 {
+  // If aLayer == aTransformedSubtreeRoot, then treat aLayer as fixed relative
+  // to the ancestor scrollable layer rather than relative to itself.
   bool isRootFixed = aLayer->GetIsFixedPosition() &&
+    aLayer != aTransformedSubtreeRoot &&
     !aLayer->GetParent()->GetIsFixedPosition();
   bool isStickyForSubtree = aLayer->GetIsStickyPosition() &&
     aLayer->GetStickyScrollContainerId() == aTransformScrollId;
   bool isFixedOrSticky = (isRootFixed || isStickyForSubtree);
 
   // We want to process all the fixed and sticky children of
   // aTransformedSubtreeRoot. Also, once we do encounter such a child, we don't
   // need to recurse any deeper because the fixed layers are relative to their
--- a/gfx/layers/d3d11/TextureD3D11.cpp
+++ b/gfx/layers/d3d11/TextureD3D11.cpp
@@ -653,17 +653,17 @@ CompositingRenderTargetD3D11::Compositin
   if (FAILED(hr)) {
     LOGD3D11("Failed to create RenderTargetView.");
   }
 }
 
 void
 CompositingRenderTargetD3D11::BindRenderTarget(ID3D11DeviceContext* aContext)
 {
-  if (!mClearOnBind) {
+  if (mClearOnBind) {
     FLOAT clear[] = { 0, 0, 0, 0 };
     aContext->ClearRenderTargetView(mRTView, clear);
     mClearOnBind = false;
   }
   ID3D11RenderTargetView* view = mRTView;
   aContext->OMSetRenderTargets(1, &view, nullptr);
 }
 
--- a/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
+++ b/gfx/layers/opengl/CompositingRenderTargetOGL.cpp
@@ -56,16 +56,17 @@ CompositingRenderTargetOGL::BindRenderTa
         NS_WARNING(msg.get());
       }
     }
 
     mCompositor->PrepareViewport(mInitParams.mSize);
   }
 
   if (mClearOnBind) {
+    mGL->fScissor(0, 0, mInitParams.mSize.width, mInitParams.mSize.height);
     mGL->fClearColor(0.0, 0.0, 0.0, 0.0);
     mGL->fClear(LOCAL_GL_COLOR_BUFFER_BIT);
     mClearOnBind = false;
   }
 }
 
 #ifdef MOZ_DUMP_PAINTING
 TemporaryRef<DataSourceSurface>
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -1194,16 +1194,19 @@ gfxUtils::EncodeSourceSurface(SourceSurf
   if (!imgData.initCapacity(bufSize)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   uint32_t numReadThisTime = 0;
   while ((rv = imgStream->Read(imgData.begin() + imgSize,
                                bufSize - imgSize,
                                &numReadThisTime)) == NS_OK && numReadThisTime > 0)
   {
+    // Update the length of the vector without overwriting the new data.
+    imgData.growByUninitialized(numReadThisTime);
+
     imgSize += numReadThisTime;
     if (imgSize == bufSize) {
       // need a bigger buffer, just double
       bufSize *= 2;
       if (!imgData.resizeUninitialized(bufSize)) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
--- a/js/public/Debug.h
+++ b/js/public/Debug.h
@@ -245,29 +245,31 @@ class BuilderOrigin : public Builder {
   public:
     BuilderOrigin(JSContext *cx, js::Debugger *debugger_)
       : Builder(cx, debugger_)
     { }
 
     JSObject *unwrap(Object &object) { return unwrapAny(object); }
 };
 
+
 
 // Finding the size of blocks allocated with malloc
 // ------------------------------------------------
 //
 // Debugger.Memory wants to be able to report how many bytes items in memory are
 // consuming. To do this, it needs a function that accepts a pointer to a block,
 // and returns the number of bytes allocated to that block. SpiderMonkey itself
 // doesn't know which function is appropriate to use, but the embedding does.
 
 // Tell Debuggers in |runtime| to use |mallocSizeOf| to find the size of
 // malloc'd blocks.
 void SetDebuggerMallocSizeOf(JSRuntime *runtime, mozilla::MallocSizeOf mallocSizeOf);
 
+
 
 // Handlers for observing Promises
 // -------------------------------
 //
 // The Debugger wants to observe behavior of promises, which are implemented by
 // Gecko with webidl and which SpiderMonkey knows nothing about. On the other
 // hand, Gecko knows nothing about which (if any) debuggers are observing a
 // promise's global. The compromise is that Gecko is responsible for calling
@@ -287,13 +289,19 @@ onNewPromise(JSContext *cx, HandleObject
 // promise, in which case neither promise has settled yet.
 //
 // It is Gecko's responsibility to ensure that this is never called on the same
 // promise more than once (because a promise can only make the transition from
 // unsettled to settled once).
 JS_PUBLIC_API(void)
 onPromiseSettled(JSContext *cx, HandleObject promise);
 
+
+
+// Return true if the given value is a Debugger object, false otherwise.
+JS_PUBLIC_API(bool)
+IsDebugger(JS::Value val);
+
 } // namespace dbg
 } // namespace JS
 
 
 #endif /* js_Debug_h */
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -5,25 +5,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef js_UbiNode_h
 #define js_UbiNode_h
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 
 #include "jspubtd.h"
 
 #include "js/GCAPI.h"
 #include "js/HashTable.h"
 #include "js/TracingAPI.h"
 #include "js/TypeDecls.h"
+#include "js/Vector.h"
 
 // JS::ubi::Node
 //
 // JS::ubi::Node is a pointer-like type designed for internal use by heap
 // analysis tools. A ubi::Node can refer to:
 //
 // - a JS value, like a string, object, or symbol;
 // - an internal SpiderMonkey structure, like a shape or a scope chain object
@@ -134,16 +136,18 @@
 //
 // If this restriction prevents us from implementing interesting tools, we may
 // teach the GC how to root ubi::Nodes, fix up hash tables that use them as
 // keys, etc.
 
 namespace JS {
 namespace ubi {
 
+using mozilla::Maybe;
+
 class Edge;
 class EdgeRange;
 
 // The base class implemented by each ubi::Node referent type. Subclasses must
 // not add data members to this class.
 class Base {
     friend class Node;
 
@@ -417,18 +421,114 @@ class EdgeRange {
     virtual void popFront() = 0;
 
   private:
     EdgeRange(const EdgeRange &) MOZ_DELETE;
     EdgeRange &operator=(const EdgeRange &) MOZ_DELETE;
 };
 
 
+// A dumb Edge concrete class. All but the most essential members have the
+// default behavior.
+class SimpleEdge : public Edge {
+    SimpleEdge(SimpleEdge &) MOZ_DELETE;
+    SimpleEdge &operator=(const SimpleEdge &) MOZ_DELETE;
+
+  public:
+    SimpleEdge() : Edge() { }
+
+    // Construct an initialized SimpleEdge, taking ownership of |name|.
+    SimpleEdge(char16_t *name, const Node &referent) {
+        this->name = name;
+        this->referent = referent;
+    }
+    ~SimpleEdge() {
+        js_free(const_cast<char16_t *>(name));
+    }
+
+    // Move construction and assignment.
+    SimpleEdge(SimpleEdge &&rhs) {
+        name = rhs.name;
+        referent = rhs.referent;
+
+        rhs.name = nullptr;
+    }
+    SimpleEdge &operator=(SimpleEdge &&rhs) {
+        MOZ_ASSERT(&rhs != this);
+        this->~SimpleEdge();
+        new(this) SimpleEdge(mozilla::Move(rhs));
+        return *this;
+    }
+};
+
+typedef mozilla::Vector<SimpleEdge, 8, js::TempAllocPolicy> SimpleEdgeVector;
+
+
+// RootList is a class that can be pointed to by a |ubi::Node|, creating a
+// fictional root-of-roots which has edges to every GC root in the JS
+// runtime. Having a single root |ubi::Node| is useful for algorithms written
+// with the assumption that there aren't multiple roots (such as computing
+// dominator trees) and you want a single point of entry. It also ensures that
+// the roots themselves get visited by |ubi::BreadthFirst| (they would otherwise
+// only be used as starting points).
+//
+// RootList::init itself causes a minor collection, but once the list of roots
+// has been created, GC must not occur, as the referent ubi::Nodes are not
+// stable across GC. The init calls emplace |gcp|'s AutoCheckCannotGC, whose
+// lifetime must extend at least as long as the RootList itself.
+//
+// Example usage:
+//
+//    {
+//        mozilla::Maybe<JS::AutoCheckCannotGC> maybeNoGC;
+//        JS::ubi::RootList rootList(cx, maybeNoGC);
+//        if (!rootList.init(cx))
+//            return false;
+//
+//        // The AutoCheckCannotGC is guaranteed to exist if init returned true.
+//        MOZ_ASSERT(maybeNoGC.isSome());
+//
+//        JS::ubi::Node root(&rootList);
+//
+//        ...
+//    }
+class MOZ_STACK_CLASS RootList {
+    Maybe<AutoCheckCannotGC> &noGC;
+
+  public:
+    SimpleEdgeVector edges;
+    bool             wantNames;
+
+    RootList(JSContext *cx, Maybe<AutoCheckCannotGC> &noGC, bool wantNames = false);
+
+    // Find all GC roots.
+    bool init(JSContext *cx);
+    // Find only GC roots in the provided set of |Zone|s.
+    bool init(JSContext *cx, ZoneSet &debuggees);
+    // Find only GC roots in the given Debugger object's set of debuggee zones.
+    bool init(JSContext *cx, HandleObject debuggees);
+};
+
+
 // Concrete classes for ubi::Node referent types.
 
+template<>
+struct Concrete<RootList> : public Base {
+    EdgeRange *edges(JSContext *cx, bool wantNames) const MOZ_OVERRIDE;
+    const char16_t *typeName() const MOZ_OVERRIDE { return concreteTypeName; }
+
+  protected:
+    explicit Concrete(RootList *ptr) : Base(ptr) { }
+    RootList &get() const { return *static_cast<RootList *>(ptr); }
+
+  public:
+    static const char16_t concreteTypeName[];
+    static void construct(void *storage, RootList *ptr) { new (storage) Concrete(ptr); }
+};
+
 // A reusable ubi::Concrete specialization base class for types supported by
 // JS_TraceChildren.
 template<typename Referent>
 class TracerConcrete : public Base {
     const char16_t *typeName() const MOZ_OVERRIDE { return concreteTypeName; }
     EdgeRange *edges(JSContext *, bool wantNames) const MOZ_OVERRIDE;
     JS::Zone *zone() const MOZ_OVERRIDE;
 
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -42,18 +42,19 @@ namespace js {}
  */
 #define JS_FRESH_NURSERY_PATTERN 0x2F
 #define JS_SWEPT_NURSERY_PATTERN 0x2B
 #define JS_ALLOCATED_NURSERY_PATTERN 0x2D
 #define JS_FRESH_TENURED_PATTERN 0x4F
 #define JS_MOVED_TENURED_PATTERN 0x49
 #define JS_SWEPT_TENURED_PATTERN 0x4B
 #define JS_ALLOCATED_TENURED_PATTERN 0x4D
-#define JS_SWEPT_CODE_PATTERN 0x3b
-#define JS_SWEPT_FRAME_PATTERN 0x5b
+#define JS_EMPTY_STOREBUFFER_PATTERN 0x1B
+#define JS_SWEPT_CODE_PATTERN 0x3B
+#define JS_SWEPT_FRAME_PATTERN 0x5B
 #define JS_POISONED_FORKJOIN_CHUNK 0xBD
 
 #define JS_STATIC_ASSERT(cond)           static_assert(cond, "JS_STATIC_ASSERT")
 #define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
 
 extern MOZ_NORETURN JS_PUBLIC_API(void)
 JS_Assert(const char *s, const char *file, int ln);
 
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -5807,18 +5807,19 @@ Parser<ParseHandler>::statement(bool can
                 return null();
             if (!report(ParseWarning, false, null(), JSMSG_USE_ASM_DIRECTIVE_FAIL))
                 return null();
         }
         return expressionStatement();
 
       case TOK_YIELD: {
         TokenKind next;
-        TokenStream::Modifier modifier = yieldExpressionsSupported() ? TokenStream::Operand
-                                                                     : TokenStream::None;
+        TokenStream::Modifier modifier = yieldExpressionsSupported()
+                                         ? TokenStream::Operand
+                                         : TokenStream::None;
         if (!tokenStream.peekToken(&next, modifier))
             return null();
         if (next == TOK_COLON) {
             if (!checkYieldNameValidity())
                 return null();
             return labeledStatement();
         }
         return expressionStatement();
--- a/js/src/gc/StoreBuffer.cpp
+++ b/js/src/gc/StoreBuffer.cpp
@@ -17,17 +17,17 @@
 
 using namespace js;
 using namespace js::gc;
 using mozilla::ReentrancyGuard;
 
 /*** Edges ***/
 
 void
-StoreBuffer::SlotsEdge::mark(JSTracer *trc)
+StoreBuffer::SlotsEdge::mark(JSTracer *trc) const
 {
     NativeObject *obj = object();
 
     // Beware JSObject::swap exchanging a native object for a non-native one.
     if (!obj->isNative())
         return;
 
     if (IsInsideNursery(obj))
@@ -43,181 +43,60 @@ StoreBuffer::SlotsEdge::mark(JSTracer *t
         int32_t start = Min(uint32_t(start_), obj->slotSpan());
         int32_t end = Min(uint32_t(start_) + count_, obj->slotSpan());
         MOZ_ASSERT(end >= start);
         MarkObjectSlots(trc, obj, start, end - start);
     }
 }
 
 void
-StoreBuffer::WholeCellEdges::mark(JSTracer *trc)
+StoreBuffer::WholeCellEdges::mark(JSTracer *trc) const
 {
     MOZ_ASSERT(edge->isTenured());
     JSGCTraceKind kind = GetGCThingTraceKind(edge);
     if (kind <= JSTRACE_OBJECT) {
         JSObject *object = static_cast<JSObject *>(edge);
         if (object->is<ArgumentsObject>())
             ArgumentsObject::trace(trc, object);
         MarkChildren(trc, object);
         return;
     }
     MOZ_ASSERT(kind == JSTRACE_JITCODE);
     static_cast<jit::JitCode *>(edge)->trace(trc);
 }
 
 void
-StoreBuffer::CellPtrEdge::mark(JSTracer *trc)
+StoreBuffer::CellPtrEdge::mark(JSTracer *trc) const
 {
     if (!*edge)
         return;
 
     MOZ_ASSERT(GetGCThingTraceKind(*edge) == JSTRACE_OBJECT);
     MarkObjectRoot(trc, reinterpret_cast<JSObject**>(edge), "store buffer edge");
 }
 
 void
-StoreBuffer::ValueEdge::mark(JSTracer *trc)
+StoreBuffer::ValueEdge::mark(JSTracer *trc) const
 {
     if (!deref())
         return;
 
     MarkValueRoot(trc, edge, "store buffer edge");
 }
 
 /*** MonoTypeBuffer ***/
 
 template <typename T>
 void
-StoreBuffer::MonoTypeBuffer<T>::handleOverflow(StoreBuffer *owner)
-{
-    if (!owner->isAboutToOverflow()) {
-        /*
-         * Compact the buffer now, and if that fails to free enough space then
-         * trigger a minor collection.
-         */
-        compact(owner);
-        if (isLowOnSpace())
-            owner->setAboutToOverflow();
-    } else {
-         /*
-          * A minor GC has already been triggered, so there's no point
-          * compacting unless the buffer is totally full.
-          */
-        if (storage_->availableInCurrentChunk() < sizeof(T))
-            maybeCompact(owner);
-    }
-}
-
-template <typename T>
-void
-StoreBuffer::MonoTypeBuffer<T>::compactRemoveDuplicates(StoreBuffer *owner)
-{
-    typedef HashSet<T, typename T::Hasher, SystemAllocPolicy> DedupSet;
-
-    DedupSet duplicates;
-    if (!duplicates.init())
-        return; /* Failure to de-dup is acceptable. */
-
-    LifoAlloc::Enum insert(*storage_);
-    for (LifoAlloc::Enum e(*storage_); !e.empty(); e.popFront<T>()) {
-        T *edge = e.get<T>();
-        if (!duplicates.has(*edge)) {
-            insert.updateFront<T>(*edge);
-            insert.popFront<T>();
-
-            /* Failure to insert will leave the set with duplicates. Oh well. */
-            duplicates.put(*edge);
-        }
-    }
-    storage_->release(insert.mark());
-
-    duplicates.clear();
-}
-
-template <typename T>
-void
-StoreBuffer::MonoTypeBuffer<T>::compact(StoreBuffer *owner)
-{
-    MOZ_ASSERT(storage_);
-    compactRemoveDuplicates(owner);
-    usedAtLastCompact_ = storage_->used();
-}
-
-template <typename T>
-void
-StoreBuffer::MonoTypeBuffer<T>::maybeCompact(StoreBuffer *owner)
-{
-    MOZ_ASSERT(storage_);
-    if (storage_->used() != usedAtLastCompact_)
-        compact(owner);
-}
-
-template <typename T>
-void
 StoreBuffer::MonoTypeBuffer<T>::mark(StoreBuffer *owner, JSTracer *trc)
 {
-    MOZ_ASSERT(owner->isEnabled());
-    ReentrancyGuard g(*owner);
-    if (!storage_)
-        return;
-
-    maybeCompact(owner);
-    for (LifoAlloc::Enum e(*storage_); !e.empty(); e.popFront<T>()) {
-        T *edge = e.get<T>();
-        edge->mark(trc);
-    }
-}
-
-/*** RelocatableMonoTypeBuffer ***/
-
-template <typename T>
-void
-StoreBuffer::RelocatableMonoTypeBuffer<T>::compactMoved(StoreBuffer *owner)
-{
-    LifoAlloc &storage = *this->storage_;
-    EdgeSet invalidated;
-    if (!invalidated.init())
-        CrashAtUnhandlableOOM("RelocatableMonoTypeBuffer::compactMoved: Failed to init table.");
-
-    /* Collect the set of entries which are currently invalid. */
-    for (LifoAlloc::Enum e(storage); !e.empty(); e.popFront<T>()) {
-        T *edge = e.get<T>();
-        if (edge->isTagged()) {
-            if (!invalidated.put(edge->untagged().edge))
-                CrashAtUnhandlableOOM("RelocatableMonoTypeBuffer::compactMoved: Failed to put removal.");
-        } else {
-            invalidated.remove(edge->untagged().edge);
-        }
-    }
-
-    /* Remove all entries which are in the invalidated set. */
-    LifoAlloc::Enum insert(storage);
-    for (LifoAlloc::Enum e(storage); !e.empty(); e.popFront<T>()) {
-        T *edge = e.get<T>();
-        if (!edge->isTagged() && !invalidated.has(edge->untagged().edge)) {
-            insert.updateFront<T>(*edge);
-            insert.popFront<T>();
-        }
-    }
-    storage.release(insert.mark());
-
-    invalidated.clear();
-
-#ifdef DEBUG
-    for (LifoAlloc::Enum e(storage); !e.empty(); e.popFront<T>())
-        MOZ_ASSERT(!e.get<T>()->isTagged());
-#endif
-}
-
-template <typename T>
-void
-StoreBuffer::RelocatableMonoTypeBuffer<T>::compact(StoreBuffer *owner)
-{
-    compactMoved(owner);
-    StoreBuffer::MonoTypeBuffer<T>::compact(owner);
+    MOZ_ASSERT(stores_.initialized());
+    sinkStores(owner);
+    for (typename StoreSet::Range r = stores_.all(); !r.empty(); r.popFront())
+        r.front().mark(trc);
 }
 
 /*** GenericBuffer ***/
 
 void
 StoreBuffer::GenericBuffer::mark(StoreBuffer *owner, JSTracer *trc)
 {
     MOZ_ASSERT(owner->isEnabled());
@@ -368,12 +247,10 @@ JS::HeapValueRelocate(JS::Value *valuep)
     JSRuntime *runtime = static_cast<js::gc::Cell *>(valuep->toGCThing())->runtimeFromMainThread();
     runtime->gc.storeBuffer.removeRelocatableValueFromAnyThread(valuep);
 }
 
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotsEdge>;
 template struct StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeCellEdges>;
-template struct StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::ValueEdge>;
-template struct StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::CellPtrEdge>;
 
 #endif /* JSGC_GENERATIONAL */
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -76,117 +76,98 @@ static const size_t LifoAllocBlockSize =
 class StoreBuffer
 {
     friend class mozilla::ReentrancyGuard;
 
     /* The size at which a block is about to overflow. */
     static const size_t LowAvailableThreshold = (size_t)(LifoAllocBlockSize * 1.0 / 16.0);
 
     /*
-     * If the space available in the store buffer hits the
-     * LowAvailableThreshold and gets compacted, but still doesn't have at
-     * least HighAvailableThreshold space available, then we will trigger a
-     * minor GC. HighAvailableThreshold should be set to provide enough space
-     * for the mutator to run for a while in between compactions. (If
-     * HighAvailableThreshold is too low, we will thrash and spend most of the
-     * time compacting. If it is too high, we will tenure things too early.)
-     */
-    static const size_t HighAvailableThreshold = (size_t)(LifoAllocBlockSize * 1.0 / 4.0);
-
-    /*
      * This buffer holds only a single type of edge. Using this buffer is more
      * efficient than the generic buffer when many writes will be to the same
      * type of edge: e.g. Value or Cell*.
      */
     template<typename T>
     struct MonoTypeBuffer
     {
-        LifoAlloc *storage_;
-        size_t usedAtLastCompact_;
+        /* The canonical set of stores. */
+        typedef HashSet<T, typename T::Hasher, SystemAllocPolicy> StoreSet;
+        StoreSet stores_;
 
-        explicit MonoTypeBuffer() : storage_(nullptr), usedAtLastCompact_(0) {}
-        ~MonoTypeBuffer() { js_delete(storage_); }
+        /*
+         * A small, fixed-size buffer in front of the canonical set to simplify
+         * insertion via jit code.
+         */
+        const static size_t NumBufferEntries = 4096 / sizeof(T);
+        T buffer_[NumBufferEntries];
+        T *insert_;
+
+        /* Maximum number of entries before we request a minor GC. */
+        const static size_t MaxEntries = 48 * 1024 / sizeof(T);
+
+        explicit MonoTypeBuffer() { clearBuffer(); }
+        ~MonoTypeBuffer() { stores_.finish(); }
 
         bool init() {
-            if (!storage_)
-                storage_ = js_new<LifoAlloc>(LifoAllocBlockSize);
+            if (!stores_.initialized() && !stores_.init())
+                return false;
             clear();
-            return bool(storage_);
+            return true;
+        }
+
+        void clearBuffer() {
+            JS_POISON(buffer_, JS_EMPTY_STOREBUFFER_PATTERN, NumBufferEntries * sizeof(T));
+            insert_ = buffer_;
         }
 
         void clear() {
-            if (!storage_)
-                return;
-
-            storage_->used() ? storage_->releaseAll() : storage_->freeAll();
-            usedAtLastCompact_ = 0;
-        }
-
-        bool isAboutToOverflow() const {
-            return !storage_->isEmpty() && storage_->availableInCurrentChunk() < LowAvailableThreshold;
-        }
-
-        bool isLowOnSpace() const {
-            return !storage_->isEmpty() && storage_->availableInCurrentChunk() < HighAvailableThreshold;
+            clearBuffer();
+            if (stores_.initialized())
+                stores_.clear();
         }
 
-        void handleOverflow(StoreBuffer *owner);
-
-        /* Compaction algorithms. */
-        void compactRemoveDuplicates(StoreBuffer *owner);
-
-        /*
-         * Attempts to reduce the usage of the buffer by removing unnecessary
-         * entries.
-         */
-        virtual void compact(StoreBuffer *owner);
-
-        /* Compacts if any entries have been added since the last compaction. */
-        void maybeCompact(StoreBuffer *owner);
-
         /* Add one item to the buffer. */
         void put(StoreBuffer *owner, const T &t) {
-            MOZ_ASSERT(storage_);
+            MOZ_ASSERT(stores_.initialized());
+            *insert_++ = t;
+            if (MOZ_UNLIKELY(insert_ == buffer_ + NumBufferEntries))
+                sinkStores(owner);
+        }
+
+        /* Move any buffered stores to the canonical store set. */
+        void sinkStores(StoreBuffer *owner) {
+            MOZ_ASSERT(stores_.initialized());
 
-            T *tp = storage_->new_<T>(t);
-            if (!tp)
-                CrashAtUnhandlableOOM("Failed to allocate for MonoTypeBuffer::put.");
+            for (T *p = buffer_; p < insert_; ++p) {
+                if (!stores_.put(*p))
+                    CrashAtUnhandlableOOM("Failed to allocate for MonoTypeBuffer::sinkStores.");
+            }
+            clearBuffer();
 
-            if (isAboutToOverflow())
-                handleOverflow(owner);
+            if (MOZ_UNLIKELY(stores_.count() > MaxEntries))
+                owner->setAboutToOverflow();
+        }
+
+        /* Remove an item from the store buffer. */
+        void unput(StoreBuffer *owner, const T &v) {
+            sinkStores(owner);
+            stores_.remove(v);
         }
 
         /* Mark the source of all edges in the store buffer. */
         void mark(StoreBuffer *owner, JSTracer *trc);
 
         size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
-            return storage_ ? storage_->sizeOfIncludingThis(mallocSizeOf) : 0;
+            return stores_.sizeOfExcludingThis(mallocSizeOf);
         }
 
       private:
         MonoTypeBuffer &operator=(const MonoTypeBuffer& other) MOZ_DELETE;
     };
 
-    /*
-     * Overrides the MonoTypeBuffer to support pointers that may be moved in
-     * memory outside of the GC's control.
-     */
-    template <typename T>
-    struct RelocatableMonoTypeBuffer : public MonoTypeBuffer<T>
-    {
-        /* Override compaction to filter out removed items. */
-        void compactMoved(StoreBuffer *owner);
-        virtual void compact(StoreBuffer *owner) MOZ_OVERRIDE;
-
-        /* Record a removal from the buffer. */
-        void unput(StoreBuffer *owner, const T &v) {
-            MonoTypeBuffer<T>::put(owner, v.tagged());
-        }
-    };
-
     struct GenericBuffer
     {
         LifoAlloc *storage_;
 
         explicit GenericBuffer() : storage_(nullptr) {}
         ~GenericBuffer() { js_delete(storage_); }
 
         bool init() {
@@ -246,50 +227,52 @@ class StoreBuffer
         static HashNumber hash(const Lookup &l) { return uintptr_t(l.edge) >> 3; }
         static bool match(const Edge &k, const Lookup &l) { return k == l; }
     };
 
     struct CellPtrEdge
     {
         Cell **edge;
 
+        CellPtrEdge() : edge(nullptr) {}
         explicit CellPtrEdge(Cell **v) : edge(v) {}
         bool operator==(const CellPtrEdge &other) const { return edge == other.edge; }
         bool operator!=(const CellPtrEdge &other) const { return edge != other.edge; }
 
         bool maybeInRememberedSet(const Nursery &nursery) const {
             MOZ_ASSERT(IsInsideNursery(*edge));
             return !nursery.isInside(edge);
         }
 
-        void mark(JSTracer *trc);
+        void mark(JSTracer *trc) const;
 
         CellPtrEdge tagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) | 1)); }
         CellPtrEdge untagged() const { return CellPtrEdge((Cell **)(uintptr_t(edge) & ~1)); }
         bool isTagged() const { return bool(uintptr_t(edge) & 1); }
 
         typedef PointerEdgeHasher<CellPtrEdge> Hasher;
     };
 
     struct ValueEdge
     {
         JS::Value *edge;
 
+        ValueEdge() : edge(nullptr) {}
         explicit ValueEdge(JS::Value *v) : edge(v) {}
         bool operator==(const ValueEdge &other) const { return edge == other.edge; }
         bool operator!=(const ValueEdge &other) const { return edge != other.edge; }
 
         Cell *deref() const { return edge->isGCThing() ? static_cast<Cell *>(edge->toGCThing()) : nullptr; }
 
         bool maybeInRememberedSet(const Nursery &nursery) const {
             MOZ_ASSERT(IsInsideNursery(deref()));
             return !nursery.isInside(edge);
         }
 
-        void mark(JSTracer *trc);
+        void mark(JSTracer *trc) const;
 
         ValueEdge tagged() const { return ValueEdge((JS::Value *)(uintptr_t(edge) | 1)); }
         ValueEdge untagged() const { return ValueEdge((JS::Value *)(uintptr_t(edge) & ~1)); }
         bool isTagged() const { return bool(uintptr_t(edge) & 1); }
 
         typedef PointerEdgeHasher<ValueEdge> Hasher;
     };
 
@@ -298,16 +281,17 @@ class StoreBuffer
         // These definitions must match those in HeapSlot::Kind.
         const static int SlotKind = 0;
         const static int ElementKind = 1;
 
         uintptr_t objectAndKind_; // NativeObject* | Kind
         int32_t start_;
         int32_t count_;
 
+        SlotsEdge() : objectAndKind_(0), start_(0), count_(0) {}
         SlotsEdge(NativeObject *object, int kind, int32_t start, int32_t count)
           : objectAndKind_(uintptr_t(object) | kind), start_(start), count_(count)
         {
             MOZ_ASSERT((uintptr_t(object) & 1) == 0);
             MOZ_ASSERT(kind <= 1);
             MOZ_ASSERT(start >= 0);
             MOZ_ASSERT(count > 0);
         }
@@ -324,42 +308,43 @@ class StoreBuffer
         bool operator!=(const SlotsEdge &other) const {
             return !(*this == other);
         }
 
         bool maybeInRememberedSet(const Nursery &) const {
             return !IsInsideNursery(JS::AsCell(reinterpret_cast<JSObject *>(object())));
         }
 
-        void mark(JSTracer *trc);
+        void mark(JSTracer *trc) const;
 
         typedef struct {
             typedef SlotsEdge Lookup;
             static HashNumber hash(const Lookup &l) { return l.objectAndKind_ ^ l.start_ ^ l.count_; }
             static bool match(const SlotsEdge &k, const Lookup &l) { return k == l; }
         } Hasher;
     };
 
     struct WholeCellEdges
     {
         Cell *edge;
 
+        WholeCellEdges() : edge(nullptr) {}
         explicit WholeCellEdges(Cell *cell) : edge(cell) {
             MOZ_ASSERT(edge->isTenured());
         }
 
         bool operator==(const WholeCellEdges &other) const { return edge == other.edge; }
         bool operator!=(const WholeCellEdges &other) const { return edge != other.edge; }
 
         bool maybeInRememberedSet(const Nursery &) const { return true; }
 
         static bool supportsDeduplication() { return true; }
         void *deduplicationKey() const { return (void *)edge; }
 
-        void mark(JSTracer *trc);
+        void mark(JSTracer *trc) const;
 
         typedef PointerEdgeHasher<WholeCellEdges> Hasher;
     };
 
     template <typename Key>
     struct CallbackRef : public BufferableRef
     {
         typedef void (*MarkCallback)(JSTracer *trc, Key *key, void *data);
@@ -420,18 +405,18 @@ class StoreBuffer
         if (edge.maybeInRememberedSet(nursery_))
             buffer.put(this, edge);
     }
 
     MonoTypeBuffer<ValueEdge> bufferVal;
     MonoTypeBuffer<CellPtrEdge> bufferCell;
     MonoTypeBuffer<SlotsEdge> bufferSlot;
     MonoTypeBuffer<WholeCellEdges> bufferWholeCell;
-    RelocatableMonoTypeBuffer<ValueEdge> bufferRelocVal;
-    RelocatableMonoTypeBuffer<CellPtrEdge> bufferRelocCell;
+    MonoTypeBuffer<ValueEdge> bufferRelocVal;
+    MonoTypeBuffer<CellPtrEdge> bufferRelocCell;
     GenericBuffer bufferGeneric;
 
     JSRuntime *runtime_;
     const Nursery &nursery_;
 
     bool aboutToOverflow_;
     bool enabled_;
     mozilla::DebugOnly<bool> mEntered; /* For ReentrancyGuard. */
@@ -500,16 +485,23 @@ class StoreBuffer
     void markGenericEntries(JSTracer *trc)    { bufferGeneric.mark(this, trc); }
 
     /* We cannot call InParallelSection directly because of a circular dependency. */
     bool inParallelSection() const;
 
     /* For use by our owned buffers and for testing. */
     void setAboutToOverflow();
 
+    /* For jit access to the raw buffer. */
+    void oolSinkStoresForWholeCellBuffer() { bufferWholeCell.sinkStores(this); }
+    void *addressOfWholeCellBufferPointer() const { return (void *)&bufferWholeCell.insert_; }
+    void *addressOfWholeCellBufferEnd() const {
+        return (void *)(bufferWholeCell.buffer_ + bufferWholeCell.NumBufferEntries);
+    }
+
     void addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::GCSizes *sizes);
 };
 
 } /* namespace gc */
 } /* namespace js */
 
 #endif /* JSGC_GENERATIONAL */
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Memory-takeCensus-04.js
@@ -0,0 +1,26 @@
+// Test that Debugger.Memory.prototype.takeCensus finds GC roots that are on the
+// stack.
+
+var g = newGlobal();
+var dbg = new Debugger(g);
+
+g.eval(`
+  function withTypedArrayOnStack(f) {
+    (function () {
+      var onStack = new Int8Array();
+      f();
+    }())
+  }
+`);
+
+assertEq("Int8Array" in dbg.memory.takeCensus().objects, false,
+         "There shouldn't exist any typed arrays in the census.");
+
+var typedArrayCount;
+g.withTypedArrayOnStack(() => {
+  typedArrayCount = dbg.memory.takeCensus().objects.Int8Array.count;
+});
+
+assertEq(typedArrayCount, 1,
+         "Should have one typed array in the census, because there " +
+         "was one on the stack.");
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Memory-takeCensus-05.js
@@ -0,0 +1,14 @@
+// Test that Debugger.Memory.prototype.takeCensus finds cross compartment
+// wrapper GC roots.
+
+var g = newGlobal();
+var dbg = new Debugger(g);
+
+assertEq("Int8Array" in dbg.memory.takeCensus().objects, false,
+         "There shouldn't exist any typed arrays in the census.");
+
+this.ccw = g.eval("new Int8Array()");
+
+assertEq(dbg.memory.takeCensus().objects.Int8Array.count, 1,
+         "Should have one typed array in the census, because there " +
+         "is one cross-compartment wrapper.");
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4316,16 +4316,60 @@ CodeGenerator::visitNewArrayCopyOnWrite(
         return false;
 
     masm.createGCObject(objReg, tempReg, templateObject, initialHeap, ool->entry());
 
     masm.bind(ool->rejoin());
     return true;
 }
 
+typedef ArrayObject *(*ArrayConstructorOneArgFn)(JSContext *, HandleTypeObject, int32_t length);
+static const VMFunction ArrayConstructorOneArgInfo =
+    FunctionInfo<ArrayConstructorOneArgFn>(ArrayConstructorOneArg);
+
+bool
+CodeGenerator::visitNewArrayDynamicLength(LNewArrayDynamicLength *lir)
+{
+    Register lengthReg = ToRegister(lir->length());
+    Register objReg = ToRegister(lir->output());
+    Register tempReg = ToRegister(lir->temp());
+
+    ArrayObject *templateObject = lir->mir()->templateObject();
+    gc::InitialHeap initialHeap = lir->mir()->initialHeap();
+
+    OutOfLineCode *ool = oolCallVM(ArrayConstructorOneArgInfo, lir,
+                                   (ArgList(), ImmGCPtr(templateObject->type()), lengthReg),
+                                   StoreRegisterTo(objReg));
+    if (!ool)
+        return false;
+
+    size_t numSlots = gc::GetGCKindSlots(templateObject->asTenured().getAllocKind());
+    size_t inlineLength = numSlots >= ObjectElements::VALUES_PER_HEADER
+                        ? numSlots - ObjectElements::VALUES_PER_HEADER
+                        : 0;
+
+    // Try to do the allocation inline if the template object is big enough
+    // for the length in lengthReg. If the length is bigger we could still
+    // use the template object and not allocate the elements, but it's more
+    // efficient to do a single big allocation than (repeatedly) reallocating
+    // the array later on when filling it.
+    if (!templateObject->hasSingletonType() && templateObject->length() <= inlineLength)
+        masm.branch32(Assembler::Above, lengthReg, Imm32(templateObject->length()), ool->entry());
+    else
+        masm.jump(ool->entry());
+
+    masm.createGCObject(objReg, tempReg, templateObject, initialHeap, ool->entry());
+
+    size_t lengthOffset = NativeObject::offsetOfFixedElements() + ObjectElements::offsetOfLength();
+    masm.store32(lengthReg, Address(objReg, lengthOffset));
+
+    masm.bind(ool->rejoin());
+    return true;
+}
+
 // Out-of-line object allocation for JSOP_NEWOBJECT.
 class OutOfLineNewObject : public OutOfLineCodeBase<CodeGenerator>
 {
     LNewObject *lir_;
 
   public:
     explicit OutOfLineNewObject(LNewObject *lir)
       : lir_(lir)
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -148,16 +148,17 @@ class CodeGenerator : public CodeGenerat
     bool visitCallDirectEvalS(LCallDirectEvalS *lir);
     bool visitCallDirectEvalV(LCallDirectEvalV *lir);
     bool visitDoubleToInt32(LDoubleToInt32 *lir);
     bool visitFloat32ToInt32(LFloat32ToInt32 *lir);
     bool visitNewArrayCallVM(LNewArray *lir);
     bool visitNewArray(LNewArray *lir);
     bool visitOutOfLineNewArray(OutOfLineNewArray *ool);
     bool visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite *lir);
+    bool visitNewArrayDynamicLength(LNewArrayDynamicLength *lir);
     bool visitNewObjectVMCall(LNewObject *lir);
     bool visitNewObject(LNewObject *lir);
     bool visitOutOfLineNewObject(OutOfLineNewObject *ool);
     bool visitNewTypedObject(LNewTypedObject *lir);
     bool visitNewDeclEnvObject(LNewDeclEnvObject *lir);
     bool visitNewCallObject(LNewCallObject *lir);
     bool visitNewSingletonCallObject(LNewSingletonCallObject *lir);
     bool visitNewCallObjectPar(LNewCallObjectPar *lir);
--- a/js/src/jit/ExecutableAllocatorWin.cpp
+++ b/js/src/jit/ExecutableAllocatorWin.cpp
@@ -154,17 +154,17 @@ RegisterExecutableMemory(void *p, size_t
     r->unwindInfo.countOfUnwindCodes = 0;
     r->unwindInfo.frameRegister = 0;
     r->unwindInfo.frameOffset = 0;
     r->unwindInfo.exceptionHandler = offsetof(ExceptionHandlerRecord, thunk);
 
     // mov imm64, rax
     r->thunk[0]  = 0x48;
     r->thunk[1]  = 0xb8;
-    void *handler = &ExceptionHandler;
+    void *handler = JS_FUNC_TO_DATA_PTR(void *, ExceptionHandler);
     memcpy(&r->thunk[2], &handler, 8);
 
     // jmp rax
     r->thunk[10] = 0xff;
     r->thunk[11] = 0xe0;
 
     DWORD oldProtect;
     if (!VirtualProtect(p, pageSize, PAGE_EXECUTE_READ, &oldProtect))
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -721,16 +721,38 @@ class LNewArrayCopyOnWrite : public LIns
         return getTemp(0);
     }
 
     MNewArrayCopyOnWrite *mir() const {
         return mir_->toNewArrayCopyOnWrite();
     }
 };
 
+class LNewArrayDynamicLength : public LInstructionHelper<1, 1, 1>
+{
+  public:
+    LIR_HEADER(NewArrayDynamicLength)
+
+    explicit LNewArrayDynamicLength(const LAllocation &length, const LDefinition &temp) {
+        setOperand(0, length);
+        setTemp(0, temp);
+    }
+
+    const LAllocation *length() {
+        return getOperand(0);
+    }
+    const LDefinition *temp() {
+        return getTemp(0);
+    }
+
+    MNewArrayDynamicLength *mir() const {
+        return mir_->toNewArrayDynamicLength();
+    }
+};
+
 class LNewObject : public LInstructionHelper<1, 0, 1>
 {
   public:
     LIR_HEADER(NewObject)
 
     explicit LNewObject(const LDefinition &temp) {
         setTemp(0, temp);
     }
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -41,16 +41,17 @@
     _(Parameter)                    \
     _(Callee)                       \
     _(IsConstructing)               \
     _(TableSwitch)                  \
     _(TableSwitchV)                 \
     _(Goto)                         \
     _(NewArray)                     \
     _(NewArrayCopyOnWrite)          \
+    _(NewArrayDynamicLength)        \
     _(ArraySplice)                  \
     _(NewObject)                    \
     _(NewTypedObject)               \
     _(NewDeclEnvObject)             \
     _(NewCallObject)                \
     _(NewSingletonCallObject)       \
     _(NewStringObject)              \
     _(NewPar)                       \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -164,16 +164,26 @@ LIRGenerator::visitNewArray(MNewArray *i
 bool
 LIRGenerator::visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite *ins)
 {
     LNewArrayCopyOnWrite *lir = new(alloc()) LNewArrayCopyOnWrite(temp());
     return define(lir, ins) && assignSafepoint(lir, ins);
 }
 
 bool
+LIRGenerator::visitNewArrayDynamicLength(MNewArrayDynamicLength *ins)
+{
+    MDefinition *length = ins->length();
+    MOZ_ASSERT(length->type() == MIRType_Int32);
+
+    LNewArrayDynamicLength *lir = new(alloc()) LNewArrayDynamicLength(useRegister(length), temp());
+    return define(lir, ins) && assignSafepoint(lir, ins);
+}
+
+bool
 LIRGenerator::visitNewObject(MNewObject *ins)
 {
     LNewObject *lir = new(alloc()) LNewObject(temp());
     return define(lir, ins) && assignSafepoint(lir, ins);
 }
 
 bool
 LIRGenerator::visitNewTypedObject(MNewTypedObject *ins)
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -67,16 +67,17 @@ class LIRGenerator : public LIRGenerator
     bool visitCloneLiteral(MCloneLiteral *ins);
     bool visitParameter(MParameter *param);
     bool visitCallee(MCallee *callee);
     bool visitIsConstructing(MIsConstructing *ins);
     bool visitGoto(MGoto *ins);
     bool visitTableSwitch(MTableSwitch *tableswitch);
     bool visitNewArray(MNewArray *ins);
     bool visitNewArrayCopyOnWrite(MNewArrayCopyOnWrite *ins);
+    bool visitNewArrayDynamicLength(MNewArrayDynamicLength *ins);
     bool visitNewObject(MNewObject *ins);
     bool visitNewTypedObject(MNewTypedObject *ins);
     bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
     bool visitNewCallObject(MNewCallObject *ins);
     bool visitNewRunOnceCallObject(MNewRunOnceCallObject *ins);
     bool visitNewStringObject(MNewStringObject *ins);
     bool visitNewDerivedTypedObject(MNewDerivedTypedObject *ins);
     bool visitNewPar(MNewPar *ins);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -352,23 +352,40 @@ IonBuilder::inlineArray(CallInfo &callIn
                 if (!TypeSetIncludes(elemTypes.maybeTypes(), value->type(), value->resultTypeSet())) {
                     elemTypes.freeze(constraints());
                     return InliningStatus_NotInlined;
                 }
             }
         }
     }
 
+    types::TemporaryTypeSet::DoubleConversion conversion =
+        getInlineReturnTypeSet()->convertDoubleElements(constraints());
+    if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
+        templateObject->setShouldConvertDoubleElements();
+    else
+        templateObject->clearShouldConvertDoubleElements();
+
     // A single integer argument denotes initial length.
     if (callInfo.argc() == 1) {
         if (callInfo.getArg(0)->type() != MIRType_Int32)
             return InliningStatus_NotInlined;
+
         MDefinition *arg = callInfo.getArg(0);
-        if (!arg->isConstant())
-            return InliningStatus_NotInlined;
+        if (!arg->isConstant()) {
+            callInfo.setImplicitlyUsedUnchecked();
+            ArrayObject *templateArray = &templateObject->as<ArrayObject>();
+            MNewArrayDynamicLength *ins =
+                MNewArrayDynamicLength::New(alloc(), constraints(), templateArray,
+                                            templateArray->type()->initialHeap(constraints()),
+                                            arg);
+            current->add(ins);
+            current->push(ins);
+            return InliningStatus_Inlined;
+        }
 
         // Negative lengths generate a RangeError, unhandled by the inline path.
         initLength = arg->toConstant()->value().toInt32();
         if (initLength >= NativeObject::NELEMENTS_LIMIT)
             return InliningStatus_NotInlined;
 
         // Make sure initLength matches the template object's length. This is
         // not guaranteed to be the case, for instance if we're inlining the
@@ -380,23 +397,16 @@ IonBuilder::inlineArray(CallInfo &callIn
         if (initLength > ArrayObject::EagerAllocationMaxLength)
             return InliningStatus_NotInlined;
 
         allocating = NewArray_FullyAllocating;
     }
 
     callInfo.setImplicitlyUsedUnchecked();
 
-    types::TemporaryTypeSet::DoubleConversion conversion =
-        getInlineReturnTypeSet()->convertDoubleElements(constraints());
-    if (conversion == types::TemporaryTypeSet::AlwaysConvertToDoubles)
-        templateObject->setShouldConvertDoubleElements();
-    else
-        templateObject->clearShouldConvertDoubleElements();
-
     MConstant *templateConst = MConstant::NewConstraintlessObject(alloc(), templateObject);
     current->add(templateConst);
 
     MNewArray *ins = MNewArray::New(alloc(), constraints(), initLength, templateConst,
                                     templateObject->type()->initialHeap(constraints()),
                                     allocating);
     current->add(ins);
     current->push(ins);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -2644,16 +2644,60 @@ class MNewArrayCopyOnWrite : public MNul
         return initialHeap_;
     }
 
     virtual AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
+class MNewArrayDynamicLength
+  : public MUnaryInstruction,
+    public IntPolicy<0>::Data
+{
+    AlwaysTenured<ArrayObject*> templateObject_;
+    gc::InitialHeap initialHeap_;
+
+    MNewArrayDynamicLength(types::CompilerConstraintList *constraints, ArrayObject *templateObject,
+                           gc::InitialHeap initialHeap, MDefinition *length)
+      : MUnaryInstruction(length),
+        templateObject_(templateObject),
+        initialHeap_(initialHeap)
+    {
+        setGuard(); // Need to throw if length is negative.
+        setResultType(MIRType_Object);
+        if (!templateObject->hasSingletonType())
+            setResultTypeSet(MakeSingletonTypeSet(constraints, templateObject));
+    }
+
+  public:
+    INSTRUCTION_HEADER(NewArrayDynamicLength)
+
+    static MNewArrayDynamicLength *New(TempAllocator &alloc, types::CompilerConstraintList *constraints,
+                                       ArrayObject *templateObject, gc::InitialHeap initialHeap,
+                                       MDefinition *length)
+    {
+        return new(alloc) MNewArrayDynamicLength(constraints, templateObject, initialHeap, length);
+    }
+
+    MDefinition *length() const {
+        return getOperand(0);
+    }
+    ArrayObject *templateObject() const {
+        return templateObject_;
+    }
+    gc::InitialHeap initialHeap() const {
+        return initialHeap_;
+    }
+
+    virtual AliasSet getAliasSet() const {
+        return AliasSet::None();
+    }
+};
+
 class MNewObject : public MUnaryInstruction
 {
     gc::InitialHeap initialHeap_;
     bool templateObjectIsClassPrototype_;
 
     MNewObject(types::CompilerConstraintList *constraints, MConstant *templateConst,
                gc::InitialHeap initialHeap, bool templateObjectIsClassPrototype)
       : MUnaryInstruction(templateConst),
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -106,16 +106,17 @@ namespace jit {
     _(ToDouble)                                                             \
     _(ToFloat32)                                                            \
     _(ToInt32)                                                              \
     _(TruncateToInt32)                                                      \
     _(ToString)                                                             \
     _(ToObjectOrNull)                                                       \
     _(NewArray)                                                             \
     _(NewArrayCopyOnWrite)                                                  \
+    _(NewArrayDynamicLength)                                                \
     _(NewObject)                                                            \
     _(NewTypedObject)                                                       \
     _(NewDeclEnvObject)                                                     \
     _(NewCallObject)                                                        \
     _(NewRunOnceCallObject)                                                 \
     _(NewStringObject)                                                      \
     _(ObjectState)                                                          \
     _(ArrayState)                                                           \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -198,16 +198,17 @@ class ParallelSafetyVisitor : public MDe
     SAFE_OP(ToFloat32)
     SAFE_OP(ToInt32)
     SAFE_OP(TruncateToInt32)
     SAFE_OP(MaybeToDoubleElement)
     CUSTOM_OP(ToString)
     UNSAFE_OP(ToObjectOrNull)
     CUSTOM_OP(NewArray)
     UNSAFE_OP(NewArrayCopyOnWrite)
+    UNSAFE_OP(NewArrayDynamicLength)
     UNSAFE_OP(NewTypedObject)
     CUSTOM_OP(NewObject)
     CUSTOM_OP(NewCallObject)
     CUSTOM_OP(NewRunOnceCallObject)
     CUSTOM_OP(NewDerivedTypedObject)
     SAFE_OP(ObjectState)
     SAFE_OP(ArrayState)
     UNSAFE_OP(InitElem)
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3114,17 +3114,17 @@ IsArrayConstructor(const Value &v)
     // constructor would be represented as a wrapper.
     return v.isObject() &&
            v.toObject().is<JSFunction>() &&
            v.toObject().as<JSFunction>().isNative() &&
            v.toObject().as<JSFunction>().native() == js_Array;
 }
 
 static bool
-ArrayFromCallArgs(JSContext *cx, RootedTypeObject &type, CallArgs &args)
+ArrayFromCallArgs(JSContext *cx, HandleTypeObject type, CallArgs &args)
 {
     if (!InitArrayTypes(cx, type, args.array(), args.length()))
         return false;
     JSObject *obj = (args.length() == 0)
         ? NewDenseEmptyArray(cx)
         : NewDenseCopiedArray(cx, args.length(), args.array());
     if (!obj)
         return false;
@@ -3291,16 +3291,31 @@ js_Array(JSContext *cx, unsigned argc, V
     RootedObject obj(cx, NewDenseArray(cx, length, type, allocating));
     if (!obj)
         return false;
 
     args.rval().setObject(*obj);
     return true;
 }
 
+ArrayObject *
+js::ArrayConstructorOneArg(JSContext *cx, HandleTypeObject type, int32_t lengthInt)
+{
+    if (lengthInt < 0) {
+        JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
+        return nullptr;
+    }
+
+    uint32_t length = uint32_t(lengthInt);
+    AllocatingBehaviour allocating = (length <= ArrayObject::EagerAllocationMaxLength)
+                                   ? NewArray_FullyAllocating
+                                   : NewArray_PartlyAllocating;
+    return NewDenseArray(cx, length, type, allocating);
+}
+
 static JSObject *
 CreateArrayPrototype(JSContext *cx, JSProtoKey key)
 {
     MOZ_ASSERT(key == JSProto_Array);
     RootedObject proto(cx, cx->global()->getOrCreateObjectPrototype(cx));
     if (!proto)
         return nullptr;
 
--- a/js/src/jsarray.h
+++ b/js/src/jsarray.h
@@ -191,16 +191,19 @@ array_slice(JSContext *cx, unsigned argc
  * a newborn array -- that is, one which has not been exposed to script for
  * arbitrary manipulation.  (This method optimizes on the assumption that
  * extending the array to accommodate the element will never make the array
  * sparse, which requires that the array be completely filled.)
  */
 extern bool
 NewbornArrayPush(JSContext *cx, HandleObject obj, const Value &v);
 
+extern ArrayObject *
+ArrayConstructorOneArg(JSContext *cx, HandleTypeObject type, int32_t lengthInt);
+
 } /* namespace js */
 
 #ifdef DEBUG
 extern bool
 js_ArrayInfo(JSContext *cx, unsigned argc, js::Value *vp);
 #endif
 
 /* Array constructor native. Exposed only so the JIT can know its address. */
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/extensions/element-setting-ToNumber-neuters.js
@@ -0,0 +1,40 @@
+// |reftest| skip-if(!xulRuntime.shell) -- needs neuter()
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+"use strict"; // make test fail when limitation below is fixed
+
+var gTestfile = 'element-setting-ToNumber-neuters.js';
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 1001547;
+var summary =
+  "Don't assert assigning into memory neutered while converting the value to " +
+  "assign into a number";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+// Technically per current spec the element-sets should throw in strict mode,
+// but we just silently do nothing for now, somewhat due to limitations of our
+// internal MOP (which can't easily say "try this special behavior, else fall
+// back on normal logic"), somewhat because it's consistent with current
+// behavior (as of this test's addition) for out-of-bounds sets.
+
+var ab1 = new ArrayBuffer(64);
+var ta1 = new Uint32Array(ab1);
+ta1[4] = { valueOf: function() { neuter(ab1, "change-data"); return 5; } };
+
+var ab2 = new ArrayBuffer(64);
+var ta2 = new Uint32Array(ab2);
+ta2[4] = { valueOf: function() { neuter(ab2, "same-data"); return 5; } };
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
new file mode 100644
--- /dev/null
+++ b/js/src/tests/js1_8_5/extensions/typedarray-set-neutering.js
@@ -0,0 +1,77 @@
+// |reftest| skip-if(!xulRuntime.shell)
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+//-----------------------------------------------------------------------------
+var BUGNUMBER = 983344;
+var summary =
+  "Uint8Array.prototype.set issues when this array changes during setting";
+
+print(BUGNUMBER + ": " + summary);
+
+/**************
+ * BEGIN TEST *
+ **************/
+
+var ab1 = new ArrayBuffer(200);
+var a1 = new Uint8Array(ab1);
+var a1_2 = new Uint8Array(10);
+
+var src1 = [ 10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             ];
+Object.defineProperty(src1, 4, {
+  get: function () {
+    neuter(ab1, "change-data");
+    gc();
+    return 200;
+  }
+});
+
+a1.set(src1);
+
+// Not really needed
+Array.reverse(a1_2);
+
+var ab2 = new ArrayBuffer(200);
+var a2 = new Uint8Array(ab2);
+var a2_2 = new Uint8Array(10);
+
+var src2 = [ 10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             10, 20, 30, 40,
+             ];
+Object.defineProperty(src2, 4, {
+  get: function () {
+    neuter(ab2, "same-data");
+    gc();
+    return 200;
+  }
+});
+
+a2.set(src2);
+
+// Not really needed
+Array.reverse(a2_2);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+  reportCompare(true, true);
+
+print("Tests complete");
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -7250,8 +7250,21 @@ JS::dbg::onNewPromise(JSContext *cx, Han
 }
 
 JS_PUBLIC_API(void)
 JS::dbg::onPromiseSettled(JSContext *cx, HandleObject promise)
 {
     AssertIsPromise(cx, promise);
     Debugger::slowPathPromiseHook(cx, Debugger::OnPromiseSettled, promise);
 }
+
+JS_PUBLIC_API(bool)
+JS::dbg::IsDebugger(JS::Value val)
+{
+    if (!val.isObject())
+        return false;
+
+    JSObject &obj = val.toObject();
+    if (obj.getClass() != &Debugger::jsclass)
+        return false;
+
+    return js::Debugger::fromJSObject(&obj) != nullptr;
+}
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -172,16 +172,17 @@ typedef JSObject Env;
 
 class Debugger : private mozilla::LinkedListElement<Debugger>
 {
     friend class Breakpoint;
     friend class DebuggerMemory;
     friend class SavedStacks;
     friend class mozilla::LinkedListElement<Debugger>;
     friend bool (::JS_DefineDebuggerObject)(JSContext *cx, JS::HandleObject obj);
+    friend bool (::JS::dbg::IsDebugger)(JS::Value val);
     friend bool SavedStacksMetadataCallback(JSContext *cx, JSObject **pmetadata);
     friend void JS::dbg::onNewPromise(JSContext *cx, HandleObject promise);
     friend void JS::dbg::onPromiseSettled(JSContext *cx, HandleObject promise);
 
   public:
     enum Hook {
         OnDebuggerStatement,
         OnExceptionUnwind,
@@ -481,16 +482,18 @@ class Debugger : private mozilla::Linked
     inline const js::HeapPtrNativeObject &toJSObject() const;
     inline js::HeapPtrNativeObject &toJSObjectRef();
     static inline Debugger *fromJSObject(JSObject *obj);
     static Debugger *fromChildJSObject(JSObject *obj);
 
     bool hasMemory() const;
     DebuggerMemory &memory() const;
 
+    GlobalObjectSet::Range allDebuggees() const { return debuggees.all(); }
+
     /*********************************** Methods for interaction with the GC. */
 
     /*
      * A Debugger object is live if:
      *   * the Debugger JSObject is live (Debugger::trace handles this case); OR
      *   * it is in the middle of dispatching an event (the event dispatching
      *     code roots it in this case); OR
      *   * it is enabled, and it is debugging at least one live compartment,
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -29,16 +29,17 @@
 using namespace js;
 
 using JS::ubi::BreadthFirst;
 using JS::ubi::Edge;
 using JS::ubi::Node;
 
 using mozilla::Maybe;
 using mozilla::Move;
+using mozilla::Nothing;
 
 /* static */ DebuggerMemory *
 DebuggerMemory::create(JSContext *cx, Debugger *dbg)
 {
 
     Value memoryProto = dbg->object->getReservedSlot(Debugger::JSSLOT_DEBUG_MEMORY_PROTO);
     RootedNativeObject memory(cx, NewNativeObjectWithGivenProto(cx, &class_,
                                                                 &memoryProto.toObject(), nullptr));
@@ -749,44 +750,54 @@ typedef BreadthFirst<DefaultCensusHandle
 
 } // namespace dbg
 } // namespace js
 
 bool
 DebuggerMemory::takeCensus(JSContext *cx, unsigned argc, Value *vp)
 {
     THIS_DEBUGGER_MEMORY(cx, argc, vp, "Debugger.Memory.prototype.census", args, memory);
-    Debugger *debugger = memory->getDebugger();
 
     dbg::Census census(cx);
     if (!census.init())
         return false;
+
     dbg::DefaultCensusHandler handler(census);
     if (!handler.init(census))
         return false;
 
+    Debugger *dbg = memory->getDebugger();
+
+    // Populate census.debuggeeZones and ensure that all of our debuggee globals
+    // are rooted so that they are visible in the RootList.
+    JS::AutoObjectVector debuggees(cx);
+    for (GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
+        if (!census.debuggeeZones.put(r.front()->zone()) ||
+            !debuggees.append(static_cast<JSObject *>(r.front())))
+        {
+            return false;
+        }
+    }
+
     {
-        JS::AutoCheckCannotGC noGC;
+        Maybe<JS::AutoCheckCannotGC> maybeNoGC;
+        JS::ubi::RootList rootList(cx, maybeNoGC);
+        if (!rootList.init(cx, census.debuggeeZones))
+            return false;
 
-        dbg::DefaultCensusTraversal traversal(cx, handler, noGC);
+        dbg::DefaultCensusTraversal traversal(cx, handler, maybeNoGC.ref());
         if (!traversal.init())
             return false;
         traversal.wantNames = false;
 
-        // Walk the debuggee compartments, using it to set the starting points
-        // (the debuggee globals) for the traversal, and to populate
-        // census.debuggeeZones.
-        for (GlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
-            if (!census.debuggeeZones.put(r.front()->zone()) ||
-                !traversal.addStart(static_cast<JSObject *>(r.front())))
-                return false;
+        if (!traversal.addStart(JS::ubi::Node(&rootList)) ||
+            !traversal.traverse())
+        {
+            return false;
         }
-
-        if (!traversal.traverse())
-            return false;
     }
 
     return handler.report(census, args.rval());
 }
 
 
 
 /* Debugger.Memory property and method tables. */
--- a/js/src/vm/TypedArrayCommon.h
+++ b/js/src/vm/TypedArrayCommon.h
@@ -155,76 +155,88 @@ class ElementSpecific
         T *dest = static_cast<T*>(target->viewData()) + offset;
         uint32_t count = source->length();
 
         if (source->type() == target->type()) {
             mozilla::PodCopy(dest, static_cast<T*>(source->viewData()), count);
             return true;
         }
 
+#ifdef __arm__
+#  define JS_VOLATILE_ARM volatile // Inhibit unaligned accesses on ARM.
+#else
+#  define JS_VOLATILE_ARM /* nothing */
+#endif
+
         void *data = source->viewData();
         switch (source->type()) {
           case Scalar::Int8: {
-#ifdef __arm__
-            // NB: Using volatile to fix unaligned access on ARM
-            volatile
-#endif
+            JS_VOLATILE_ARM
             int8_t *src = static_cast<int8_t*>(data);
 
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Uint8:
           case Scalar::Uint8Clamped: {
+            JS_VOLATILE_ARM
             uint8_t *src = static_cast<uint8_t*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Int16: {
+            JS_VOLATILE_ARM
             int16_t *src = static_cast<int16_t*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Uint16: {
+            JS_VOLATILE_ARM
             uint16_t *src = static_cast<uint16_t*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Int32: {
+            JS_VOLATILE_ARM
             int32_t *src = static_cast<int32_t*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Uint32: {
+            JS_VOLATILE_ARM
             uint32_t *src = static_cast<uint32_t*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Float32: {
+            JS_VOLATILE_ARM
             float *src = static_cast<float*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           case Scalar::Float64: {
+            JS_VOLATILE_ARM
             double *src = static_cast<double*>(data);
             for (uint32_t i = 0; i < count; ++i)
                 *dest++ = T(*src++);
             break;
           }
           default:
             MOZ_CRASH("setFromTypedArray with a typed array with bogus type");
         }
 
+#undef JS_VOLATILE_ARM
+
         return true;
     }
 
     /*
      * Copy |source[0]| to |source[len]| (exclusive) elements into the typed
      * array |target|, starting at index |offset|.  |source| must not be a
      * typed array.
      */
--- a/js/src/vm/UbiNode.cpp
+++ b/js/src/vm/UbiNode.cpp
@@ -11,33 +11,40 @@
 #include "mozilla/Scoped.h"
 
 #include "jscntxt.h"
 #include "jsinfer.h"
 #include "jsobj.h"
 #include "jsscript.h"
 
 #include "jit/IonCode.h"
+#include "js/Debug.h"
 #include "js/TracingAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 #include "js/Vector.h"
+#include "vm/GlobalObject.h"
 #include "vm/ScopeObject.h"
 #include "vm/Shape.h"
 #include "vm/String.h"
 #include "vm/Symbol.h"
 
 #include "jsobjinlines.h"
+#include "vm/Debugger-inl.h"
 
+using mozilla::Some;
 using JS::HandleValue;
 using JS::Value;
+using JS::ZoneSet;
 using JS::ubi::Concrete;
 using JS::ubi::Edge;
 using JS::ubi::EdgeRange;
 using JS::ubi::Node;
+using JS::ubi::SimpleEdge;
+using JS::ubi::SimpleEdgeVector;
 using JS::ubi::TracerConcrete;
 using JS::ubi::TracerConcreteWithCompartment;
 
 // All operations on null ubi::Nodes crash.
 const char16_t *Concrete<void>::typeName() const          { MOZ_CRASH("null ubi::Node"); }
 EdgeRange *Concrete<void>::edges(JSContext *, bool) const { MOZ_CRASH("null ubi::Node"); }
 JS::Zone *Concrete<void>::zone() const                    { MOZ_CRASH("null ubi::Node"); }
 JSCompartment *Concrete<void>::compartment() const        { MOZ_CRASH("null ubi::Node"); }
@@ -98,52 +105,16 @@ Node::exposeToJS() const
         v.setSymbol(as<JS::Symbol>());
     } else {
         v.setUndefined();
     }
 
     return v;
 }
 
-// A dumb Edge concrete class. All but the most essential members have the
-// default behavior.
-class SimpleEdge : public Edge {
-    SimpleEdge(SimpleEdge &) MOZ_DELETE;
-    SimpleEdge &operator=(const SimpleEdge &) MOZ_DELETE;
-
-  public:
-    SimpleEdge() : Edge() { }
-
-    // Construct an initialized SimpleEdge, taking ownership of |name|.
-    SimpleEdge(char16_t *name, const Node &referent) {
-        this->name = name;
-        this->referent = referent;
-    }
-    ~SimpleEdge() {
-        js_free(const_cast<char16_t *>(name));
-    }
-
-    // Move construction and assignment.
-    SimpleEdge(SimpleEdge &&rhs) {
-        name = rhs.name;
-        referent = rhs.referent;
-
-        rhs.name = nullptr;
-    }
-    SimpleEdge &operator=(SimpleEdge &&rhs) {
-        MOZ_ASSERT(&rhs != this);
-        this->~SimpleEdge();
-        new(this) SimpleEdge(mozilla::Move(rhs));
-        return *this;
-    }
-};
-
-
-typedef mozilla::Vector<SimpleEdge, 8, js::TempAllocPolicy> SimpleEdgeVector;
-
 
 // A JSTracer subclass that adds a SimpleEdge to a Vector for each edge on
 // which it is invoked.
 class SimpleEdgeVectorTracer : public JSTracer {
     // The vector to which we add SimpleEdges.
     SimpleEdgeVector *vec;
 
     // True if we should populate the edge's names.
@@ -280,8 +251,105 @@ template class TracerConcrete<JS::Symbol
 template class TracerConcreteWithCompartment<JSScript>;
 template class TracerConcrete<js::LazyScript>;
 template class TracerConcrete<js::jit::JitCode>;
 template class TracerConcreteWithCompartment<js::Shape>;
 template class TracerConcreteWithCompartment<js::BaseShape>;
 template class TracerConcrete<js::types::TypeObject>;
 }
 }
+
+
+namespace JS {
+namespace ubi {
+
+RootList::RootList(JSContext *cx, Maybe<AutoCheckCannotGC> &noGC, bool wantNames /* = false */)
+  : noGC(noGC),
+    edges(cx),
+    wantNames(wantNames)
+{ }
+
+
+bool
+RootList::init(JSContext *cx)
+{
+    SimpleEdgeVectorTracer tracer(cx, &edges, wantNames);
+    JS_TraceRuntime(&tracer);
+    if (!tracer.okay)
+        return false;
+    noGC.emplace(cx->runtime());
+    return true;
+}
+
+bool
+RootList::init(JSContext *cx, ZoneSet &debuggees)
+{
+    SimpleEdgeVector allRootEdges(cx);
+    SimpleEdgeVectorTracer tracer(cx, &allRootEdges, wantNames);
+
+    JS_TraceRuntime(&tracer);
+    if (!tracer.okay)
+        return false;
+    JS_TraceIncomingCCWs(&tracer, debuggees);
+    if (!tracer.okay)
+        return false;
+
+    for (SimpleEdgeVector::Range r = allRootEdges.all(); !r.empty(); r.popFront()) {
+        SimpleEdge &edge = r.front();
+        Zone *zone = edge.referent.zone();
+        if (zone && !debuggees.has(zone))
+            continue;
+        if (!edges.append(mozilla::Move(edge)))
+            return false;
+    }
+
+    noGC.emplace(cx->runtime());
+    return true;
+}
+
+bool
+RootList::init(JSContext *cx, HandleObject debuggees)
+{
+    MOZ_ASSERT(debuggees && JS::dbg::IsDebugger(ObjectValue(*debuggees)));
+    js::Debugger *dbg = js::Debugger::fromJSObject(debuggees);
+
+    ZoneSet debuggeeZones;
+    if (!debuggeeZones.init())
+        return false;
+
+    for (js::GlobalObjectSet::Range r = dbg->allDebuggees(); !r.empty(); r.popFront()) {
+        if (!debuggeeZones.put(r.front()->zone()))
+            return false;
+    }
+
+    return init(cx, debuggeeZones);
+}
+
+// An EdgeRange concrete class that holds a pre-existing vector of SimpleEdges.
+class PreComputedEdgeRange : public EdgeRange {
+    SimpleEdgeVector &edges;
+    size_t           i;
+
+    void settle() {
+        front_ = i < edges.length() ? &edges[i] : nullptr;
+    }
+
+  public:
+    explicit PreComputedEdgeRange(JSContext *cx, SimpleEdgeVector &edges)
+      : edges(edges),
+        i(0)
+    {
+        settle();
+    }
+
+    void popFront() MOZ_OVERRIDE { i++; settle(); }
+};
+
+const char16_t Concrete<RootList>::concreteTypeName[] = MOZ_UTF16("RootList");
+
+EdgeRange *
+Concrete<RootList>::edges(JSContext *cx, bool wantNames) const {
+    MOZ_ASSERT_IF(wantNames, get().wantNames);
+    return js_new<PreComputedEdgeRange>(cx, get().edges);
+}
+
+} // namespace ubi
+} // namespace JS
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -243,18 +243,16 @@ nsPresContext::nsPresContext(nsIDocument
 
   mCounterStylesDirty = true;
 
   // if text perf logging enabled, init stats struct
   PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textperf);
   if (log && log->level >= PR_LOG_WARNING) {
     mTextPerf = new gfxTextPerfMetrics();
   }
-
-  PR_INIT_CLIST(&mDOMMediaQueryLists);
 }
 
 void
 nsPresContext::Destroy()
 {
   if (mEventManager) {
     // unclear if these are needed, but can't hurt
     mEventManager->NotifyDestroyPresContext(this);
@@ -320,19 +318,16 @@ nsPresContext::Destroy()
   }
 }
 
 nsPresContext::~nsPresContext()
 {
   NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
   SetShell(nullptr);
 
-  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
-                    "must not have media query lists left");
-
   Destroy();
 }
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext)
    NS_INTERFACE_MAP_ENTRY(nsISupports)
    NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END
 
@@ -350,48 +345,25 @@ nsPresContext::LastRelease()
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventManager);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
 
-  // We own only the items in mDOMMediaQueryLists that have listeners;
-  // this reference is managed by their AddListener and RemoveListener
-  // methods.
-  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
-       l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
-    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
-    if (mql->HasListeners()) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
-      cb.NoteXPCOMChild(mql);
-    }
-  }
-
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrintSettings);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrefChangedTimer);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeviceContext); // worth bothering?
-  // We own only the items in mDOMMediaQueryLists that have listeners;
-  // this reference is managed by their AddListener and RemoveListener
-  // methods.
-  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
-       l != &tmp->mDOMMediaQueryLists; ) {
-    PRCList *next = PR_NEXT_LINK(l);
-    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
-    mql->RemoveAllListeners();
-    l = next;
-  }
-
   // NS_RELEASE(tmp->mLanguage); // an atom
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrintSettings);
 
   tmp->Destroy();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -1905,45 +1877,45 @@ nsPresContext::MediaFeatureValuesChanged
 
   if (aRestyleHint || aChangeHint) {
     RebuildAllStyleData(aChangeHint, aRestyleHint);
   }
 
   mPendingViewportChange = false;
 
   if (mDocument->IsBeingUsedAsImage()) {
-    MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists));
+    MOZ_ASSERT(PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists()));
     return;
   }
 
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
   // Media query list listeners should be notified from a queued task
   // (in HTML5 terms), although we also want to notify them on certain
   // flushes.  (We're already running off an event.)
   //
   // Note that we do this after the new style from media queries in
   // style sheets has been computed.
 
-  if (!PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists)) {
+  if (!PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists())) {
     // We build a list of all the notifications we're going to send
     // before we send any of them.  (The spec says the notifications
     // should be a queued task, so any removals that happen during the
     // notifications shouldn't affect what gets notified.)  Furthermore,
     // we hold strong pointers to everything we're going to make
     // notification calls to, since each notification involves calling
     // arbitrary script that might otherwise destroy these objects, or,
     // for that matter, |this|.
     //
     // Note that we intentionally send the notifications to media query
     // list in the order they were created and, for each list, to the
     // listeners in the order added.
     MediaQueryList::NotifyList notifyList;
-    for (PRCList *l = PR_LIST_HEAD(&mDOMMediaQueryLists);
-         l != &mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
+    for (PRCList *l = PR_LIST_HEAD(mDocument->MediaQueryLists());
+         l != mDocument->MediaQueryLists(); l = PR_NEXT_LINK(l)) {
       MediaQueryList *mql = static_cast<MediaQueryList*>(l);
       mql->MediumFeaturesChanged(notifyList);
     }
 
     if (!notifyList.IsEmpty()) {
       for (uint32_t i = 0, i_end = notifyList.Length(); i != i_end; ++i) {
         nsAutoMicroTask mt;
         MediaQueryList::HandleChangeData &d = notifyList[i];
@@ -1977,27 +1949,16 @@ nsPresContext::HandleMediaFeatureValuesC
 {
   // Null-check mShell in case the shell has been destroyed (and the
   // event is the only thing holding the pres context alive).
   if (mPendingMediaFeatureValuesChanged && mShell) {
     MediaFeatureValuesChanged(nsRestyleHint(0));
   }
 }
 
-already_AddRefed<MediaQueryList>
-nsPresContext::MatchMedia(const nsAString& aMediaQueryList)
-{
-  nsRefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
-
-  // Insert the new item at the end of the linked list.
-  PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
-
-  return result.forget();
-}
-
 nsCompatibility
 nsPresContext::CompatibilityMode() const
 {
   return Document()->GetCompatibilityMode();
 }
 
 void
 nsPresContext::SetPaginatedScrolling(bool aPaginated)
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -67,17 +67,16 @@ class nsIWidget;
 class nsDeviceContext;
 
 namespace mozilla {
 class EventStateManager;
 class RestyleManager;
 class CounterStyleManager;
 namespace dom {
 class FontFaceSet;
-class MediaQueryList;
 }
 namespace layers {
 class ContainerLayer;
 }
 }
 
 // supported values for cached bool types
 enum nsPresContext_CachedBoolPrefType {
@@ -285,22 +284,16 @@ public:
   void PostMediaFeatureValuesChangedEvent();
   void HandleMediaFeatureValuesChangedEvent();
   void FlushPendingMediaFeatureValuesChanged() {
     if (mPendingMediaFeatureValuesChanged)
       MediaFeatureValuesChanged(nsRestyleHint(0));
   }
 
   /**
-   * Support for window.matchMedia()
-   */
-  already_AddRefed<mozilla::dom::MediaQueryList>
-    MatchMedia(const nsAString& aMediaQueryList);
-
-  /**
    * Access compatibility mode for this context.  This is the same as
    * our document's compatibility mode.
    */
   nsCompatibility CompatibilityMode() const;
 
   /**
    * Notify the context that the document's compatibility mode has changed
    */
@@ -1234,18 +1227,16 @@ public:
   // Should we disable font size inflation because we're inside of
   // shrink-wrapping calculations on an inflation container?
   bool                  mInflationDisabledForShrinkWrap;
 
 protected:
 
   mozilla::WeakPtr<nsDocShell>             mContainer;
 
-  PRCList               mDOMMediaQueryLists;
-
   // Base minimum font size, independent of the language-specific global preference. Defaults to 0
   int32_t               mBaseMinFontSize;
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
 
   float                 mLastFontInflationScreenWidth;
 
   int32_t               mCurAppUnitsPerDevPixel;
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -182,66 +182,92 @@ nsFileControlFrame::DnDListener::HandleE
 
   bool defaultPrevented = false;
   aEvent->GetDefaultPrevented(&defaultPrevented);
   if (defaultPrevented) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIDOMDragEvent> dragEvent = do_QueryInterface(aEvent);
-  if (!dragEvent || !IsValidDropData(dragEvent)) {
+  if (!dragEvent) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
+  dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
+  if (!IsValidDropData(dataTransfer)) {
+    return NS_OK;
+  }
+
+
+  nsIContent* content = mFrame->GetContent();
+  bool supportsMultiple = content && content->HasAttr(kNameSpaceID_None, nsGkAtoms::multiple);
+  if (!CanDropTheseFiles(dataTransfer, supportsMultiple)) {
+    dataTransfer->SetDropEffect(NS_LITERAL_STRING("none"));
+    aEvent->StopPropagation();
     return NS_OK;
   }
 
   nsAutoString eventType;
   aEvent->GetType(eventType);
   if (eventType.EqualsLiteral("dragover")) {
     // Prevent default if we can accept this drag data
     aEvent->PreventDefault();
     return NS_OK;
   }
 
   if (eventType.EqualsLiteral("drop")) {
     aEvent->StopPropagation();
     aEvent->PreventDefault();
 
-    nsIContent* content = mFrame->GetContent();
     NS_ASSERTION(content, "The frame has no content???");
 
     HTMLInputElement* inputElement = HTMLInputElement::FromContent(content);
     NS_ASSERTION(inputElement, "No input element for this file upload control frame!");
 
-    nsCOMPtr<nsIDOMDataTransfer> dataTransfer;
-    dragEvent->GetDataTransfer(getter_AddRefs(dataTransfer));
-
     nsCOMPtr<nsIDOMFileList> fileList;
     dataTransfer->GetFiles(getter_AddRefs(fileList));
 
     inputElement->SetFiles(fileList, true);
     nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
                                          NS_LITERAL_STRING("change"), true,
                                          false);
   }
 
   return NS_OK;
 }
 
 /* static */ bool
-nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDragEvent* aEvent)
+nsFileControlFrame::DnDListener::IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer)
 {
-  nsCOMPtr<nsIDOMDataTransfer> domDataTransfer;
-  aEvent->GetDataTransfer(getter_AddRefs(domDataTransfer));
-  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(domDataTransfer);
+  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
   NS_ENSURE_TRUE(dataTransfer, false);
 
   // We only support dropping files onto a file upload control
   nsRefPtr<DOMStringList> types = dataTransfer->Types();
   return types->Contains(NS_LITERAL_STRING("Files"));
 }
 
+/* static */ bool
+nsFileControlFrame::DnDListener::CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer,
+                                                   bool aSupportsMultiple)
+{
+  nsCOMPtr<DataTransfer> dataTransfer = do_QueryInterface(aDOMDataTransfer);
+  NS_ENSURE_TRUE(dataTransfer, false);
+
+  nsCOMPtr<nsIDOMFileList> fileList;
+  dataTransfer->GetFiles(getter_AddRefs(fileList));
+
+  uint32_t listLength = 0;
+  if (fileList) {
+    fileList->GetLength(&listLength);
+  }
+  return listLength <= 1 || aSupportsMultiple;
+}
+
 nscoord
 nsFileControlFrame::GetMinISize(nsRenderingContext *aRenderingContext)
 {
   nscoord result;
   DISPLAY_MIN_WIDTH(this, result);
 
   // Our min width is our pref width
   result = GetPrefISize(aRenderingContext);
--- a/layout/forms/nsFileControlFrame.h
+++ b/layout/forms/nsFileControlFrame.h
@@ -9,17 +9,17 @@
 #include "mozilla/Attributes.h"
 #include "nsBlockFrame.h"
 #include "nsIFormControlFrame.h"
 #include "nsIDOMEventListener.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsCOMPtr.h"
 
 class nsTextControlFrame;
-class nsIDOMDragEvent;
+class nsIDOMDataTransfer;
 
 class nsFileControlFrame : public nsBlockFrame,
                            public nsIFormControlFrame,
                            public nsIAnonymousContentCreator
 {
 public:
   explicit nsFileControlFrame(nsStyleContext* aContext);
 
@@ -112,17 +112,18 @@ protected:
   class DnDListener: public MouseListener {
   public:
     explicit DnDListener(nsFileControlFrame* aFrame)
       : MouseListener(aFrame)
     {}
 
     NS_DECL_NSIDOMEVENTLISTENER
 
-    static bool IsValidDropData(nsIDOMDragEvent* aEvent);
+    static bool IsValidDropData(nsIDOMDataTransfer* aDOMDataTransfer);
+    static bool CanDropTheseFiles(nsIDOMDataTransfer* aDOMDataTransfer, bool aSupportsMultiple);
   };
 
   virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE
   {
     return nsBlockFrame::IsFrameOfType(aFlags &
       ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
   }
 
--- a/layout/generic/WritingModes.h
+++ b/layout/generic/WritingModes.h
@@ -11,17 +11,22 @@
 
 // If WRITING_MODE_VERTICAL_ENABLED is defined, we will attempt to support
 // the vertical writing-mode values; if it is not defined, then
 // WritingMode.IsVertical() will be hard-coded to return false, allowing
 // many conditional branches to be optimized away while we're in the process
 // of transitioning layout to use writing-mode and logical directions, but
 // not yet ready to ship vertical support.
 
-/* #define WRITING_MODE_VERTICAL_ENABLED 1 */
+// XXX To be removed, and the #ifdef blocks below made unconditional,
+//     once we're confident we can leave it permanently enabled.
+
+#ifndef RELEASE_BUILD
+#define WRITING_MODE_VERTICAL_ENABLED 1
+#endif
 
 // It is the caller's responsibility to operate on logical-coordinate objects
 // with matched writing modes. Failure to do so will be a runtime bug; the
 // compiler can't catch it, but in debug mode, we'll throw an assertion.
 // NOTE that in non-debug builds, a writing mode mismatch error will NOT be
 // detected, yet the results will be nonsense (and may lead to further layout
 // failures). Therefore, it is important to test (and fuzz-test) writing-mode
 // support using debug builds.
--- a/layout/style/MediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -1,55 +1,56 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
 #include "mozilla/dom/MediaQueryList.h"
 #include "nsPresContext.h"
 #include "nsIMediaList.h"
 #include "nsCSSParser.h"
 #include "nsIDocument.h"
 
 namespace mozilla {
 namespace dom {
 
-MediaQueryList::MediaQueryList(nsPresContext *aPresContext,
+MediaQueryList::MediaQueryList(nsIDocument *aDocument,
                                const nsAString &aMediaQueryList)
-  : mPresContext(aPresContext),
+  : mDocument(aDocument),
     mMediaList(new nsMediaList),
     mMatchesValid(false)
 {
   PR_INIT_CLIST(this);
 
   nsCSSParser parser;
   parser.ParseMediaList(aMediaQueryList, nullptr, 0, mMediaList, false);
 }
 
 MediaQueryList::~MediaQueryList()
 {
-  if (mPresContext) {
+  if (mDocument) {
     PR_REMOVE_LINK(this);
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaQueryList)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallbacks)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaQueryList)
-  if (tmp->mPresContext) {
+  if (tmp->mDocument) {
     PR_REMOVE_LINK(tmp);
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
   }
   tmp->RemoveAllListeners();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(MediaQueryList)
 
 NS_INTERFACE_MAP_BEGIN(MediaQueryList)
@@ -133,21 +134,43 @@ MediaQueryList::RemoveAllListeners()
     // See NS_ADDREF_THIS() in AddListener.
     NS_RELEASE_THIS();
   }
 }
 
 void
 MediaQueryList::RecomputeMatches()
 {
-  if (!mPresContext) {
+  if (!mDocument) {
     return;
   }
 
-  mMatches = mMediaList->Matches(mPresContext, nullptr);
+  if (mDocument->GetParentDocument()) {
+    // Flush frames on the parent so our prescontext will get
+    // recreated as needed.
+    mDocument->GetParentDocument()->FlushPendingNotifications(Flush_Frames);
+    // That might have killed our document, so recheck that.
+    if (!mDocument) {
+      return;
+    }
+  }
+
+  nsIPresShell* shell = mDocument->GetShell();
+  if (!shell) {
+    // XXXbz What's the right behavior here?  Spec doesn't say.
+    return;
+  }
+
+  nsPresContext* presContext = shell->GetPresContext();
+  if (!presContext) {
+    // XXXbz What's the right behavior here?  Spec doesn't say.
+    return;
+  }
+
+  mMatches = mMediaList->Matches(presContext, nullptr);
   mMatchesValid = true;
 }
 
 void
 MediaQueryList::MediumFeaturesChanged(NotifyList &aListenersToNotify)
 {
   mMatchesValid = false;
 
@@ -164,20 +187,17 @@ MediaQueryList::MediumFeaturesChanged(No
       }
     }
   }
 }
 
 nsISupports*
 MediaQueryList::GetParentObject() const
 {
-  if (!mPresContext) {
-    return nullptr;
-  }
-  return mPresContext->Document();
+  return mDocument;
 }
 
 JSObject*
 MediaQueryList::WrapObject(JSContext* aCx)
 {
   return MediaQueryListBinding::Wrap(aCx, this);
 }
 
--- a/layout/style/MediaQueryList.h
+++ b/layout/style/MediaQueryList.h
@@ -1,41 +1,43 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
 #ifndef mozilla_dom_MediaQueryList_h
 #define mozilla_dom_MediaQueryList_h
 
 #include "nsISupports.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
+#include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "prclist.h"
 #include "mozilla/Attributes.h"
 #include "nsWrapperCache.h"
 #include "mozilla/dom/MediaQueryListBinding.h"
 
-class nsPresContext;
+class nsIDocument;
 class nsMediaList;
 
 namespace mozilla {
 namespace dom {
 
 class MediaQueryList MOZ_FINAL : public nsISupports,
                                  public nsWrapperCache,
                                  public PRCList
 {
 public:
   // The caller who constructs is responsible for calling Evaluate
   // before calling any other methods.
-  MediaQueryList(nsPresContext *aPresContext,
+  MediaQueryList(nsIDocument *aDocument,
                  const nsAString &aMediaQueryList);
 private:
   ~MediaQueryList();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaQueryList)
 
@@ -62,31 +64,31 @@ public:
   void GetMedia(nsAString& aMedia);
   bool Matches();
   void AddListener(mozilla::dom::MediaQueryListListener& aListener);
   void RemoveListener(mozilla::dom::MediaQueryListListener& aListener);
 
 private:
   void RecomputeMatches();
 
-  // We only need a pointer to the pres context to support lazy
+  // We only need a pointer to the document to support lazy
   // reevaluation following dynamic changes.  However, this lazy
   // reevaluation is perhaps somewhat important, since some usage
   // patterns may involve the creation of large numbers of
   // MediaQueryList objects which almost immediately become garbage
   // (after a single call to the .matches getter).
   //
   // This pointer does make us a little more dependent on cycle
   // collection.
   //
-  // We have a non-null mPresContext for our entire lifetime except
-  // after cycle collection unlinking.  Having a non-null mPresContext
-  // is equivalent to being in that pres context's mDOMMediaQueryLists
+  // We have a non-null mDocument for our entire lifetime except
+  // after cycle collection unlinking.  Having a non-null mDocument
+  // is equivalent to being in that document's mDOMMediaQueryLists
   // linked list.
-  nsRefPtr<nsPresContext> mPresContext;
+  nsCOMPtr<nsIDocument> mDocument;
 
   nsRefPtr<nsMediaList> mMediaList;
   bool mMatches;
   bool mMatchesValid;
   CallbackList mCallbacks;
 };
 
 } // namespace dom
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -92,16 +92,17 @@ support-files = bug517224.sjs
 [test_bug652486.html]
 [test_bug657143.html]
 [test_bug664955.html]
 [test_bug667520.html]
 [test_bug645998.html]
 support-files = file_bug645998-1.css file_bug645998-2.css
 [test_bug716226.html]
 [test_bug765590.html]
+[test_bug771043.html]
 [test_bug798567.html]
 [test_bug798843_pref.html]
 [test_bug829816.html]
 [test_bug874919.html]
 support-files = file_bug829816.css
 [test_bug887741_at-rules_in_declaration_lists.html]
 [test_bug892929.html]
 [test_cascade.html]
new file mode 100644
--- /dev/null
+++ b/layout/style/test/test_bug771043.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=771043
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 771043</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 771043 **/
+  var expectedValue;
+  var callCount = 0;
+  var storedHeight;
+  function callback(arg) {
+    ++callCount;
+    is(arg.matches, expectedValue,
+       "Should have the right value on call #" + callCount + " to the callback");
+    SimpleTest.executeSoon(tests.shift());
+  }
+
+  function flushLayout() {
+    storedHeight = document.querySelector("iframe").offsetHeight;
+  }
+
+  function setHeight(height) {
+    var ifr = document.querySelector("iframe");
+    ifr.style.height = height + "px";
+    flushLayout();
+  }
+
+  SimpleTest.waitForExplicitFinish();
+
+  var tests = [
+    () => { expectedValue = true; setHeight(50); },
+    () => { expectedValue = false; setHeight(200); },
+    () => {
+      var ifr = document.querySelector("iframe");
+      ifr.style.display = "none";
+      flushLayout();
+      ifr.style.display = "";
+      expectedValue = true;
+      setHeight(50);
+    },
+    () => { expectedValue = false; setHeight(200); },
+    SimpleTest.finish.bind(SimpleTest)
+  ];
+
+  addLoadEvent(function() {
+    var mql = frames[0].matchMedia("(orientation: landscape)");
+    mql.addListener(callback);
+
+    tests.shift()();
+  });
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=771043">Mozilla Bug 771043</a>
+<!-- Important: the iframe needs to be displayed -->
+<p id="display"><iframe style="width: 100px; height: 200px"</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp
@@ -73,16 +73,17 @@
 #include "nsIDOMLocation.h"
 #include "nsNullPrincipal.h"
 #include "mozilla/PeerIdentity.h"
 #include "mozilla/dom/RTCConfigurationBinding.h"
 #include "mozilla/dom/RTCStatsReportBinding.h"
 #include "mozilla/dom/RTCPeerConnectionBinding.h"
 #include "mozilla/dom/PeerConnectionImplBinding.h"
 #include "mozilla/dom/DataChannelBinding.h"
+#include "mozilla/dom/PluginCrashedEvent.h"
 #include "MediaStreamList.h"
 #include "MediaStreamTrack.h"
 #include "AudioStreamTrack.h"
 #include "VideoStreamTrack.h"
 #include "nsIScriptGlobalObject.h"
 #include "DOMMediaStream.h"
 #include "rlogringbuffer.h"
 #include "WebrtcGlobalInformation.h"
@@ -1784,63 +1785,30 @@ PeerConnectionImpl::PluginCrash(uint64_t
 
 #ifdef MOZILLA_INTERNAL_API
   nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
   if (!doc) {
     NS_WARNING("Couldn't get document for PluginCrashed event!");
     return true;
   }
 
-  ErrorResult rv;
-  nsRefPtr<Event> event =
-    doc->CreateEvent(NS_LITERAL_STRING("customevent"), rv);
-  nsCOMPtr<nsIDOMCustomEvent> customEvent(do_QueryObject(event));
-  if (!customEvent) {
-    NS_WARNING("Couldn't QI event for PluginCrashed event!");
-    return true;
-  }
-
-  nsCOMPtr<nsIWritableVariant> variant;
-  variant = do_CreateInstance("@mozilla.org/variant;1");
-  if (!variant) {
-    NS_WARNING("Couldn't create detail variant for PluginCrashed event!");
-    return true;
-  }
-
-  customEvent->InitCustomEvent(NS_LITERAL_STRING("PluginCrashed"),
-                               true, true, variant);
+  PluginCrashedEventInit init;
+  init.mPluginDumpID = aPluginDumpID;
+  init.mPluginName = aPluginName;
+  init.mSubmittedCrashReport = false;
+  init.mGmpPlugin = true;
+  init.mBubbles = true;
+  init.mCancelable = true;
+
+  nsRefPtr<PluginCrashedEvent> event =
+    PluginCrashedEvent::Constructor(doc, NS_LITERAL_STRING("PluginCrashed"), init);
+
   event->SetTrusted(true);
   event->GetInternalNSEvent()->mFlags.mOnlyChromeDispatch = true;
 
-  nsCOMPtr<nsIWritablePropertyBag2> propBag;
-  propBag = do_CreateInstance("@mozilla.org/hash-property-bag;1");
-  if (!propBag) {
-    NS_WARNING("Couldn't create a property bag for PluginCrashed event!");
-    return true;
-  }
-
-  // add a "pluginDumpID" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("pluginDumpID"),
-                                aPluginDumpID);
-
-
-  // add a "pluginName" property to this event
-  propBag->SetPropertyAsAString(NS_LITERAL_STRING("pluginName"),
-                                aPluginName);
-
-  // add a "pluginName" property to this event
-  propBag->SetPropertyAsBool(NS_LITERAL_STRING("gmpPlugin"),
-                             true);
-
-  // add a "submittedCrashReport" property to this event
-  propBag->SetPropertyAsBool(NS_LITERAL_STRING("submittedCrashReport"),
-                             false);
-
-  variant->SetAsISupports(propBag);
-
   EventDispatcher::DispatchDOMEvent(mWindow, nullptr, event, nullptr, nullptr);
 #endif
 
   return true;
 }
 
 nsresult
 PeerConnectionImpl::CloseInt()
--- a/mfbt/ChaosMode.h
+++ b/mfbt/ChaosMode.h
@@ -2,33 +2,54 @@
 /* vim: set ts=8 sts=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/. */
 
 #ifndef mozilla_ChaosMode_h
 #define mozilla_ChaosMode_h
 
+#include "mozilla/EnumSet.h"
+
 #include <stdint.h>
 #include <stdlib.h>
 
 namespace mozilla {
 
 /**
  * When "chaos mode" is activated, code that makes implicitly nondeterministic
  * choices is encouraged to make random and extreme choices, to test more
  * code paths and uncover bugs.
  */
 class ChaosMode
 {
 public:
-  static bool isActive()
+  enum ChaosFeature {
+    None = 0x0,
+    // Altering thread scheduling.
+    ThreadScheduling = 0x1,
+    // Altering network request scheduling.
+    NetworkScheduling = 0x2,
+    // Altering timer scheduling.
+    TimerScheduling = 0x4,
+    // Read and write less-than-requested amounts.
+    IOAmounts = 0x8,
+    // Iterate over hash tables in random order.
+    HashTableIteration = 0x10,
+    Any = 0xffffffff,
+  };
+
+private:
+  // Change this to any non-None value to activate ChaosMode.
+  static const ChaosFeature sChaosFeatures = None;
+
+public:
+  static bool isActive(ChaosFeature aFeature)
   {
-    // Flip this to true to activate chaos mode
-    return false;
+    return sChaosFeatures & aFeature;
   }
 
   /**
    * Returns a somewhat (but not uniformly) random uint32_t < aBound.
    * Not to be used for anything except ChaosMode, since it's not very random.
    */
   static uint32_t randomUint32LessThan(uint32_t aBound)
   {
--- a/mozglue/android/APKOpen.cpp
+++ b/mozglue/android/APKOpen.cpp
@@ -23,17 +23,16 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <zlib.h>
 #include "dlfcn.h"
 #include "APKOpen.h"
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/prctl.h>
-#include "Zip.h"
 #include "sqlite3.h"
 #include "SQLiteBridge.h"
 #include "NSSBridge.h"
 #include "ElfLoader.h"
 #include "application.ini.h"
 
 /* Android headers don't define RUSAGE_THREAD */
 #ifndef RUSAGE_THREAD
@@ -212,18 +211,16 @@ loadGeckoLibs(const char *apkName)
 {
   chdir(getenv("GRE_HOME"));
 
   uint64_t t0 = TimeStamp_Now();
   struct rusage usage1_thread, usage1;
   getrusage(RUSAGE_THREAD, &usage1_thread);
   getrusage(RUSAGE_SELF, &usage1);
   
-  RefPtr<Zip> zip = ZipCollection::GetZip(apkName);
-
   char *file = new char[strlen(apkName) + sizeof("!/assets/" ANDROID_CPU_ARCH "/libxul.so")];
   sprintf(file, "%s!/assets/" ANDROID_CPU_ARCH "/libxul.so", apkName);
   xul_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
   delete[] file;
 
   if (!xul_handle) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Couldn't get a handle to libxul!");
     return FAILURE;
@@ -268,17 +265,16 @@ loadSQLiteLibs(const char *apkName)
     return SUCCESS;
 
 #ifdef MOZ_FOLD_LIBS
   if (loadNSSLibs(apkName) != SUCCESS)
     return FAILURE;
 #else
   chdir(getenv("GRE_HOME"));
 
-  RefPtr<Zip> zip = ZipCollection::GetZip(apkName);
   if (!lib_mapping) {
     lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
   }
 
   char *file = new char[strlen(apkName) + sizeof("!/assets/" ANDROID_CPU_ARCH "/libmozsqlite3.so")];
   sprintf(file, "%s!/assets/" ANDROID_CPU_ARCH "/libmozsqlite3.so", apkName);
   sqlite_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
   delete [] file;
@@ -296,17 +292,16 @@ loadSQLiteLibs(const char *apkName)
 static mozglueresult
 loadNSSLibs(const char *apkName)
 {
   if (nss_handle && nspr_handle && plc_handle)
     return SUCCESS;
 
   chdir(getenv("GRE_HOME"));
 
-  RefPtr<Zip> zip = ZipCollection::GetZip(apkName);
   if (!lib_mapping) {
     lib_mapping = (struct mapping_info *)calloc(MAX_MAPPING_INFO, sizeof(*lib_mapping));
   }
 
   char *file = new char[strlen(apkName) + sizeof("!/assets/" ANDROID_CPU_ARCH "/libnss3.so")];
   sprintf(file, "%s!/assets/" ANDROID_CPU_ARCH "/libnss3.so", apkName);
   nss_handle = __wrap_dlopen(file, RTLD_GLOBAL | RTLD_LAZY);
   delete [] file;
--- a/netwerk/base/src/nsSocketTransportService2.cpp
+++ b/netwerk/base/src/nsSocketTransportService2.cpp
@@ -221,17 +221,17 @@ nsSocketTransportService::AddToPollList(
         SOCKET_LOG(("  Active List size of %d met\n", mActiveCount));
         if (!GrowActiveList()) {
             NS_ERROR("too many active sockets");
             return NS_ERROR_OUT_OF_MEMORY;
         }
     }
     
     uint32_t newSocketIndex = mActiveCount;
-    if (ChaosMode::isActive()) {
+    if (ChaosMode::isActive(ChaosMode::NetworkScheduling)) {
       newSocketIndex = ChaosMode::randomUint32LessThan(mActiveCount + 1);
       PodMove(mActiveList + newSocketIndex + 1, mActiveList + newSocketIndex,
               mActiveCount - newSocketIndex);
       PodMove(mPollList + newSocketIndex + 2, mPollList + newSocketIndex + 1,
               mActiveCount - newSocketIndex);
     }
     mActiveList[newSocketIndex] = *sock;
     mActiveCount++;
--- a/netwerk/cache2/CacheStorage.cpp
+++ b/netwerk/cache2/CacheStorage.cpp
@@ -64,16 +64,21 @@ NS_IMETHODIMP CacheStorage::AsyncOpenURI
   nsCOMPtr<nsIURI> noRefURI;
   rv = aURI->CloneIgnoringRef(getter_AddRefs(noRefURI));
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIApplicationCache> appCache;
   if (LookupAppCache()) {
     rv = ChooseApplicationCache(noRefURI, getter_AddRefs(appCache));
     NS_ENSURE_SUCCESS(rv, rv);
+
+    if (appCache) {
+      // From a chosen appcache open only as readonly
+      aFlags &= ~nsICacheStorage::OPEN_TRUNCATE;
+    }
   }
 
   if (appCache) {
     nsAutoCString cacheKey;
     rv = noRefURI->GetAsciiSpec(cacheKey);
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString scheme;
--- a/netwerk/protocol/http/nsHttpConnection.cpp
+++ b/netwerk/protocol/http/nsHttpConnection.cpp
@@ -1639,17 +1639,18 @@ nsHttpConnection::OnWriteSegment(char *b
     if (count == 0) {
         // some WriteSegments implementations will erroneously call the reader
         // to provide 0 bytes worth of data.  we must protect against this case
         // or else we'd end up closing the socket prematurely.
         NS_ERROR("bad WriteSegments implementation");
         return NS_ERROR_FAILURE; // stop iterating
     }
 
-    if (ChaosMode::isActive() && ChaosMode::randomUint32LessThan(2)) {
+    if (ChaosMode::isActive(ChaosMode::IOAmounts) &&
+        ChaosMode::randomUint32LessThan(2)) {
         // read 1...count bytes
         count = ChaosMode::randomUint32LessThan(count) + 1;
     }
 
     nsresult rv = mSocketIn->Read(buf, count, countWritten);
     if (NS_FAILED(rv))
         mSocketInCondition = rv;
     else if (*countWritten == 0)
--- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp
+++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp
@@ -50,17 +50,17 @@ InsertTransactionSorted(nsTArray<nsHttpT
 {
     // insert into queue with smallest valued number first.  search in reverse
     // order under the assumption that many of the existing transactions will
     // have the same priority (usually 0).
 
     for (int32_t i=pendingQ.Length()-1; i>=0; --i) {
         nsHttpTransaction *t = pendingQ[i];
         if (trans->Priority() >= t->Priority()) {
-            if (ChaosMode::isActive()) {
+	  if (ChaosMode::isActive(ChaosMode::NetworkScheduling)) {
                 int32_t samePriorityCount;
                 for (samePriorityCount = 0; i - samePriorityCount >= 0; ++samePriorityCount) {
                     if (pendingQ[i - samePriorityCount]->Priority() != trans->Priority()) {
                         break;
                     }
                 }
                 // skip over 0...all of the elements with the same priority.
                 i -= ChaosMode::randomUint32LessThan(samePriorityCount + 1);
--- a/netwerk/test/unit/head_cache2.js
+++ b/netwerk/test/unit/head_cache2.js
@@ -42,16 +42,18 @@ const RECREATE =        1 << 10;
 // Do not give me the entry
 const NOTWANTED =       1 << 11;
 // Tell the cache to wait for the entry to be completely written first
 const COMPLETE =        1 << 12;
 // Don't write meta/data and don't set valid in the callback, consumer will do it manually
 const DONTFILL =        1 << 13;
 // Used in combination with METAONLY, don't call setValid() on the entry after metadata has been set
 const DONTSETVALID =    1 << 14;
+// Notify before checking the data, useful for proper callback ordering checks
+const NOTIFYBEFOREREAD = 1 << 15;
 
 var log_c2 = true;
 function LOG_C2(o, m)
 {
   if (!log_c2) return;
   if (!m)
     dump("TEST-INFO | CACHE2: " + o + "\n");
   else
@@ -232,16 +234,18 @@ OpenCallback.prototype =
         })
       })
     }
     else { // NORMAL
       do_check_true(!!entry);
       do_check_eq(entry.getMetaDataElement("meto"), this.workingMetadata);
       if (this.behavior & THROWAVAIL)
         this.throwAndNotify(entry);
+      if (this.behavior & NOTIFYBEFOREREAD)
+        this.goon(entry, true);
 
       var wrapper = Cc["@mozilla.org/scriptableinputstream;1"].
                     createInstance(Ci.nsIScriptableInputStream);
       var self = this;
       pumpReadStream(entry.openInputStream(0), function(data) {
         do_check_eq(data, self.workingData);
         self.onDataCheckPassed = true;
         LOG_C2(self, "entry read done");
--- a/netwerk/test/unit/test_cache2-14b-concurent-readers-complete.js
+++ b/netwerk/test/unit/test_cache2-14b-concurent-readers-complete.js
@@ -9,31 +9,40 @@ function run_test()
     })
   );
 
   var mc = new MultipleCallbacks(3, finish_cache2_test);
 
   var order = 0;
 
   asyncOpenCacheEntry("http://x/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
-    new OpenCallback(NORMAL|COMPLETE, "x1m", "x1d", function(entry) {
-      ++order;
-      do_check_eq(order, newCacheBackEndUsed() ? 3 : 1);
-      mc.fired();
+    new OpenCallback(NORMAL|COMPLETE|NOTIFYBEFOREREAD, "x1m", "x1d", function(entry, beforeReading) {
+      if (beforeReading) {
+        ++order;
+        do_check_eq(order, newCacheBackEndUsed() ? 3 : 1);
+      } else {
+        mc.fired();
+      }
     })
   );
   asyncOpenCacheEntry("http://x/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
-    new OpenCallback(NORMAL, "x1m", "x1d", function(entry) {
-      ++order;
-      do_check_eq(order, newCacheBackEndUsed() ? 1 : 2);
-      mc.fired();
+    new OpenCallback(NORMAL|NOTIFYBEFOREREAD, "x1m", "x1d", function(entry, beforeReading) {
+      if (beforeReading) {
+        ++order;
+        do_check_eq(order, newCacheBackEndUsed() ? 1 : 2);
+      } else {
+        mc.fired();
+      }
     })
   );
   asyncOpenCacheEntry("http://x/", "disk", Ci.nsICacheStorage.OPEN_NORMALLY, null,
-    new OpenCallback(NORMAL, "x1m", "x1d", function(entry) {
-      ++order;
-      do_check_eq(order, newCacheBackEndUsed() ? 2 : 3);
-      mc.fired();
+    new OpenCallback(NORMAL|NOTIFYBEFOREREAD, "x1m", "x1d", function(entry, beforeReading) {
+      if (beforeReading) {
+        ++order;
+        do_check_eq(order, newCacheBackEndUsed() ? 2 : 3);
+      } else {
+        mc.fired();
+      }
     })
   );
 
   do_test_pending();
 }
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -884,17 +884,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.
-        """, 'libs'),
+        """, 'misc'),
 
     '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/RootHashes.inc
+++ b/security/manager/boot/src/RootHashes.inc
@@ -112,16 +112,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* COMODO_ECC_Certification_Authority */
     { 0x17, 0x93, 0x92, 0x7A, 0x06, 0x14, 0x54, 0x97, 0x89, 0xAD, 0xCE, 0x2F, 0x8F, 0x34, 0xF7, 0xF0,
       0xB6, 0x6D, 0x0F, 0x3A, 0xE3, 0xA3, 0xB8, 0x4D, 0x21, 0xEC, 0x15, 0xDB, 0xBA, 0x4F, 0xAD, 0xC7 },
       66 /* Bin Number */
   },
   {
+    /* GlobalSign */
+    { 0x17, 0x9F, 0xBC, 0x14, 0x8A, 0x3D, 0xD0, 0x0F, 0xD2, 0x4E, 0xA1, 0x34, 0x58, 0xCC, 0x43, 0xBF,
+      0xA7, 0xF5, 0x9C, 0x81, 0x82, 0xD7, 0x83, 0xA5, 0x13, 0xF6, 0xEB, 0xEC, 0x10, 0x0C, 0x89, 0x24 },
+      158 /* Bin Number */
+  },
+  {
     /* QuoVadis_Root_CA_3 */
     { 0x18, 0xF1, 0xFC, 0x7F, 0x20, 0x5D, 0xF8, 0xAD, 0xDD, 0xEB, 0x7F, 0xE0, 0x07, 0xDD, 0x57, 0xE3,
       0xAF, 0x37, 0x5A, 0x9C, 0x4D, 0x8D, 0x73, 0x54, 0x6B, 0xF4, 0xF1, 0xFE, 0xD1, 0xE1, 0x8D, 0x35 },
       33 /* Bin Number */
   },
   {
     /* China_Internet_Network_Information_Center_EV_Certificates_Root */
     { 0x1C, 0x01, 0xC6, 0xF4, 0xDB, 0xB2, 0xFE, 0xFC, 0x22, 0x55, 0x8B, 0x2B, 0xCA, 0x32, 0x56, 0x3F,
@@ -256,28 +262,40 @@ static const struct CertAuthorityHash RO
   },
   {
     /* Certification_Authority_of_WoSign */
     { 0x4B, 0x22, 0xD5, 0xA6, 0xAE, 0xC9, 0x9F, 0x3C, 0xDB, 0x79, 0xAA, 0x5E, 0xC0, 0x68, 0x38, 0x47,
       0x9C, 0xD5, 0xEC, 0xBA, 0x71, 0x64, 0xF7, 0xF2, 0x2D, 0xC1, 0xD6, 0x5F, 0x63, 0xD8, 0x57, 0x08 },
       152 /* Bin Number */
   },
   {
+    /* USERTrust_ECC_Certification_Authority */
+    { 0x4F, 0xF4, 0x60, 0xD5, 0x4B, 0x9C, 0x86, 0xDA, 0xBF, 0xBC, 0xFC, 0x57, 0x12, 0xE0, 0x40, 0x0D,
+      0x2B, 0xED, 0x3F, 0xBC, 0x4D, 0x4F, 0xBD, 0xAA, 0x86, 0xE0, 0x6A, 0xDC, 0xD2, 0xA9, 0xAD, 0x7A },
+      156 /* Bin Number */
+  },
+  {
     /* ComSign_Secured_CA */
     { 0x50, 0x79, 0x41, 0xC7, 0x44, 0x60, 0xA0, 0xB4, 0x70, 0x86, 0x22, 0x0D, 0x4E, 0x99, 0x32, 0x57,
       0x2A, 0xB5, 0xD1, 0xB5, 0xBB, 0xCB, 0x89, 0x80, 0xAB, 0x1C, 0xB1, 0x76, 0x51, 0xA8, 0x44, 0xD2 },
       76 /* Bin Number */
   },
   {
     /* OU_Security_Communication_RootCA2_O__SECOM_Trust_Systems_CO__LTD___C_JP */
     { 0x51, 0x3B, 0x2C, 0xEC, 0xB8, 0x10, 0xD4, 0xCD, 0xE5, 0xDD, 0x85, 0x39, 0x1A, 0xDF, 0xC6, 0xC2,
       0xDD, 0x60, 0xD8, 0x7B, 0xB7, 0x36, 0xD2, 0xB5, 0x21, 0x48, 0x4A, 0xA4, 0x7A, 0x0E, 0xBE, 0xF6 },
       118 /* Bin Number */
   },
   {
+    /* COMODO_RSA_Certification_Authority */
+    { 0x52, 0xF0, 0xE1, 0xC4, 0xE5, 0x8E, 0xC6, 0x29, 0x29, 0x1B, 0x60, 0x31, 0x7F, 0x07, 0x46, 0x71,
+      0xB8, 0x5D, 0x7E, 0xA8, 0x0D, 0x5B, 0x07, 0x27, 0x34, 0x63, 0x53, 0x4B, 0x32, 0xB4, 0x02, 0x34 },
+      154 /* Bin Number */
+  },
+  {
     /* DigiCert_Trusted_Root_G4 */
     { 0x55, 0x2F, 0x7B, 0xDC, 0xF1, 0xA7, 0xAF, 0x9E, 0x6C, 0xE6, 0x72, 0x01, 0x7F, 0x4F, 0x12, 0xAB,
       0xF7, 0x72, 0x40, 0xC7, 0x8E, 0x76, 0x1A, 0xC2, 0x03, 0xD1, 0xD9, 0xD2, 0x0A, 0xC8, 0x99, 0x88 },
       151 /* Bin Number */
   },
   {
     /* Actalis_Authentication_Root_CA */
     { 0x55, 0x92, 0x60, 0x84, 0xEC, 0x96, 0x3A, 0x64, 0xB9, 0x6E, 0x2A, 0xBE, 0x01, 0xCE, 0x0B, 0xA8,
@@ -658,16 +676,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* SwissSign_Silver_CA___G2 */
     { 0xBE, 0x6C, 0x4D, 0xA2, 0xBB, 0xB9, 0xBA, 0x59, 0xB6, 0xF3, 0x93, 0x97, 0x68, 0x37, 0x42, 0x46,
       0xC3, 0xC0, 0x05, 0x99, 0x3F, 0xA9, 0x8F, 0x02, 0x0D, 0x1D, 0xED, 0xBE, 0xD4, 0x8A, 0x81, 0xD5 },
       57 /* Bin Number */
   },
   {
+    /* GlobalSign */
+    { 0xBE, 0xC9, 0x49, 0x11, 0xC2, 0x95, 0x56, 0x76, 0xDB, 0x6C, 0x0A, 0x55, 0x09, 0x86, 0xD7, 0x6E,
+      0x3B, 0xA0, 0x05, 0x66, 0x7C, 0x44, 0x2C, 0x97, 0x62, 0xB4, 0xFB, 0xB7, 0x73, 0xDE, 0x22, 0x8C },
+      157 /* Bin Number */
+  },
+  {
     /* SecureSign_RootCA11 */
     { 0xBF, 0x0F, 0xEE, 0xFB, 0x9E, 0x3A, 0x58, 0x1A, 0xD5, 0xF9, 0xE9, 0xDB, 0x75, 0x89, 0x98, 0x57,
       0x43, 0xD2, 0x61, 0x08, 0x5C, 0x4D, 0x31, 0x4F, 0x6F, 0x5D, 0x72, 0x59, 0xAA, 0x42, 0x16, 0x12 },
       97 /* Bin Number */
   },
   {
     /* TWCA_Root_Certification_Authority */
     { 0xBF, 0xD8, 0x8F, 0xE1, 0x10, 0x1C, 0x41, 0xAE, 0x3E, 0x80, 0x1B, 0xF8, 0xBE, 0x56, 0x35, 0x0E,
@@ -832,16 +856,22 @@ static const struct CertAuthorityHash RO
   },
   {
     /* OU_Security_Communication_RootCA1_O_SECOM_Trust_net_C_JP */
     { 0xE7, 0x5E, 0x72, 0xED, 0x9F, 0x56, 0x0E, 0xEC, 0x6E, 0xB4, 0x80, 0x00, 0x73, 0xA4, 0x3F, 0xC3,
       0xAD, 0x19, 0x19, 0x5A, 0x39, 0x22, 0x82, 0x01, 0x78, 0x95, 0x97, 0x4A, 0x99, 0x02, 0x6B, 0x6C },
       34 /* Bin Number */
   },
   {
+    /* USERTrust_RSA_Certification_Authority */
+    { 0xE7, 0x93, 0xC9, 0xB0, 0x2F, 0xD8, 0xAA, 0x13, 0xE2, 0x1C, 0x31, 0x22, 0x8A, 0xCC, 0xB0, 0x81,
+      0x19, 0x64, 0x3B, 0x74, 0x9C, 0x89, 0x89, 0x64, 0xB1, 0x74, 0x6D, 0x46, 0xC3, 0xD4, 0xCB, 0xD2 },
+      155 /* Bin Number */
+  },
+  {
     /* OU_certSIGN_ROOT_CA_O_certSIGN_C_RO */
     { 0xEA, 0xA9, 0x62, 0xC4, 0xFA, 0x4A, 0x6B, 0xAF, 0xEB, 0xE4, 0x15, 0x19, 0x6D, 0x35, 0x1C, 0xCD,
       0x88, 0x8D, 0x4F, 0x53, 0xF3, 0xFA, 0x8A, 0xE6, 0xD7, 0xC4, 0x66, 0xA9, 0x4E, 0x60, 0x42, 0xBB },
       83 /* Bin Number */
   },
   {
     /* VeriSign_Class_3_Public_Primary_Certification_Authority___G3 */
     { 0xEB, 0x04, 0xCF, 0x5E, 0xB1, 0xF3, 0x9A, 0xFA, 0x76, 0x2F, 0x2B, 0xB1, 0x20, 0xF2, 0x96, 0xCB,
--- a/security/manager/tools/KnownRootHashes.json
+++ b/security/manager/tools/KnownRootHashes.json
@@ -768,12 +768,37 @@
       "label": "Certification_Authority_of_WoSign",
       "binNumber": 152,
       "sha256Fingerprint": "SyLVpq7JnzzbeapewGg4R5zV7LpxZPfyLcHWX2PYVwg="
     },
     {
       "label": "CA______",
       "binNumber": 153,
       "sha256Fingerprint": "1vA0vZSqIz8Cl+ykJFsoOXPkR6pZDzEMd/SP34MRIlQ="
+    },
+    {
+      "label": "COMODO_RSA_Certification_Authority",
+      "binNumber": 154,
+      "sha256Fingerprint": "UvDhxOWOxikpG2AxfwdGcbhdfqgNWwcnNGNTSzK0AjQ="
+    },
+    {
+      "label": "USERTrust_RSA_Certification_Authority",
+      "binNumber": 155,
+      "sha256Fingerprint": "55PJsC/YqhPiHDEiisywgRlkO3SciYlksXRtRsPUy9I="
+    },
+    {
+      "label": "USERTrust_ECC_Certification_Authority",
+      "binNumber": 156,
+      "sha256Fingerprint": "T/Rg1Uuchtq/vPxXEuBADSvtP7xNT72qhuBq3NKprXo="
+    },
+    {
+      "label": "GlobalSign",
+      "binNumber": 157,
+      "sha256Fingerprint": "vslJEcKVVnbbbApVCYbXbjugBWZ8RCyXYrT7t3PeIow="
+    },
+    {
+      "label": "GlobalSign",
+      "binNumber": 158,
+      "sha256Fingerprint": "F5+8FIo90A/STqE0WMxDv6f1nIGC14OlE/br7BAMiSQ="
     }
   ],
-  "maxBin": 153
+  "maxBin": 158
 }
\ No newline at end of file
--- a/security/manager/tools/PreloadedHPKPins.json
+++ b/security/manager/tools/PreloadedHPKPins.json
@@ -123,18 +123,18 @@
         "AddTrust External Root",
         "AddTrust Low-Value Services Root",
         "AddTrust Public Services Root",
         "AddTrust Qualified Certificates Root",
         "AffirmTrust Commercial",
         "AffirmTrust Networking",
         "AffirmTrust Premium",
         "AffirmTrust Premium ECC",
-        "America Online Root Certification Authority 1",
-        "America Online Root Certification Authority 2",
+        // "America Online Root Certification Authority 1",
+        // "America Online Root Certification Authority 2",
         "Baltimore CyberTrust Root",
         "Comodo AAA Services root",
         "COMODO Certification Authority",
         "COMODO ECC Certification Authority",
         "Comodo Secure Services root",
         "Comodo Trusted Services root",
         "Cybertrust Global Root",
         "DigiCert Assured ID Root CA",
@@ -167,21 +167,21 @@
         "Starfield Services Root Certificate Authority - G2",
         "StartCom Certification Authority",
         "StartCom Certification Authority",
         "StartCom Certification Authority G2",
         "TC TrustCenter Class 2 CA II",
         "TC TrustCenter Class 3 CA II",
         "TC TrustCenter Universal CA I",
         "TC TrustCenter Universal CA III",
-        "Thawte Premium Server CA",
+        // "Thawte Premium Server CA",
         "thawte Primary Root CA",
         "thawte Primary Root CA - G2",
         "thawte Primary Root CA - G3",
-        "Thawte Server CA",
+        // "Thawte Server CA",
         "UTN DATACorp SGC Root CA",
         "UTN USERFirst Hardware Root CA",
         // "ValiCert Class 1 VA",
         // "ValiCert Class 2 VA",
         "Verisign Class 3 Public Primary Certification Authority",
         "Verisign Class 3 Public Primary Certification Authority",
         "Verisign Class 3 Public Primary Certification Authority - G2",
         "Verisign Class 3 Public Primary Certification Authority - G3",
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -1707,18 +1707,17 @@ class Mochitest(MochitestUtilsMixin):
     return result
 
   def runTests(self, options, onLaunch=None):
     """ Prepare, configure, run tests and cleanup """
 
     self.setTestRoot(options)
 
     # Until we have all green, this only runs on bc* jobs (not dt* jobs)
-    # skipping on e10s jobs as we have a few extra failures
-    if options.browserChrome and not options.subsuite and not options.e10s:
+    if options.browserChrome and not options.subsuite:
       options.runByDir = True
 
     if not options.runByDir:
       return self.runMochitests(options, onLaunch)
 
     # code for --run-by-dir
     dirs = self.getDirectories(options)
 
--- a/testing/talos/talos.json
+++ b/testing/talos/talos.json
@@ -1,16 +1,16 @@
 {
     "talos.zip": {
-        "url": "http://talos-bundles.pvt.build.mozilla.org/zips/talos.e4a77270a43a.zip",
+        "url": "http://talos-bundles.pvt.build.mozilla.org/zips/talos.f3179facd945.zip",
         "path": ""
     },
     "global": {
         "talos_repo": "https://hg.mozilla.org/build/talos",
-        "talos_revision": "2bdbc49134c4"
+        "talos_revision": "f3179facd945"
     },
     "extra_options": {
         "android": [ "--apkPath=%(apk_path)s" ]
     },
     "suites": {
         "chromez": {
             "tests": ["tresize", "tcanvasmark"]
         },
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -2979,17 +2979,17 @@ int
 XREMain::XRE_mainInit(bool* aExitFlag)
 {
   if (!aExitFlag)
     return 1;
   *aExitFlag = false;
 
   StartupTimeline::Record(StartupTimeline::MAIN);
 
-  if (ChaosMode::isActive()) {
+  if (ChaosMode::isActive(ChaosMode::Any)) {
     printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");
   }
 
   nsresult rv;
   ArgResult ar;
 
 #ifdef DEBUG
   if (PR_GetEnv("XRE_MAIN_BREAK"))
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -116,16 +116,17 @@ STUB(gdk_x11_display_get_user_time)
 STUB(gdk_x11_display_get_xdisplay)
 STUB(gdk_x11_get_default_root_xwindow)
 STUB(gdk_x11_get_default_xdisplay)
 STUB(gdk_x11_get_xatom_by_name)
 STUB(gdk_x11_lookup_xdisplay)
 STUB(gdk_x11_screen_get_xscreen)
 STUB(gdk_x11_visual_get_xvisual)
 STUB(gdk_x11_window_lookup_for_display)
+STUB(gdk_x11_window_set_user_time)
 STUB(gdk_x11_xatom_to_atom)
 STUB(gtk_accel_label_new)
 STUB(gtk_alignment_get_type)
 STUB(gtk_alignment_new)
 STUB(gtk_alignment_set_padding)
 STUB(gtk_arrow_get_type)
 STUB(gtk_arrow_new)
 STUB(gtk_bindings_activate)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -1290,23 +1290,17 @@ SetUserTimeAndStartupIDForActivatedWindo
         sn_launchee_context_new(snd, gdk_screen_get_number(screen),
                                 desktopStartupID.get());
     if (!ctx) {
         sn_display_unref(snd);
         return;
     }
 
     if (sn_launchee_context_get_id_has_timestamp(ctx)) {
-        PRLibrary* gtkLibrary;
-        SetUserTimeFunc setUserTimeFunc = (SetUserTimeFunc)
-            PR_FindFunctionSymbolAndLibrary("gdk_x11_window_set_user_time", &gtkLibrary);
-        if (setUserTimeFunc) {
-            setUserTimeFunc(gdkWindow, sn_launchee_context_get_timestamp(ctx));
-            PR_UnloadLibrary(gtkLibrary);
-        }
+        gdk_x11_window_set_user_time(gdkWindow, sn_launchee_context_get_timestamp(ctx));
     }
 
     sn_launchee_context_setup_window(ctx, gdk_x11_window_get_xid(gdkWindow));
     sn_launchee_context_complete(ctx);
 
     sn_launchee_context_unref(ctx);
     sn_display_unref(snd);
 #endif
--- a/widget/windows/GfxInfo.cpp
+++ b/widget/windows/GfxInfo.cpp
@@ -961,16 +961,23 @@ GfxInfo::GetGfxDriverInfo()
 
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA500,   V(5,0,0,2026));
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA900,   GfxDriverInfo::allDriverVersions);
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA950,   V(8,15,10,1930));
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMA3150,  V(8,14,10,1972));
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX3000, V(7,15,10,1666));
     IMPLEMENT_INTEL_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7, IntelGMAX4500HD, V(7,15,10,1666));
 
+    // Bug 1074378
+    APPEND_TO_DRIVER_BLOCKLIST(DRIVER_OS_WINDOWS_7,
+      (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel),
+      (GfxDeviceFamily*) GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD),
+      GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
+      DRIVER_EQUAL, V(8,15,10,1749), "8.15.10.2342");
+
     /* OpenGL on any Intel hardware is discouraged */
     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
       nsIGfxInfo::FEATURE_OPENGL_LAYERS, nsIGfxInfo::FEATURE_DISCOURAGED,
       DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions );
     APPEND_TO_DRIVER_BLOCKLIST2( DRIVER_OS_ALL,
       (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorIntel), GfxDriverInfo::allDevices,
       nsIGfxInfo::FEATURE_WEBGL_OPENGL, nsIGfxInfo::FEATURE_DISCOURAGED,
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -702,17 +702,17 @@ PLDHashTable::Enumerate(PLDHashEnumerato
   // and ::NextEntry methods below in this file.
   char* entryAddr = mEntryStore;
   uint32_t capacity = Capacity();
   uint32_t tableSize = capacity * mEntrySize;
   char* entryLimit = entryAddr + tableSize;
   uint32_t i = 0;
   bool didRemove = false;
 
-  if (ChaosMode::isActive()) {
+  if (ChaosMode::isActive(ChaosMode::HashTableIteration)) {
     // Start iterating at a random point in the hashtable. It would be
     // even more chaotic to iterate in fully random order, but that's a lot
     // more work.
     entryAddr += ChaosMode::randomUint32LessThan(capacity) * mEntrySize;
     if (entryAddr >= entryLimit) {
       entryAddr -= tableSize;
     }
   }
@@ -850,17 +850,17 @@ PLDHashTable::Iterator::Iterator(const P
   // The following code is taken from, and should be kept in sync with, the
   // PLDHashTable::Enumerate method above. The variables i and entryAddr (which
   // vary over the course of the for loop) are converted into mEntryOffset and
   // mEntryAddr, respectively.
   uint32_t capacity = mTable->Capacity();
   uint32_t tableSize = capacity * mTable->EntrySize();
   char* entryLimit = mEntryAddr + tableSize;
 
-  if (ChaosMode::isActive()) {
+  if (ChaosMode::isActive(ChaosMode::HashTableIteration)) {
     // Start iterating at a random point in the hashtable. It would be
     // even more chaotic to iterate in fully random order, but that's a lot
     // more work.
     mEntryAddr += ChaosMode::randomUint32LessThan(capacity) * mTable->mEntrySize;
     if (mEntryAddr >= entryLimit) {
       mEntryAddr -= tableSize;
     }
   }
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -232,17 +232,17 @@ TimerThread::Run()
     // Have to use PRIntervalTime here, since PR_WaitCondVar takes it
     PRIntervalTime waitFor;
     bool forceRunThisTimer = forceRunNextTimer;
     forceRunNextTimer = false;
 
     if (mSleeping) {
       // Sleep for 0.1 seconds while not firing timers.
       uint32_t milliseconds = 100;
-      if (ChaosMode::isActive()) {
+      if (ChaosMode::isActive(ChaosMode::TimerScheduling)) {
         milliseconds = ChaosMode::randomUint32LessThan(200);
       }
       waitFor = PR_MillisecondsToInterval(milliseconds);
     } else {
       waitFor = PR_INTERVAL_NO_TIMEOUT;
       TimeStamp now = TimeStamp::Now();
       nsTimerImpl* timer = nullptr;
 
@@ -319,17 +319,17 @@ TimerThread::Run()
         // is due now or overdue.
         //
         // Note that we can only sleep for integer values of a certain
         // resolution. We use halfMicrosecondsIntervalResolution, calculated
         // before, to do the optimal rounding (i.e., of how to decide what
         // interval is so small we should not wait at all).
         double microseconds = (timeout - now).ToMilliseconds() * 1000;
 
-        if (ChaosMode::isActive()) {
+        if (ChaosMode::isActive(ChaosMode::TimerScheduling)) {
           // The mean value of sFractions must be 1 to ensure that
           // the average of a long sequence of timeouts converges to the
           // actual sum of their times.
           static const float sFractions[] = {
             0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 1.75f, 2.75f
           };
           microseconds *=
             sFractions[ChaosMode::randomUint32LessThan(ArrayLength(sFractions))];
--- a/xpcom/threads/nsEventQueue.cpp
+++ b/xpcom/threads/nsEventQueue.cpp
@@ -85,17 +85,17 @@ nsEventQueue::GetEvent(bool aMayWait, ns
 }
 
 void
 nsEventQueue::PutEvent(nsIRunnable* aRunnable)
 {
   // Avoid calling AddRef+Release while holding our monitor.
   nsRefPtr<nsIRunnable> event(aRunnable);
 
-  if (ChaosMode::isActive()) {
+  if (ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
     // With probability 0.5, yield so other threads have a chance to
     // dispatch events to this queue first.
     if (ChaosMode::randomUint32LessThan(2)) {
       PR_Sleep(PR_INTERVAL_NO_WAIT);
     }
   }
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -280,17 +280,17 @@ private:
   nsThreadShutdownContext* mShutdownContext;
 };
 
 //-----------------------------------------------------------------------------
 
 static void
 SetupCurrentThreadForChaosMode()
 {
-  if (!ChaosMode::isActive()) {
+  if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
     return;
   }
 
 #ifdef XP_LINUX
   // PR_SetThreadPriority doesn't really work since priorities >
   // PR_PRIORITY_NORMAL can't be set by non-root users. Instead we'll just use
   // setpriority(2) to set random 'nice values'. In regular Linux this is only
   // a dynamic adjustment so it still doesn't really do what we want, but tools
@@ -883,17 +883,17 @@ nsThread::SetPriority(int32_t aPriority)
   } else if (mPriority < PRIORITY_NORMAL) {
     pri = PR_PRIORITY_HIGH;
   } else if (mPriority > PRIORITY_NORMAL) {
     pri = PR_PRIORITY_LOW;
   } else {
     pri = PR_PRIORITY_NORMAL;
   }
   // If chaos mode is active, retain the randomly chosen priority
-  if (!ChaosMode::isActive()) {
+  if (!ChaosMode::isActive(ChaosMode::ThreadScheduling)) {
     PR_SetThreadPriority(mThread, pri);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThread::AdjustPriority(int32_t aDelta)