Merge mozilla-central to b2g-inbound
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Wed, 07 Jan 2015 14:33:35 +0100
changeset 235534 d5707dca171371b2c695b7e8e9e44b7f504f1254
parent 235533 fb568b084a1c3b356d1c9d85ddc35e2ce639f902 (current diff)
parent 235422 206205dd8bd137e25298c261030184bcd058148a (diff)
child 235535 ec519dcb27a6caf1d6b714a3e1278d8add09f6c6
push id366
push usercmanchester@mozilla.com
push dateThu, 08 Jan 2015 16:40:24 +0000
milestone37.0a1
Merge mozilla-central to b2g-inbound
js/src/gc/ForkJoinNursery-inl.h
js/src/gc/ForkJoinNursery.cpp
js/src/gc/ForkJoinNursery.h
js/src/jit-test/lib/parallelarray-helpers.js
js/src/jit-test/tests/asm.js/testBug978714.js
js/src/jit-test/tests/auto-regress/bug784015.js
js/src/jit-test/tests/collections/Array-build-basic.js
js/src/jit-test/tests/collections/Array-build-surfaces.js
js/src/jit-test/tests/gc/bug-1014972.js
js/src/jit-test/tests/gc/bug-1055034.js
js/src/jit-test/tests/gc/bug-975959.js
js/src/jit-test/tests/gc/bug-992866.js
js/src/jit-test/tests/ion/900683.js
js/src/jit-test/tests/ion/bug905989.js
js/src/jit-test/tests/ion/bug906885.js
js/src/jit-test/tests/ion/bug908867.js
js/src/jit-test/tests/ion/bug911708.js
js/src/jit-test/tests/ion/bug916761.js
js/src/jit-test/tests/ion/bug936361.js
js/src/jit-test/tests/ion/bug938431.js
js/src/jit-test/tests/ion/bug977674.js
js/src/jit-test/tests/parallel/Array-buildPar-in-loop.js
js/src/jit-test/tests/parallel/Array-buildPar-nested.js
js/src/jit-test/tests/parallel/Array-buildPar.js
js/src/jit-test/tests/parallel/Array-filterPar-all.js
js/src/jit-test/tests/parallel/Array-filterPar-every-third-element.js
js/src/jit-test/tests/parallel/Array-filterPar-non-divisible.js
js/src/jit-test/tests/parallel/Array-filterPar-none.js
js/src/jit-test/tests/parallel/Array-filterPar-short.js
js/src/jit-test/tests/parallel/Array-filterPar-truthy.js
js/src/jit-test/tests/parallel/Array-filterPar-very-few.js
js/src/jit-test/tests/parallel/Array-mapPar-add-from-upvar-field.js
js/src/jit-test/tests/parallel/Array-mapPar-assign-to-def-prop.js
js/src/jit-test/tests/parallel/Array-mapPar-factorial.js
js/src/jit-test/tests/parallel/Array-mapPar-fn-args.js
js/src/jit-test/tests/parallel/Array-mapPar-inc.js
js/src/jit-test/tests/parallel/Array-mapPar-nested.js
js/src/jit-test/tests/parallel/Array-mapPar-short.js
js/src/jit-test/tests/parallel/Array-reducePar-bail.js
js/src/jit-test/tests/parallel/Array-reducePar-fn-args.js
js/src/jit-test/tests/parallel/Array-reducePar-length-one.js
js/src/jit-test/tests/parallel/Array-reducePar-mul-short.js
js/src/jit-test/tests/parallel/Array-reducePar-mul.js
js/src/jit-test/tests/parallel/Array-reducePar-nested-sum-each-row.js
js/src/jit-test/tests/parallel/Array-reducePar-sum.js
js/src/jit-test/tests/parallel/Array-scanPar-fn-args.js
js/src/jit-test/tests/parallel/Array-scanPar-one.js
js/src/jit-test/tests/parallel/Array-scanPar-sorted.js
js/src/jit-test/tests/parallel/Array-scanPar-sum.js
js/src/jit-test/tests/parallel/Array-throws.js
js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js
js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js
js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js
js/src/jit-test/tests/parallel/TypedObj-mapPar-return-scalar.js
js/src/jit-test/tests/parallel/alloc-array-nonwritable.js
js/src/jit-test/tests/parallel/alloc-array.js
js/src/jit-test/tests/parallel/alloc-different-objs.js
js/src/jit-test/tests/parallel/alloc-many-objs.js
js/src/jit-test/tests/parallel/alloc-obj.js
js/src/jit-test/tests/parallel/alloc-too-many-objs.js
js/src/jit-test/tests/parallel/arguments-index.js
js/src/jit-test/tests/parallel/arguments-length.js
js/src/jit-test/tests/parallel/bailout-executed.js
js/src/jit-test/tests/parallel/bailout-never-executed.js
js/src/jit-test/tests/parallel/binary-arith-numbers.js
js/src/jit-test/tests/parallel/bitops-values.js
js/src/jit-test/tests/parallel/bug1009788.js
js/src/jit-test/tests/parallel/bug1014973.js
js/src/jit-test/tests/parallel/bug1022948.js
js/src/jit-test/tests/parallel/bug1024567.js
js/src/jit-test/tests/parallel/bug1024756.js
js/src/jit-test/tests/parallel/bug1029440.js
js/src/jit-test/tests/parallel/bug1032264.js
js/src/jit-test/tests/parallel/bug1033115-2.js
js/src/jit-test/tests/parallel/bug1033115.js
js/src/jit-test/tests/parallel/bug1037657.js
js/src/jit-test/tests/parallel/bug1083681.js
js/src/jit-test/tests/parallel/bug853576.js
js/src/jit-test/tests/parallel/bug909743.js
js/src/jit-test/tests/parallel/bug944975.js
js/src/jit-test/tests/parallel/bug970427.js
js/src/jit-test/tests/parallel/bug971385.js
js/src/jit-test/tests/parallel/bug975636.js
js/src/jit-test/tests/parallel/bug976889.js
js/src/jit-test/tests/parallel/bug977647.js
js/src/jit-test/tests/parallel/bug977853-convert-doubles.js
js/src/jit-test/tests/parallel/bug977900.js
js/src/jit-test/tests/parallel/bug983558.js
js/src/jit-test/tests/parallel/cat.pgm
js/src/jit-test/tests/parallel/closure-allocate-invoke.js
js/src/jit-test/tests/parallel/closure-creation.js
js/src/jit-test/tests/parallel/closure-eta-expand.js
js/src/jit-test/tests/parallel/closure-invoke.js
js/src/jit-test/tests/parallel/closure-nested-branch.js
js/src/jit-test/tests/parallel/closure-nested-compute.js
js/src/jit-test/tests/parallel/closure-nested.js
js/src/jit-test/tests/parallel/compare-strict-poly.js
js/src/jit-test/tests/parallel/compare-strings-eq.js
js/src/jit-test/tests/parallel/compare-strings-ne.js
js/src/jit-test/tests/parallel/compare-values.js
js/src/jit-test/tests/parallel/comprehension-throws.js
js/src/jit-test/tests/parallel/createthis.js
js/src/jit-test/tests/parallel/enumerate-1.js
js/src/jit-test/tests/parallel/gc-timeout.js
js/src/jit-test/tests/parallel/ic-getelement.js
js/src/jit-test/tests/parallel/ic-getproperty.js
js/src/jit-test/tests/parallel/ic-setelement.js
js/src/jit-test/tests/parallel/ic-setproperty.js
js/src/jit-test/tests/parallel/int32-overflow.js
js/src/jit-test/tests/parallel/mandelbrot.js
js/src/jit-test/tests/parallel/math-fcns.js
js/src/jit-test/tests/parallel/parallelarraycompiledout.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-boxed-shared.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-boxed-to.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-boxed.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-nursery-grow.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-string.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-tenured.js
js/src/jit-test/tests/parallel/pjsgc-cat-convolve-mapPar-wastrel.js
js/src/jit-test/tests/parallel/pjsgc-raytrace.js
js/src/jit-test/tests/parallel/spew.js
js/src/jit-test/tests/parallel/stack-overflow.js
js/src/jit-test/tests/parallel/strict-equals-1.js
js/src/jit-test/tests/parallel/strings.js
js/src/jit-test/tests/parallel/surfaces-1.js
js/src/jit-test/tests/parallel/surfaces-2.js
js/src/jit-test/tests/parallel/surfaces-3.js
js/src/jit-test/tests/parallel/throw-executed.js
js/src/jit-test/tests/parallel/throw-never-executed.js
js/src/jit-test/tests/parallel/timeout.js
js/src/jit-test/tests/parallel/write-array.js
js/src/jit-test/tests/parallel/write-illegal-array-elt.js
js/src/jit-test/tests/parallel/write-illegal-obj.js
js/src/jit-test/tests/parallel/write-obj.js
js/src/parjs-benchmarks/README.txt
js/src/parjs-benchmarks/SimPJS-test.js
js/src/parjs-benchmarks/cat-convolve-mapPar-wide.js
js/src/parjs-benchmarks/cat-convolve-mapPar.js
js/src/parjs-benchmarks/cat-expected.pgm
js/src/parjs-benchmarks/cat.pgm
js/src/parjs-benchmarks/obsolete/README.txt
js/src/parjs-benchmarks/obsolete/allocator.js
js/src/parjs-benchmarks/obsolete/edges.js
js/src/parjs-benchmarks/obsolete/liquid-resize-par.js
js/src/parjs-benchmarks/obsolete/liquid-resize.js
js/src/parjs-benchmarks/obsolete/mandelbrot.js
js/src/parjs-benchmarks/obsolete/nbody-seeded.js
js/src/parjs-benchmarks/obsolete/rectarray.js
js/src/parjs-benchmarks/obsolete/run.sh
js/src/parjs-benchmarks/obsolete/seedrandom.js
js/src/parjs-benchmarks/obsolete/util.js
js/src/parjs-benchmarks/ray-expected.ppm
js/src/parjs-benchmarks/ray.js
js/src/parjs-benchmarks/unhex.c
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -269,21 +269,32 @@ let gFxAccounts = {
     if (gBrowser.currentURI.spec.split("?")[0] == "about:accounts") {
       // If the current tab is about:accounts, assume the user just completed a
       // migration step and don't bother them with a redundant notification.
       return;
     }
     let note = null;
     switch (this._migrationInfo.state) {
       case this.fxaMigrator.STATE_USER_FXA: {
-        let msg = this.strings.GetStringFromName("needUserLong");
-        let upgradeLabel =
-          this.strings.GetStringFromName("upgradeToFxA.label");
-        let upgradeAccessKey =
-          this.strings.GetStringFromName("upgradeToFxA.accessKey");
+        // There are 2 cases here - no email address means it is an offer on
+        // the first device (so the user is prompted to create an account).
+        // If there is an email address it is the "join the party" flow, so the
+        // user is prompted to sign in with the address they previously used.
+        let msg, upgradeLabel, upgradeAccessKey;
+        if (this._migrationInfo.email) {
+          msg = this.strings.formatStringFromName("signInAfterUpgradeOnOtherDevice.description",
+                                                  [this._migrationInfo.email],
+                                                  1);
+          upgradeLabel = this.strings.GetStringFromName("signInAfterUpgradeOnOtherDevice.label");
+          upgradeAccessKey = this.strings.GetStringFromName("signInAfterUpgradeOnOtherDevice.accessKey");
+        } else {
+          msg = this.strings.GetStringFromName("needUserLong");
+          upgradeLabel = this.strings.GetStringFromName("upgradeToFxA.label");
+          upgradeAccessKey = this.strings.GetStringFromName("upgradeToFxA.accessKey");
+        }
         note = new Weave.Notification(
           undefined, msg, undefined, Weave.Notifications.PRIORITY_WARNING, [
             new Weave.NotificationButton(upgradeLabel, upgradeAccessKey, () => {
               this.fxaMigrator.createFxAccount(window);
             }),
           ]
         );
         break;
@@ -316,21 +327,19 @@ let gFxAccounts = {
     switch (button.getAttribute("fxastatus")) {
     case "signedin":
       this.openPreferences();
       break;
     case "error":
       this.openSignInAgainPage("menupanel");
       break;
     case "migrate-signup":
-      this.fxaMigrator.createFxAccount(window);
-      break;
     case "migrate-verify":
-      // Instead of using the migrator module directly here the UX calls for
-      // us to open prefs which has a "resend" button.
+      // The migration flow calls for the menu item to open sync prefs rather
+      // than requesting migration start immediately.
       this.openPreferences();
       break;
     default:
       this.openAccountsPage(null, { entryPoint: "menupanel" });
       break;
     }
 
     PanelUI.hide();
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2077,17 +2077,17 @@ function getShortcutOrURIAndPostData(aUR
   let offset = aURL.indexOf(" ");
   if (offset > 0) {
     keyword = aURL.substr(0, offset);
     param = aURL.substr(offset + 1);
   }
 
   let engine = Services.search.getEngineByAlias(keyword);
   if (engine) {
-    let submission = engine.getSubmission(param);
+    let submission = engine.getSubmission(param, null, "keyword");
     postData = submission.postData;
     aCallback({ postData: submission.postData, url: submission.uri.spec,
                 mayInheritPrincipal: mayInheritPrincipal });
     return;
   }
 
   [shortcutURL, postData] =
     PlacesUtils.getURLAndPostDataForKeyword(keyword);
@@ -3563,16 +3563,21 @@ const BrowserSearch = {
       return;
     }
 
     let countId = this._getSearchEngineId(engine) + "." + source;
 
     let count = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS");
     count.add(countId);
   },
+
+  recordOneoffSearchInTelemetry: function (engine, source, type, where) {
+    let id = this._getSearchEngineId(engine) + "." + source;
+    BrowserUITelemetry.countOneoffSearchEvent(id, type, where);
+  }
 };
 
 const SearchHighlight = {
   eventsReady: false,
   // The pref that controls how many times to show the highlight.
   countPref: "browser.search.highlightCount",
   // The current highlight to show.
   currentPos: 0,
--- a/browser/base/content/test/newtab/browser.ini
+++ b/browser/base/content/test/newtab/browser.ini
@@ -40,9 +40,8 @@ support-files =
   searchEngine2xLogo.xml
   searchEngine1x2xLogo.xml
   ../general/searchSuggestionEngine.xml
   ../general/searchSuggestionEngine.sjs
 [browser_newtab_sponsored_icon_click.js]
 [browser_newtab_undo.js]
 [browser_newtab_unpin.js]
 [browser_newtab_update.js]
-skip-if = true # Bug 1008029
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -918,24 +918,29 @@
         <body><![CDATA[
           // Ignore all right-clicks
           if (aEvent.button == 2)
             return;
 
           var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController);
 
           // Check for unmodified left-click, and use default behavior
+          var searchBar = BrowserSearch.searchBar;
+          searchBar.telemetrySearchDetails = {
+            index: controller.selection.currentIndex,
+            kind: "mouse"
+          };
+
           if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey &&
               !aEvent.altKey && !aEvent.metaKey) {
             controller.handleEnter(true);
             return;
           }
 
           // Check for middle-click or modified clicks on the search bar
-          var searchBar = BrowserSearch.searchBar;
           if (searchBar && searchBar.textbox == this.mInput) {
             // Handle search bar popup clicks
             var search = controller.getValueAt(this.selectedIndex);
 
             // close the autocomplete popup and revert the entered search term
             this.closePopup();
             controller.handleEscape();
 
@@ -991,17 +996,17 @@
         <xul:label anonid="searchbar-oneoffheader-after" flex="10000" value="&searchWith.label;"/>
       </xul:hbox>
       <xul:description anonid="search-panel-one-offs"
                        class="search-panel-one-offs"
                        xbl:inherits="hidden=showonlysettings"/>
       <xul:vbox anonid="add-engines"/>
       <xul:button anonid="search-settings"
                   xbl:inherits="showonlysettings"
-                  oncommand="openPreferences('paneSearch')"
+                  oncommand="BrowserUITelemetry.countSearchSettingsEvent('searchbar');openPreferences('paneSearch')"
                   class="search-setting-button search-panel-header"
                   label="&changeSearchSettings.button;"/>
     </content>
     <implementation>
       <method name="updateHeader">
         <body><![CDATA[
           let currentEngine = Services.search.currentEngine;
           let uri = currentEngine.iconURI;
--- a/browser/components/loop/content/shared/js/otSdkDriver.js
+++ b/browser/components/loop/content/shared/js/otSdkDriver.js
@@ -189,22 +189,32 @@ loop.OTSdkDriver = (function() {
     /**
      * Handles the session event for the connection for this client being
      * destroyed.
      *
      * @param {SessionDisconnectEvent} event The event details:
      * https://tokbox.com/opentok/libraries/client/js/reference/SessionDisconnectEvent.html
      */
     _onSessionDisconnected: function(event) {
-      // We only need to worry about the network disconnected reason here.
-      if (event.reason === "networkDisconnected") {
-        this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
-          reason: FAILURE_REASONS.NETWORK_DISCONNECTED
-        }));
+      var reason;
+      switch (event.reason) {
+        case "networkDisconnected":
+          reason = FAILURE_REASONS.NETWORK_DISCONNECTED;
+          break;
+        case "forceDisconnected":
+          reason = FAILURE_REASONS.EXPIRED_OR_INVALID;
+          break;
+        default:
+          // Other cases don't need to be handled.
+          return;
       }
+
+      this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
+        reason: reason
+      }));
     },
 
     /**
      * Handles the connection event for a newly connecting peer.
      *
      * @param {ConnectionEvent} event The event details
      * https://tokbox.com/opentok/libraries/client/js/reference/ConnectionEvent.html
      */
--- a/browser/components/loop/test/shared/otSdkDriver_test.js
+++ b/browser/components/loop/test/shared/otSdkDriver_test.js
@@ -262,16 +262,29 @@ describe("loop.OTSdkDriver", function ()
           });
 
           sinon.assert.calledOnce(dispatcher.dispatch);
           sinon.assert.calledWithMatch(dispatcher.dispatch,
             sinon.match.hasOwn("name", "connectionFailure"));
           sinon.assert.calledWithMatch(dispatcher.dispatch,
             sinon.match.hasOwn("reason", FAILURE_REASONS.NETWORK_DISCONNECTED));
         });
+
+      it("should dispatch a connectionFailure action if the session was " +
+         "forcibly disconnected", function() {
+          session.trigger("sessionDisconnected", {
+            reason: "forceDisconnected"
+          });
+
+          sinon.assert.calledOnce(dispatcher.dispatch);
+          sinon.assert.calledWithMatch(dispatcher.dispatch,
+            sinon.match.hasOwn("name", "connectionFailure"));
+          sinon.assert.calledWithMatch(dispatcher.dispatch,
+            sinon.match.hasOwn("reason", FAILURE_REASONS.EXPIRED_OR_INVALID));
+        });
     });
 
     describe("streamCreated", function() {
       var fakeStream;
 
       beforeEach(function() {
         fakeStream = {
           fakeStream: 3
--- a/browser/components/preferences/in-content/sync.js
+++ b/browser/components/preferences/in-content/sync.js
@@ -109,22 +109,16 @@ let gSyncPane = {
 
     window.addEventListener("unload", function() {
       topics.forEach(function (topic) {
         Weave.Svc.Obs.remove(topic, this.updateWeavePrefs, this);
       }, gSyncPane);
       Weave.Svc.Obs.remove(migrateTopic, gSyncPane.updateMigrationState, gSyncPane);
     }, false);
 
-    // ask the migration module to broadcast its current state (and nothing will
-    // happen if it's not loaded - which is good, as that means no migration
-    // is pending/necessary) - we don't want to suck that module in just to
-    // find there's nothing to do.
-    Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
-
     XPCOMUtils.defineLazyGetter(this, '_stringBundle', () => {
       return Services.strings.createBundle("chrome://browser/locale/preferences/preferences.properties");
     }),
 
     XPCOMUtils.defineLazyGetter(this, '_accountsStringBundle', () => {
       return Services.strings.createBundle("chrome://browser/locale/accounts.properties");
     }),
 
@@ -213,26 +207,35 @@ let gSyncPane = {
       gSyncUtils.changeName(this);
     });
     setEventListener("tosPP-small-ToS", "click", gSyncPane.openToS);
     setEventListener("tosPP-small-PP", "click", gSyncPane.openPrivacyPolicy);
     setEventListener("sync-migrate-upgrade", "click", function () {
       let win = Services.wm.getMostRecentWindow("navigator:browser");
       fxaMigrator.createFxAccount(win);
     });
+    setEventListener("sync-migrate-unlink", "click", function () {
+      gSyncPane.startOverMigration();
+    });
     setEventListener("sync-migrate-forget", "click", function () {
       fxaMigrator.forgetFxAccount();
     });
     setEventListener("sync-migrate-resend", "click", function () {
       let win = Services.wm.getMostRecentWindow("navigator:browser");
       fxaMigrator.resendVerificationMail(win);
     });
   },
 
   updateWeavePrefs: function () {
+    // ask the migration module to broadcast its current state (and nothing will
+    // happen if it's not loaded - which is good, as that means no migration
+    // is pending/necessary) - we don't want to suck that module in just to
+    // find there's nothing to do.
+    Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
+
     let service = Components.classes["@mozilla.org/weave/service;1"]
                   .getService(Components.interfaces.nsISupports)
                   .wrappedJSObject;
     // service.fxAccountsEnabled is false iff sync is already configured for
     // the legacy provider.
     if (service.fxAccountsEnabled) {
       // determine the fxa status...
       this.page = PAGE_PLEASE_WAIT;
@@ -294,19 +297,45 @@ let gSyncPane = {
     }
   },
 
   updateMigrationState: function(subject, state) {
     let selIndex;
     switch (state) {
       case fxaMigrator.STATE_USER_FXA: {
         let sb = this._accountsStringBundle;
+        // There are 2 cases here - no email address means it is an offer on
+        // the first device (so the user is prompted to create an account).
+        // If there is an email address it is the "join the party" flow, so the
+        // user is prompted to sign in with the address they previously used.
+        let email = subject ? subject.QueryInterface(Components.interfaces.nsISupportsString).data : null;
+        let elt = document.getElementById("sync-migrate-upgrade-description");
+        elt.textContent = email ?
+                          sb.formatStringFromName("signInAfterUpgradeOnOtherDevice.description",
+                                                  [email], 1) :
+                          sb.GetStringFromName("needUserLong");
+
+        // The "upgrade" button.
         let button = document.getElementById("sync-migrate-upgrade");
-        button.setAttribute("label", sb.GetStringFromName("upgradeToFxA.label"));
-        button.setAttribute("accesskey", sb.GetStringFromName("upgradeToFxA.accessKey"));
+        button.setAttribute("label",
+                            sb.GetStringFromName(email
+                                                 ? "signInAfterUpgradeOnOtherDevice.label"
+                                                 : "upgradeToFxA.label"));
+        button.setAttribute("accesskey",
+                            sb.GetStringFromName(email
+                                                 ? "signInAfterUpgradeOnOtherDevice.accessKey"
+                                                 : "upgradeToFxA.accessKey"));
+        // The "unlink" button - this is only shown for first migration
+        button = document.getElementById("sync-migrate-unlink");
+        if (email) {
+          button.hidden = true;
+        } else {
+          button.setAttribute("label", sb.GetStringFromName("unlinkMigration.label"));
+          button.setAttribute("accesskey", sb.GetStringFromName("unlinkMigration.accessKey"));
+        }
         selIndex = 0;
         break;
       }
       case fxaMigrator.STATE_USER_FXA_VERIFIED: {
         let sb = this._accountsStringBundle;
         let email = subject.QueryInterface(Components.interfaces.nsISupportsString).data;
         let label = sb.formatStringFromName("needVerifiedUserLong", [email], 1);
         let elt = document.getElementById("sync-migrate-verify-label");
@@ -350,16 +379,39 @@ let gSyncPane = {
       if (buttonChoice == 1)
         return;
     }
 
     Weave.Service.startOver();
     this.updateWeavePrefs();
   },
 
+  // When the "Unlink" button in the migration header is selected we display
+  // a slightly different message.
+  startOverMigration: function () {
+    let flags = Services.prompt.BUTTON_POS_0 * Services.prompt.BUTTON_TITLE_IS_STRING +
+                Services.prompt.BUTTON_POS_1 * Services.prompt.BUTTON_TITLE_CANCEL +
+                Services.prompt.BUTTON_POS_1_DEFAULT;
+    let sb = this._accountsStringBundle;
+    let buttonChoice =
+      Services.prompt.confirmEx(window,
+                                sb.GetStringFromName("unlinkVerificationTitle"),
+                                sb.GetStringFromName("unlinkVerificationDescription"),
+                                flags,
+                                sb.GetStringFromName("unlinkVerificationConfirm"),
+                                null, null, null, {});
+
+    // If the user selects cancel, just bail
+    if (buttonChoice == 1)
+      return;
+
+    Weave.Service.startOver();
+    this.updateWeavePrefs();
+  },
+
   updatePass: function () {
     if (Weave.Status.login == Weave.LOGIN_FAILED_LOGIN_REJECTED)
       gSyncUtils.changePassword();
     else
       gSyncUtils.updatePassphrase();
   },
 
   resetPass: function () {
--- a/browser/components/preferences/in-content/sync.xul
+++ b/browser/components/preferences/in-content/sync.xul
@@ -41,18 +41,19 @@
        data-category="paneSync"
        hidden="true">
 
   <vbox id="sync-migration" flex="1" hidden="true">
 
     <deck id="sync-migration-deck">
       <!-- When we are in the "need FxA user" state -->
       <hbox align="center">
-        <label>&migrate.upgradeNeeded;</label>
+        <description id="sync-migrate-upgrade-description" flex="1"/>
         <spacer flex="1"/>
+        <button id="sync-migrate-unlink"/>
         <button id="sync-migrate-upgrade"/>
       </hbox>
 
       <!-- When we are in the "need the user to be verified" state -->
       <hbox align="center">
         <label id="sync-migrate-verify-label"/>
         <spacer flex="1"/>
         <button id="sync-migrate-forget"/>
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -496,43 +496,72 @@
 #ifdef XP_MACOSX
                                                    aEvent.metaKey))
 #else
                                                    aEvent.ctrlKey))
 #endif
               where = "tab-background";
           }
 
+          let selection = this.telemetrySearchDetails;
           this.doSearch(textValue, where, aEngine);
+
+          if (!selection || (selection.index == -1)) {
+            let target = aEvent.originalTarget;
+            let source = "unknown";
+            let type = "unknown";
+            if (aEvent instanceof KeyboardEvent) {
+              type = "key";
+              if (this._textbox.getSelectedOneOff()) {
+                source = "oneoff";
+              }
+            } else if (aEvent instanceof MouseEvent) {
+              type = "mouse";
+              if (target.classList.contains("searchbar-engine-one-off-item")) {
+                source = "oneoff";
+              } else if (target.classList.contains("search-panel-header") ||
+                         target.parentNode.classList.contains("search-panel-header")) {
+                source = "header";
+              }
+            }
+
+            BrowserSearch.recordOneoffSearchInTelemetry(aEngine, source, type, where);
+          }
+
           if (where == "tab-background")
             this.focus();
         ]]></body>
       </method>
 
       <method name="doSearch">
         <parameter name="aData"/>
         <parameter name="aWhere"/>
         <parameter name="aEngine"/>
         <body><![CDATA[
           var textBox = this._textbox;
-        
+
           // Save the current value in the form history
           if (aData && !PrivateBrowsingUtils.isWindowPrivate(window)) {
             this.FormHistory.update(
               { op : "bump",
                 fieldname : textBox.getAttribute("autocompletesearchparam"),
                 value : aData },
               { handleError : function(aError) {
                   Components.utils.reportError("Saving search to form history failed: " + aError.message);
               }});
           }
 
           let engine = aEngine || this.currentEngine;
           var submission = engine.getSubmission(aData, null, "searchbar");
-          BrowserSearch.recordSearchInHealthReport(engine, "searchbar");
+          let telemetrySearchDetails = this.telemetrySearchDetails;
+          this.telemetrySearchDetails = null;
+          if (telemetrySearchDetails && telemetrySearchDetails.index == -1) {
+            telemetrySearchDetails = null;
+          }
+          BrowserSearch.recordSearchInHealthReport(engine, "searchbar", telemetrySearchDetails);
           // null parameter below specifies HTML response for search
           let params = {
             postData: submission.postData,
             inBackground: aWhere == "tab-background"
           };
           openUILinkIn(submission.uri.spec,
                        aWhere == "tab-background" ? "tab" : aWhere,
                        params);
@@ -937,16 +966,21 @@
         <parameter name="aEvent"/>
         <body><![CDATA[
           var evt = aEvent || this.mEnterEvent;
 
           let engine;
           let oneOff = this.getSelectedOneOff();
           if (oneOff)
             engine = oneOff.engine;
+          if (this.mEnterEvent && this._selectionDetails &&
+              this._selectionDetails.currentIndex != -1) {
+            BrowserSearch.searchBar.telemetrySearchDetails = this._selectionDetails;
+            this._selectionDetails = null;
+          }
           document.getBindingParent(this).handleSearchCommand(evt, engine);
 
           this.mEnterEvent = null;
         ]]></body>
       </method>
 
       <method name="getSelectedOneOff">
         <body><![CDATA[
--- a/browser/components/search/test/browser_amazon_behavior.js
+++ b/browser/components/search/test/browser_amazon_behavior.js
@@ -11,16 +11,17 @@ const BROWSER_SEARCH_PREF = "browser.sea
 
 
 function test() {
   let engine = Services.search.getEngineByName("Amazon.com");
   ok(engine, "Amazon is installed");
 
   let previouslySelectedEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
+  engine.alias = "a";
 
   let base = "http://www.amazon.com/exec/obidos/external-search/?field-keywords=foo&mode=blended&tag=mozilla-20&sourceid=Mozilla-search";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
   is(url, base, "Check search URL for 'foo'");
 
@@ -42,16 +43,25 @@ function test() {
       searchURL: base,
       run: function () {
         gURLBar.value = "? foo";
         gURLBar.focus();
         EventUtils.synthesizeKey("VK_RETURN", {});
       }
     },
     {
+      name: "keyword search",
+      searchURL: base,
+      run: function () {
+        gURLBar.value = "a foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
       name: "search bar search",
       searchURL: base,
       run: function () {
         let sb = BrowserSearch.searchBar;
         sb.focus();
         sb.value = "foo";
         registerCleanupFunction(function () {
           sb.value = "";
@@ -134,16 +144,17 @@ function test() {
 
       req.cancel(Components.results.NS_ERROR_FAILURE);
 
       executeSoon(nextTest);
     }
   }
 
   registerCleanupFunction(function () {
+    engine.alias = undefined;
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
     Services.search.currentEngine = previouslySelectedEngine;
   });
 
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     gBrowser.addProgressListener(listener);
--- a/browser/components/search/test/browser_bing_behavior.js
+++ b/browser/components/search/test/browser_bing_behavior.js
@@ -11,17 +11,18 @@ const BROWSER_SEARCH_PREF = "browser.sea
 
 
 function test() {
   let engine = Services.search.getEngineByName("Bing");
   ok(engine, "Bing is installed");
 
   let previouslySelectedEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
-
+  engine.alias = "b";
+  
   let base = "http://www.bing.com/search?q=foo&pc=MOZI";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
   is(url, base, "Check search URL for 'foo'");
 
   waitForExplicitFinish();
@@ -42,16 +43,25 @@ function test() {
       searchURL: base + "&form=MOZLBR",
       run: function () {
         gURLBar.value = "? foo";
         gURLBar.focus();
         EventUtils.synthesizeKey("VK_RETURN", {});
       }
     },
     {
+      name: "keyword search with alias",
+      searchURL: base + "&form=MOZLBR",
+      run: function () {
+        gURLBar.value = "b foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
       name: "search bar search",
       searchURL: base + "&form=MOZSBR",
       run: function () {
         let sb = BrowserSearch.searchBar;
         sb.focus();
         sb.value = "foo";
         registerCleanupFunction(function () {
           sb.value = "";
@@ -134,16 +144,17 @@ function test() {
 
       req.cancel(Components.results.NS_ERROR_FAILURE);
 
       executeSoon(nextTest);
     }
   }
 
   registerCleanupFunction(function () {
+    engine.alias = undefined;
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
     Services.search.currentEngine = previouslySelectedEngine;
   });
 
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     gBrowser.addProgressListener(listener);
--- a/browser/components/search/test/browser_eBay_behavior.js
+++ b/browser/components/search/test/browser_eBay_behavior.js
@@ -11,16 +11,17 @@ const BROWSER_SEARCH_PREF = "browser.sea
 
 
 function test() {
   let engine = Services.search.getEngineByName("eBay");
   ok(engine, "eBay is installed");
 
   let previouslySelectedEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
+  engine.alias = 'e';
 
   let base = "http://rover.ebay.com/rover/1/711-47294-18009-3/4?mfe=search&mpre=http://www.ebay.com/sch/i.html?_nkw=foo";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
   is(url, base, "Check search URL for 'foo'");
 
@@ -42,16 +43,25 @@ function test() {
       searchURL: base,
       run: function () {
         gURLBar.value = "? foo";
         gURLBar.focus();
         EventUtils.synthesizeKey("VK_RETURN", {});
       }
     },
     {
+      name: "keyword search",
+      searchURL: base,
+      run: function () {
+        gURLBar.value = "e foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
       name: "search bar search",
       searchURL: base,
       run: function () {
         let sb = BrowserSearch.searchBar;
         sb.focus();
         sb.value = "foo";
         registerCleanupFunction(function () {
           sb.value = "";
@@ -134,16 +144,17 @@ function test() {
 
       req.cancel(Components.results.NS_ERROR_FAILURE);
 
       executeSoon(nextTest);
     }
   }
 
   registerCleanupFunction(function () {
+    engine.alias = undefined;
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
     Services.search.currentEngine = previouslySelectedEngine;
   });
 
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     gBrowser.addProgressListener(listener);
--- a/browser/components/search/test/browser_google_behavior.js
+++ b/browser/components/search/test/browser_google_behavior.js
@@ -8,16 +8,17 @@
 "use strict";
 
 function test() {
   let engine = Services.search.getEngineByName("Google");
   ok(engine, "Google is installed");
 
   let previouslySelectedEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
+  engine.alias = "g";
 
   let base = "https://www.google.com/search?q=foo&ie=utf-8&oe=utf-8";
 
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
   is(url, base, "Check search URL for 'foo'");
@@ -40,16 +41,25 @@ function test() {
       searchURL: base,
       run: function () {
         gURLBar.value = "? foo";
         gURLBar.focus();
         EventUtils.synthesizeKey("VK_RETURN", {});
       }
     },
     {
+      name: "keyword search",
+      searchURL: base,
+      run: function () {
+        gURLBar.value = "g foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
       name: "search bar search",
       searchURL: base,
       run: function () {
         let sb = BrowserSearch.searchBar;
         sb.focus();
         sb.value = "foo";
         registerCleanupFunction(function () {
           sb.value = "";
@@ -132,16 +142,17 @@ function test() {
 
       req.cancel(Components.results.NS_ERROR_FAILURE);
 
       executeSoon(nextTest);
     }
   }
 
   registerCleanupFunction(function () {
+    engine.alias = undefined;
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
     Services.search.currentEngine = previouslySelectedEngine;
   });
 
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     gBrowser.addProgressListener(listener);
--- a/browser/components/search/test/browser_yahoo_behavior.js
+++ b/browser/components/search/test/browser_yahoo_behavior.js
@@ -11,16 +11,17 @@ const BROWSER_SEARCH_PREF = "browser.sea
 
 
 function test() {
   let engine = Services.search.getEngineByName("Yahoo");
   ok(engine, "Yahoo is installed");
 
   let previouslySelectedEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
+  engine.alias = "y";
 
   let base = "https://search.yahoo.com/yhs/search?p=foo&ei=UTF-8&hspart=mozilla&hsimp=yhs-001";
   let url;
 
   // Test search URLs (including purposes).
   url = engine.getSubmission("foo").uri.spec;
   is(url, base, "Check search URL for 'foo'");
 
@@ -42,16 +43,25 @@ function test() {
       searchURL: base,
       run: function () {
         gURLBar.value = "? foo";
         gURLBar.focus();
         EventUtils.synthesizeKey("VK_RETURN", {});
       }
     },
     {
+      name: "keyword search",
+      searchURL: base,
+      run: function () {
+        gURLBar.value = "y foo";
+        gURLBar.focus();
+        EventUtils.synthesizeKey("VK_RETURN", {});
+      }
+    },
+    {
       name: "search bar search",
       searchURL: base,
       run: function () {
         let sb = BrowserSearch.searchBar;
         sb.focus();
         sb.value = "foo";
         registerCleanupFunction(function () {
           sb.value = "";
@@ -134,16 +144,17 @@ function test() {
 
       req.cancel(Components.results.NS_ERROR_FAILURE);
 
       executeSoon(nextTest);
     }
   }
 
   registerCleanupFunction(function () {
+    engine.alias = undefined;
     gBrowser.removeProgressListener(listener);
     gBrowser.removeTab(tab);
     Services.search.currentEngine = previouslySelectedEngine;
   });
 
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     gBrowser.addProgressListener(listener);
--- a/browser/devtools/netmonitor/test/browser_net_details-no-duplicated-content.js
+++ b/browser/devtools/netmonitor/test/browser_net_details-no-duplicated-content.js
@@ -97,20 +97,59 @@ let test = Task.async(function* () {
 
     ok(true, "Received NETWORK_EVENT. Selecting the item.");
     let item = RequestsMenu.getItemAtIndex(0);
     RequestsMenu.selectedItem = item;
 
     info("Item selected. Waiting for NETWORKDETAILSVIEW_POPULATED");
     yield onDetailsPopulated;
 
-    info("Selecting tab at index " + tabIndex);
+    info("Received populated event. Selecting tab at index " + tabIndex);
     NetworkDetails.widget.selectedIndex = tabIndex;
 
-    ok(true, "Received NETWORKDETAILSVIEW_POPULATED. Waiting for request to finish");
+    info("Waiting for request to finish.");
     yield onRequestFinished;
 
-    ok(true, "Request finished. Waiting for tab update to complete");
-    let onDetailsUpdateFinished = waitFor(panel, EVENTS.TAB_UPDATED);
-    yield onDetailsUpdateFinished;
-    ok(true, "Details were updated");
+    ok(true, "Request finished.");
+
+    /**
+     * Because this test uses lazy updates there's four scenarios to consider:
+     * #1: Everything is updated and test is ready to continue.
+     * #2: There's updates that are waiting to be flushed.
+     * #3: Updates are flushed but the tab update is still running.
+     * #4: There's pending updates and a tab update is still running.
+     *
+     * For case #1 there's not going to be a TAB_UPDATED event so don't wait for
+     * it (bug 1106181).
+     *
+     * For cases #2 and #3 it's enough to wait for one TAB_UPDATED event as for
+     * - case #2 the next flush will perform the final update and single
+     *   TAB_UPDATED event is emitted.
+     * - case #3 the running update is the final update that'll emit one
+     *   TAB_UPDATED event.
+     *
+     * For case #4 we must wait for the updates to be flushed before we can
+     * start waiting for TAB_UPDATED event or we'll continue the test right
+     * after the pending update finishes.
+     */
+    let hasQueuedUpdates = RequestsMenu._updateQueue.length !== 0;
+    let hasRunningTabUpdate = NetworkDetails._viewState.updating[tabIndex];
+
+    if (hasQueuedUpdates || hasRunningTabUpdate) {
+      info("There's pending updates - waiting for them to finish.");
+      info("  hasQueuedUpdates: " + hasQueuedUpdates);
+      info("  hasRunningTabUpdate: " + hasRunningTabUpdate);
+
+      if (hasQueuedUpdates && hasRunningTabUpdate) {
+        info("Waiting for updates to be flushed.");
+        // _flushRequests calls .populate which emits the following event
+        yield waitFor(panel, EVENTS.NETWORKDETAILSVIEW_POPULATED);
+
+        info("Requests flushed.");
+      }
+
+      info("Waiting for final tab update.");
+      yield waitFor(panel, EVENTS.TAB_UPDATED);
+    }
+
+    info("All updates completed.");
   }
 });
--- a/browser/devtools/performance/views/overview.js
+++ b/browser/devtools/performance/views/overview.js
@@ -64,17 +64,19 @@ let OverviewView = {
     PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
     PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
   },
 
   /**
    * Sets up the framerate graph.
    */
   _showFramerateGraph: Task.async(function *() {
-    this.framerateGraph = new LineGraphWidget($("#time-framerate"), L10N.getStr("graphs.fps"));
+    this.framerateGraph = new LineGraphWidget($("#time-framerate"), {
+      metric: L10N.getStr("graphs.fps")
+    });
     this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
     yield this.framerateGraph.ready();
   }),
 
   /**
    * Sets up the markers overivew graph.
    */
   _showMarkersGraph: Task.async(function *() {
--- a/browser/devtools/profiler/ui-profile.js
+++ b/browser/devtools/profiler/ui-profile.js
@@ -387,17 +387,19 @@ let ProfileView = {
       oldGraph.destroy();
     }
 
     // Don't create a graph if there's not enough data to show.
     if (!framerateData || framerateData.length < 2) {
       return null;
     }
 
-    let graph = new LineGraphWidget($(".framerate", panel), L10N.getStr("graphs.fps"));
+    let graph = new LineGraphWidget($(".framerate", panel), {
+      metric: L10N.getStr("graphs.fps")
+    });
     graph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
     graph.dataOffsetX = beginAt;
 
     yield graph.setDataWhenReady(framerateData);
 
     graph.on("mouseup", this._onGraphMouseUp);
     graph.on("scroll", this._onGraphScroll);
 
new file mode 100644
--- /dev/null
+++ b/browser/devtools/projecteditor/lib/plugins/rename/rename.js
@@ -0,0 +1,66 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+const { Class } = require("sdk/core/heritage");
+const { registerPlugin, Plugin } = require("projecteditor/plugins/core");
+const { getLocalizedString } = require("projecteditor/helpers/l10n");
+
+var RenamePlugin = Class({
+  extends: Plugin,
+
+  init: function(host) {
+    this.host.addCommand(this, {
+      id: "cmd-rename"
+    });
+    this.contextMenuItem = this.host.createMenuItem({
+      parent: this.host.contextMenuPopup,
+      label: getLocalizedString("projecteditor.renameLabel"),
+      command: "cmd-rename"
+    });
+  },
+
+  onCommand: function(cmd) {
+    if (cmd === "cmd-rename") {
+      let tree = this.host.projectTree;
+      let resource = tree.getSelectedResource();
+      let parent = resource.parent;
+      let oldName = resource.basename;
+
+      tree.promptEdit(oldName, resource).then(name => {
+        if (name === oldName) {
+          return resource;
+        }
+        if (resource.hasChild(parent, name)) {
+          let matches = name.match(/([^\d.]*)(\d*)([^.]*)(.*)/);
+          let template = matches[1] + "{1}" + matches[3] + matches[4];
+          name = this.suggestName(resource, template, parseInt(matches[2]) || 2);
+        }
+        return parent.rename(oldName,name);
+      }).then(resource => {
+        this.host.project.refresh();
+        tree.selectResource(resource);
+        if (!resource.isDir) {
+          this.host.currentEditor.focus();
+        }
+      }).then(null, console.error);
+    }
+  },
+
+  suggestName: function(resource, template, start=1) {
+    let i = start;
+    let name;
+    let parent = resource.parent;
+    do {
+      name = template.replace("\{1\}", i === 1 ? "" : i);
+      i++;
+    } while (resource.hasChild(parent, name));
+
+    return name;
+  }
+});
+
+exports.RenamePlugin = RenamePlugin;
+registerPlugin(RenamePlugin);
--- a/browser/devtools/projecteditor/lib/projecteditor.js
+++ b/browser/devtools/projecteditor/lib/projecteditor.js
@@ -22,16 +22,17 @@ const { Services } = Cu.import("resource
 const ITCHPAD_URL = "chrome://browser/content/devtools/projecteditor.xul";
 const { confirm } = require("projecteditor/helpers/prompts");
 const { getLocalizedString } = require("projecteditor/helpers/l10n");
 
 // Enabled Plugins
 require("projecteditor/plugins/dirty/dirty");
 require("projecteditor/plugins/delete/delete");
 require("projecteditor/plugins/new/new");
+require("projecteditor/plugins/rename/rename");
 require("projecteditor/plugins/save/save");
 require("projecteditor/plugins/image-view/plugin");
 require("projecteditor/plugins/app-manager/plugin");
 require("projecteditor/plugins/status-bar/plugin");
 
 // Uncomment to enable logging.
 // require("projecteditor/plugins/logging/logging");
 
--- a/browser/devtools/projecteditor/lib/stores/resource.js
+++ b/browser/devtools/projecteditor/lib/stores/resource.js
@@ -122,16 +122,31 @@ var Resource = Class({
     resource.parent = this;
     this.children.add(resource);
     this.store.notifyAdd(resource);
     emit(this, "children-changed", this);
     return resource;
   },
 
   /**
+   * Checks a resource has child with specific name.
+   *
+   * @param Resource resource
+   * @param string name
+   */
+  hasChild: function(resource, name) {
+    for (let child of resource.children) {
+      if (child.basename === name) {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  /**
    * Remove a resource to children set and notify of the change.
    *
    * @param Resource resource
    */
   removeChild: function(resource) {
     resource.parent = null;
     this.children.remove(resource);
     this.store.notifyRemove(resource);
@@ -299,16 +314,37 @@ var FileResource = Class({
       if (!resource) {
         throw new Error("Error creating " + newPath);
       }
       return resource;
     });
   },
 
   /**
+   * Rename the file from the filesystem
+   *
+   * @returns Promise
+   *          Resolves with the renamed FileResource.
+   */
+  rename: function(oldName, newName) {
+    let oldPath = OS.Path.join(this.path, oldName);
+    let newPath = OS.Path.join(this.path, newName);
+
+    return OS.File.move(oldPath, newPath).then(() => {
+      return this.store.refresh();
+    }).then(() => {
+      let resource = this.store.resources.get(newPath);
+      if (!resource) {
+        throw new Error("Error creating " + newPath);
+      }
+      return resource;
+    });
+  },
+
+  /**
    * Write a string to this file.
    *
    * @param string content
    * @returns Promise
    *          Resolves once it has been written to disk.
    *          Rejected if there is an error
    */
   save: function(content) {
--- a/browser/devtools/projecteditor/lib/tree.js
+++ b/browser/devtools/projecteditor/lib/tree.js
@@ -272,16 +272,49 @@ var TreeView = Class({
         item.parentNode.removeChild(item);
       },
     });
 
     return deferred.promise;
   },
 
   /**
+   * Prompt the user to rename file in the tree.
+   *
+   * @param string initial
+   *               The suggested starting file name
+   * @param resource
+   *
+   * @returns Promise
+   *          Resolves once the prompt has been successful,
+   *          Rejected if it is cancelled
+   */
+  promptEdit: function(initial, resource) {
+    let deferred = promise.defer();
+    let placeholder = this._containers.get(resource).elt;
+
+    new InplaceEditor({
+      element: placeholder,
+      initial: initial,
+      start: editor => {
+        editor.input.select();
+      },
+      done: function(val, commit) {
+        if (commit) {
+          deferred.resolve(val);
+        } else {
+          deferred.reject(val);
+        }
+      },
+    });
+
+    return deferred.promise;
+  },
+
+  /**
    * Add a new Store into the TreeView
    *
    * @param Store model
    */
   addModel: function(model) {
     if (this.models.has(model)) {
       // Requesting to add a model that already exists
       return;
--- a/browser/devtools/projecteditor/moz.build
+++ b/browser/devtools/projecteditor/moz.build
@@ -47,16 +47,20 @@ EXTRA_JS_MODULES.devtools.projecteditor.
 EXTRA_JS_MODULES.devtools.projecteditor.plugins.logging += [
     'lib/plugins/logging/logging.js',
 ]
 
 EXTRA_JS_MODULES.devtools.projecteditor.plugins.new += [
     'lib/plugins/new/new.js',
 ]
 
+EXTRA_JS_MODULES.devtools.projecteditor.plugins.rename += [
+    'lib/plugins/rename/rename.js',
+]
+
 EXTRA_JS_MODULES.devtools.projecteditor.plugins.save += [
     'lib/plugins/save/save.js',
 ]
 
 EXTRA_JS_MODULES.devtools.projecteditor.plugins['status-bar'] += [
     'lib/plugins/status-bar/plugin.js',
 ]
 
--- a/browser/devtools/projecteditor/test/browser.ini
+++ b/browser/devtools/projecteditor/test/browser.ini
@@ -7,16 +7,17 @@ support-files =
   helper_edits.js
 
 [browser_projecteditor_app_options.js]
 skip-if = buildapp == 'mulet'
 [browser_projecteditor_confirm_unsaved.js]
 [browser_projecteditor_contextmenu_01.js]
 [browser_projecteditor_contextmenu_02.js]
 [browser_projecteditor_delete_file.js]
+[browser_projecteditor_rename_file.js]
 skip-if = buildapp == 'mulet'
 [browser_projecteditor_editing_01.js]
 skip-if = buildapp == 'mulet'
 [browser_projecteditor_editors_image.js]
 [browser_projecteditor_external_change.js]
 [browser_projecteditor_immediate_destroy.js]
 [browser_projecteditor_init.js]
 [browser_projecteditor_menubar_01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/projecteditor/test/browser_projecteditor_rename_file.js
@@ -0,0 +1,59 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test file rename functionality
+
+add_task(function*() {
+  let projecteditor = yield addProjectEditorTabForTempDirectory();
+  ok(true, "ProjectEditor has loaded");
+
+  let root = [...projecteditor.project.allStores()][0].root;
+  is(root.path, TEMP_PATH, "The root store is set to the correct temp path.");
+  for (let child of root.children) {
+    yield renameWithContextMenu(projecteditor, projecteditor.projectTree.getViewContainer(child));
+  }
+});
+
+function openContextMenuOn(node) {
+  EventUtils.synthesizeMouseAtCenter(
+    node,
+    {button: 2, type: "contextmenu"},
+    node.ownerDocument.defaultView
+  );
+}
+
+function renameWithContextMenu(projecteditor, container) {
+  let defer = promise.defer();
+  let popup = projecteditor.contextMenuPopup;
+  let resource = container.resource;
+  info ("Going to attempt renaming for: " + resource.path);
+
+  onPopupShow(popup).then(function () {
+    let renameCommand = popup.querySelector("[command=cmd-rename]");
+    ok (renameCommand, "Rename command exists in popup");
+    is (renameCommand.getAttribute("hidden"), "", "Rename command is visible");
+    is (renameCommand.getAttribute("disabled"), "", "Rename command is enabled");
+
+    projecteditor.project.on("refresh-complete", function refreshComplete() {
+      projecteditor.project.off("refresh-complete", refreshComplete);
+      OS.File.stat(resource.path + ".renamed").then(() => {
+        ok (true, "File is renamed");
+        defer.resolve();
+      }, (ex) => {
+        ok (false, "Failed to rename file");
+        defer.resolve();
+      });
+    });
+
+    renameCommand.click();
+    popup.hidePopup();
+    EventUtils.sendString(resource.basename + ".renamed", projecteditor.window);
+    EventUtils.synthesizeKey("VK_RETURN", {}, projecteditor.window);
+  });
+
+  openContextMenuOn(container.label);
+  return defer.promise;
+}
--- a/browser/devtools/shared/test/browser.ini
+++ b/browser/devtools/shared/test/browser.ini
@@ -24,16 +24,17 @@ support-files =
 [browser_graphs-07a.js]
 [browser_graphs-07b.js]
 [browser_graphs-08.js]
 [browser_graphs-09a.js]
 [browser_graphs-09b.js]
 [browser_graphs-09c.js]
 [browser_graphs-09d.js]
 [browser_graphs-09e.js]
+[browser_graphs-09f.js]
 [browser_graphs-10a.js]
 [browser_graphs-10b.js]
 [browser_graphs-11a.js]
 [browser_graphs-11b.js]
 [browser_graphs-12.js]
 [browser_graphs-13.js]
 [browser_graphs-14.js]
 [browser_inplace-editor.js]
--- a/browser/devtools/shared/test/browser_css_color.js
+++ b/browser/devtools/shared/test/browser_css_color.js
@@ -48,16 +48,17 @@ function testColorUtils() {
     is(color.hex, hex, "color.hex === hex");
     is(color.hsl, hsl, "color.hsl === hsl");
     is(color.rgb, rgb, "color.rgb === rgb");
 
     testToString(color, name, hex, hsl, rgb);
     testColorMatch(name, hex, hsl, rgb, color.rgba);
   }
   testProcessCSSString();
+  testSetAlpha();
   finishUp();
 }
 
 function testToString(color, name, hex, hsl, rgb) {
   switchColorUnit(colorUtils.CssColor.COLORUNIT.name);
   is(color.toString(), name, "toString() with authored type");
 
   switchColorUnit(colorUtils.CssColor.COLORUNIT.hex);
@@ -133,16 +134,39 @@ function testProcessCSSString() {
                  "color #0F0; font-weight: bold; " +
                  "background-color: transparent; " +
                  "border-top-color: rgba(0, 0, 255, 0.5);";
   let after = colorUtils.processCSSString(before);
 
   is(after, expected, "CSS string processed correctly");
 }
 
+function testSetAlpha() {
+  let values = [
+    ["longhex", "#ff0000", 0.5, "rgba(255, 0, 0, 0.5)"],
+    ["hex", "#f0f", 0.2, "rgba(255, 0, 255, 0.2)"],
+    ["rgba", "rgba(120, 34, 23, 1)", 0.25, "rgba(120, 34, 23, 0.25)"],
+    ["rgb", "rgb(120, 34, 23)", 0.25, "rgba(120, 34, 23, 0.25)"],
+    ["hsl", "hsl(208, 100%, 97%)", 0.75, "rgba(239, 247, 255, 0.75)"],
+    ["hsla", "hsla(208, 100%, 97%, 1)", 0.75, "rgba(239, 247, 255, 0.75)"]
+  ];
+  values.forEach(([type, value, alpha, expected]) => {
+    is(colorUtils.setAlpha(value, alpha), expected, "correctly sets alpha value for " + type);
+  });
+
+  try {
+    colorUtils.setAlpha("rgb(24, 25, 45, 1)", 1);
+    ok(false, "Should fail when passing in an invalid color.");
+  } catch (e) {
+    ok(true, "Fails when setAlpha receives an invalid color.");
+  }
+
+  is(colorUtils.setAlpha("#fff"), "rgba(255, 255, 255, 1)", "sets alpha to 1 if invalid.");
+}
+
 function finishUp() {
   Services = colorUtils = Loader = null;
   gBrowser.removeCurrentTab();
   finish();
 }
 
 function getTestData() {
   return [
--- a/browser/devtools/shared/test/browser_graphs-09a.js
+++ b/browser/devtools/shared/test/browser_graphs-09a.js
@@ -13,17 +13,17 @@ let test = Task.async(function*() {
   yield promiseTab("about:blank");
   yield performTest();
   gBrowser.removeCurrentTab();
   finish();
 });
 
 function* performTest() {
   let [host, win, doc] = yield createHost();
-  let graph = new LineGraphWidget(doc.body, "fps");
+  let graph = new LineGraphWidget(doc.body, { metric: "fps" });
 
   yield testGraph(graph);
 
   graph.destroy();
   host.destroy();
 }
 
 function* testGraph(graph) {
new file mode 100644
--- /dev/null
+++ b/browser/devtools/shared/test/browser_graphs-09f.js
@@ -0,0 +1,55 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests the constructor options for `min`, `max` and `avg` on displaying the
+// gutter/tooltips and lines.
+
+const TEST_DATA = [{ delta: 100, value: 60 }, { delta: 200, value: 1 }];
+let {LineGraphWidget} = Cu.import("resource:///modules/devtools/Graphs.jsm", {});
+let {DOMHelpers} = Cu.import("resource:///modules/devtools/DOMHelpers.jsm", {});
+let {Promise} = devtools.require("resource://gre/modules/Promise.jsm");
+let {Hosts} = devtools.require("devtools/framework/toolbox-hosts");
+
+let test = Task.async(function*() {
+  yield promiseTab("about:blank");
+  yield performTest();
+  gBrowser.removeCurrentTab();
+  finish();
+});
+
+function* performTest() {
+  let [host, win, doc] = yield createHost();
+
+  yield testGraph(doc.body, { avg: false });
+  yield testGraph(doc.body, { min: false });
+  yield testGraph(doc.body, { max: false });
+  yield testGraph(doc.body, { min: false, max: false, avg: false });
+  yield testGraph(doc.body, {});
+
+  host.destroy();
+}
+
+function* testGraph (parent, options) {
+  options.metric = "fps";
+  let graph = new LineGraphWidget(parent, options);
+  yield graph.setDataWhenReady(TEST_DATA);
+  let shouldGutterShow = options.min === false && options.max === false;
+
+  is(graph._gutter.hidden, shouldGutterShow,
+    `The gutter should ${shouldGutterShow ? "" : "not "}be shown`);
+
+  is(graph._maxTooltip.hidden, options.max === false,
+    `The max tooltip should ${options.max === false ? "not " : ""}be shown`);
+  is(graph._maxGutterLine.hidden, options.max === false,
+    `The max gutter should ${options.max === false ? "not " : ""}be shown`);
+  is(graph._minTooltip.hidden, options.min === false,
+    `The min tooltip should ${options.min === false ? "not " : ""}be shown`);
+  is(graph._minGutterLine.hidden, options.min === false,
+    `The min gutter should ${options.min === false ? "not " : ""}be shown`);
+  is(graph._avgTooltip.hidden, options.avg === false,
+    `The avg tooltip should ${options.avg === false ? "not " : ""}be shown`);
+  is(graph._avgGutterLine.hidden, options.avg === false,
+    `The avg gutter should ${options.avg === false ? "not " : ""}be shown`);
+
+  graph.destroy();
+}
--- a/browser/devtools/shared/widgets/Graphs.jsm
+++ b/browser/devtools/shared/widgets/Graphs.jsm
@@ -1164,30 +1164,42 @@ AbstractCanvasGraph.prototype = {
  *     { delta: x2, value: y2 },
  *     ...
  *     { delta: xn, value: yn }
  *   ]
  * where each item in the array represents a point in the graph.
  *
  * @param nsIDOMNode parent
  *        The parent node holding the graph.
- * @param string metric [optional]
- *        The metric displayed in the graph, e.g. "fps" or "bananas".
+ * @param object options [optional]
+ *        `metric`: The metric displayed in the graph, e.g. "fps" or "bananas".
+ *        `min`: Boolean whether to show the min tooltip/gutter/line (default: true)
+ *        `max`: Boolean whether to show the max tooltip/gutter/line (default: true)
+ *        `avg`: Boolean whether to show the avg tooltip/gutter/line (default: true)
  */
-this.LineGraphWidget = function(parent, metric, ...args) {
+this.LineGraphWidget = function(parent, options, ...args) {
+  options = options || {};
+  let metric = options.metric;
+
+  this._showMin = options.min !== false;
+  this._showMax = options.max !== false;
+  this._showAvg = options.avg !== false;
   AbstractCanvasGraph.apply(this, [parent, "line-graph", ...args]);
 
   this.once("ready", () => {
+    // Create all gutters and tooltips incase the showing of min/max/avg
+    // are changed later
     this._gutter = this._createGutter();
+
     this._maxGutterLine = this._createGutterLine("maximum");
-    this._avgGutterLine = this._createGutterLine("average");
+    this._maxTooltip = this._createTooltip("maximum", "start", "max", metric);
     this._minGutterLine = this._createGutterLine("minimum");
-    this._maxTooltip = this._createTooltip("maximum", "start", "max", metric);
+    this._minTooltip = this._createTooltip("minimum", "start", "min", metric);
+    this._avgGutterLine = this._createGutterLine("average");
     this._avgTooltip = this._createTooltip("average", "end", "avg", metric);
-    this._minTooltip = this._createTooltip("minimum", "start", "min", metric);
   });
 };
 
 LineGraphWidget.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
   backgroundColor: LINE_GRAPH_BACKGROUND_COLOR,
   backgroundGradientStart: LINE_GRAPH_BACKGROUND_GRADIENT_START,
   backgroundGradientEnd: LINE_GRAPH_BACKGROUND_GRADIENT_END,
   strokeColor: LINE_GRAPH_STROKE_COLOR,
@@ -1357,47 +1369,50 @@ LineGraphWidget.prototype = Heritage.ext
    * @param number dataScaleY
    */
   _drawOverlays: function(ctx, minValue, maxValue, avgValue, dataScaleY) {
     let width = this._width;
     let height = this._height;
     let totalTicks = this._data.length;
 
     // Draw the maximum value horizontal line.
-
-    ctx.strokeStyle = this.maximumLineColor;
-    ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
-    ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
-    ctx.beginPath();
-    let maximumY = height - maxValue * dataScaleY;
-    ctx.moveTo(0, maximumY);
-    ctx.lineTo(width, maximumY);
-    ctx.stroke();
+    if (this._showMax) {
+      ctx.strokeStyle = this.maximumLineColor;
+      ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
+      ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
+      ctx.beginPath();
+      let maximumY = height - maxValue * dataScaleY;
+      ctx.moveTo(0, maximumY);
+      ctx.lineTo(width, maximumY);
+      ctx.stroke();
+    }
 
     // Draw the average value horizontal line.
-
-    ctx.strokeStyle = this.averageLineColor;
-    ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
-    ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
-    ctx.beginPath();
-    let averageY = height - avgValue * dataScaleY;
-    ctx.moveTo(0, averageY);
-    ctx.lineTo(width, averageY);
-    ctx.stroke();
+    if (this._showAvg) {
+      ctx.strokeStyle = this.averageLineColor;
+      ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
+      ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
+      ctx.beginPath();
+      let averageY = height - avgValue * dataScaleY;
+      ctx.moveTo(0, averageY);
+      ctx.lineTo(width, averageY);
+      ctx.stroke();
+    }
 
     // Draw the minimum value horizontal line.
-
-    ctx.strokeStyle = this.minimumLineColor;
-    ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
-    ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
-    ctx.beginPath();
-    let minimumY = height - minValue * dataScaleY;
-    ctx.moveTo(0, minimumY);
-    ctx.lineTo(width, minimumY);
-    ctx.stroke();
+    if (this._showMin) {
+      ctx.strokeStyle = this.minimumLineColor;
+      ctx.lineWidth = LINE_GRAPH_HELPER_LINES_WIDTH;
+      ctx.setLineDash(LINE_GRAPH_HELPER_LINES_DASH);
+      ctx.beginPath();
+      let minimumY = height - minValue * dataScaleY;
+      ctx.moveTo(0, minimumY);
+      ctx.lineTo(width, minimumY);
+      ctx.stroke();
+    }
 
     // Update the tooltips text and gutter lines.
 
     this._maxTooltip.querySelector("[text=value]").textContent =
       L10N.numberWithDecimals(maxValue, 2);
     this._avgTooltip.querySelector("[text=value]").textContent =
       L10N.numberWithDecimals(avgValue, 2);
     this._minTooltip.querySelector("[text=value]").textContent =
@@ -1426,20 +1441,24 @@ LineGraphWidget.prototype = Heritage.ext
     this._avgGutterLine.style.top = avgPosY + "px";
     this._minGutterLine.style.top = minPosY + "px";
 
     this._maxTooltip.setAttribute("with-arrows", this.withTooltipArrows);
     this._avgTooltip.setAttribute("with-arrows", this.withTooltipArrows);
     this._minTooltip.setAttribute("with-arrows", this.withTooltipArrows);
 
     let distanceMinMax = Math.abs(maxTooltipTop - minTooltipTop);
-    this._maxTooltip.hidden = !totalTicks || distanceMinMax < LINE_GRAPH_MIN_MAX_TOOLTIP_DISTANCE;
-    this._avgTooltip.hidden = !totalTicks;
-    this._minTooltip.hidden = !totalTicks;
-    this._gutter.hidden = !totalTicks || !this.withTooltipArrows;
+    this._maxTooltip.hidden = this._showMax === false || !totalTicks || distanceMinMax < LINE_GRAPH_MIN_MAX_TOOLTIP_DISTANCE;
+    this._avgTooltip.hidden = this._showAvg === false || !totalTicks;
+    this._minTooltip.hidden = this._showMin === false || !totalTicks;
+    this._gutter.hidden = (this._showMin === false && this._showMax === false) || !totalTicks || !this.withTooltipArrows;
+
+    this._maxGutterLine.hidden = this._showMax === false;
+    this._avgGutterLine.hidden = this._showAvg === false;
+    this._minGutterLine.hidden = this._showMin === false;
   },
 
   /**
    * Creates the gutter node when constructing this graph.
    * @return nsIDOMNode
    */
   _createGutter: function() {
     let gutter = this._document.createElementNS(HTML_NS, "div");
--- a/browser/devtools/timeline/test/browser.ini
+++ b/browser/devtools/timeline/test/browser.ini
@@ -5,15 +5,16 @@ support-files =
   head.js
 
 [browser_timeline_aaa_run_first_leaktest.js]
 [browser_timeline_blueprint.js]
 [browser_timeline_filters.js]
 [browser_timeline_overview-initial-selection-01.js]
 [browser_timeline_overview-initial-selection-02.js]
 [browser_timeline_overview-update.js]
+[browser_timeline_overview-theme.js]
 [browser_timeline_panels.js]
 [browser_timeline_recording-without-memory.js]
 [browser_timeline_recording.js]
 [browser_timeline_waterfall-background.js]
 [browser_timeline_waterfall-generic.js]
 [browser_timeline_waterfall-styles.js]
 [browser_timeline_waterfall-sidebar.js]
--- a/browser/devtools/timeline/test/browser_timeline_filters.js
+++ b/browser/devtools/timeline/test/browser_timeline_filters.js
@@ -43,39 +43,39 @@ add_task(function*() {
   ok($(".waterfall-marker-bar[type=Paint]"), "Found at least one 'Paint' marker (1)");
 
   let heightBefore = overview.fixedHeight;
   EventUtils.synthesizeMouseAtCenter(menuItem1, {type: "mouseup"}, panel.panelWin);
   yield once(menuItem1, "command");
 
   yield waitUntil(() => !waterfall._outstandingMarkers.length);
 
-  // A row is 11px. See markers-overview.js
-  is(overview.fixedHeight, heightBefore - 11, "Overview is smaller");
+  is(overview.fixedHeight, heightBefore, "Overview height hasn't changed");
   ok(!$(".waterfall-marker-bar[type=Styles]"), "No 'Styles' marker (2)");
   ok($(".waterfall-marker-bar[type=Reflow]"), "Found at least one 'Reflow' marker (2)");
   ok($(".waterfall-marker-bar[type=Paint]"), "Found at least one 'Paint' marker (2)");
 
   heightBefore = overview.fixedHeight;
   EventUtils.synthesizeMouseAtCenter(menuItem2, {type: "mouseup"}, panel.panelWin);
   yield once(menuItem2, "command");
 
   yield waitUntil(() => !waterfall._outstandingMarkers.length);
 
-  is(overview.fixedHeight, heightBefore - 11, "Overview is smaller");
+  is(overview.fixedHeight, heightBefore, "Overview height hasn't changed");
   ok(!$(".waterfall-marker-bar[type=Styles]"), "No 'Styles' marker (3)");
   ok(!$(".waterfall-marker-bar[type=Reflow]"), "No 'Reflow' marker (3)");
   ok($(".waterfall-marker-bar[type=Paint]"), "Found at least one 'Paint' marker (3)");
 
   heightBefore = overview.fixedHeight;
   EventUtils.synthesizeMouseAtCenter(menuItem3, {type: "mouseup"}, panel.panelWin);
   yield once(menuItem3, "command");
 
   yield waitUntil(() => !waterfall._outstandingMarkers.length);
 
+  // A row is 11px. See markers-overview.js
   is(overview.fixedHeight, heightBefore - 11, "Overview is smaller");
   ok(!$(".waterfall-marker-bar[type=Styles]"), "No 'Styles' marker (4)");
   ok(!$(".waterfall-marker-bar[type=Reflow]"), "No 'Reflow' marker (4)");
   ok(!$(".waterfall-marker-bar[type=Paint]"), "No 'Paint' marker (4)");
 
   for (let item of [menuItem1, menuItem2, menuItem3]) {
     EventUtils.synthesizeMouseAtCenter(item, {type: "mouseup"}, panel.panelWin);
     yield once(item, "command");
new file mode 100644
--- /dev/null
+++ b/browser/devtools/timeline/test/browser_timeline_overview-theme.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests if the markers and memory overviews render with the correct
+ * theme on load, and rerenders when changed.
+ */
+
+const LIGHT_BG = "#fcfcfc";
+const DARK_BG = "#14171a";
+
+add_task(function*() {
+  let { target, panel } = yield initTimelinePanel("about:blank");
+  let { $, EVENTS, TimelineView, TimelineController } = panel.panelWin;
+
+  $("#memory-checkbox").checked = true;
+
+  setTheme("dark");
+
+  yield TimelineController.updateMemoryRecording();
+  is(TimelineView.markersOverview.backgroundColor, DARK_BG,
+    "correct theme on load for markers.");
+  is(TimelineView.memoryOverview.backgroundColor, DARK_BG,
+    "correct theme on load for memory.");
+
+  yield TimelineController.toggleRecording();
+  ok(true, "Recording has started.");
+
+  yield TimelineController.toggleRecording();
+  ok(true, "Recording has ended.");
+
+  let refreshed = Promise.all([
+    once(TimelineView.markersOverview, "refresh"),
+    once(TimelineView.memoryOverview, "refresh"),
+  ]);
+
+  setTheme("light");
+  yield refreshed;
+
+  ok(true, "Both memory and markers were rerendered after theme change.");
+  is(TimelineView.markersOverview.backgroundColor, LIGHT_BG,
+    "correct theme on after toggle for markers.");
+  is(TimelineView.memoryOverview.backgroundColor, LIGHT_BG,
+    "correct theme on after toggle for memory.");
+
+  refreshed = Promise.all([
+    once(TimelineView.markersOverview, "refresh"),
+    once(TimelineView.memoryOverview, "refresh"),
+  ]);
+
+  setTheme("dark");
+  yield refreshed;
+
+  ok(true, "Both memory and markers were rerendered after theme change.");
+  is(TimelineView.markersOverview.backgroundColor, DARK_BG,
+    "correct theme on after toggle for markers once more.");
+  is(TimelineView.memoryOverview.backgroundColor, DARK_BG,
+    "correct theme on after toggle for memory once more.");
+
+  refreshed = Promise.all([
+    once(TimelineView.markersOverview, "refresh"),
+    once(TimelineView.memoryOverview, "refresh"),
+  ]);
+
+  // Set theme back to light
+  setTheme("light");
+  yield refreshed;
+});
+
+/**
+ * Mimics selecting the theme selector in the toolbox;
+ * sets the preference and emits an event on gDevTools to trigger
+ * the themeing.
+ */
+function setTheme (newTheme) {
+  let oldTheme = Services.prefs.getCharPref("devtools.theme");
+  info("Setting `devtools.theme` to \"" + newTheme + "\"");
+  Services.prefs.setCharPref("devtools.theme", newTheme);
+  gDevTools.emit("pref-changed", {
+    pref: "devtools.theme",
+    newValue: newTheme,
+    oldValue: oldTheme
+  });
+}
--- a/browser/devtools/timeline/test/browser_timeline_waterfall-sidebar.js
+++ b/browser/devtools/timeline/test/browser_timeline_waterfall-sidebar.js
@@ -2,17 +2,17 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 /**
  * Tests if the sidebar is properly updated when a marker is selected.
  */
 
 add_task(function*() {
   let { target, panel } = yield initTimelinePanel(SIMPLE_URL);
-  let { $, $$, EVENTS, TimelineController, TimelineView } = panel.panelWin;
+  let { $, $$, EVENTS, TimelineController, TimelineView, TIMELINE_BLUEPRINT} = panel.panelWin;
   let { L10N } = devtools.require("devtools/timeline/global");
 
   yield TimelineController.toggleRecording();
   ok(true, "Recording has started.");
 
   yield waitUntil(() => {
     // Wait until we get 3 different markers.
     let markers = TimelineController.getMarkers();
@@ -34,17 +34,19 @@ add_task(function*() {
   ok(bars.length > 2, "got at least 3 markers");
 
   let sidebar = $("#timeline-waterfall-details");
   for (let i = 0; i < bars.length; i++) {
     let bar = bars[i];
     bar.click();
     let m = markers[i];
 
-    is($("#timeline-waterfall-details .marker-details-type").getAttribute("value"), m.name,
+    let name = TIMELINE_BLUEPRINT[m.name].label;
+
+    is($("#timeline-waterfall-details .marker-details-type").getAttribute("value"), name,
       "sidebar title matches markers name");
 
     let printedStartTime = $(".marker-details-start .marker-details-labelvalue").getAttribute("value");
     let printedEndTime = $(".marker-details-end .marker-details-labelvalue").getAttribute("value");
     let printedDuration= $(".marker-details-duration .marker-details-labelvalue").getAttribute("value");
 
     let toMs = ms => L10N.getFormatStrWithNumbers("timeline.tick", ms);
 
--- a/browser/devtools/timeline/timeline.js
+++ b/browser/devtools/timeline/timeline.js
@@ -1,18 +1,20 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
+Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/devtools/Loader.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
+Cu.import("resource:///modules/devtools/gDevTools.jsm");
 
 devtools.lazyRequireGetter(this, "promise");
 devtools.lazyRequireGetter(this, "EventEmitter",
   "devtools/toolkit/event-emitter");
 
 devtools.lazyRequireGetter(this, "MarkersOverview",
   "devtools/timeline/markers-overview", true);
 devtools.lazyRequireGetter(this, "MemoryOverview",
@@ -93,16 +95,17 @@ let TimelineController = {
   /**
    * Initialization function, called when the tool is started.
    */
   initialize: function() {
     this._onRecordingTick = this._onRecordingTick.bind(this);
     this._onMarkers = this._onMarkers.bind(this);
     this._onMemory = this._onMemory.bind(this);
     this._onFrames = this._onFrames.bind(this);
+
     gFront.on("markers", this._onMarkers);
     gFront.on("memory", this._onMemory);
     gFront.on("frames", this._onFrames);
   },
 
   /**
    * Destruction function, called when the tool is closed.
    */
@@ -288,37 +291,44 @@ let TimelineView = {
    * Initialization function, called when the tool is started.
    */
   initialize: Task.async(function*() {
     let blueprint = this._getFilteredBluePrint();
     this.markersOverview = new MarkersOverview($("#markers-overview"), blueprint);
     this.waterfall = new Waterfall($("#timeline-waterfall"), $("#timeline-pane"), blueprint);
     this.markerDetails = new MarkerDetails($("#timeline-waterfall-details"), $("#timeline-waterfall-container > splitter"));
 
+    this._onThemeChange = this._onThemeChange.bind(this);
     this._onSelecting = this._onSelecting.bind(this);
     this._onRefresh = this._onRefresh.bind(this);
+
+    gDevTools.on("pref-changed", this._onThemeChange);
     this.markersOverview.on("selecting", this._onSelecting);
     this.markersOverview.on("refresh", this._onRefresh);
     this.markerDetails.on("resize", this._onRefresh);
 
     this._onMarkerSelected = this._onMarkerSelected.bind(this);
     this.waterfall.on("selected", this._onMarkerSelected);
     this.waterfall.on("unselected", this._onMarkerSelected);
 
+    let theme = Services.prefs.getCharPref("devtools.theme");
+    this.markersOverview.setTheme(theme);
+
     yield this.markersOverview.ready();
 
     yield this.waterfall.recalculateBounds();
 
     this._buildFilterPopup();
   }),
 
   /**
    * Destruction function, called when the tool is closed.
    */
   destroy: function() {
+    gDevTools.off("pref-changed", this._onThemeChange);
     this.markerDetails.off("resize", this._onRefresh);
     this.markerDetails.destroy();
     this.waterfall.off("selected", this._onMarkerSelected);
     this.waterfall.off("unselected", this._onMarkerSelected);
     this.waterfall.destroy();
     this.markersOverview.off("selecting", this._onSelecting);
     this.markersOverview.off("refresh", this._onRefresh);
     this.markersOverview.destroy();
@@ -328,17 +338,20 @@ let TimelineView = {
       this.memoryOverview.destroy();
     }
   },
 
   /**
    * Shows the memory overview graph.
    */
   showMemoryOverview: Task.async(function*() {
+    let theme = Services.prefs.getCharPref("devtools.theme");
+
     this.memoryOverview = new MemoryOverview($("#memory-overview"));
+    this.memoryOverview.setTheme(theme);
     yield this.memoryOverview.ready();
 
     let interval = TimelineController.getInterval();
     let memory = TimelineController.getMemory();
     this.memoryOverview.setData({ interval, memory });
 
     CanvasGraphUtils.linkAnimation(this.markersOverview, this.memoryOverview);
     CanvasGraphUtils.linkSelection(this.markersOverview, this.memoryOverview);
@@ -570,16 +583,30 @@ let TimelineView = {
       // Style used by pseudo element ::before in timeline.css.in
       let bulletStyle = `--bullet-bg: ${markerDetails.fill};`
       bulletStyle += `--bullet-border: ${markerDetails.stroke}`;
       menuitem.setAttribute("style", bulletStyle);
 
       popup.appendChild(menuitem);
     }
   },
+
+  /*
+   * Called when the developer tools theme changes. Redraws
+   * the graphs with the new theme setting.
+   */
+  _onThemeChange: function (_, theme) {
+    if (this.memoryOverview) {
+      this.memoryOverview.setTheme(theme.newValue);
+      this.memoryOverview.refresh({ force: true });
+    }
+
+    this.markersOverview.setTheme(theme.newValue);
+    this.markersOverview.refresh({ force: true });
+  }
 };
 
 /**
  * Convenient way of emitting events from the panel window.
  */
 EventEmitter.decorate(this);
 
 /**
--- a/browser/devtools/timeline/widgets/global.js
+++ b/browser/devtools/timeline/widgets/global.js
@@ -25,45 +25,45 @@ const L10N = new ViewHelpers.L10N(STRING
  * Whenever this is changed, browser_timeline_waterfall-styles.js *must* be
  * updated as well.
  */
 const TIMELINE_BLUEPRINT = {
   "Styles": {
     group: 0,
     fill: "hsl(285,50%,68%)",
     stroke: "hsl(285,50%,48%)",
-    label: L10N.getStr("timeline.label.styles")
+    label: L10N.getStr("timeline.label.styles2")
   },
   "Reflow": {
-    group: 2,
+    group: 0,
+    fill: "hsl(285,50%,68%)",
+    stroke: "hsl(285,50%,48%)",
+    label: L10N.getStr("timeline.label.reflow2")
+  },
+  "Paint": {
+    group: 0,
     fill: "hsl(104,57%,71%)",
     stroke: "hsl(104,57%,51%)",
-    label: L10N.getStr("timeline.label.reflow")
-  },
-  "Paint": {
-    group: 1,
-    fill: "hsl(39,82%,69%)",
-    stroke: "hsl(39,82%,49%)",
     label: L10N.getStr("timeline.label.paint")
   },
   "DOMEvent": {
-    group: 3,
-    fill: "hsl(219,82%,69%)",
-    stroke: "hsl(219,82%,69%)",
+    group: 1,
+    fill: "hsl(39,82%,69%)",
+    stroke: "hsl(39,82%,49%)",
     label: L10N.getStr("timeline.label.domevent")
   },
+  "Javascript": {
+    group: 1,
+    fill: "hsl(39,82%,69%)",
+    stroke: "hsl(39,82%,49%)",
+    label: L10N.getStr("timeline.label.javascript2")
+  },
   "ConsoleTime": {
-    group: 4,
+    group: 2,
     fill: "hsl(0,0%,80%)",
     stroke: "hsl(0,0%,60%)",
     label: L10N.getStr("timeline.label.consoleTime")
   },
-  "Javascript": {
-    group: 4,
-    fill: "hsl(0,0%,80%)",
-    stroke: "hsl(0,0%,60%)",
-    label: L10N.getStr("timeline.label.javascript")
-  },
 };
 
 // Exported symbols.
 exports.L10N = L10N;
 exports.TIMELINE_BLUEPRINT = TIMELINE_BLUEPRINT;
--- a/browser/devtools/timeline/widgets/markers-overview.js
+++ b/browser/devtools/timeline/widgets/markers-overview.js
@@ -9,70 +9,65 @@
  * markers are visible in the "waterfall".
  */
 
 const {Cc, Ci, Cu, Cr} = require("chrome");
 
 Cu.import("resource:///modules/devtools/Graphs.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
+const { colorUtils: { setAlpha }} = require("devtools/css-color");
+const { getColor } = require("devtools/shared/theme");
+
 loader.lazyRequireGetter(this, "L10N",
   "devtools/timeline/global", true);
 
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-
 const OVERVIEW_HEADER_HEIGHT = 14; // px
 const OVERVIEW_ROW_HEIGHT = 11; // row height
 
-const OVERVIEW_BACKGROUND_COLOR = "#fff";
-const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
-const OVERVIEW_SELECTION_LINE_COLOR = "#555";
-const OVERVIEW_SELECTION_BACKGROUND_COLOR = "rgba(76,158,217,0.25)";
-const OVERVIEW_SELECTION_STRIPES_COLOR = "rgba(255,255,255,0.1)";
+const OVERVIEW_BODY_HEIGHT = 55; // 11px * 5 groups
+const OVERVIEW_SELECTION_LINE_COLOR = "#666";
+const OVERVIEW_CLIPHEAD_LINE_COLOR = "#555";
 
 const OVERVIEW_HEADER_TICKS_MULTIPLE = 100; // ms
 const OVERVIEW_HEADER_TICKS_SPACING_MIN = 75; // px
 const OVERVIEW_HEADER_SAFE_BOUNDS = 50; // px
-const OVERVIEW_HEADER_BACKGROUND = "#fff";
-const OVERVIEW_HEADER_TEXT_COLOR = "#18191a";
 const OVERVIEW_HEADER_TEXT_FONT_SIZE = 9; // px
 const OVERVIEW_HEADER_TEXT_FONT_FAMILY = "sans-serif";
 const OVERVIEW_HEADER_TEXT_PADDING_LEFT = 6; // px
 const OVERVIEW_HEADER_TEXT_PADDING_TOP = 1; // px
-const OVERVIEW_TIMELINE_STROKES = "#ccc";
 const OVERVIEW_MARKERS_COLOR_STOPS = [0, 0.1, 0.75, 1];
 const OVERVIEW_MARKER_DURATION_MIN = 4; // ms
 const OVERVIEW_GROUP_VERTICAL_PADDING = 5; // px
-const OVERVIEW_GROUP_ALTERNATING_BACKGROUND = "rgba(0,0,0,0.05)";
 
 /**
  * An overview for the markers data.
  *
  * @param nsIDOMNode parent
  *        The parent node holding the overview.
  * @param Object blueprint
  *        List of names and colors defining markers.
  */
 function MarkersOverview(parent, blueprint, ...args) {
   AbstractCanvasGraph.apply(this, [parent, "markers-overview", ...args]);
 
+  this.setTheme();
+
   // Set the list of names, properties and colors used to paint this overview.
   this.setBlueprint(blueprint);
 
   this.once("ready", () => {
     // Populate this overview with some dummy initial data.
     this.setData({ interval: { startTime: 0, endTime: 1000 }, markers: [] });
   });
 }
 
 MarkersOverview.prototype = Heritage.extend(AbstractCanvasGraph.prototype, {
   clipheadLineColor: OVERVIEW_CLIPHEAD_LINE_COLOR,
   selectionLineColor: OVERVIEW_SELECTION_LINE_COLOR,
-  selectionBackgroundColor: OVERVIEW_SELECTION_BACKGROUND_COLOR,
-  selectionStripesColor: OVERVIEW_SELECTION_STRIPES_COLOR,
   headerHeight: OVERVIEW_HEADER_HEIGHT,
   rowHeight: OVERVIEW_ROW_HEIGHT,
   groupPadding: OVERVIEW_GROUP_VERTICAL_PADDING,
 
   /**
    * Compute the height of the overview.
    */
   get fixedHeight() {
@@ -133,25 +128,25 @@ MarkersOverview.prototype = Heritage.ext
     let groupHeight = this.rowHeight * this._pixelRatio;
     let groupPadding = this.groupPadding * this._pixelRatio;
 
     let totalTime = (endTime - startTime) || 0;
     let dataScale = this.dataScaleX = availableWidth / totalTime;
 
     // Draw the header and overview background.
 
-    ctx.fillStyle = OVERVIEW_HEADER_BACKGROUND;
+    ctx.fillStyle = this.headerBackgroundColor;
     ctx.fillRect(0, 0, canvasWidth, headerHeight);
 
-    ctx.fillStyle = OVERVIEW_BACKGROUND_COLOR;
+    ctx.fillStyle = this.backgroundColor;
     ctx.fillRect(0, headerHeight, canvasWidth, canvasHeight);
 
     // Draw the alternating odd/even group backgrounds.
 
-    ctx.fillStyle = OVERVIEW_GROUP_ALTERNATING_BACKGROUND;
+    ctx.fillStyle = this.alternatingBackgroundColor;
     ctx.beginPath();
 
     for (let i = 0; i < totalGroups; i += 2) {
       let top = headerHeight + i * groupHeight;
       ctx.rect(0, top, canvasWidth, groupHeight);
     }
 
     ctx.fill();
@@ -161,18 +156,18 @@ MarkersOverview.prototype = Heritage.ext
     let fontSize = OVERVIEW_HEADER_TEXT_FONT_SIZE * this._pixelRatio;
     let fontFamily = OVERVIEW_HEADER_TEXT_FONT_FAMILY;
     let textPaddingLeft = OVERVIEW_HEADER_TEXT_PADDING_LEFT * this._pixelRatio;
     let textPaddingTop = OVERVIEW_HEADER_TEXT_PADDING_TOP * this._pixelRatio;
     let tickInterval = this._findOptimalTickInterval(dataScale);
 
     ctx.textBaseline = "middle";
     ctx.font = fontSize + "px " + fontFamily;
-    ctx.fillStyle = OVERVIEW_HEADER_TEXT_COLOR;
-    ctx.strokeStyle = OVERVIEW_TIMELINE_STROKES;
+    ctx.fillStyle = this.headerTextColor;
+    ctx.strokeStyle = this.headerTimelineStrokeColor;
     ctx.beginPath();
 
     for (let x = 0; x < availableWidth; x += tickInterval) {
       let lineLeft = x;
       let textLeft = lineLeft + textPaddingLeft;
       let time = Math.round(x / dataScale);
       let label = L10N.getFormatStr("timeline.tick", time);
       ctx.fillText(label, textLeft, headerHeight / 2 + textPaddingTop);
@@ -227,12 +222,28 @@ MarkersOverview.prototype = Heritage.ext
     while (true) {
       let scaledStep = dataScale * timingStep;
       if (scaledStep < spacingMin) {
         timingStep <<= 1;
         continue;
       }
       return scaledStep;
     }
+  },
+
+  /**
+   * Sets the theme via `theme` to either "light" or "dark",
+   * and updates the internal styling to match. Requires a redraw
+   * to see the effects.
+   */
+  setTheme: function (theme) {
+    theme = theme || "light";
+    this.backgroundColor = getColor("body-background", theme);
+    this.selectionBackgroundColor = setAlpha(getColor("selection-background", theme), 0.25);
+    this.selectionStripesColor = setAlpha("#fff", 0.1);
+    this.headerBackgroundColor = getColor("body-background", theme);
+    this.headerTextColor = getColor("body-color", theme);
+    this.headerTimelineStrokeColor = setAlpha(getColor("body-color-alt", theme), 0.1);
+    this.alternatingBackgroundColor = setAlpha(getColor("body-color", theme), 0.05);
   }
 });
 
 exports.MarkersOverview = MarkersOverview;
--- a/browser/devtools/timeline/widgets/memory-overview.js
+++ b/browser/devtools/timeline/widgets/memory-overview.js
@@ -8,67 +8,56 @@
  * of all the memory measurements taken while streaming the timeline data.
  */
 
 const {Cc, Ci, Cu, Cr} = require("chrome");
 
 Cu.import("resource:///modules/devtools/Graphs.jsm");
 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
 
+const { colorUtils: { setAlpha }} = require("devtools/css-color");
+const { getColor } = require("devtools/shared/theme");
+
 loader.lazyRequireGetter(this, "L10N",
   "devtools/timeline/global", true);
 
 const HTML_NS = "http://www.w3.org/1999/xhtml";
 
 const OVERVIEW_HEIGHT = 30; // px
-
-const OVERVIEW_BACKGROUND_COLOR = "#fff";
-const OVERVIEW_BACKGROUND_GRADIENT_START = "rgba(0,136,204,0.1)";
-const OVERVIEW_BACKGROUND_GRADIENT_END = "rgba(0,136,204,0.0)";
 const OVERVIEW_STROKE_WIDTH = 1; // px
-const OVERVIEW_STROKE_COLOR = "rgba(0,136,204,1)";
-const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
-const OVERVIEW_SELECTION_LINE_COLOR = "#555";
 const OVERVIEW_MAXIMUM_LINE_COLOR = "rgba(0,136,204,0.4)";
 const OVERVIEW_AVERAGE_LINE_COLOR = "rgba(0,136,204,0.7)";
 const OVERVIEW_MINIMUM_LINE_COLOR = "rgba(0,136,204,0.9)";
-
-const OVERVIEW_SELECTION_BACKGROUND_COLOR = "rgba(76,158,217,0.25)";
-const OVERVIEW_SELECTION_STRIPES_COLOR = "rgba(255,255,255,0.1)";
+const OVERVIEW_CLIPHEAD_LINE_COLOR = "#666";
+const OVERVIEW_SELECTION_LINE_COLOR = "#555";
 
 /**
  * An overview for the memory data.
  *
  * @param nsIDOMNode parent
  *        The parent node holding the overview.
  */
 function MemoryOverview(parent) {
-  LineGraphWidget.call(this, parent, L10N.getStr("graphs.memory"));
-
+  LineGraphWidget.call(this, parent, { metric: L10N.getStr("graphs.memory") });
+  this.setTheme();
   this.once("ready", () => {
     // Populate this overview with some dummy initial data.
     this.setData({ interval: { startTime: 0, endTime: 1000 }, memory: [] });
   });
 }
 
 MemoryOverview.prototype = Heritage.extend(LineGraphWidget.prototype, {
   dampenValuesFactor: 0.95,
   fixedHeight: OVERVIEW_HEIGHT,
-  backgroundColor: OVERVIEW_BACKGROUND_COLOR,
-  backgroundGradientStart: OVERVIEW_BACKGROUND_GRADIENT_START,
-  backgroundGradientEnd: OVERVIEW_BACKGROUND_GRADIENT_END,
-  strokeColor: OVERVIEW_STROKE_COLOR,
   strokeWidth: OVERVIEW_STROKE_WIDTH,
   maximumLineColor: OVERVIEW_MAXIMUM_LINE_COLOR,
   averageLineColor: OVERVIEW_AVERAGE_LINE_COLOR,
   minimumLineColor: OVERVIEW_MINIMUM_LINE_COLOR,
   clipheadLineColor: OVERVIEW_CLIPHEAD_LINE_COLOR,
   selectionLineColor: OVERVIEW_SELECTION_LINE_COLOR,
-  selectionBackgroundColor: OVERVIEW_SELECTION_BACKGROUND_COLOR,
-  selectionStripesColor: OVERVIEW_SELECTION_STRIPES_COLOR,
   withTooltipArrows: false,
   withFixedTooltipPositions: true,
 
   /**
    * Disables selection and empties this graph.
    */
   clearView: function() {
     this.selectionEnabled = false;
@@ -77,12 +66,27 @@ MemoryOverview.prototype = Heritage.exte
   },
 
   /**
    * Sets the data source for this graph.
    */
   setData: function({ interval, memory }) {
     this.dataOffsetX = interval.startTime;
     LineGraphWidget.prototype.setData.call(this, memory);
+  },
+
+  /**
+   * Sets the theme via `theme` to either "light" or "dark",
+   * and updates the internal styling to match. Requires a redraw
+   * to see the effects.
+   */
+  setTheme: function (theme) {
+    theme = theme || "light";
+    this.backgroundColor = getColor("body-background", theme);
+    this.backgroundGradientStart = setAlpha(getColor("highlight-blue", theme), 0.1);
+    this.backgroundGradientEnd = setAlpha(getColor("highlight-blue", theme), 0);
+    this.strokeColor = getColor("highlight-blue", theme);
+    this.selectionBackgroundColor = setAlpha(getColor("selection-background", theme), 0.25);
+    this.selectionStripesColor = "rgba(255, 255, 255, 0.1)";
   }
 });
 
 exports.MemoryOverview = MemoryOverview;
--- a/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-param-flags.js
+++ b/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-param-flags.js
@@ -4,25 +4,26 @@
 /**
  * Test AudioNode#getParamFlags()
  */
 
 add_task(function*() {
   let { target, front } = yield initBackend(SIMPLE_NODES_URL);
   let [_, nodes] = yield Promise.all([
     front.setup({ reload: true }),
-    getN(front, "create-node", 14)
+    getN(front, "create-node", 15)
   ]);
 
   let allNodeParams = yield Promise.all(nodes.map(node => node.getParams()));
   let nodeTypes = [
     "AudioDestinationNode",
     "AudioBufferSourceNode", "ScriptProcessorNode", "AnalyserNode", "GainNode",
     "DelayNode", "BiquadFilterNode", "WaveShaperNode", "PannerNode", "ConvolverNode",
-    "ChannelSplitterNode", "ChannelMergerNode", "DynamicsCompressorNode", "OscillatorNode"
+    "ChannelSplitterNode", "ChannelMergerNode", "DynamicsCompressorNode", "OscillatorNode",
+    "StereoPannerNode"
   ];
 
   // For some reason nodeTypes.forEach and params.forEach fail here so we use
   // simple for loops.
   for (let i = 0; i < nodeTypes.length; i++) {
     let type = nodeTypes[i];
     let params = allNodeParams[i];
 
--- a/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-params-01.js
+++ b/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-params-01.js
@@ -4,25 +4,26 @@
 /**
  * Test AudioNode#getParams()
  */
 
 add_task(function*() {
   let { target, front } = yield initBackend(SIMPLE_NODES_URL);
   let [_, nodes] = yield Promise.all([
     front.setup({ reload: true }),
-    getN(front, "create-node", 14)
+    getN(front, "create-node", 15)
   ]);
 
   let allNodeParams = yield Promise.all(nodes.map(node => node.getParams()));
   let nodeTypes = [
     "AudioDestinationNode",
     "AudioBufferSourceNode", "ScriptProcessorNode", "AnalyserNode", "GainNode",
     "DelayNode", "BiquadFilterNode", "WaveShaperNode", "PannerNode", "ConvolverNode",
-    "ChannelSplitterNode", "ChannelMergerNode", "DynamicsCompressorNode", "OscillatorNode"
+    "ChannelSplitterNode", "ChannelMergerNode", "DynamicsCompressorNode", "OscillatorNode",
+    "StereoPannerNode"
   ];
 
   nodeTypes.forEach((type, i) => {
     let params = allNodeParams[i];
     params.forEach(({param, value, flags}) => {
       ok(param in NODE_DEFAULT_VALUES[type], "expected parameter for " + type);
 
       ok(typeof flags === "object", type + " has a flags object");
--- a/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-params-02.js
+++ b/browser/devtools/webaudioeditor/test/browser_audionode-actor-get-params-02.js
@@ -5,25 +5,25 @@
  * Tests that default properties are returned with the correct type
  * from the AudioNode actors.
  */
 
 add_task(function*() {
   let { target, front } = yield initBackend(SIMPLE_NODES_URL);
   let [_, nodes] = yield Promise.all([
     front.setup({ reload: true }),
-    getN(front, "create-node", 14)
+    getN(front, "create-node", 15)
   ]);
 
   let allParams = yield Promise.all(nodes.map(node => node.getParams()));
   let types = [
     "AudioDestinationNode", "AudioBufferSourceNode", "ScriptProcessorNode",
     "AnalyserNode", "GainNode", "DelayNode", "BiquadFilterNode", "WaveShaperNode",
     "PannerNode", "ConvolverNode", "ChannelSplitterNode", "ChannelMergerNode",
-    "DynamicsCompressorNode", "OscillatorNode"
+    "DynamicsCompressorNode", "OscillatorNode", "StereoPannerNode"
   ];
 
   allParams.forEach((params, i) => {
     compare(params, NODE_DEFAULT_VALUES[types[i]], types[i]);
   });
 
   yield removeTab(target.tab);
 });
--- a/browser/devtools/webaudioeditor/test/browser_wa_navigate.js
+++ b/browser/devtools/webaudioeditor/test/browser_wa_navigate.js
@@ -20,25 +20,25 @@ add_task(function*() {
 
   var { nodes, edges } = countGraphObjects(panelWin);
   ise(nodes, 3, "should only be 3 nodes.");
   ise(edges, 2, "should only be 2 edges.");
 
   navigate(target, SIMPLE_NODES_URL);
 
   var [actors] = yield Promise.all([
-    getN(gFront, "create-node", 14),
-    waitForGraphRendered(panelWin, 14, 0)
+    getN(gFront, "create-node", 15),
+    waitForGraphRendered(panelWin, 15, 0)
   ]);
 
   is($("#reload-notice").hidden, true,
     "The 'reload this page' notice should be hidden after context found after navigation.");
   is($("#waiting-notice").hidden, true,
     "The 'waiting for an audio context' notice should be hidden after context found after navigation.");
   is($("#content").hidden, false,
     "The tool's content should reappear without closing and reopening the toolbox.");
 
   var { nodes, edges } = countGraphObjects(panelWin);
-  ise(nodes, 14, "after navigation, should have 14 nodes");
+  ise(nodes, 15, "after navigation, should have 15 nodes");
   ise(edges, 0, "after navigation, should have 0 edges.");
 
   yield teardown(target);
 });
--- a/browser/devtools/webaudioeditor/test/browser_wa_properties-view-params.js
+++ b/browser/devtools/webaudioeditor/test/browser_wa_properties-view-params.js
@@ -12,18 +12,18 @@ add_task(function*() {
   let { gFront, $, $$, EVENTS, InspectorView } = panelWin;
   let gVars = InspectorView._propsView;
 
   let started = once(gFront, "start-context");
 
   reload(target);
 
   let [actors] = yield Promise.all([
-    getN(gFront, "create-node", 14),
-    waitForGraphRendered(panelWin, 14, 0)
+    getN(gFront, "create-node", 15),
+    waitForGraphRendered(panelWin, 15, 0)
   ]);
   let nodeIds = actors.map(actor => actor.actorID);
   let types = [
     "AudioDestinationNode", "AudioBufferSourceNode", "ScriptProcessorNode",
     "AnalyserNode", "GainNode", "DelayNode", "BiquadFilterNode", "WaveShaperNode",
     "PannerNode", "ConvolverNode", "ChannelSplitterNode", "ChannelMergerNode",
     "DynamicsCompressorNode", "OscillatorNode"
   ];
--- a/browser/devtools/webaudioeditor/test/doc_simple-node-creation.html
+++ b/browser/devtools/webaudioeditor/test/doc_simple-node-creation.html
@@ -13,16 +13,16 @@
     <script type="text/javascript;version=1.8">
       "use strict";
 
       let ctx = new AudioContext();
       let NODE_CREATION_METHODS = [
           "createBufferSource", "createScriptProcessor", "createAnalyser",
           "createGain", "createDelay", "createBiquadFilter", "createWaveShaper",
           "createPanner", "createConvolver", "createChannelSplitter", "createChannelMerger",
-          "createDynamicsCompressor", "createOscillator"
+          "createDynamicsCompressor", "createOscillator", "createStereoPanner"
       ];
       let nodes = NODE_CREATION_METHODS.map(method => ctx[method]());
 
     </script>
   </body>
 
 </html>
--- a/browser/devtools/webaudioeditor/test/head.js
+++ b/browser/devtools/webaudioeditor/test/head.js
@@ -492,10 +492,13 @@ const NODE_DEFAULT_VALUES = {
     "reduction": 0,
     "attack": 0.003000000026077032,
     "release": 0.25
   },
   "OscillatorNode": {
     "type": "sine",
     "frequency": 440,
     "detune": 0
+  },
+  "StereoPannerNode": {
+    "pan": 0
   }
 };
--- a/browser/locales/en-US/chrome/browser/accounts.properties
+++ b/browser/locales/en-US/chrome/browser/accounts.properties
@@ -5,27 +5,40 @@
 # LOCALIZATION NOTE (needUserShort)
 # %S = Firefox Accounts brand name from syncBrand.dtd
 needUserShort = %S required for sync
 needUserLong = We've rebuilt Sync to make it easier for everyone. Please upgrade to a Firefox Account to continue syncing.
 
 upgradeToFxA.label = Upgrade
 upgradeToFxA.accessKey = U
 
+# LOCALIZATION NOTE (signInAfterUpgradeOnOtherDevice.description)
+# %S = Email address of user's Firefox Account
+signInAfterUpgradeOnOtherDevice.description = Sync was upgraded on another device by %S. Resume syncing?
+signInAfterUpgradeOnOtherDevice.label = Sign In
+signInAfterUpgradeOnOtherDevice.accessKey = S
+
 # LOCALIZATION NOTE (needVerifiedUserShort, needVerifiedUserLong)
 # %S = Email address of user's Firefox Account
 needVerifiedUserShort = %S not verified
 needVerifiedUserLong = Please click the verification link in the email sent to %S
 
 resendVerificationEmail.label = Resend
 resendVerificationEmail.accessKey = R
 
 forgetMigration.label = Forget
 forgetMigration.accessKey = F
 
+unlinkMigration.label = Unlink Sync
+unlinkMigration.accessKey = L
+
+unlinkVerificationTitle = Unlink old version of Sync?
+unlinkVerificationDescription = If you no longer want to be reminded about upgrading Sync, you can unlink your old Sync account to remove it.
+unlinkVerificationConfirm = Unlink
+
 # These strings are used in a dialog we display after the user requests we resend
 # a verification email.
 verificationSentTitle = Verification Sent
 # LOCALIZATION NOTE (verificationSentHeading) - %S = Email address of user's Firefox Account
 verificationSentHeading = A verification link has been sent to %S
 verificationSentDescription = Please check your email and click the link to begin syncing.
 
 verificationNotSentTitle = Unable to Send Verification
--- a/browser/locales/en-US/chrome/browser/devtools/projecteditor.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/projecteditor.properties
@@ -41,16 +41,21 @@ projecteditor.deleteFolderPromptMessage=
 # to make sure if a file should be removed.
 projecteditor.deleteFilePromptMessage=Are you sure you want to delete this file?
 
 # LOCALIZATION NOTE (projecteditor.newLabel):
 # This string is displayed as a menu item for adding a new file to
 # the directory.
 projecteditor.newLabel=New…
 
+# LOCALIZATION NOTE (projecteditor.renameLabel):
+# This string is displayed as a menu item for renaming a file in
+# the directory.
+projecteditor.renameLabel=Rename
+
 # LOCALIZATION NOTE (projecteditor.saveLabel):
 # This string is displayed as a menu item for saving the current file.
 projecteditor.saveLabel=Save
 
 # LOCALIZATION NOTE (projecteditor.saveAsLabel):
 # This string is displayed as a menu item for saving the current file
 # with a new name.
 projecteditor.saveAsLabel=Save As…
--- a/browser/locales/en-US/chrome/browser/devtools/timeline.properties
+++ b/browser/locales/en-US/chrome/browser/devtools/timeline.properties
@@ -30,20 +30,21 @@ timeline.tooltip=Performance Timeline
 timeline.tick=%S ms
 
 # LOCALIZATION NOTE (timeline.records):
 # This string is displayed in the timeline waterfall, as a title for the menu.
 timeline.records=RECORDS
 
 # LOCALIZATION NOTE (timeline.label.*):
 # These strings are displayed in the timeline waterfall, identifying markers.
-timeline.label.styles=Styles
-timeline.label.reflow=Reflow
+# We want to use the same wording as Google Chrome
+timeline.label.styles2=Recalculate Style
+timeline.label.reflow2=Layout
 timeline.label.paint=Paint
-timeline.label.javascript=Javascript
+timeline.label.javascript2=Function Call
 timeline.label.domevent=DOM Event
 timeline.label.consoleTime=Console
 
 # LOCALIZATION NOTE (graphs.memory):
 # This string is displayed in the memory graph of the Performance tool,
 # as the unit used to memory consumption. This label should be kept
 # AS SHORT AS POSSIBLE so it doesn't obstruct important parts of the graph.
 graphs.memory=MB
--- a/browser/locales/en-US/chrome/browser/preferences/sync.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/sync.dtd
@@ -73,11 +73,8 @@ both, to better adapt this sentence to t
 <!ENTITY verify.label                "Verify Email">
 <!ENTITY forget.label                "Forget this Email">
 
 <!ENTITY welcome.description "Access your tabs, bookmarks, passwords and more wherever you use &brandShortName;.">
 <!ENTITY welcome.signIn.label "Sign In">
 <!ENTITY welcome.createAccount.label "Create Account">
 
 <!ENTITY welcome.useOldSync.label "Using an older version of Sync?">
-
-<!-- Sync Migration -->
-<!ENTITY migrate.upgradeNeeded      "The sync account system is being discontinued. A new Firefox Account is required to sync.">
--- a/browser/modules/BrowserUITelemetry.jsm
+++ b/browser/modules/BrowserUITelemetry.jsm
@@ -280,19 +280,21 @@ this.BrowserUITelemetry = {
     // our measurements because at that point all browser windows have
     // probably been closed, since the vast majority of saved-session
     // pings are gathered during shutdown.
     let win = RecentWindow.getMostRecentBrowserWindow({
       private: false,
       allowPopups: false,
     });
 
-    // If there are no such windows, we're out of luck. :(
-    this._firstWindowMeasurements = win ? this._getWindowMeasurements(win)
-                                        : {};
+    Services.search.init(rv => {
+      // If there are no such windows, we're out of luck. :(
+      this._firstWindowMeasurements = win ? this._getWindowMeasurements(win, rv)
+                                          : {};
+    });
   },
 
   _registerWindow: function(aWindow) {
     aWindow.addEventListener("unload", this);
     let document = aWindow.document;
 
     for (let areaID of CustomizableUI.areas) {
       let areaNode = document.getElementById(areaID);
@@ -459,17 +461,17 @@ this.BrowserUITelemetry = {
     // If not, we need to check if one of the ancestors of the clicked
     // item is in our list of built-in items to check.
     let candidate = getIDBasedOnFirstIDedAncestor(item);
     if (ALL_BUILTIN_ITEMS.indexOf(candidate) != -1) {
       this._countMouseUpEvent("click-builtin-item", candidate, aEvent.button);
     }
   },
 
-  _getWindowMeasurements: function(aWindow) {
+  _getWindowMeasurements: function(aWindow, searchResult) {
     let document = aWindow.document;
     let result = {};
 
     // Determine if the window is in the maximized, normal or
     // fullscreen state.
     result.sizemode = document.documentElement.getAttribute("sizemode");
 
     // Determine if the Bookmarks bar is currently visible
@@ -548,16 +550,20 @@ this.BrowserUITelemetry = {
         let visibleTabsNum = someWin.gBrowser.visibleTabs.length;
         visibleTabs.push(visibleTabsNum);
         hiddenTabs.push(someWin.gBrowser.tabs.length - visibleTabsNum);
       }
     }
     result.visibleTabs = visibleTabs;
     result.hiddenTabs = hiddenTabs;
 
+    if (Components.isSuccessCode(searchResult)) {
+      result.currentSearchEngine = Services.search.currentEngine;
+    }
+
     return result;
   },
 
   getToolbarMeasures: function() {
     let result = this._firstWindowMeasurements || {};
     result.countableEvents = this._countableEvents;
     result.durations = this._durations;
     return result;
@@ -572,16 +578,24 @@ this.BrowserUITelemetry = {
     if ((/^[a-zA-Z]+:[^\/\\]/).test(query)) {
       this._countEvent(["search", "urlbar-keyword"]);
     }
     if (selection) {
       this._countEvent(["search", "selection", source, selection.index, selection.kind]);
     }
   },
 
+  countOneoffSearchEvent: function(id, type, where) {
+    this._countEvent(["search-oneoff", id, type, where]);
+  },
+
+  countSearchSettingsEvent: function(source) {
+    this._countEvent(["click-builtin-item", source, "search-settings"]);
+  },
+
   _logAwesomeBarSearchResult: function (url) {
     let spec = Services.search.parseSubmissionURL(url);
     if (spec.engine) {
       let matchedEngine = "default";
       if (spec.engine.name !== Services.search.currentEngine.name) {
         matchedEngine = "other";
       }
       this.countSearchEvent("autocomplete-" + matchedEngine);
--- a/browser/themes/shared/customizableui/panelUIOverlay.inc.css
+++ b/browser/themes/shared/customizableui/panelUIOverlay.inc.css
@@ -642,40 +642,42 @@ toolbarpaletteitem[place="palette"] > to
   box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
 }
 
 #PanelUI-fxa-status:not([disabled]):hover,
 #PanelUI-fxa-status:not([disabled]):hover:active {
   outline: none;
 }
 
+#PanelUI-update-status {
+  color: black;
+}
+
 #PanelUI-update-status[update-status="succeeded"] {
-  background-color: hsla(96, 65%, 75%, 0.1);
+  background-color: hsla(96, 65%, 75%, 0.5);
 }
 
 #PanelUI-update-status[update-status="succeeded"]:not([disabled]):hover {
-  background-color: hsla(96, 65%, 75%, 0.4);
+  background-color: hsla(96, 65%, 75%, 0.8);
 }
 
 #PanelUI-update-status[update-status="succeeded"]:not([disabled]):hover:active {
-  background-color: hsla(96, 65%, 75%, 0.6);
-  box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
+  background-color: hsl(96, 65%, 75%);
 }
 
 #PanelUI-update-status[update-status="failed"] {
-  background-color: hsla(359, 69%, 84%, 0.1);
+  background-color: hsla(359, 69%, 84%, 0.5);
 }
 
 #PanelUI-update-status[update-status="failed"]:not([disabled]):hover {
-  background-color: hsla(359, 69%, 84%, 0.4);
+  background-color: hsla(359, 69%, 84%, 0.8);
 }
 
 #PanelUI-update-status[update-status="failed"]:not([disabled]):hover:active {
-  background-color: hsla(359, 69%, 84%, 0.6);
-  box-shadow: 0 1px 0 hsla(210,4%,10%,.05) inset;
+  background-color: hsl(359, 69%, 84%);
 }
 
 #PanelUI-quit:not([disabled]):hover {
   background-color: #d94141;
   outline-color: #c23a3a;
 }
 
 #PanelUI-quit:not([disabled]):hover:active {
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -286,16 +286,21 @@ description > html|a {
 
 /**
  * End Dialog
  */
 
 /**
  * Sync migration
  */
+#sync-migrate-upgrade-description {
+  /* description elts need a min-width to wrap correctly - bug 630864? */
+  min-width: 100px
+}
+
 #sync-migration {
   border: 1px solid rgba(0, 0, 0, 0.32);
   background-color: InfoBackground;
   color: InfoText;
   text-shadow: none;
   margin: 5px 0 0 0;
   animation: fadein 3000ms;
 }
--- a/build/autoconf/android.m4
+++ b/build/autoconf/android.m4
@@ -348,16 +348,23 @@ case "$target" in
         if test -d "$tools_directory" -a -f "$tools_directory/aapt"; then
             android_build_tools="$tools_directory"
             break
         fi
     done
     if test -z "$android_build_tools" ; then
         android_build_tools="$android_platform_tools" # SDK Tools < r22
     fi
+    all_android_build_tools=""
+    for suffix in `ls "$android_sdk_root/build-tools" | sed -e "s,android-,999.," | sort -t. -k 1,1nr -k 2,2nr -k 3,3nr -k 4,4nr -k 5,5nr`; do
+        tools_directory=`echo "$android_sdk_root/build-tools/$suffix" | sed -e "s,999.,android-,"`
+        if test -d "$tools_directory" -a -f "$tools_directory/aapt"; then
+            all_android_build_tools="$all_android_build_tools:$tools_directory"
+        fi
+    done
 
     if test -d "$android_build_tools" -a -f "$android_build_tools/aapt"; then
         AC_MSG_RESULT([$android_build_tools])
     else
         AC_MSG_ERROR([not found. Please check your SDK for the subdirectory of build-tools. With the current configuration, it should be in $android_sdk_root/build_tools])
     fi
 
     ANDROID_SDK="${android_sdk}"
@@ -385,17 +392,17 @@ case "$target" in
     AC_SUBST(ANDROID_COMPAT_LIB)
     if ! test -e $ANDROID_COMPAT_LIB ; then
         AC_MSG_ERROR([You must download the Android v4 support library when targeting Android.  Run the Android SDK tool and install Android Support Library under Extras.  See https://developer.android.com/tools/extras/support-library.html for more info. (looked for $ANDROID_COMPAT_LIB)])
     fi
     AC_MSG_RESULT([$ANDROID_COMPAT_LIB])
 
     dnl Google has a history of moving the Android tools around.  We don't
     dnl care where they are, so let's try to find them anywhere we can.
-    ALL_ANDROID_TOOLS_PATHS="$ANDROID_TOOLS:$ANDROID_BUILD_TOOLS:$ANDROID_PLATFORM_TOOLS"
+    ALL_ANDROID_TOOLS_PATHS="$ANDROID_TOOLS$all_android_build_tools:$ANDROID_PLATFORM_TOOLS"
     MOZ_PATH_PROG(ZIPALIGN, zipalign, :, [$ALL_ANDROID_TOOLS_PATHS])
     MOZ_PATH_PROG(DX, dx, :, [$ALL_ANDROID_TOOLS_PATHS])
     MOZ_PATH_PROG(AAPT, aapt, :, [$ALL_ANDROID_TOOLS_PATHS])
     MOZ_PATH_PROG(AIDL, aidl, :, [$ALL_ANDROID_TOOLS_PATHS])
     MOZ_PATH_PROG(ADB, adb, :, [$ALL_ANDROID_TOOLS_PATHS])
 
     if test -z "$ZIPALIGN" -o "$ZIPALIGN" = ":"; then
       AC_MSG_ERROR([The program zipalign was not found.  Use --with-android-sdk={android-sdk-dir}.])
--- a/docshell/base/TimelineMarker.h
+++ b/docshell/base/TimelineMarker.h
@@ -98,17 +98,16 @@ protected:
 
 private:
 
   const char* mName;
   TracingMetadata mMetaData;
   DOMHighResTimeStamp mTime;
   nsString mCause;
 
-  // While normally it is not a good idea to make a persistent
-  // root, in this case changing nsDocShell to participate in
-  // cycle collection was deemed too invasive, the stack trace
-  // can't actually cause a cycle, and the markers are only held
+  // While normally it is not a good idea to make a persistent root,
+  // in this case changing nsDocShell to participate in cycle
+  // collection was deemed too invasive, and the markers are only held
   // here temporarily to boot.
   mozilla::Maybe<JS::PersistentRooted<JSObject*>> mStackTrace;
 };
 
 #endif /* TimelineMarker_h__ */
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -10,14 +10,15 @@ skip-if = buildapp == 'mulet'
 skip-if = os == "win" || (os == "mac" && os_version == "10.8") # disabled until bug 1112480 lands
 [css-animations/test_animation-player-playstate.html]
 [css-animations/test_animation-player-ready.html]
 [css-animations/test_animation-target.html]
 [css-animations/test_element-get-animation-players.html]
 skip-if = buildapp == 'mulet'
 [css-transitions/test_animation-effect-name.html]
 [css-transitions/test_animation-pausing.html]
+skip-if = os == "win" # bug 1117955, to be restored in bug 1112480
 [css-transitions/test_animation-player-ready.html]
 [css-transitions/test_animation-target.html]
 [css-transitions/test_element-get-animation-players.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_deferred_start.html]
 skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && toolkit != 'gonk') # bug 1113425
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1680,22 +1680,22 @@ nsFocusManager::Blur(nsPIDOMWindow* aWin
     SendFocusOrBlurEvent(NS_BLUR_CONTENT, presShell,
                          content->GetComposedDoc(), content, 1, false);
   }
 
   // if we are leaving the document or the window was lowered, make the caret
   // invisible.
   if (aIsLeavingDocument || !mActiveWindow) {
     SetCaretVisible(presShell, false, nullptr);
-    nsRefPtr<SelectionCarets> selectionCarets = presShell->GetSelectionCarets();
-    if (selectionCarets) {
-      selectionCarets->NotifyBlur();
-    }
   }
 
+  nsRefPtr<SelectionCarets> selectionCarets = presShell->GetSelectionCarets();
+  if (selectionCarets) {
+    selectionCarets->NotifyBlur(aIsLeavingDocument || !mActiveWindow);
+  }
 
   // at this point, it is expected that this window will be still be
   // focused, but the focused content will be null, as it was cleared before
   // the event. If this isn't the case, then something else was focused during
   // the blur event above and we should just return. However, if
   // aIsLeavingDocument is set, a new document is desired, so make sure to
   // blur the document and window.
   if (mFocusedWindow != window ||
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -76,19 +76,19 @@ public:
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual EventStates IntrinsicState() const MOZ_OVERRIDE;
 
-  virtual void OnDNSPrefetchDeferred();
-  virtual void OnDNSPrefetchRequested();
-  virtual bool HasDeferredDNSPrefetchRequest();
+  virtual void OnDNSPrefetchDeferred() MOZ_OVERRIDE;
+  virtual void OnDNSPrefetchRequested() MOZ_OVERRIDE;
+  virtual bool HasDeferredDNSPrefetchRequest() MOZ_OVERRIDE;
 
   // WebIDL API
   void GetHref(nsAString& aValue, ErrorResult& rv)
   {
     GetHTMLURIAttr(nsGkAtoms::href, aValue);
   }
   void SetHref(const nsAString& aValue, mozilla::ErrorResult& rv)
   {
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -35,24 +35,24 @@ public:
   virtual int32_t TabIndexDefault() MOZ_OVERRIDE;
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLButtonElement, button)
 
   // nsIDOMHTMLButtonElement
   NS_DECL_NSIDOMHTMLBUTTONELEMENT
 
   // overriden nsIFormControl methods
-  NS_IMETHOD_(uint32_t) GetType() const { return mType; }
+  NS_IMETHOD_(uint32_t) GetType() const MOZ_OVERRIDE { return mType; }
   NS_IMETHOD Reset() MOZ_OVERRIDE;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) MOZ_OVERRIDE;
   NS_IMETHOD SaveState() MOZ_OVERRIDE;
   bool RestoreState(nsPresState* aState) MOZ_OVERRIDE;
   virtual bool IsDisabledForEvents(uint32_t aMessage) MOZ_OVERRIDE;
 
-  virtual void FieldSetDisabledChanged(bool aNotify) MOZ_OVERRIDE; 
+  virtual void FieldSetDisabledChanged(bool aNotify) MOZ_OVERRIDE;
 
   // nsIDOMEventTarget
   virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) MOZ_OVERRIDE;
 
   // nsINode
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
--- a/dom/html/HTMLContentElement.cpp
+++ b/dom/html/HTMLContentElement.cpp
@@ -344,26 +344,20 @@ DistributedContentList::Item(uint32_t aI
   nsIContent* item = Item(aIndex);
   if (!item) {
     return NS_ERROR_FAILURE;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
-uint32_t
-DistributedContentList::Length() const
-{
-  return mDistributedNodes.Length();
-}
-
 NS_IMETHODIMP
 DistributedContentList::GetLength(uint32_t* aLength)
 {
-  *aLength = Length();
+  *aLength = mDistributedNodes.Length();
   return NS_OK;
 }
 
 int32_t
 DistributedContentList::IndexOf(nsIContent* aContent)
 {
   return mDistributedNodes.IndexOf(aContent);
 }
--- a/dom/html/HTMLContentElement.h
+++ b/dom/html/HTMLContentElement.h
@@ -24,45 +24,45 @@ public:
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLContentElement, content)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLContentElement,
                                            nsGenericHTMLElement)
 
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const;
+  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
-  virtual nsIDOMNode* AsDOMNode() { return this; }
+  virtual nsIDOMNode* AsDOMNode() MOZ_OVERRIDE { return this; }
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
-                              bool aCompileEventHandlers);
+                              bool aCompileEventHandlers) MOZ_OVERRIDE;
 
   virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true);
+                              bool aNullParent = true) MOZ_OVERRIDE;
 
   /**
    * Returns whether if the selector of this insertion point
    * matches the provided content.
    */
   bool Match(nsIContent* aContent);
   bool IsInsertionPoint() const { return mIsInsertionPoint; }
   nsCOMArray<nsIContent>& MatchedNodes() { return mMatchedNodes; }
   void AppendMatchedNode(nsIContent* aContent);
   void RemoveMatchedNode(nsIContent* aContent);
   void InsertMatchedNode(uint32_t aIndex, nsIContent* aContent);
   void ClearMatchedNodes();
 
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                            nsIAtom* aPrefix, const nsAString& aValue,
-                           bool aNotify);
+                           bool aNotify) MOZ_OVERRIDE;
 
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                             bool aNotify);
+                             bool aNotify) MOZ_OVERRIDE;
 
   // WebIDL methods.
   already_AddRefed<DistributedContentList> GetDistributedNodes();
   void GetSelect(nsAString& aSelect)
   {
     Element::GetAttr(kNameSpaceID_None, nsGkAtoms::select, aSelect);
   }
   void SetSelect(const nsAString& aSelect)
@@ -102,20 +102,19 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(DistributedContentList)
 
   // nsIDOMNodeList
   NS_DECL_NSIDOMNODELIST
 
   // nsINodeList
-  virtual nsIContent* Item(uint32_t aIndex);
-  virtual int32_t IndexOf(nsIContent* aContent);
-  virtual nsINode* GetParentObject() { return mParent; }
-  virtual uint32_t Length() const;
+  virtual nsIContent* Item(uint32_t aIndex) MOZ_OVERRIDE;
+  virtual int32_t IndexOf(nsIContent* aContent) MOZ_OVERRIDE;
+  virtual nsINode* GetParentObject() MOZ_OVERRIDE { return mParent; }
   virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 protected:
   virtual ~DistributedContentList();
   nsRefPtr<HTMLContentElement> mParent;
   nsCOMArray<nsIContent> mDistributedNodes;
 };
 
 } // namespace dom
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -88,17 +88,17 @@ public:
   // XPCOM Validity is OK for us
 
   // XPCOM GetValidationMessage is OK for us
 
   // XPCOM CheckValidity is OK for us
 
   // XPCOM SetCustomValidity is OK for us
 
-  virtual EventStates IntrinsicState() const;
+  virtual EventStates IntrinsicState() const MOZ_OVERRIDE;
 
 
   /*
    * This method will update the fieldset's validity.  This method has to be
    * called by fieldset elements whenever their validity state or status regarding
    * constraint validation changes.
    *
    * @note If an element becomes barred from constraint validation, it has to
--- a/dom/html/HTMLFormControlsCollection.h
+++ b/dom/html/HTMLFormControlsCollection.h
@@ -31,17 +31,17 @@ public:
 
   void DropFormReference();
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMHTMLCollection interface
   NS_DECL_NSIDOMHTMLCOLLECTION
 
-  virtual Element* GetElementAt(uint32_t index);
+  virtual Element* GetElementAt(uint32_t index) MOZ_OVERRIDE;
   virtual nsINode* GetParentObject() MOZ_OVERRIDE;
 
   virtual Element*
   GetFirstNamedElement(const nsAString& aName, bool& aFound) MOZ_OVERRIDE;
 
   void
   NamedGetter(const nsAString& aName,
               bool& aFound,
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -53,17 +53,17 @@ public:
 
   // nsIDOMHTMLFormElement
   NS_DECL_NSIDOMHTMLFORMELEMENT
 
   // nsIWebProgressListener
   NS_DECL_NSIWEBPROGRESSLISTENER
 
   // nsIForm
-  NS_IMETHOD_(nsIFormControl*) GetElementAt(int32_t aIndex) const;
+  NS_IMETHOD_(nsIFormControl*) GetElementAt(int32_t aIndex) const MOZ_OVERRIDE;
   NS_IMETHOD_(uint32_t) GetElementCount() const MOZ_OVERRIDE;
   NS_IMETHOD_(int32_t) IndexOfControl(nsIFormControl* aControl) MOZ_OVERRIDE;
   NS_IMETHOD_(nsIFormControl*) GetDefaultSubmitElement() const MOZ_OVERRIDE;
 
   // nsIRadioGroupContainer
   void SetCurrentRadioButton(const nsAString& aName,
                              HTMLInputElement* aRadio) MOZ_OVERRIDE;
   HTMLInputElement* GetCurrentRadioButton(const nsAString& aName) MOZ_OVERRIDE;
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -47,17 +47,17 @@ public:
   virtual bool Draggable() const MOZ_OVERRIDE;
 
   // nsIDOMHTMLImageElement
   NS_DECL_NSIDOMHTMLIMAGEELEMENT
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLImageElement, img)
 
   // override from nsImageLoadingContent
-  CORSMode GetCORSMode();
+  CORSMode GetCORSMode() MOZ_OVERRIDE;
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult) MOZ_OVERRIDE;
   virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
                                               int32_t aModType) const MOZ_OVERRIDE;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -362,17 +362,17 @@ public:
     if (NS_SUCCEEDED(mTopDir->GetDirectoryEntries(getter_AddRefs(entries))) &&
         entries) {
       mDirEnumeratorStack.AppendElement(entries);
       LookupAndCacheNext();
     }
   }
 
   NS_IMETHOD
-  GetNext(nsISupports** aResult)
+  GetNext(nsISupports** aResult) MOZ_OVERRIDE
   {
     MOZ_ASSERT(!NS_IsMainThread(),
                "Walking the directory tree involves I/O, so using this "
                "enumerator can block a thread for a long time!");
 
     if (!mNextFile) {
       return NS_ERROR_FAILURE;
     }
@@ -396,17 +396,17 @@ public:
       fileImpl->SetPath(Substring(path, 0, uint32_t(length)));
     }
     *aResult = domFile.forget().downcast<nsIDOMFile>().take();
     LookupAndCacheNext();
     return NS_OK;
   }
 
   NS_IMETHOD
-  HasMoreElements(bool* aResult)
+  HasMoreElements(bool* aResult) MOZ_OVERRIDE
   {
     *aResult = !!mNextFile;
     return NS_OK;
   }
 
 private:
 
   void
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -172,18 +172,18 @@ public:
                               bool aNullParent = true) MOZ_OVERRIDE;
 
   virtual void DoneCreatingElement() MOZ_OVERRIDE;
 
   virtual EventStates IntrinsicState() const MOZ_OVERRIDE;
 
   // Element
 private:
-  virtual void AddStates(EventStates aStates);
-  virtual void RemoveStates(EventStates aStates);
+  virtual void AddStates(EventStates aStates) MOZ_OVERRIDE;
+  virtual void RemoveStates(EventStates aStates) MOZ_OVERRIDE;
 
 public:
 
   // nsITextControlElement
   NS_IMETHOD SetValueChanged(bool aValueChanged) MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsSingleLineTextControl() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsTextArea() const MOZ_OVERRIDE;
   NS_IMETHOD_(bool) IsPlainTextControl() const MOZ_OVERRIDE;
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -153,17 +153,17 @@ protected:
 
   // nsStyleLinkElement
   virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) MOZ_OVERRIDE;
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsScoped,
                                  bool* aIsAlternate) MOZ_OVERRIDE;
-  virtual CORSMode GetCORSMode() const;
+  virtual CORSMode GetCORSMode() const MOZ_OVERRIDE;
 protected:
   // nsGenericHTMLElement
   virtual void GetItemValueText(nsAString& text) MOZ_OVERRIDE;
   virtual void SetItemValueText(const nsAString& text) MOZ_OVERRIDE;
   nsRefPtr<nsDOMTokenList > mRelList;
 private:
   nsRefPtr<ImportLoader> mImportLoader;
 };
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -532,17 +532,17 @@ public:
                                          ErrorResult& aRv);
 
   MediaWaitingFor WaitingFor() const;
 
   mozilla::dom::EventHandlerNonNull* GetOnencrypted();
   void SetOnencrypted(mozilla::dom::EventHandlerNonNull* listener);
 
   void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
-                         const nsAString& aInitDataType);
+                         const nsAString& aInitDataType) MOZ_OVERRIDE;
 
 
   bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
 
   // Returns the principal of the "top level" document; the origin displayed
   // in the URL bar of the browser window.
   already_AddRefed<nsIPrincipal> GetTopLevelPrincipal();
 
--- a/dom/html/HTMLOptionsCollection.h
+++ b/dom/html/HTMLOptionsCollection.h
@@ -53,17 +53,17 @@ protected:
 public:
 
   // nsIDOMHTMLOptionsCollection interface
   NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
 
   // nsIDOMHTMLCollection interface, all its methods are defined in
   // nsIDOMHTMLOptionsCollection
 
-  virtual Element* GetElementAt(uint32_t aIndex);
+  virtual Element* GetElementAt(uint32_t aIndex) MOZ_OVERRIDE;
   virtual nsINode* GetParentObject() MOZ_OVERRIDE;
 
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(HTMLOptionsCollection,
                                                          nsIHTMLCollection)
 
   // Helpers for HTMLSelectElement
   /**
    * Insert an option
--- a/dom/html/HTMLOutputElement.h
+++ b/dom/html/HTMLOutputElement.h
@@ -23,17 +23,17 @@ public:
 
   explicit HTMLOutputElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                              FromParser aFromParser = NOT_FROM_PARSER);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIFormControl
-  NS_IMETHOD_(uint32_t) GetType() const { return NS_FORM_OUTPUT; }
+  NS_IMETHOD_(uint32_t) GetType() const MOZ_OVERRIDE { return NS_FORM_OUTPUT; }
   NS_IMETHOD Reset() MOZ_OVERRIDE;
   NS_IMETHOD SubmitNamesValues(nsFormSubmission* aFormSubmission) MOZ_OVERRIDE;
 
   virtual bool IsDisabled() const MOZ_OVERRIDE { return false; }
 
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult) const MOZ_OVERRIDE;
 
   bool ParseAttribute(int32_t aNamespaceID, nsIAtom* aAttribute,
--- a/dom/html/HTMLPropertiesCollection.h
+++ b/dom/html/HTMLPropertiesCollection.h
@@ -64,17 +64,17 @@ protected:
   virtual ~HTMLPropertiesCollection();
 
   virtual JSObject* GetWrapperPreserveColorInternal() MOZ_OVERRIDE
   {
     return nsWrapperCache::GetWrapperPreserveColor();
   }
 public:
 
-  virtual Element* GetElementAt(uint32_t aIndex);
+  virtual Element* GetElementAt(uint32_t aIndex) MOZ_OVERRIDE;
 
   void SetDocument(nsIDocument* aDocument);
   nsINode* GetParentObject() MOZ_OVERRIDE;
 
   virtual Element*
   GetFirstNamedElement(const nsAString& aName, bool& aFound) MOZ_OVERRIDE
   {
     // HTMLPropertiesCollection.namedItem and the named getter call the
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -37,17 +37,17 @@ public:
   // nsIDOMHTMLScriptElement
   NS_DECL_NSIDOMHTMLSCRIPTELEMENT
 
   // nsIScriptElement
   virtual void GetScriptType(nsAString& type) MOZ_OVERRIDE;
   virtual void GetScriptText(nsAString& text) MOZ_OVERRIDE;
   virtual void GetScriptCharset(nsAString& charset) MOZ_OVERRIDE;
   virtual void FreezeUriAsyncDefer() MOZ_OVERRIDE;
-  virtual CORSMode GetCORSMode() const;
+  virtual CORSMode GetCORSMode() const MOZ_OVERRIDE;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) MOZ_OVERRIDE;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsIAtom* aAttribute,
                               const nsAString& aValue,
--- a/dom/html/HTMLShadowElement.h
+++ b/dom/html/HTMLShadowElement.h
@@ -28,20 +28,20 @@ public:
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLShadowElement,
                                            nsGenericHTMLElement)
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
-                              bool aCompileEventHandlers);
+                              bool aCompileEventHandlers) MOZ_OVERRIDE;
 
   virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true);
+                              bool aNullParent = true) MOZ_OVERRIDE;
 
   bool IsInsertionPoint() { return mIsInsertionPoint; }
 
   /**
    * Sets the ShadowRoot that will be rendered in place of
    * this shadow insertion point.
    */
   void SetProjectedShadow(ShadowRoot* aProjectedShadow);
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -27,18 +27,18 @@ class TableRowsCollection : public nsIHT
                             public nsWrapperCache
 {
 public:
   explicit TableRowsCollection(HTMLTableElement* aParent);
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_NSIDOMHTMLCOLLECTION
 
-  virtual Element* GetElementAt(uint32_t aIndex);
-  virtual nsINode* GetParentObject()
+  virtual Element* GetElementAt(uint32_t aIndex) MOZ_OVERRIDE;
+  virtual nsINode* GetParentObject() MOZ_OVERRIDE
   {
     return mParent;
   }
 
   virtual Element*
   GetFirstNamedElement(const nsAString& aName, bool& aFound) MOZ_OVERRIDE;
   virtual void GetSupportedNames(unsigned aFlags,
                                  nsTArray<nsString>& aNames) MOZ_OVERRIDE;
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -106,18 +106,18 @@ public:
 
   already_AddRefed<VideoPlaybackQuality> GetVideoPlaybackQuality();
 
 protected:
   virtual ~HTMLVideoElement();
 
   virtual JSObject* WrapNode(JSContext* aCx) MOZ_OVERRIDE;
 
-  virtual void WakeLockCreate();
-  virtual void WakeLockRelease();
+  virtual void WakeLockCreate() MOZ_OVERRIDE;
+  virtual void WakeLockRelease() MOZ_OVERRIDE;
   void UpdateScreenWakeLock();
 
   nsRefPtr<WakeLock> mScreenWakeLock;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     nsRuleData* aData);
 };
--- a/dom/html/ImageDocument.h
+++ b/dom/html/ImageDocument.h
@@ -74,17 +74,17 @@ public:
   {
     ScrollImageTo(aX, aY, true);
   }
   void ToggleImageSize();
 
 protected:
   virtual ~ImageDocument();
 
-  virtual nsresult CreateSyntheticDocument();
+  virtual nsresult CreateSyntheticDocument() MOZ_OVERRIDE;
 
   nsresult CheckOverflowing(bool changeState);
 
   void UpdateTitleAndCharset();
 
   void ScrollImageTo(int32_t aX, int32_t aY, bool restoreImage);
 
   float GetRatio() {
--- a/dom/html/MediaDocument.h
+++ b/dom/html/MediaDocument.h
@@ -30,17 +30,17 @@ public:
                                      nsILoadGroup*       aLoadGroup,
                                      nsISupports*        aContainer,
                                      nsIStreamListener** aDocListener,
                                      bool                aReset = true,
                                      nsIContentSink*     aSink = nullptr) MOZ_OVERRIDE;
 
   virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aGlobalObject) MOZ_OVERRIDE;
 
-  virtual bool WillIgnoreCharsetOverride()
+  virtual bool WillIgnoreCharsetOverride() MOZ_OVERRIDE
   {
     return true;
   }
 
 protected:
   void BecomeInteractive();
 
   virtual nsresult CreateSyntheticDocument();
--- a/dom/html/PluginDocument.cpp
+++ b/dom/html/PluginDocument.cpp
@@ -32,20 +32,20 @@ public:
   NS_DECL_NSIPLUGINDOCUMENT
 
   virtual nsresult StartDocumentLoad(const char*         aCommand,
                                      nsIChannel*         aChannel,
                                      nsILoadGroup*       aLoadGroup,
                                      nsISupports*        aContainer,
                                      nsIStreamListener** aDocListener,
                                      bool                aReset = true,
-                                     nsIContentSink*     aSink = nullptr);
+                                     nsIContentSink*     aSink = nullptr) MOZ_OVERRIDE;
 
-  virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject);
-  virtual bool CanSavePresentation(nsIRequest *aNewRequest);
+  virtual void SetScriptGlobalObject(nsIScriptGlobalObject* aScriptGlobalObject) MOZ_OVERRIDE;
+  virtual bool CanSavePresentation(nsIRequest *aNewRequest) MOZ_OVERRIDE;
 
   const nsCString& GetType() const { return mMimeType; }
   Element*         GetPluginContent() { return mPluginContent; }
 
   void StartLayout() { MediaDocument::StartLayout(); }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(PluginDocument, MediaDocument)
 protected:
--- a/dom/html/UndoManager.cpp
+++ b/dom/html/UndoManager.cpp
@@ -100,18 +100,18 @@ UndoTxn::Merge(nsITransaction* aTransact
 /////////////////////////////////////////////////
 
 /**
  * Transaction to handle an attribute change to a nsIContent.
  */
 class UndoAttrChanged : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UndoAttrChanged)
-  NS_IMETHOD RedoTransaction();
-  NS_IMETHOD UndoTransaction();
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
   nsresult Init();
   UndoAttrChanged(mozilla::dom::Element* aElement, int32_t aNameSpaceID,
                   nsIAtom* aAttribute, int32_t aModType);
 protected:
   ~UndoAttrChanged() {}
 
   nsresult SaveRedoState();
   nsCOMPtr<nsIContent> mElement;
@@ -211,18 +211,18 @@ struct UndoCharacterChangedData {
 };
 
 /**
  * Transaction to handle a text change to a nsIContent.
  */
 class UndoTextChanged : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UndoTextChanged)
-  NS_IMETHOD RedoTransaction();
-  NS_IMETHOD UndoTransaction();
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
   UndoTextChanged(nsIContent* aContent,
                   CharacterDataChangeInfo* aChange);
 protected:
   ~UndoTextChanged() {}
 
   void SaveRedoState();
   nsCOMPtr<nsIContent> mContent;
   UndoCharacterChangedData mChange;
@@ -326,18 +326,18 @@ UndoTextChanged::SaveRedoState()
 
 /**
  * Transaction to handle appending content to a nsIContent.
  */
 class UndoContentAppend : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UndoContentAppend)
   nsresult Init(int32_t aFirstIndex);
-  NS_IMETHOD RedoTransaction();
-  NS_IMETHOD UndoTransaction();
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
   explicit UndoContentAppend(nsIContent* aContent);
 protected:
   ~UndoContentAppend() {}
   nsCOMPtr<nsIContent> mContent;
   nsCOMArray<nsIContent> mChildren;
 };
 
 NS_IMPL_CYCLE_COLLECTION(UndoContentAppend, mContent, mChildren)
@@ -396,18 +396,18 @@ UndoContentAppend::UndoTransaction()
 /////////////////////////////////////////////////
 
 /**
  * Transaction to handle inserting content into a nsIContent.
  */
 class UndoContentInsert : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UndoContentInsert)
-  NS_IMETHOD UndoTransaction();
-  NS_IMETHOD RedoTransaction();
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
   UndoContentInsert(nsIContent* aContent, nsIContent* aChild,
                     int32_t aInsertIndex);
 protected:
   ~UndoContentInsert() {}
   nsCOMPtr<nsIContent> mContent;
   nsCOMPtr<nsIContent> mChild;
   nsCOMPtr<nsIContent> mNextNode;
 };
@@ -484,18 +484,18 @@ UndoContentInsert::UndoTransaction()
 /////////////////////////////////////////////////
 
 /**
  * Transaction to handle removing content from an nsIContent.
  */
 class UndoContentRemove : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(UndoContentRemove)
-  NS_IMETHOD UndoTransaction();
-  NS_IMETHOD RedoTransaction();
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
   nsresult Init(int32_t aInsertIndex);
   UndoContentRemove(nsIContent* aContent, nsIContent* aChild,
                     int32_t aInsertIndex);
 protected:
   ~UndoContentRemove() {}
   nsCOMPtr<nsIContent> mContent;
   nsCOMPtr<nsIContent> mChild;
   nsCOMPtr<nsIContent> mNextNode;
@@ -732,18 +732,18 @@ UndoMutationObserver::ContentRemoved(nsI
 class FunctionCallTxn : public UndoTxn {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(FunctionCallTxn)
 
   // Flags
   static const uint32_t CALL_ON_REDO = 1;
   static const uint32_t CALL_ON_UNDO = 2;
 
-  NS_IMETHOD RedoTransaction();
-  NS_IMETHOD UndoTransaction();
+  NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
+  NS_IMETHOD UndoTransaction() MOZ_OVERRIDE;
   FunctionCallTxn(DOMTransaction* aTransaction, uint32_t aFlags);
 protected:
   ~FunctionCallTxn() {}
   /**
    * Call a function member on the transaction object with the
    * specified function name.
    */
   nsRefPtr<DOMTransaction> mTransaction;
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -172,17 +172,17 @@ class nsGenericHTMLElementTearoff : publ
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   explicit nsGenericHTMLElementTearoff(nsGenericHTMLElement* aElement)
     : mElement(aElement)
   {
   }
 
-  NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
+  NS_IMETHOD GetStyle(nsIDOMCSSStyleDeclaration** aStyle) MOZ_OVERRIDE
   {
     NS_ADDREF(*aStyle = mElement->Style());
     return NS_OK;
   }
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGenericHTMLElementTearoff,
                                            nsIDOMElementCSSInlineStyle)
 
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -67,26 +67,26 @@ public:
 
   // From Element
   nsresult CopyInnerTo(mozilla::dom::Element* aDest);
 
   void GetTitle(nsString& aTitle)
   {
     GetHTMLAttr(nsGkAtoms::title, aTitle);
   }
-  NS_IMETHODIMP SetTitle(const nsAString& aTitle)
+  NS_IMETHODIMP SetTitle(const nsAString& aTitle) MOZ_OVERRIDE
   {
     SetHTMLAttr(nsGkAtoms::title, aTitle);
     return NS_OK;
   }
   void GetLang(nsString& aLang)
   {
     GetHTMLAttr(nsGkAtoms::lang, aLang);
   }
-  NS_IMETHODIMP SetLang(const nsAString& aLang)
+  NS_IMETHODIMP SetLang(const nsAString& aLang) MOZ_OVERRIDE
   {
     SetHTMLAttr(nsGkAtoms::lang, aLang);
     return NS_OK;
   }
   void GetDir(nsString& aDir)
   {
     GetHTMLEnumAttr(nsGkAtoms::dir, aDir);
   }
@@ -294,17 +294,17 @@ public:
 protected:
   virtual ~nsGenericHTMLElement() {}
 
   // These methods are used to implement element-specific behavior of Get/SetItemValue
   // when an element has @itemprop but no @itemscope.
   virtual void GetItemValueText(nsAString& text);
   virtual void SetItemValueText(const nsAString& text);
 public:
-  virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager();
+  virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() MOZ_OVERRIDE;
   virtual bool UndoScope() MOZ_OVERRIDE;
   virtual void SetUndoScope(bool aUndoScope, mozilla::ErrorResult& aError) MOZ_OVERRIDE;
   // Callback for destructor of of dataset to ensure to null out weak pointer.
   nsresult ClearDataset();
 
   /**
    * Get width and height, using given image request if attributes are unset.
    * Pass a reference to the image request, since the method may change the
@@ -1246,17 +1246,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   nsINode* GetScopeChainParent() const MOZ_OVERRIDE;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE;
   virtual void SaveSubtreeState() MOZ_OVERRIDE;
 
   // nsIFormControl
-  virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet();
+  virtual mozilla::dom::HTMLFieldSetElement* GetFieldSet() MOZ_OVERRIDE;
   virtual mozilla::dom::Element* GetFormElement() MOZ_OVERRIDE;
   mozilla::dom::HTMLFormElement* GetForm() const
   {
     return mForm;
   }
   virtual void SetForm(nsIDOMHTMLFormElement* aForm) MOZ_OVERRIDE;
   virtual void ClearForm(bool aRemoveFromForm) MOZ_OVERRIDE;
 
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -129,30 +129,30 @@ public:
   nsresult Init(nsIDocument* aDoc, nsIURI* aURI, nsISupports* aContainer,
                 nsIChannel* aChannel);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLContentSink, nsContentSink)
 
   // nsIContentSink
-  NS_IMETHOD WillParse(void);
-  NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode);
-  NS_IMETHOD DidBuildModel(bool aTerminated);
-  NS_IMETHOD WillInterrupt(void);
-  NS_IMETHOD WillResume(void);
-  NS_IMETHOD SetParser(nsParserBase* aParser);
-  virtual void FlushPendingNotifications(mozFlushType aType);
-  NS_IMETHOD SetDocumentCharset(nsACString& aCharset);
-  virtual nsISupports *GetTarget();
-  virtual bool IsScriptExecuting();
+  NS_IMETHOD WillParse(void) MOZ_OVERRIDE;
+  NS_IMETHOD WillBuildModel(nsDTDMode aDTDMode) MOZ_OVERRIDE;
+  NS_IMETHOD DidBuildModel(bool aTerminated) MOZ_OVERRIDE;
+  NS_IMETHOD WillInterrupt(void) MOZ_OVERRIDE;
+  NS_IMETHOD WillResume(void) MOZ_OVERRIDE;
+  NS_IMETHOD SetParser(nsParserBase* aParser) MOZ_OVERRIDE;
+  virtual void FlushPendingNotifications(mozFlushType aType) MOZ_OVERRIDE;
+  NS_IMETHOD SetDocumentCharset(nsACString& aCharset) MOZ_OVERRIDE;
+  virtual nsISupports *GetTarget() MOZ_OVERRIDE;
+  virtual bool IsScriptExecuting() MOZ_OVERRIDE;
 
   // nsIHTMLContentSink
-  NS_IMETHOD OpenContainer(ElementType aNodeType);
-  NS_IMETHOD CloseContainer(ElementType aTag);
+  NS_IMETHOD OpenContainer(ElementType aNodeType) MOZ_OVERRIDE;
+  NS_IMETHOD CloseContainer(ElementType aTag) MOZ_OVERRIDE;
 
 protected:
   virtual ~HTMLContentSink();
 
   nsCOMPtr<nsIHTMLDocument> mHTMLDocument;
 
   // The maximum length of a text run
   int32_t mMaxTextRun;
@@ -170,27 +170,27 @@ protected:
   bool mHaveSeenHead;
 
   // Boolean indicating whether we've notified insertion of our root content
   // yet.  We want to make sure to only do this once.
   bool mNotifiedRootInsertion;
 
   mozilla::dom::NodeInfo* mNodeInfoCache[NS_HTML_TAG_MAX + 1];
 
-  nsresult FlushTags();
+  nsresult FlushTags() MOZ_OVERRIDE;
 
   // Routines for tags that require special handling
   nsresult CloseHTML();
   nsresult OpenBody();
   nsresult CloseBody();
 
   void CloseHeadContext();
 
   // nsContentSink overrides
-  void UpdateChildCounts();
+  void UpdateChildCounts() MOZ_OVERRIDE;
 
   void NotifyInsert(nsIContent* aContent,
                     nsIContent* aChildContent,
                     int32_t aIndexInContainer);
   void NotifyRootInsertion();
 };
 
 class SinkContext
--- a/dom/html/nsHTMLDocument.h
+++ b/dom/html/nsHTMLDocument.h
@@ -73,20 +73,20 @@ public:
   // nsIHTMLDocument
   virtual void SetCompatibilityMode(nsCompatibility aMode) MOZ_OVERRIDE;
 
   virtual bool IsWriting() MOZ_OVERRIDE
   {
     return mWriteLevel != uint32_t(0);
   }
 
-  virtual nsContentList* GetForms();
- 
-  virtual nsContentList* GetFormControls();
- 
+  virtual nsContentList* GetForms() MOZ_OVERRIDE;
+
+  virtual nsContentList* GetFormControls() MOZ_OVERRIDE;
+
   // nsIDOMDocument interface
   using nsDocument::CreateElement;
   using nsDocument::CreateElementNS;
   NS_FORWARD_NSIDOMDOCUMENT(nsDocument::)
 
   // And explicitly import the things from nsDocument that we just shadowed
   using nsDocument::GetImplementation;
   using nsDocument::GetTitle;
@@ -150,17 +150,17 @@ public:
   void EndUpdate(nsUpdateType aUpdateType) MOZ_OVERRIDE;
 
   virtual nsresult SetEditingState(EditingState aState) MOZ_OVERRIDE;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
 
   virtual void RemovedFromDocShell() MOZ_OVERRIDE;
 
-  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId)
+  virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId) MOZ_OVERRIDE
   {
     return nsDocument::GetElementById(aElementId);
   }
 
   virtual void DocAddSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const MOZ_OVERRIDE;
   // DocAddSizeOfIncludingThis is inherited from nsIDocument.
 
   virtual bool WillIgnoreCharsetOverride() MOZ_OVERRIDE;
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -209,46 +209,46 @@ public:
 
   nsTextInputSelectionImpl(nsFrameSelection *aSel, nsIPresShell *aShell, nsIContent *aLimiter);
 
   void SetScrollableFrame(nsIScrollableFrame *aScrollableFrame);
   nsFrameSelection* GetConstFrameSelection()
     { return mFrameSelection; }
 
   //NSISELECTIONCONTROLLER INTERFACES
-  NS_IMETHOD SetDisplaySelection(int16_t toggle);
-  NS_IMETHOD GetDisplaySelection(int16_t *_retval);
-  NS_IMETHOD SetSelectionFlags(int16_t aInEnable);
-  NS_IMETHOD GetSelectionFlags(int16_t *aOutEnable);
-  NS_IMETHOD GetSelection(int16_t type, nsISelection **_retval);
-  NS_IMETHOD ScrollSelectionIntoView(int16_t aType, int16_t aRegion, int16_t aFlags);
-  NS_IMETHOD RepaintSelection(int16_t type);
+  NS_IMETHOD SetDisplaySelection(int16_t toggle) MOZ_OVERRIDE;
+  NS_IMETHOD GetDisplaySelection(int16_t* _retval) MOZ_OVERRIDE;
+  NS_IMETHOD SetSelectionFlags(int16_t aInEnable) MOZ_OVERRIDE;
+  NS_IMETHOD GetSelectionFlags(int16_t *aOutEnable) MOZ_OVERRIDE;
+  NS_IMETHOD GetSelection(int16_t type, nsISelection** _retval) MOZ_OVERRIDE;
+  NS_IMETHOD ScrollSelectionIntoView(int16_t aType, int16_t aRegion, int16_t aFlags) MOZ_OVERRIDE;
+  NS_IMETHOD RepaintSelection(int16_t type) MOZ_OVERRIDE;
   NS_IMETHOD RepaintSelection(nsPresContext* aPresContext, SelectionType aSelectionType);
-  NS_IMETHOD SetCaretEnabled(bool enabled);
-  NS_IMETHOD SetCaretReadOnly(bool aReadOnly);
-  NS_IMETHOD GetCaretEnabled(bool *_retval);
-  NS_IMETHOD GetCaretVisible(bool *_retval);
-  NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility);
+  NS_IMETHOD SetCaretEnabled(bool enabled) MOZ_OVERRIDE;
+  NS_IMETHOD SetCaretReadOnly(bool aReadOnly) MOZ_OVERRIDE;
+  NS_IMETHOD GetCaretEnabled(bool* _retval) MOZ_OVERRIDE;
+  NS_IMETHOD GetCaretVisible(bool* _retval) MOZ_OVERRIDE;
+  NS_IMETHOD SetCaretVisibilityDuringSelection(bool aVisibility) MOZ_OVERRIDE;
   NS_IMETHOD PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend) MOZ_OVERRIDE;
-  NS_IMETHOD CharacterMove(bool aForward, bool aExtend);
-  NS_IMETHOD CharacterExtendForDelete();
-  NS_IMETHOD CharacterExtendForBackspace();
-  NS_IMETHOD WordMove(bool aForward, bool aExtend);
-  NS_IMETHOD WordExtendForDelete(bool aForward);
-  NS_IMETHOD LineMove(bool aForward, bool aExtend);
-  NS_IMETHOD IntraLineMove(bool aForward, bool aExtend);
-  NS_IMETHOD PageMove(bool aForward, bool aExtend);
-  NS_IMETHOD CompleteScroll(bool aForward);
-  NS_IMETHOD CompleteMove(bool aForward, bool aExtend);
-  NS_IMETHOD ScrollPage(bool aForward);
-  NS_IMETHOD ScrollLine(bool aForward);
-  NS_IMETHOD ScrollCharacter(bool aRight);
-  NS_IMETHOD SelectAll(void);
-  NS_IMETHOD CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool *_retval);
-  virtual nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset, int16_t aEndOffset, bool* aRetval);
+  NS_IMETHOD CharacterMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD CharacterExtendForDelete() MOZ_OVERRIDE;
+  NS_IMETHOD CharacterExtendForBackspace() MOZ_OVERRIDE;
+  NS_IMETHOD WordMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD WordExtendForDelete(bool aForward) MOZ_OVERRIDE;
+  NS_IMETHOD LineMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD IntraLineMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD PageMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD CompleteScroll(bool aForward) MOZ_OVERRIDE;
+  NS_IMETHOD CompleteMove(bool aForward, bool aExtend) MOZ_OVERRIDE;
+  NS_IMETHOD ScrollPage(bool aForward) MOZ_OVERRIDE;
+  NS_IMETHOD ScrollLine(bool aForward) MOZ_OVERRIDE;
+  NS_IMETHOD ScrollCharacter(bool aRight) MOZ_OVERRIDE;
+  NS_IMETHOD SelectAll(void) MOZ_OVERRIDE;
+  NS_IMETHOD CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool* _retval) MOZ_OVERRIDE;
+  virtual nsresult CheckVisibilityContent(nsIContent* aNode, int16_t aStartOffset, int16_t aEndOffset, bool* aRetval) MOZ_OVERRIDE;
 
 private:
   nsRefPtr<nsFrameSelection> mFrameSelection;
   nsCOMPtr<nsIContent>       mLimiter;
   nsIScrollableFrame        *mScrollFrame;
   nsWeakPtr mPresShellWeak;
 };
 
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -29,17 +29,17 @@ public:
 
   virtual bool RecvAsyncMessage(const nsString& aMsg,
                                 const ClonedMessageData& aData,
                                 const InfallibleTArray<jsipc::CpowEntry>& aCpows,
                                 const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
   virtual PBlobChild*
   SendPBlobConstructor(PBlobChild* actor,
-                       const BlobConstructorParams& params);
+                       const BlobConstructorParams& aParams) MOZ_OVERRIDE;
 
   jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
 
   virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
                                        const TabId& aTabId,
                                        const IPCTabContext& aContext,
                                        const uint32_t& aChromeFlags,
                                        const ContentParentId& aCpID,
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -211,17 +211,17 @@ namespace dom {
 class MemoryReportRequestChild : public PMemoryReportRequestChild,
                                  public nsIRunnable
 {
 public:
     NS_DECL_ISUPPORTS
 
     MemoryReportRequestChild(uint32_t aGeneration, bool aAnonymize,
                              const MaybeFileDesc& aDMDFile);
-    NS_IMETHOD Run();
+    NS_IMETHOD Run() MOZ_OVERRIDE;
 private:
     virtual ~MemoryReportRequestChild();
 
     uint32_t mGeneration;
     bool     mAnonymize;
     FileDescriptor mDMDFile;
 };
 
@@ -801,20 +801,20 @@ class MemoryReportCallback MOZ_FINAL : p
 public:
     NS_DECL_ISUPPORTS
 
     explicit MemoryReportCallback(const nsACString& aProcess)
     : mProcess(aProcess)
     {
     }
 
-    NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
+    NS_IMETHOD Callback(const nsACString& aProcess, const nsACString &aPath,
                         int32_t aKind, int32_t aUnits, int64_t aAmount,
-                        const nsACString &aDescription,
-                        nsISupports *aiWrappedReports)
+                        const nsACString& aDescription,
+                        nsISupports* aiWrappedReports) MOZ_OVERRIDE
     {
         MemoryReportsWrapper *wrappedReports =
             static_cast<MemoryReportsWrapper *>(aiWrappedReports);
 
         MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits,
                                aAmount, nsCString(aDescription));
         wrappedReports->mReports->AppendElement(memreport);
         return NS_OK;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -57,19 +57,19 @@ class ContentChild : public PContentChil
     typedef mozilla::dom::ClonedMessageData ClonedMessageData;
     typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
     typedef mozilla::ipc::PFileDescriptorSetChild PFileDescriptorSetChild;
     typedef mozilla::ipc::URIParams URIParams;
 
 public:
     ContentChild();
     virtual ~ContentChild();
-    NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
-    NS_IMETHOD_(MozExternalRefCountType) AddRef(void) { return 1; }
-    NS_IMETHOD_(MozExternalRefCountType) Release(void) { return 1; }
+    NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE;
+    NS_IMETHOD_(MozExternalRefCountType) AddRef(void) MOZ_OVERRIDE { return 1; }
+    NS_IMETHOD_(MozExternalRefCountType) Release(void) MOZ_OVERRIDE { return 1; }
 
     struct AppInfo
     {
         nsCString version;
         nsCString buildID;
         nsCString name;
         nsCString UAName;
         nsCString ID;
@@ -137,24 +137,28 @@ public:
     AllocPBackgroundChild(Transport* aTransport, ProcessId aOtherProcess)
                           MOZ_OVERRIDE;
 
     virtual PBrowserChild* AllocPBrowserChild(const TabId& aTabId,
                                               const IPCTabContext& aContext,
                                               const uint32_t& aChromeFlags,
                                               const ContentParentId& aCpID,
                                               const bool& aIsForApp,
-                                              const bool& aIsForBrowser);
-    virtual bool DeallocPBrowserChild(PBrowserChild*);
+                                              const bool& aIsForBrowser)
+                                              MOZ_OVERRIDE;
+    virtual bool DeallocPBrowserChild(PBrowserChild*) MOZ_OVERRIDE;
 
-    virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequestChild(const DeviceStorageParams&);
-    virtual bool DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*);
+    virtual PDeviceStorageRequestChild* AllocPDeviceStorageRequestChild(const DeviceStorageParams&)
+                                                                        MOZ_OVERRIDE;
+    virtual bool DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild*)
+                                                   MOZ_OVERRIDE;
 
-    virtual PFileSystemRequestChild* AllocPFileSystemRequestChild(const FileSystemParams&);
-    virtual bool DeallocPFileSystemRequestChild(PFileSystemRequestChild*);
+    virtual PFileSystemRequestChild* AllocPFileSystemRequestChild(const FileSystemParams&)
+                                                                  MOZ_OVERRIDE;
+    virtual bool DeallocPFileSystemRequestChild(PFileSystemRequestChild*) MOZ_OVERRIDE;
 
     virtual PBlobChild* AllocPBlobChild(const BlobConstructorParams& aParams)
                                         MOZ_OVERRIDE;
     virtual bool DeallocPBlobChild(PBlobChild* aActor) MOZ_OVERRIDE;
 
     virtual PCrashReporterChild*
     AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
                              const uint32_t& processType) MOZ_OVERRIDE;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -380,17 +380,17 @@ bool ContentParent::sNuwaReady = false;
 class MemoryReportRequestParent : public PMemoryReportRequestParent
 {
 public:
     MemoryReportRequestParent();
     virtual ~MemoryReportRequestParent();
 
     virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
-    virtual bool Recv__delete__(const uint32_t& generation, const InfallibleTArray<MemoryReport>& report);
+    virtual bool Recv__delete__(const uint32_t& aGeneration, const InfallibleTArray<MemoryReport>& aReport) MOZ_OVERRIDE;
 private:
     ContentParent* Owner()
     {
         return static_cast<ContentParent*>(Manager());
     }
 };
 
 MemoryReportRequestParent::MemoryReportRequestParent()
@@ -1337,17 +1337,17 @@ public:
         mTimer = do_CreateInstance("@mozilla.org/timer;1");
 
         uint32_t timeoutSec =
             Preferences::GetInt("dom.ipc.systemMessageCPULockTimeoutSec", 30);
         mTimer->InitWithCallback(this, timeoutSec * 1000,
                                  nsITimer::TYPE_ONE_SHOT);
     }
 
-    NS_IMETHOD Notify(nsITimer* aTimer)
+    NS_IMETHOD Notify(nsITimer* aTimer) MOZ_OVERRIDE
     {
         // Careful: ShutDown() may delete |this|.
         ShutDown();
         return NS_OK;
     }
 
 private:
     ~SystemMessageHandledListener() {}
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -497,18 +497,18 @@ private:
                                           MOZ_OVERRIDE;
     virtual bool DeallocPBlobParent(PBlobParent* aActor) MOZ_OVERRIDE;
 
     virtual bool DeallocPCrashReporterParent(PCrashReporterParent* crashreporter) MOZ_OVERRIDE;
 
     virtual bool RecvGetRandomValues(const uint32_t& length,
                                      InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
 
-    virtual bool RecvIsSecureURI(const uint32_t& type, const URIParams& uri,
-                                 const uint32_t& flags, bool* isSecureURI);
+    virtual bool RecvIsSecureURI(const uint32_t& aType, const URIParams& aURI,
+                                 const uint32_t& aFlags, bool* aIsSecureURI) MOZ_OVERRIDE;
 
     virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
 
     virtual PMemoryReportRequestParent*
     AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
                                     const bool &aAnonymize,
                                     const bool &aMinimizeMemoryUsage,
                                     const MaybeFileDesc &aDMDFile) MOZ_OVERRIDE;
--- a/dom/ipc/ScreenManagerParent.h
+++ b/dom/ipc/ScreenManagerParent.h
@@ -38,17 +38,17 @@ class ScreenManagerParent : public PScre
                                  const int32_t& aTop,
                                  const int32_t& aWidth,
                                  const int32_t& aHeight,
                                  ScreenDetails* aRetVal,
                                  bool* aSuccess) MOZ_OVERRIDE;
 
   virtual bool RecvScreenForBrowser(PBrowserParent* aBrowser,
                                     ScreenDetails* aRetVal,
-                                    bool* aSuccess);
+                                    bool* aSuccess) MOZ_OVERRIDE;
 
  private:
   bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);
   nsCOMPtr<nsIScreenManager> mScreenMgr;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -75,30 +75,30 @@ public:
   NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager)
   NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager)
   NS_IMETHOD SendSyncMessage(const nsAString& aMessageName,
                              JS::Handle<JS::Value> aObject,
                              JS::Handle<JS::Value> aRemote,
                              nsIPrincipal* aPrincipal,
                              JSContext* aCx,
                              uint8_t aArgc,
-                             JS::MutableHandle<JS::Value> aRetval)
+                             JS::MutableHandle<JS::Value> aRetval) MOZ_OVERRIDE
   {
     return mMessageManager
       ? mMessageManager->SendSyncMessage(aMessageName, aObject, aRemote,
                                          aPrincipal, aCx, aArgc, aRetval)
       : NS_ERROR_NULL_POINTER;
   }
   NS_IMETHOD SendRpcMessage(const nsAString& aMessageName,
                             JS::Handle<JS::Value> aObject,
                             JS::Handle<JS::Value> aRemote,
                             nsIPrincipal* aPrincipal,
                             JSContext* aCx,
                             uint8_t aArgc,
-                            JS::MutableHandle<JS::Value> aRetval)
+                            JS::MutableHandle<JS::Value> aRetval) MOZ_OVERRIDE
   {
     return mMessageManager
       ? mMessageManager->SendRpcMessage(aMessageName, aObject, aRemote,
                                         aPrincipal, aCx, aArgc, aRetval)
       : NS_ERROR_NULL_POINTER;
   }
   NS_IMETHOD GetContent(nsIDOMWindow** aContent) MOZ_OVERRIDE;
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) MOZ_OVERRIDE;
@@ -107,19 +107,19 @@ public:
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
   NS_IMETHOD PrivateNoteIntentionalCrash() MOZ_OVERRIDE;
   NS_IMETHOD Btoa(const nsAString& aBinaryData,
                   nsAString& aAsciiBase64String) MOZ_OVERRIDE;
   NS_IMETHOD Atob(const nsAString& aAsciiString,
                   nsAString& aBinaryData) MOZ_OVERRIDE;
 
-  NS_IMETHOD AddEventListener(const nsAString& aType,
-                              nsIDOMEventListener* aListener,
-                              bool aUseCapture)
+  nsresult AddEventListener(const nsAString& aType,
+                            nsIDOMEventListener* aListener,
+                            bool aUseCapture)
   {
     // By default add listeners only for trusted events!
     return DOMEventTargetHelper::AddEventListener(aType, aListener,
                                                   aUseCapture, false, 2);
   }
   using DOMEventTargetHelper::AddEventListener;
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
@@ -128,17 +128,17 @@ public:
   {
     return DOMEventTargetHelper::AddEventListener(aType, aListener,
                                                   aUseCapture,
                                                   aWantsUntrusted,
                                                   optional_argc);
   }
 
   nsresult
-  PreHandleEvent(EventChainPreVisitor& aVisitor)
+  PreHandleEvent(EventChainPreVisitor& aVisitor) MOZ_OVERRIDE
   {
     aVisitor.mForceContentDispatch = true;
     return NS_OK;
   }
 
   virtual JSContext* GetJSContextForEventHandlers() MOZ_OVERRIDE;
   virtual nsIPrincipal* GetPrincipal() MOZ_OVERRIDE;
   virtual JSObject* GetGlobalJSObject() MOZ_OVERRIDE;
@@ -503,17 +503,17 @@ protected:
     virtual ~TabChild();
 
     virtual PRenderFrameChild* AllocPRenderFrameChild() MOZ_OVERRIDE;
     virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) MOZ_OVERRIDE;
     virtual bool RecvDestroy() MOZ_OVERRIDE;
     virtual bool RecvSetUpdateHitRegion(const bool& aEnabled) MOZ_OVERRIDE;
     virtual bool RecvSetIsDocShellActive(const bool& aIsActive) MOZ_OVERRIDE;
 
-    virtual bool RecvRequestNotifyAfterRemotePaint();
+    virtual bool RecvRequestNotifyAfterRemotePaint() MOZ_OVERRIDE;
 
     virtual bool RecvParentActivated(const bool& aActivated) MOZ_OVERRIDE;
 
 #ifdef MOZ_WIDGET_GONK
     void MaybeRequestPreinitCamera();
 #endif
 
 private:
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2368,48 +2368,48 @@ public:
   FakeChannel(const nsCString& aUri, uint64_t aCallbackId, Element* aElement)
     : mCallbackId(aCallbackId)
     , mElement(aElement)
   {
     NS_NewURI(getter_AddRefs(mUri), aUri);
   }
 
   NS_DECL_ISUPPORTS
-#define NO_IMPL { return NS_ERROR_NOT_IMPLEMENTED; }
+#define NO_IMPL MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
   NS_IMETHOD GetName(nsACString&) NO_IMPL
   NS_IMETHOD IsPending(bool*) NO_IMPL
   NS_IMETHOD GetStatus(nsresult*) NO_IMPL
   NS_IMETHOD Cancel(nsresult) NO_IMPL
   NS_IMETHOD Suspend() NO_IMPL
   NS_IMETHOD Resume() NO_IMPL
   NS_IMETHOD GetLoadGroup(nsILoadGroup**) NO_IMPL
   NS_IMETHOD SetLoadGroup(nsILoadGroup*) NO_IMPL
   NS_IMETHOD SetLoadFlags(nsLoadFlags) NO_IMPL
   NS_IMETHOD GetLoadFlags(nsLoadFlags*) NO_IMPL
   NS_IMETHOD GetOriginalURI(nsIURI**) NO_IMPL
   NS_IMETHOD SetOriginalURI(nsIURI*) NO_IMPL
-  NS_IMETHOD GetURI(nsIURI** aUri)
+  NS_IMETHOD GetURI(nsIURI** aUri) MOZ_OVERRIDE
   {
     NS_IF_ADDREF(mUri);
     *aUri = mUri;
     return NS_OK;
   }
   NS_IMETHOD GetOwner(nsISupports**) NO_IMPL
   NS_IMETHOD SetOwner(nsISupports*) NO_IMPL
-  NS_IMETHOD GetLoadInfo(nsILoadInfo** aLoadInfo)
+  NS_IMETHOD GetLoadInfo(nsILoadInfo** aLoadInfo) MOZ_OVERRIDE
   {
     NS_IF_ADDREF(*aLoadInfo = mLoadInfo);
     return NS_OK;
   }
-  NS_IMETHOD SetLoadInfo(nsILoadInfo* aLoadInfo)
+  NS_IMETHOD SetLoadInfo(nsILoadInfo* aLoadInfo) MOZ_OVERRIDE
   {
     mLoadInfo = aLoadInfo;
     return NS_OK;
   }
-  NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor** aRequestor)
+  NS_IMETHOD GetNotificationCallbacks(nsIInterfaceRequestor** aRequestor) MOZ_OVERRIDE
   {
     NS_ADDREF(*aRequestor = this);
     return NS_OK;
   }
   NS_IMETHOD SetNotificationCallbacks(nsIInterfaceRequestor*) NO_IMPL
   NS_IMETHOD GetSecurityInfo(nsISupports**) NO_IMPL
   NS_IMETHOD GetContentType(nsACString&) NO_IMPL
   NS_IMETHOD SetContentType(const nsACString&) NO_IMPL
@@ -2419,25 +2419,25 @@ public:
   NS_IMETHOD SetContentLength(int64_t) NO_IMPL
   NS_IMETHOD Open(nsIInputStream**) NO_IMPL
   NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL
   NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL
   NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL
   NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL
   NS_IMETHOD SetContentDispositionFilename(const nsAString&) NO_IMPL
   NS_IMETHOD GetContentDispositionHeader(nsACString&) NO_IMPL
-  NS_IMETHOD OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo);
-  NS_IMETHOD OnAuthCancelled(nsISupports *aContext, bool userCancel);
-  NS_IMETHOD GetInterface(const nsIID & uuid, void **result)
+  NS_IMETHOD OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo) MOZ_OVERRIDE;
+  NS_IMETHOD OnAuthCancelled(nsISupports *aContext, bool userCancel) MOZ_OVERRIDE;
+  NS_IMETHOD GetInterface(const nsIID & uuid, void **result) MOZ_OVERRIDE
   {
     return QueryInterface(uuid, result);
   }
   NS_IMETHOD GetAssociatedWindow(nsIDOMWindow**) NO_IMPL
   NS_IMETHOD GetTopWindow(nsIDOMWindow**) NO_IMPL
-  NS_IMETHOD GetTopFrameElement(nsIDOMElement** aElement)
+  NS_IMETHOD GetTopFrameElement(nsIDOMElement** aElement) MOZ_OVERRIDE
   {
     nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(mElement);
     elem.forget(aElement);
     return NS_OK;
   }
   NS_IMETHOD GetNestedFrameId(uint64_t*) NO_IMPL
   NS_IMETHOD IsAppOfType(uint32_t, bool*) NO_IMPL
   NS_IMETHOD GetIsContent(bool*) NO_IMPL
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -122,18 +122,18 @@ public:
      * capturer.
      */
     bool TryCapture(const WidgetGUIEvent& aEvent);
 
     void Destroy();
 
     virtual bool RecvMoveFocus(const bool& aForward) MOZ_OVERRIDE;
     virtual bool RecvEvent(const RemoteDOMEvent& aEvent) MOZ_OVERRIDE;
-    virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& event);
-    virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& event);
+    virtual bool RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent) MOZ_OVERRIDE;
+    virtual bool RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent) MOZ_OVERRIDE;
     virtual bool RecvBrowserFrameOpenWindow(PBrowserParent* aOpener,
                                             const nsString& aURL,
                                             const nsString& aName,
                                             const nsString& aFeatures,
                                             bool* aOutWindowOpened) MOZ_OVERRIDE;
     virtual bool AnswerCreateWindow(const uint32_t& aChromeFlags,
                                     const bool& aCalledFromJS,
                                     const bool& aPositionSpecified,
@@ -192,19 +192,19 @@ public:
                                      const int32_t& aFocusChange) MOZ_OVERRIDE;
     virtual bool RecvRequestFocus(const bool& aCanRaise) MOZ_OVERRIDE;
     virtual bool RecvEnableDisableCommands(const nsString& aAction,
                                            const nsTArray<nsCString>& aEnabledCommands,
                                            const nsTArray<nsCString>& aDisabledCommands) MOZ_OVERRIDE;
     virtual bool RecvSetCursor(const uint32_t& aValue, const bool& aForce) MOZ_OVERRIDE;
     virtual bool RecvSetBackgroundColor(const nscolor& aValue) MOZ_OVERRIDE;
     virtual bool RecvSetStatus(const uint32_t& aType, const nsString& aStatus) MOZ_OVERRIDE;
-    virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible);
-    virtual bool RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip);
-    virtual bool RecvHideTooltip();
+    virtual bool RecvIsParentWindowMainWidgetVisible(bool* aIsVisible) MOZ_OVERRIDE;
+    virtual bool RecvShowTooltip(const uint32_t& aX, const uint32_t& aY, const nsString& aTooltip) MOZ_OVERRIDE;
+    virtual bool RecvHideTooltip() MOZ_OVERRIDE;
     virtual bool RecvGetDPI(float* aValue) MOZ_OVERRIDE;
     virtual bool RecvGetDefaultScale(double* aValue) MOZ_OVERRIDE;
     virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue) MOZ_OVERRIDE;
     virtual bool RecvZoomToRect(const uint32_t& aPresShellId,
                                 const ViewID& aViewId,
                                 const CSSRect& aRect) MOZ_OVERRIDE;
     virtual bool RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
                                            const ViewID& aViewId,
--- a/dom/media/fmp4/gonk/GonkDecoderModule.cpp
+++ b/dom/media/fmp4/gonk/GonkDecoderModule.cpp
@@ -24,18 +24,16 @@ void
 GonkDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 }
 
 nsresult
 GonkDecoderModule::Shutdown()
 {
-  MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
-
   return NS_OK;
 }
 
 already_AddRefed<MediaDataDecoder>
 GonkDecoderModule::CreateVideoDecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
                                      mozilla::layers::LayersBackend aLayersBackend,
                                      mozilla::layers::ImageContainer* aImageContainer,
                                      MediaTaskQueue* aVideoTaskQueue,
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -927,18 +927,18 @@ WriteToFile(nsIFile* aPath,
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 static nsresult
 ReadFromFile(nsIFile* aPath,
-             const nsCString& aFileName,
-             nsCString& aOutData,
+             const nsACString& aFileName,
+             nsACString& aOutData,
              int32_t aMaxLength)
 {
   nsCOMPtr<nsIFile> path;
   nsresult rv = aPath->Clone(getter_AddRefs(path));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -965,18 +965,18 @@ ReadFromFile(nsIFile* aPath,
   PR_Close(f);
   if (NS_WARN_IF(len != size)) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
-static nsresult
-ReadSalt(nsIFile* aPath, nsCString& aOutData)
+nsresult
+ReadSalt(nsIFile* aPath, nsACString& aOutData)
 {
   return ReadFromFile(aPath, NS_LITERAL_CSTRING("salt"),
                       aOutData, NodeIdSaltLength);
 
 }
 
 NS_IMETHODIMP
 GeckoMediaPluginService::IsPersistentStorageAllowed(const nsACString& aNodeId,
@@ -1136,17 +1136,17 @@ GeckoMediaPluginService::GetNodeId(const
   }
 
   aOutId = salt;
   mPersistentStorageAllowed.Put(salt, true);
 
   return NS_OK;
 }
 
-static bool
+bool
 MatchOrigin(nsIFile* aPath, const nsACString& aOrigin)
 {
   // http://en.wikipedia.org/wiki/Domain_Name_System#Domain_name_syntax
   static const uint32_t MaxDomainLength = 253;
 
   nsresult rv;
   nsCString str;
   rv = ReadFromFile(aPath, NS_LITERAL_CSTRING("origin"), str, MaxDomainLength);
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -139,12 +139,15 @@ private:
   // non-persistent sessions.
   nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
 
   // Hashes node id to whether that node id is allowed to store data
   // persistently on disk.
   nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
 };
 
+nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
+bool MatchOrigin(nsIFile* aPath, const nsACString& aOrigin);
+
 } // namespace gmp
 } // namespace mozilla
 
 #endif // GMPService_h_
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -115,16 +115,52 @@ GetGMPThread()
 {
   nsRefPtr<GeckoMediaPluginService> service =
     GeckoMediaPluginService::GetGeckoMediaPluginService();
   nsCOMPtr<nsIThread> thread;
   EXPECT_TRUE(NS_SUCCEEDED(service->GetThread(getter_AddRefs(thread))));
   return thread.forget();
 }
 
+template<typename T>
+static nsresult
+EnumerateDir(const nsACString& aDir, T&& aDirIter)
+{
+  nsRefPtr<GeckoMediaPluginService> service =
+    GeckoMediaPluginService::GetGeckoMediaPluginService();
+  MOZ_ASSERT(service);
+
+  // $profileDir/gmp/
+  nsCOMPtr<nsIFile> path;
+  nsresult rv = service->GetStorageDir(getter_AddRefs(path));
+  NS_ENSURE_SUCCESS(rv, rv);
+  // $profileDir/gmp/$aDir/
+  rv = path->AppendNative(aDir);
+  NS_ENSURE_SUCCESS(rv, rv);
+  // Iterate all sub-folders of $profileDir/gmp/$aDir/
+  nsCOMPtr<nsISimpleEnumerator> iter;
+  rv = path->GetDirectoryEntries(getter_AddRefs(iter));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  bool hasMore = false;
+  while (NS_SUCCEEDED(iter->HasMoreElements(&hasMore)) && hasMore) {
+    nsCOMPtr<nsISupports> supports;
+    rv = iter->GetNext(getter_AddRefs(supports));
+    if (NS_FAILED(rv)) {
+      continue;
+    }
+    nsCOMPtr<nsIFile> entry(do_QueryInterface(supports, &rv));
+    if (NS_FAILED(rv)) {
+      continue;
+    }
+    aDirIter(entry);
+  }
+  return NS_OK;
+}
+
 class GMPShutdownObserver : public nsIRunnable
                           , public nsIObserver {
 public:
   GMPShutdownObserver(nsIRunnable* aShutdownTask,
                       nsIRunnable* Continuation,
                       const nsACString& aNodeId)
     : mShutdownTask(aShutdownTask)
     , mContinuation(Continuation)
@@ -407,16 +443,148 @@ class GMPStorageTest : public GMPDecrypt
     // Send a message to the fake GMP for it to run its own tests internally.
     // It sends us a "test-storage complete" message when its passed, or
     // some other message if its tests fail.
     Expect(NS_LITERAL_CSTRING("test-storage complete"),
            NS_NewRunnableMethod(this, &GMPStorageTest::SetFinished));
     Update(NS_LITERAL_CSTRING("test-storage"));
   }
 
+  /**
+   * 1. Generate storage data for some sites.
+   * 2. Forget about one of the sites.
+   * 3. Check if the storage data for the forgotten site are erased correctly.
+   * 4. Check if the storage data for other sites remain unchanged.
+   */
+  void TestForgetThisSite() {
+    AssertIsOnGMPThread();
+    EXPECT_TRUE(IsGMPStorageIsEmpty());
+
+    // Generate storage data for some site.
+    CreateDecryptor(NS_LITERAL_STRING("example1.com"),
+                    NS_LITERAL_STRING("example2.com"),
+                    false);
+
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
+        this, &GMPStorageTest::TestForgetThisSite_AnotherSite);
+    Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
+    Update(NS_LITERAL_CSTRING("test-storage"));
+  }
+
+  void TestForgetThisSite_AnotherSite() {
+    Shutdown();
+
+    // Generate storage data for another site.
+    CreateDecryptor(NS_LITERAL_STRING("example3.com"),
+                    NS_LITERAL_STRING("example4.com"),
+                    false);
+
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(
+        this, &GMPStorageTest::TestForgetThisSite_CollectSiteInfo);
+    Expect(NS_LITERAL_CSTRING("test-storage complete"), r);
+    Update(NS_LITERAL_CSTRING("test-storage"));
+  }
+
+  struct NodeInfo {
+    explicit NodeInfo(const nsACString& aSite) : siteToForget(aSite) {}
+    nsCString siteToForget;
+    nsTArray<nsCString> expectedRemainingNodeIds;
+  };
+
+  class NodeIdCollector {
+  public:
+    explicit NodeIdCollector(NodeInfo* aInfo) : mNodeInfo(aInfo) {}
+    void operator()(nsIFile* aFile) {
+      nsCString salt;
+      nsresult rv = ReadSalt(aFile, salt);
+      ASSERT_TRUE(NS_SUCCEEDED(rv));
+      if (!MatchOrigin(aFile, mNodeInfo->siteToForget)) {
+        mNodeInfo->expectedRemainingNodeIds.AppendElement(salt);
+      }
+    }
+  private:
+    NodeInfo* mNodeInfo;
+  };
+
+  void TestForgetThisSite_CollectSiteInfo() {
+    nsAutoPtr<NodeInfo> siteInfo(
+        new NodeInfo(NS_LITERAL_CSTRING("example1.com")));
+    // Collect nodeIds that are expected to remain for later comparison.
+    EnumerateDir(NS_LITERAL_CSTRING("id"), NodeIdCollector(siteInfo));
+    // Invoke "Forget this site" on the main thread.
+    NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<nsAutoPtr<NodeInfo>>(
+        this, &GMPStorageTest::TestForgetThisSite_Forget, siteInfo));
+  }
+
+  void TestForgetThisSite_Forget(nsAutoPtr<NodeInfo> aSiteInfo) {
+    nsRefPtr<GeckoMediaPluginService> service =
+        GeckoMediaPluginService::GetGeckoMediaPluginService();
+    service->ForgetThisSite(NS_ConvertUTF8toUTF16(aSiteInfo->siteToForget));
+
+    nsCOMPtr<nsIThread> thread;
+    service->GetThread(getter_AddRefs(thread));
+
+    nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<nsAutoPtr<NodeInfo>>(
+        this, &GMPStorageTest::TestForgetThisSite_Verify, aSiteInfo);
+    thread->Dispatch(r, NS_DISPATCH_NORMAL);
+
+    nsCOMPtr<nsIRunnable> f = NS_NewRunnableMethod(
+        this, &GMPStorageTest::SetFinished);
+    thread->Dispatch(f, NS_DISPATCH_NORMAL);
+  }
+
+  class NodeIdVerifier {
+  public:
+    explicit NodeIdVerifier(const NodeInfo* aInfo)
+      : mNodeInfo(aInfo)
+      , mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds) {}
+    void operator()(nsIFile* aFile) {
+      nsCString salt;
+      nsresult rv = ReadSalt(aFile, salt);
+      ASSERT_TRUE(NS_SUCCEEDED(rv));
+      // Shouldn't match the origin if we clear correctly.
+      EXPECT_FALSE(MatchOrigin(aFile, mNodeInfo->siteToForget));
+      // Check if remaining nodeIDs are as expected.
+      EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
+    }
+    ~NodeIdVerifier() {
+      EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty());
+    }
+  private:
+    const NodeInfo* mNodeInfo;
+    nsTArray<nsCString> mExpectedRemainingNodeIds;
+  };
+
+  class StorageVerifier {
+  public:
+    explicit StorageVerifier(const NodeInfo* aInfo)
+      : mExpectedRemainingNodeIds(aInfo->expectedRemainingNodeIds) {}
+    void operator()(nsIFile* aFile) {
+      nsCString salt;
+      nsresult rv = aFile->GetNativeLeafName(salt);
+      ASSERT_TRUE(NS_SUCCEEDED(rv));
+      EXPECT_TRUE(mExpectedRemainingNodeIds.RemoveElement(salt));
+    }
+    ~StorageVerifier() {
+      EXPECT_TRUE(mExpectedRemainingNodeIds.IsEmpty());
+    }
+  private:
+    nsTArray<nsCString> mExpectedRemainingNodeIds;
+  };
+
+  void TestForgetThisSite_Verify(nsAutoPtr<NodeInfo> aSiteInfo) {
+    nsresult rv = EnumerateDir(
+        NS_LITERAL_CSTRING("id"), NodeIdVerifier(aSiteInfo));
+    EXPECT_TRUE(NS_SUCCEEDED(rv));
+
+    rv = EnumerateDir(
+        NS_LITERAL_CSTRING("storage"), StorageVerifier(aSiteInfo));
+    EXPECT_TRUE(NS_SUCCEEDED(rv));
+  }
+
   void TestCrossOriginStorage() {
     EXPECT_TRUE(!mDecryptor);
 
     // Open decryptor on one, origin, write a record, and test that that
     // record can't be read on another origin.
     CreateDecryptor(NS_LITERAL_STRING("example3.com"),
                     NS_LITERAL_STRING("example4.com"),
                     false);
@@ -813,16 +981,21 @@ TEST(GeckoMediaPlugins, GMPStorageGetNod
   runner->DoTest(&GMPStorageTest::TestGetNodeId);
 }
 
 TEST(GeckoMediaPlugins, GMPStorageBasic) {
   nsRefPtr<GMPStorageTest> runner = new GMPStorageTest();
   runner->DoTest(&GMPStorageTest::TestBasicStorage);
 }
 
+TEST(GeckoMediaPlugins, GMPStorageForgetThisSite) {
+  nsRefPtr<GMPStorageTest> runner = new GMPStorageTest();
+  runner->DoTest(&GMPStorageTest::TestForgetThisSite);
+}
+
 TEST(GeckoMediaPlugins, GMPStorageCrossOrigin) {
   nsRefPtr<GMPStorageTest> runner = new GMPStorageTest();
   runner->DoTest(&GMPStorageTest::TestCrossOriginStorage);
 }
 
 TEST(GeckoMediaPlugins, GMPStoragePrivateBrowsing) {
   nsRefPtr<GMPStorageTest> runner = new GMPStorageTest();
   runner->DoTest(&GMPStorageTest::TestPBStorage);
--- a/dom/media/test/test_bug448534.html
+++ b/dom/media/test/test_bug448534.html
@@ -23,17 +23,19 @@ function loaded(event) {
   if (v._finished)
     return;
   v.play();
 }
 
 function started(event) {
   var v = event.target;
   info(v.token + ": event=" + event.type);
-  if (v._finished)
+  // For a short file, it could reach the end before 'play' received. We will
+  // skip the test for 'paused' would be true when ended.
+  if (v._finished || v.ended)
     return;
   ok(!v.paused, v.token + ": Video should not be paused while playing");
   v.parentNode.removeChild(v);
   v._played = true;
 }
 
 function stopped(event) {
   var v = event.target;
--- a/extensions/spellcheck/locales/Makefile.in
+++ b/extensions/spellcheck/locales/Makefile.in
@@ -1,12 +1,7 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-include $(topsrcdir)/config/rules.mk
-
 DICTIONARY_FILES = $(strip $(wildcard $(LOCALE_SRCDIR)/hunspell/*.dic) $(wildcard $(LOCALE_SRCDIR)/hunspell/*.aff))
-
-ifneq (,$(DICTIONARY_FILES))
-libs::
-	$(INSTALL)  $(DICTIONARY_FILES) $(FINAL_TARGET)/dictionaries
-endif
+DICTIONARY_DEST = $(FINAL_TARGET)/dictionaries
+INSTALL_TARGETS += DICTIONARY
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -891,21 +891,16 @@ gfxDWriteFontList::InitFontList()
                       nullptr, nullptr, nowTime, 256);
         GetDateFormat(LOCALE_INVARIANT, 0, nullptr, nullptr, nowDate, 256);
     }
     upTime = (double) GetTickCount();
     QueryPerformanceFrequency(&frequency);
     QueryPerformanceCounter(&t1);
 
     HRESULT hr;
-    gfxFontCache *fc = gfxFontCache::GetCache();
-    if (fc) {
-        fc->AgeAllGenerations();
-    }
-
     mGDIFontTableAccess = Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", false);
 
     gfxPlatformFontList::InitFontList();
 
     mFontSubstitutes.Clear();
     mNonExistingFonts.Clear();
 
     QueryPerformanceCounter(&t2);
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -651,19 +651,16 @@ gfxGDIFontList::GetFontSubstitutes()
     }
     return NS_OK;
 }
 
 nsresult
 gfxGDIFontList::InitFontList()
 {
     Telemetry::AutoTimer<Telemetry::GDI_INITFONTLIST_TOTAL> timer;
-    gfxFontCache *fc = gfxFontCache::GetCache();
-    if (fc)
-        fc->AgeAllGenerations();
 
     // reset font lists
     gfxPlatformFontList::InitFontList();
     
     mFontSubstitutes.Clear();
     mNonExistingFonts.Clear();
 
     // iterate over available families
--- a/gfx/thebes/gfxMacPlatformFontList.h
+++ b/gfx/thebes/gfxMacPlatformFontList.h
@@ -88,18 +88,16 @@ public:
     
     virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName,
                                            uint16_t aWeight,
                                            int16_t aStretch,
                                            bool aItalic,
                                            const uint8_t* aFontData,
                                            uint32_t aLength);
 
-    void ClearPrefFonts() { mPrefFonts.Clear(); }
-
 private:
     friend class gfxPlatformMac;
 
     gfxMacPlatformFontList();
     virtual ~gfxMacPlatformFontList();
 
     // initialize font lists
     virtual nsresult InitFontList();
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -194,16 +194,23 @@ gfxPlatformFontList::~gfxPlatformFontLis
     NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
     Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
     NS_RELEASE(gFontListPrefObserver);
 }
 
 nsresult
 gfxPlatformFontList::InitFontList()
 {
+    // rebuilding fontlist so clear out font/word caches
+    gfxFontCache *fontCache = gfxFontCache::GetCache();
+    if (fontCache) {
+        fontCache->AgeAllGenerations();
+        fontCache->FlushShapedWordCaches();
+    }
+
     mFontFamilies.Clear();
     mOtherFamilyNames.Clear();
     mOtherFamilyNamesInitialized = false;
     if (mExtraNames) {
         mExtraNames->mFullnames.Clear();
         mExtraNames->mPostscriptNames.Clear();
     }
     mFaceNameListsInitialized = false;
--- a/gfx/thebes/gfxQtPlatform.h
+++ b/gfx/thebes/gfxQtPlatform.h
@@ -67,34 +67,29 @@ public:
 
     /**
      * Check whether format is supported on a platform or not (if unclear,
      * returns true).
      */
     virtual bool IsFontFormatSupported(nsIURI *aFontURI,
                                        uint32_t aFormatFlags) MOZ_OVERRIDE;
 
-    virtual void ClearPrefFonts() { mPrefFonts.Clear(); }
-
     static int32_t GetDPI();
 
     virtual gfxImageFormat GetOffscreenFormat() MOZ_OVERRIDE;
 #ifdef MOZ_X11
     static Display* GetXDisplay(QWindow* aWindow = 0);
     static Screen* GetXScreen(QWindow* aWindow = 0);
 #endif
 
     virtual int GetScreenDepth() const MOZ_OVERRIDE;
 
 protected:
     static gfxFontconfigUtils *sFontconfigUtils;
 
 private:
     virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size) MOZ_OVERRIDE;
 
-    // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
-    nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
-
     int mScreenDepth;
 };
 
 #endif /* GFX_PLATFORM_QT_H */
 
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -321,17 +321,16 @@ public:
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS(GPUAdapterReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mD3D11DeviceInitialized(false)
-  , mPrefFonts(32)
 {
     mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
     mUseClearTypeAlways = UNINITIALIZED_VALUE;
 
     mUsingGDIFonts = false;
 
     /* 
      * Initialize COM 
@@ -1094,28 +1093,16 @@ gfxWindowsPlatform::GetPlatformCMSOutput
         fprintf(stderr,
                 "ICM profile read from %s successfully\n",
                 NS_ConvertUTF16toUTF8(str).get());
 #endif // DEBUG_tor
 #endif // _WIN32
 }
 
 bool
-gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *array)
-{
-    return mPrefFonts.Get(aKey, array);
-}
-
-void
-gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& array)
-{
-    mPrefFonts.Put(aKey, array);
-}
-
-bool
 gfxWindowsPlatform::UseClearTypeForDownloadableFonts()
 {
     if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) {
         mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true);
     }
 
     return mUseClearTypeForDownloadableFonts;
 }
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -210,21 +210,16 @@ public:
     virtual bool IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags);
 
     virtual bool DidRenderingDeviceReset();
 
     /* Find a FontFamily/FontEntry object that represents a font on your system given a name */
     gfxFontFamily *FindFontFamily(const nsAString& aName);
     gfxFontEntry *FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle);
 
-    bool GetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> > *array);
-    void SetPrefFontEntries(const nsCString& aLangGroup, nsTArray<nsRefPtr<gfxFontEntry> >& array);
-
-    void ClearPrefFonts() { mPrefFonts.Clear(); }
-
     // ClearType is not always enabled even when available (e.g. Windows XP)
     // if either of these prefs are enabled and apply, use ClearType rendering
     bool UseClearTypeForDownloadableFonts();
     bool UseClearTypeAlways();
 
     static void GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion);
 
     // returns ClearType tuning information for each display
@@ -285,17 +280,14 @@ private:
     mozilla::RefPtr<IDXGIAdapter1> mAdapter;
     nsRefPtr<mozilla::layers::DeviceManagerD3D9> mDeviceManager;
     mozilla::RefPtr<ID3D11Device> mD3D11Device;
     mozilla::RefPtr<ID3D11Device> mD3D11ContentDevice;
     bool mD3D11DeviceInitialized;
     mozilla::RefPtr<mozilla::layers::ReadbackManagerD3D11> mD3D11ReadbackManager;
 
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
-
-    // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
-    nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
 };
 
 bool DoesD3D11TextureSharingWork(ID3D11Device *device);
 bool DoesD3D11DeviceWork(ID3D11Device *device);
 
 #endif /* GFX_WINDOWS_PLATFORM_H */
--- a/intl/chardet/nsCyrillicDetector.h
+++ b/intl/chardet/nsCyrillicDetector.h
@@ -87,41 +87,41 @@ class nsCyrXPCOMDetector :
       public nsICharsetDetector
 {
   public:
     // nsISupports interface
     NS_DECL_ISUPPORTS
     nsCyrXPCOMDetector(uint8_t aItems, 
                       const uint8_t ** aCyrillicClass, 
                       const char **aCharsets);
-    NS_IMETHOD Init(nsICharsetDetectionObserver* aObserver);
-    NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen, bool *oDontFeedMe);
-    NS_IMETHOD Done();
+    NS_IMETHOD Init(nsICharsetDetectionObserver* aObserver) MOZ_OVERRIDE;
+    NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen, bool *oDontFeedMe) MOZ_OVERRIDE;
+    NS_IMETHOD Done() MOZ_OVERRIDE;
   protected:
     virtual ~nsCyrXPCOMDetector();
-    virtual void Report(const char* aCharset);
+    virtual void Report(const char* aCharset) MOZ_OVERRIDE;
   private:
     nsCOMPtr<nsICharsetDetectionObserver> mObserver;
 };
 
 class nsCyrXPCOMStringDetector :  
       public nsCyrillicDetector,
       public nsIStringCharsetDetector
 {
   public:
     // nsISupports interface
     NS_DECL_ISUPPORTS
     nsCyrXPCOMStringDetector(uint8_t aItems, 
                       const uint8_t ** aCyrillicClass, 
                       const char **aCharsets);
     NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen, 
-                     const char** oCharset, nsDetectionConfident &oConf);
+                     const char** oCharset, nsDetectionConfident &oConf) MOZ_OVERRIDE;
   protected:
     virtual ~nsCyrXPCOMStringDetector();
-    virtual void Report(const char* aCharset);
+    virtual void Report(const char* aCharset) MOZ_OVERRIDE;
   private:
     nsCOMPtr<nsICharsetDetectionObserver> mObserver;
     const char* mResult;
 };
 
 class nsRUProbDetector : public nsCyrXPCOMDetector
 {
   public:
--- a/intl/locale/mac/nsDateTimeFormatMac.h
+++ b/intl/locale/mac/nsDateTimeFormatMac.h
@@ -17,37 +17,37 @@ class nsDateTimeFormatMac : public nsIDa
 public: 
   NS_DECL_THREADSAFE_ISUPPORTS 
 
   // performs a locale sensitive date formatting operation on the time_t parameter
   NS_IMETHOD FormatTime(nsILocale* locale, 
                         const nsDateFormatSelector  dateFormatSelector, 
                         const nsTimeFormatSelector timeFormatSelector, 
                         const time_t  timetTime, 
-                        nsAString& stringOut); 
+                        nsAString& stringOut) MOZ_OVERRIDE; 
 
   // performs a locale sensitive date formatting operation on the struct tm parameter
   NS_IMETHOD FormatTMTime(nsILocale* locale, 
                           const nsDateFormatSelector  dateFormatSelector, 
                           const nsTimeFormatSelector timeFormatSelector, 
                           const struct tm*  tmTime, 
-                          nsAString& stringOut); 
+                          nsAString& stringOut) MOZ_OVERRIDE; 
   // performs a locale sensitive date formatting operation on the PRTime parameter
   NS_IMETHOD FormatPRTime(nsILocale* locale, 
                           const nsDateFormatSelector  dateFormatSelector, 
                           const nsTimeFormatSelector timeFormatSelector, 
                           const PRTime  prTime, 
-                          nsAString& stringOut);
+                          nsAString& stringOut) MOZ_OVERRIDE;
 
   // performs a locale sensitive date formatting operation on the PRExplodedTime parameter
   NS_IMETHOD FormatPRExplodedTime(nsILocale* locale, 
                                   const nsDateFormatSelector  dateFormatSelector, 
                                   const nsTimeFormatSelector timeFormatSelector, 
                                   const PRExplodedTime*  explodedTime, 
-                                  nsAString& stringOut); 
+                                  nsAString& stringOut) MOZ_OVERRIDE; 
 
   nsDateTimeFormatMac() {}
 
 protected:
   virtual ~nsDateTimeFormatMac() {}
 
 private:
   // init this interface to a specified locale
--- a/intl/locale/nsCollation.h
+++ b/intl/locale/nsCollation.h
@@ -18,17 +18,17 @@ class nsIUnicodeEncoder;
 // 
 class nsCollationFactory MOZ_FINAL : public nsICollationFactory {
 
   ~nsCollationFactory() {}
 
 public: 
   NS_DECL_ISUPPORTS 
 
-  NS_IMETHOD CreateCollation(nsILocale* locale, nsICollation** instancePtr);
+  NS_IMETHOD CreateCollation(nsILocale* locale, nsICollation** instancePtr) MOZ_OVERRIDE;
 
   nsCollationFactory() {}
 };
 
 
 struct nsCollation {
 
 public: 
--- a/intl/locale/nsLanguageAtomService.h
+++ b/intl/locale/nsLanguageAtomService.h
@@ -15,25 +15,25 @@
 
 class nsLanguageAtomService MOZ_FINAL : public nsILanguageAtomService
 {
 public:
   NS_DECL_ISUPPORTS
 
   // nsILanguageAtomService
   virtual nsIAtom*
-    LookupLanguage(const nsACString &aLanguage, nsresult *aError);
+    LookupLanguage(const nsACString &aLanguage, nsresult *aError) MOZ_OVERRIDE;
 
   virtual already_AddRefed<nsIAtom>
-    LookupCharSet(const nsACString& aCharSet);
+    LookupCharSet(const nsACString& aCharSet) MOZ_OVERRIDE;
 
-  virtual nsIAtom* GetLocaleLanguage(nsresult *aError);
+  virtual nsIAtom* GetLocaleLanguage(nsresult *aError) MOZ_OVERRIDE;
 
   virtual nsIAtom* GetLanguageGroup(nsIAtom *aLanguage,
-                                                nsresult *aError);
+                                                nsresult *aError) MOZ_OVERRIDE;
 
   nsLanguageAtomService();
 
 private:
   ~nsLanguageAtomService() { }
 
 protected:
   nsresult InitLangGroupTable();
--- a/intl/locale/nsPlatformCharset.h
+++ b/intl/locale/nsPlatformCharset.h
@@ -11,18 +11,18 @@ class nsPlatformCharset : public nsIPlat
 {
   NS_DECL_ISUPPORTS
 
 public:
 
   nsPlatformCharset();
 
   NS_IMETHOD Init();
-  NS_IMETHOD GetCharset(nsPlatformCharsetSel selector, nsACString& oResult);
-  NS_IMETHOD GetDefaultCharsetForLocale(const nsAString& localeName, nsACString& oResult);
+  NS_IMETHOD GetCharset(nsPlatformCharsetSel selector, nsACString& oResult) MOZ_OVERRIDE;
+  NS_IMETHOD GetDefaultCharsetForLocale(const nsAString& localeName, nsACString& oResult) MOZ_OVERRIDE;
 
 private:
   nsCString mCharset;
   nsString mLocale; // remember the locale & charset
 
   nsresult MapToCharset(nsAString& inANSICodePage, nsACString& outCharset);
   nsresult InitGetCharset(nsACString& oString);
   nsresult VerifyCharset(nsCString &aCharset);
--- a/intl/locale/nsScriptableDateFormat.cpp
+++ b/intl/locale/nsScriptableDateFormat.cpp
@@ -21,33 +21,33 @@ class nsScriptableDateFormat : public ns
                             nsDateFormatSelector dateFormatSelector, 
                             nsTimeFormatSelector timeFormatSelector, 
                             int32_t year, 
                             int32_t month, 
                             int32_t day, 
                             int32_t hour, 
                             int32_t minute, 
                             int32_t second, 
-                            char16_t **dateTimeString);
+                            char16_t **dateTimeString) MOZ_OVERRIDE;
 
   NS_IMETHOD FormatDate(const char16_t *locale, 
                         nsDateFormatSelector dateFormatSelector, 
                         int32_t year, 
                         int32_t month, 
                         int32_t day, 
-                        char16_t **dateString)
+                        char16_t **dateString) MOZ_OVERRIDE
                         {return FormatDateTime(locale, dateFormatSelector, kTimeFormatNone, 
                                                year, month, day, 0, 0, 0, dateString);}
 
   NS_IMETHOD FormatTime(const char16_t *locale, 
                         nsTimeFormatSelector timeFormatSelector, 
                         int32_t hour, 
                         int32_t minute, 
                         int32_t second, 
-                        char16_t **timeString)
+                        char16_t **timeString) MOZ_OVERRIDE
                         {return FormatDateTime(locale, kDateFormatNone, timeFormatSelector, 
                                                1999, 1, 1, hour, minute, second, timeString);}
 
   nsScriptableDateFormat() {}
 
 private:
   nsString mStringOut;   
 
--- a/intl/lwbrk/nsJISx4051LineBreaker.h
+++ b/intl/lwbrk/nsJISx4051LineBreaker.h
@@ -13,25 +13,25 @@ class nsJISx4051LineBreaker : public nsI
   NS_DECL_ISUPPORTS
 
 private:
   virtual ~nsJISx4051LineBreaker();
 
 public:
   nsJISx4051LineBreaker();
 
-  int32_t Next( const char16_t* aText, uint32_t aLen, uint32_t aPos);
+  int32_t Next( const char16_t* aText, uint32_t aLen, uint32_t aPos) MOZ_OVERRIDE;
 
-  int32_t Prev( const char16_t* aText, uint32_t aLen, uint32_t aPos);
+  int32_t Prev( const char16_t* aText, uint32_t aLen, uint32_t aPos) MOZ_OVERRIDE;
 
   virtual void GetJISx4051Breaks(const char16_t* aText, uint32_t aLength,
                                  uint8_t aBreakMode,
-                                 uint8_t* aBreakBefore);
+                                 uint8_t* aBreakBefore) MOZ_OVERRIDE;
   virtual void GetJISx4051Breaks(const uint8_t* aText, uint32_t aLength,
                                  uint8_t aBreakMode,
-                                 uint8_t* aBreakBefore);
+                                 uint8_t* aBreakBefore) MOZ_OVERRIDE;
 
 private:
   int32_t WordMove(const char16_t* aText, uint32_t aLen, uint32_t aPos,
                    int8_t aDirection);
 };
 
 #endif  /* nsJISx4051LineBreaker_h__ */
--- a/intl/lwbrk/nsSampleWordBreaker.h
+++ b/intl/lwbrk/nsSampleWordBreaker.h
@@ -22,21 +22,21 @@ typedef enum {
 class nsSampleWordBreaker : public nsIWordBreaker
 {
   NS_DECL_ISUPPORTS
 public:
 
   nsSampleWordBreaker() ;
 
   bool BreakInBetween(const char16_t* aText1 , uint32_t aTextLen1,
-                        const char16_t* aText2 , uint32_t aTextLen2);
+                        const char16_t* aText2 , uint32_t aTextLen2) MOZ_OVERRIDE;
   nsWordRange FindWord(const char16_t* aText1 , uint32_t aTextLen1,
-                       uint32_t aOffset);
+                       uint32_t aOffset) MOZ_OVERRIDE;
 
-  int32_t NextWord(const char16_t* aText, uint32_t aLen, uint32_t aPos);
+  int32_t NextWord(const char16_t* aText, uint32_t aLen, uint32_t aPos) MOZ_OVERRIDE;
 
 protected:
   uint8_t  GetClass(char16_t aChar);
 
   virtual ~nsSampleWordBreaker();
 };
 
 #endif  /* nsSampleWordBreaker_h__ */
--- a/intl/uconv/nsUCSupport.h
+++ b/intl/uconv/nsUCSupport.h
@@ -76,18 +76,18 @@ public:
   /**
    * Class constructor.
    */
   nsBasicDecoderSupport();
 
   //--------------------------------------------------------------------
   // Interface nsIUnicodeDecoder [declaration]
 
-  virtual void SetInputErrorBehavior(int32_t aBehavior);
-  virtual char16_t GetCharacterForUnMapped();
+  virtual void SetInputErrorBehavior(int32_t aBehavior) MOZ_OVERRIDE;
+  virtual char16_t GetCharacterForUnMapped() MOZ_OVERRIDE;
 
 protected:
   int32_t   mErrBehavior;
 
   /**
    * Class destructor.
    */
   virtual ~nsBasicDecoderSupport();
--- a/intl/uconv/nsUnicodeToUTF8.h
+++ b/intl/uconv/nsUnicodeToUTF8.h
@@ -39,26 +39,26 @@ public:
   /**
    * Class constructor.
    */
   nsUnicodeToUTF8() {mHighSurrogate = 0;}
 
   NS_IMETHOD Convert(const char16_t * aSrc, 
                      int32_t * aSrcLength, 
                      char * aDest, 
-                     int32_t * aDestLength);
+                     int32_t * aDestLength) MOZ_OVERRIDE;
 
-  NS_IMETHOD Finish(char * aDest, int32_t * aDestLength);
+  NS_IMETHOD Finish(char * aDest, int32_t * aDestLength) MOZ_OVERRIDE;
 
   NS_IMETHOD GetMaxLength(const char16_t * aSrc, int32_t aSrcLength, 
-      int32_t * aDestLength);
+      int32_t * aDestLength) MOZ_OVERRIDE;
 
-  NS_IMETHOD Reset() {mHighSurrogate = 0; return NS_OK;}
+  NS_IMETHOD Reset() MOZ_OVERRIDE {mHighSurrogate = 0; return NS_OK;}
 
   NS_IMETHOD SetOutputErrorBehavior(int32_t aBehavior, 
-    nsIUnicharEncoder * aEncoder, char16_t aChar) {return NS_OK;}
+    nsIUnicharEncoder * aEncoder, char16_t aChar) MOZ_OVERRIDE {return NS_OK;}
 
 protected:
   char16_t mHighSurrogate;
 
 };
 
 #endif /* nsUnicodeToUTF8_h___ */
--- a/intl/unicharutil/nsCaseConversionImp2.h
+++ b/intl/unicharutil/nsCaseConversionImp2.h
@@ -14,22 +14,22 @@
 class nsCaseConversionImp2 : public nsICaseConversion { 
   NS_DECL_THREADSAFE_ISUPPORTS 
 
 public:
   virtual ~nsCaseConversionImp2() { }
 
   static nsCaseConversionImp2* GetInstance();
 
-  NS_IMETHOD ToUpper(char16_t aChar, char16_t* aReturn);
+  NS_IMETHOD ToUpper(char16_t aChar, char16_t* aReturn) MOZ_OVERRIDE;
 
-  NS_IMETHOD ToLower(char16_t aChar, char16_t* aReturn);
+  NS_IMETHOD ToLower(char16_t aChar, char16_t* aReturn) MOZ_OVERRIDE;
 
-  NS_IMETHOD ToTitle(char16_t aChar, char16_t* aReturn);
+  NS_IMETHOD ToTitle(char16_t aChar, char16_t* aReturn) MOZ_OVERRIDE;
 
-  NS_IMETHOD ToUpper(const char16_t* anArray, char16_t* aReturn, uint32_t aLen);
+  NS_IMETHOD ToUpper(const char16_t* anArray, char16_t* aReturn, uint32_t aLen) MOZ_OVERRIDE;
 
-  NS_IMETHOD ToLower(const char16_t* anArray, char16_t* aReturn, uint32_t aLen);
+  NS_IMETHOD ToLower(const char16_t* anArray, char16_t* aReturn, uint32_t aLen) MOZ_OVERRIDE;
 
-  NS_IMETHOD CaseInsensitiveCompare(const char16_t* aLeft, const char16_t* aRight, uint32_t aLength, int32_t *aResult);
+  NS_IMETHOD CaseInsensitiveCompare(const char16_t* aLeft, const char16_t* aRight, uint32_t aLength, int32_t *aResult) MOZ_OVERRIDE;
 };
 
 #endif
--- a/intl/unicharutil/nsCategoryImp.h
+++ b/intl/unicharutil/nsCategoryImp.h
@@ -11,12 +11,12 @@ class nsCategoryImp : public nsIUGenCate
    NS_DECL_THREADSAFE_ISUPPORTS
    
 public:
    static nsCategoryImp* GetInstance();
     
    /**
     * Give a Unichar, return a nsUGenCategory
     */
-   virtual nsUGenCategory Get(uint32_t aChar);
+   virtual nsUGenCategory Get(uint32_t aChar) MOZ_OVERRIDE;
 };
 
 #endif  /* nsCategoryImp_h__ */
--- a/intl/unicharutil/nsEntityConverter.h
+++ b/intl/unicharutil/nsEntityConverter.h
@@ -34,20 +34,20 @@ public:
 	//
 	// nsISupports
 	//
 	NS_DECL_ISUPPORTS
 
 	//
 	// nsIEntityConverter
 	//
-	NS_IMETHOD ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval);
-	NS_IMETHOD ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval);
+	NS_IMETHOD ConvertUTF32ToEntity(uint32_t character, uint32_t entityVersion, char **_retval) MOZ_OVERRIDE;
+	NS_IMETHOD ConvertToEntity(char16_t character, uint32_t entityVersion, char **_retval) MOZ_OVERRIDE;
 
-	NS_IMETHOD ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval);
+	NS_IMETHOD ConvertToEntities(const char16_t *inString, uint32_t entityVersion, char16_t **_retval) MOZ_OVERRIDE;
 
 protected:
 
   // load a version property file and generate a version list (number/name pair)
   NS_IMETHOD LoadVersionPropertyFile();
 
   // map version number to version string
   const char16_t* GetVersionName(uint32_t versionNumber);
--- a/intl/unicharutil/nsSaveAsCharset.h
+++ b/intl/unicharutil/nsSaveAsCharset.h
@@ -32,21 +32,21 @@ public:
 	//
 	// nsISupports
 	//
 	NS_DECL_ISUPPORTS
 
 	//
 	// nsIEntityConverter
 	//
-  NS_IMETHOD Init(const char *charset, uint32_t attr, uint32_t entityVersion);
+  NS_IMETHOD Init(const char *charset, uint32_t attr, uint32_t entityVersion) MOZ_OVERRIDE;
 
-  NS_IMETHOD Convert(const char16_t *inString, char **_retval);
+  NS_IMETHOD Convert(const char16_t *inString, char **_retval) MOZ_OVERRIDE;
 
-  NS_IMETHODIMP GetCharset(char * *aCharset);
+  NS_IMETHODIMP GetCharset(char * *aCharset) MOZ_OVERRIDE;
 
 protected:
 
   virtual ~nsSaveAsCharset();
 
   NS_IMETHOD DoCharsetConversion(const char16_t *inString, char **outString);
 
   NS_IMETHOD DoConversionFallBack(uint32_t inUCS4, char *outString, int32_t bufferLength);
--- a/intl/unicharutil/nsUnicodeNormalizer.h
+++ b/intl/unicharutil/nsUnicodeNormalizer.h
@@ -15,20 +15,20 @@ nsresult NS_NewUnicodeNormalizer(nsISupp
 
 
 class nsUnicodeNormalizer : public nsIUnicodeNormalizer {
 public:
    nsUnicodeNormalizer();
 
    NS_DECL_ISUPPORTS 
 
-   NS_IMETHOD NormalizeUnicodeNFD( const nsAString& aSrc, nsAString& aDest);
-   NS_IMETHOD NormalizeUnicodeNFC( const nsAString& aSrc, nsAString& aDest);
-   NS_IMETHOD NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest);
-   NS_IMETHOD NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest);
+   NS_IMETHOD NormalizeUnicodeNFD( const nsAString& aSrc, nsAString& aDest) MOZ_OVERRIDE;
+   NS_IMETHOD NormalizeUnicodeNFC( const nsAString& aSrc, nsAString& aDest) MOZ_OVERRIDE;
+   NS_IMETHOD NormalizeUnicodeNFKD( const nsAString& aSrc, nsAString& aDest) MOZ_OVERRIDE;
+   NS_IMETHOD NormalizeUnicodeNFKC( const nsAString& aSrc, nsAString& aDest) MOZ_OVERRIDE;
 
    // low-level access to the composition data needed for HarfBuzz callbacks
    static bool Compose(uint32_t a, uint32_t b, uint32_t *ab);
    static bool DecomposeNonRecursively(uint32_t comp, uint32_t *c1, uint32_t *c2);
 
 private:
    virtual ~nsUnicodeNormalizer();
 };
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1110,22 +1110,18 @@ Parser<ParseHandler>::functionBody(Funct
         return null();
 
     return pn;
 }
 
 /* See comment for use in Parser::functionDef. */
 template <>
 bool
-Parser<FullParseHandler>::makeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom,
-                                         bool *pbodyLevelHoistedUse)
-{
-    // See comment in addFreeVariablesFromLazyFunction.
-    *pbodyLevelHoistedUse = !!dn->dn_uses;
-
+Parser<FullParseHandler>::makeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *atom)
+{
     /* Turn pn into a definition. */
     pc->updateDecl(atom, pn);
 
     /* Change all uses of dn to be uses of pn. */
     for (ParseNode *pnu = dn->dn_uses; pnu; pnu = pnu->pn_link) {
         MOZ_ASSERT(pnu->isUsed());
         MOZ_ASSERT(!pnu->isDefn());
         pnu->pn_lexdef = (Definition *) pn;
@@ -1360,20 +1356,21 @@ AssociateUsesWithOuterDefinition(ParseNo
  * Beware: this function is called for functions nested in other functions or
  * global scripts but not for functions compiled through the Function
  * constructor or JSAPI. To always execute code when a function has finished
  * parsing, use Parser::functionBody.
  */
 template <>
 bool
 Parser<FullParseHandler>::leaveFunction(ParseNode *fn, ParseContext<FullParseHandler> *outerpc,
-                                        bool bodyLevelHoistedUse, FunctionSyntaxKind kind)
+                                        FunctionSyntaxKind kind)
 {
     outerpc->blockidGen = pc->blockidGen;
 
+    bool bodyLevel = outerpc->atBodyLevel();
     FunctionBox *funbox = fn->pn_funbox;
     MOZ_ASSERT(funbox == pc->sc->asFunctionBox());
 
     /* Propagate unresolved lexical names up to outerpc->lexdeps. */
     if (pc->lexdeps->count()) {
         for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
             JSAtom *atom = r.front().key();
             Definition *dn = r.front().value().get<FullParseHandler>();
@@ -1433,35 +1430,43 @@ Parser<FullParseHandler>::leaveFunction(
              *
              * The dn == outer_dn case arises with generator expressions
              * (see LegacyCompExprTransplanter::transplant, the PN_CODE/PN_NAME
              * case), and nowhere else, currently.
              */
             if (dn != outer_dn) {
                 if (ParseNode *pnu = dn->dn_uses) {
                     // In ES6, lexical bindings cannot be accessed until
-                    // initialized. If we are parsing a function with a
-                    // hoisted body-level use, all free variables that get
-                    // linked to an outer lexical binding need to be marked as
-                    // needing dead zone checks. e.g.,
+                    // initialized. If we are parsing a body-level function,
+                    // it is hoisted to the top, so we conservatively mark all
+                    // uses linked to an outer lexical binding as needing TDZ
+                    // checks. e.g.,
                     //
                     // function outer() {
-                    //   inner();
+                    //   inner2();
                     //   function inner() { use(x); }
+                    //   function inner2() { inner(); }
                     //   let x;
                     // }
                     //
                     // The use of 'x' inside 'inner' needs to be marked.
                     //
+                    // Note that to not be fully conservative requires a call
+                    // graph analysis of all body-level functions to compute
+                    // the transitive closure of which hoisted body level use
+                    // of which function forces TDZ checks on which uses. This
+                    // is unreasonably difficult to do in a single pass parser
+                    // like ours.
+                    //
                     // Similarly, if we are closing over a lexical binding
                     // from another case in a switch, those uses also need to
                     // be marked as needing dead zone checks.
                     RootedAtom name(context, atom);
                     bool markUsesAsLexical = outer_dn->isLexical() &&
-                                             (bodyLevelHoistedUse ||
+                                             (bodyLevel ||
                                               IsNonDominatingInScopedSwitch(outerpc, name, outer_dn));
                     AssociateUsesWithOuterDefinition(pnu, dn, outer_dn, markUsesAsLexical);
                 }
 
                 outer_dn->pn_dflags |= dn->pn_dflags & ~PND_PLACEHOLDER;
             }
 
             /* Mark the outer dn as escaping. */
@@ -1472,22 +1477,22 @@ Parser<FullParseHandler>::leaveFunction(
     InternalHandle<Bindings*> bindings =
         InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
     return pc->generateFunctionBindings(context, tokenStream, alloc, bindings);
 }
 
 template <>
 bool
 Parser<SyntaxParseHandler>::leaveFunction(Node fn, ParseContext<SyntaxParseHandler> *outerpc,
-                                          bool bodyLevelHoistedUse, FunctionSyntaxKind kind)
+                                          FunctionSyntaxKind kind)
 {
     outerpc->blockidGen = pc->blockidGen;
 
     FunctionBox *funbox = pc->sc->asFunctionBox();
-    return addFreeVariablesFromLazyFunction(funbox->function(), outerpc, bodyLevelHoistedUse);
+    return addFreeVariablesFromLazyFunction(funbox->function(), outerpc);
 }
 
 /*
  * defineArg is called for both the arguments of a regular function definition
  * and the arguments specified by the Function constructor.
  *
  * The 'disallowDuplicateArgs' bool indicates whether the use of another
  * feature (destructuring or default arguments) disables duplicate arguments.
@@ -1783,22 +1788,20 @@ Parser<ParseHandler>::functionArguments(
 
     return true;
 }
 
 template <>
 bool
 Parser<FullParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
                                                   ParseNode **pn_, FunctionSyntaxKind kind,
-                                                  bool *pbodyProcessed,
-                                                  bool *pbodyLevelHoistedUse)
+                                                  bool *pbodyProcessed)
 {
     ParseNode *&pn = *pn_;
     *pbodyProcessed = false;
-    *pbodyLevelHoistedUse = false;
 
     /* Function statements add a binding to the enclosing scope. */
     bool bodyLevel = pc->atBodyLevel();
 
     if (kind == Statement) {
         /*
          * Handle redeclaration and optimize cases where we can statically bind the
          * function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
@@ -1838,17 +1841,17 @@ Parser<FullParseHandler>::checkFunctionD
                     // remains a definition. But change the function node pn so
                     // that it knows where the argument is located.
                     pn->setOp(JSOP_GETARG);
                     pn->setDefn(true);
                     pn->pn_cookie = dn->pn_cookie;
                     pn->pn_dflags |= PND_BOUND;
                     dn->markAsAssigned();
                 } else {
-                    if (!makeDefIntoUse(dn, pn, funName, pbodyLevelHoistedUse))
+                    if (!makeDefIntoUse(dn, pn, funName))
                         return false;
                 }
             }
         } else if (bodyLevel) {
             /*
              * If this function was used before it was defined, claim the
              * pre-created definition node for this function that primaryExpr
              * put in pc->lexdeps on first forward reference, and recycle pn.
@@ -1861,18 +1864,16 @@ Parser<FullParseHandler>::checkFunctionD
                 fn->pn_pos.end = pn->pn_pos.end;
 
                 fn->pn_body = nullptr;
                 fn->pn_cookie.makeFree();
 
                 pc->lexdeps->remove(funName);
                 handler.freeTree(pn);
                 pn = fn;
-
-                *pbodyLevelHoistedUse = true;
             }
 
             if (!pc->define(tokenStream, funName, pn, Definition::VAR))
                 return false;
         }
 
         if (bodyLevel) {
             MOZ_ASSERT(pn->functionIsHoisted());
@@ -1931,17 +1932,17 @@ Parser<FullParseHandler>::checkFunctionD
     if (LazyScript *lazyOuter = handler.lazyOuterFunction()) {
         JSFunction *fun = handler.nextLazyInnerFunction();
         MOZ_ASSERT(!fun->isLegacyGenerator());
         FunctionBox *funbox = newFunctionBox(pn, fun, pc, Directives(/* strict = */ false),
                                              fun->generatorKind());
         if (!funbox)
             return false;
 
-        if (!addFreeVariablesFromLazyFunction(fun, pc, *pbodyLevelHoistedUse))
+        if (!addFreeVariablesFromLazyFunction(fun, pc))
             return false;
 
         // The position passed to tokenStream.advance() is an offset of the sort
         // returned by userbuf.offset() and expected by userbuf.rawCharPtrAt(),
         // while LazyScript::{begin,end} offsets are relative to the outermost
         // script source.
         uint32_t userbufBase = lazyOuter->begin() - lazyOuter->column();
         tokenStream.advance(fun->lazyScript()->end() - userbufBase);
@@ -1961,24 +1962,22 @@ PropagateTransitiveParseFlags(const T *i
      outer->setBindingsAccessedDynamically();
    if (inner->hasDebuggerStatement())
      outer->setHasDebuggerStatement();
 }
 
 template <typename ParseHandler>
 bool
 Parser<ParseHandler>::addFreeVariablesFromLazyFunction(JSFunction *fun,
-                                                       ParseContext<ParseHandler> *pc,
-                                                       bool bodyLevelHoistedUse)
-{
-    MOZ_ASSERT_IF(bodyLevelHoistedUse, fun->displayAtom() && pc->atBodyLevel());
-
+                                                       ParseContext<ParseHandler> *pc)
+{
     // Update any definition nodes in this context according to free variables
     // in a lazily parsed inner function.
 
+    bool bodyLevel = pc->atBodyLevel();
     LazyScript *lazy = fun->lazyScript();
     LazyScript::FreeVariable *freeVariables = lazy->freeVariables();
     for (size_t i = 0; i < lazy->numFreeVariables(); i++) {
         JSAtom *atom = freeVariables[i].atom();
 
         // 'arguments' will be implicitly bound within the inner function.
         if (atom == context->names().arguments)
             continue;
@@ -2001,36 +2000,34 @@ Parser<ParseHandler>::addFreeVariablesFr
         // dead zone check.
         //
         // Subtlety: we don't need to check for closing over a non-dominating
         // lexical binding in a switch, as lexical declarations currently
         // disable syntax parsing. So a non-dominating but textually preceding
         // lexical declaration would have aborted syntax parsing, and a
         // textually following declaration would return true for
         // handler.isPlaceholderDefinition(dn) below.
-        if (handler.isPlaceholderDefinition(dn) || bodyLevelHoistedUse)
+        if (handler.isPlaceholderDefinition(dn) || bodyLevel)
             freeVariables[i].setIsHoistedUse();
 
         /* Mark the outer dn as escaping. */
         handler.setFlag(handler.getDefinitionNode(dn), PND_CLOSED);
     }
 
     PropagateTransitiveParseFlags(lazy, pc->sc);
     return true;
 }
 
 template <>
 bool
 Parser<SyntaxParseHandler>::checkFunctionDefinition(HandlePropertyName funName,
                                                     Node *pn, FunctionSyntaxKind kind,
-                                                    bool *pbodyProcessed,
-                                                    bool *pbodyLevelHoistedUse)
+                                                    bool *pbodyProcessed)
 {
     *pbodyProcessed = false;
-    *pbodyLevelHoistedUse = false;
 
     /* Function statements add a binding to the enclosing scope. */
     bool bodyLevel = pc->atBodyLevel();
 
     if (kind == Statement) {
         /*
          * Handle redeclaration and optimize cases where we can statically bind the
          * function (thereby avoiding JSOP_DEFFUN and dynamic name lookup).
@@ -2044,20 +2041,18 @@ Parser<SyntaxParseHandler>::checkFunctio
                 if (!AtomToPrintableString(context, funName, &name) ||
                     !report(ParseError, false, null(), JSMSG_REDECLARED_VAR,
                             Definition::kindString(dn), name.ptr()))
                 {
                     return false;
                 }
             }
         } else if (bodyLevel) {
-            if (pc->lexdeps.lookupDefn<SyntaxParseHandler>(funName)) {
-                *pbodyLevelHoistedUse = true;
+            if (pc->lexdeps.lookupDefn<SyntaxParseHandler>(funName))
                 pc->lexdeps->remove(funName);
-            }
 
             if (!pc->define(tokenStream, funName, *pn, Definition::VAR))
                 return false;
         }
 
         if (!bodyLevel && funName == context->names().arguments)
             pc->sc->setBindingsAccessedDynamically();
     }
@@ -2144,18 +2139,17 @@ Parser<ParseHandler>::functionDef(Handle
     MOZ_ASSERT_IF(kind == Statement, funName);
 
     /* Make a TOK_FUNCTION node. */
     Node pn = handler.newFunctionDefinition();
     if (!pn)
         return null();
 
     bool bodyProcessed;
-    bool bodyLevelHoistedUse;
-    if (!checkFunctionDefinition(funName, &pn, kind, &bodyProcessed, &bodyLevelHoistedUse))
+    if (!checkFunctionDefinition(funName, &pn, kind, &bodyProcessed))
         return null();
 
     if (bodyProcessed)
         return pn;
 
     RootedObject proto(context);
     if (generatorKind == StarGenerator) {
         // If we are off the main thread, the generator meta-objects have
@@ -2176,18 +2170,17 @@ Parser<ParseHandler>::functionDef(Handle
     // of directives.
     Directives directives(pc);
     Directives newDirectives = directives;
 
     TokenStream::Position start(keepAtoms);
     tokenStream.tell(&start);
 
     while (true) {
-        if (functionArgsAndBody(pn, fun, type, kind, generatorKind, directives, &newDirectives,
-                                bodyLevelHoistedUse))
+        if (functionArgsAndBody(pn, fun, type, kind, generatorKind, directives, &newDirectives))
             break;
         if (tokenStream.hadError() || directives == newDirectives)
             return null();
 
         // Assignment must be monotonic to prevent reparsing iloops
         MOZ_ASSERT_IF(directives.strict(), newDirectives.strict());
         MOZ_ASSERT_IF(directives.asmJS(), newDirectives.asmJS());
         directives = newDirectives;
@@ -2293,18 +2286,17 @@ Parser<SyntaxParseHandler>::finishFuncti
 }
 
 template <>
 bool
 Parser<FullParseHandler>::functionArgsAndBody(ParseNode *pn, HandleFunction fun,
                                               FunctionType type, FunctionSyntaxKind kind,
                                               GeneratorKind generatorKind,
                                               Directives inheritedDirectives,
-                                              Directives *newDirectives,
-                                              bool bodyLevelHoistedUse)
+                                              Directives *newDirectives)
 {
     ParseContext<FullParseHandler> *outerpc = pc;
 
     // Create box for fun->object early to protect against last-ditch GC.
     FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
     if (!funbox)
         return false;
 
@@ -2346,17 +2338,17 @@ Parser<FullParseHandler>::functionArgsAn
             parser->tokenStream.tell(&position);
             if (!tokenStream.seek(position, parser->tokenStream))
                 return false;
 
             // Update the end position of the parse node.
             pn->pn_pos.end = tokenStream.currentToken().pos.end;
         }
 
-        if (!addFreeVariablesFromLazyFunction(fun, pc, bodyLevelHoistedUse))
+        if (!addFreeVariablesFromLazyFunction(fun, pc))
             return false;
 
         pn->pn_blockid = outerpc->blockid();
         PropagateTransitiveParseFlags(funbox, outerpc->sc);
         return true;
     } while (false);
 
     // Continue doing a full parse for this inner function.
@@ -2364,17 +2356,17 @@ Parser<FullParseHandler>::functionArgsAn
                                          outerpc->staticLevel + 1, outerpc->blockidGen,
                                          /* blockScopeDepth = */ 0);
     if (!funpc.init(tokenStream))
         return false;
 
     if (!functionArgsAndBodyGeneric(pn, fun, type, kind))
         return false;
 
-    if (!leaveFunction(pn, outerpc, bodyLevelHoistedUse, kind))
+    if (!leaveFunction(pn, outerpc, kind))
         return false;
 
     pn->pn_blockid = outerpc->blockid();
 
     /*
      * Fruit of the poisonous tree: if a closure contains a dynamic name access
      * (eval, with, etc), we consider the parent to do the same. The reason is
      * that the deoptimizing effects of dynamic name access apply equally to
@@ -2385,18 +2377,17 @@ Parser<FullParseHandler>::functionArgsAn
 }
 
 template <>
 bool
 Parser<SyntaxParseHandler>::functionArgsAndBody(Node pn, HandleFunction fun,
                                                 FunctionType type, FunctionSyntaxKind kind,
                                                 GeneratorKind generatorKind,
                                                 Directives inheritedDirectives,
-                                                Directives *newDirectives,
-                                                bool bodyLevelHoistedUse)
+                                                Directives *newDirectives)
 {
     ParseContext<SyntaxParseHandler> *outerpc = pc;
 
     // Create box for fun->object early to protect against last-ditch GC.
     FunctionBox *funbox = newFunctionBox(pn, fun, pc, inheritedDirectives, generatorKind);
     if (!funbox)
         return false;
 
@@ -2405,17 +2396,17 @@ Parser<SyntaxParseHandler>::functionArgs
                                            outerpc->staticLevel + 1, outerpc->blockidGen,
                                            /* blockScopeDepth = */ 0);
     if (!funpc.init(tokenStream))
         return false;
 
     if (!functionArgsAndBodyGeneric(pn, fun, type, kind))
         return false;
 
-    if (!leaveFunction(pn, outerpc, bodyLevelHoistedUse, kind))
+    if (!leaveFunction(pn, outerpc, kind))
         return false;
 
     // This is a lazy function inner to another lazy function. Remember the
     // inner function so that if the outer function is eventually parsed we do
     // not need any further parsing or processing of the inner function.
     MOZ_ASSERT(fun->lazyScript());
     return outerpc->innerFunctions.append(fun);
 }
@@ -7121,17 +7112,17 @@ Parser<ParseHandler>::generatorComprehen
 
     // Note that if we ever start syntax-parsing generators, we will also
     // need to propagate the closed-over variable set to the inner
     // lazyscript, as in finishFunctionDefinition.
     handler.setFunctionBody(genfn, body);
 
     PropagateTransitiveParseFlags(genFunbox, outerpc->sc);
 
-    if (!leaveFunction(genfn, outerpc, /* bodyLevelHoistedUse = */ false))
+    if (!leaveFunction(genfn, outerpc))
         return null();
 
     return genfn;
 }
 
 #if JS_HAS_GENERATOR_EXPRS
 
 /*
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -582,18 +582,17 @@ class Parser : private JS::AutoGCRooter,
      */
     bool functionArguments(FunctionSyntaxKind kind, Node *list, Node funcpn, bool *hasRest);
 
     Node functionDef(HandlePropertyName name, FunctionType type, FunctionSyntaxKind kind,
                      GeneratorKind generatorKind);
     bool functionArgsAndBody(Node pn, HandleFunction fun,
                              FunctionType type, FunctionSyntaxKind kind,
                              GeneratorKind generatorKind,
-                             Directives inheritedDirectives, Directives *newDirectives,
-                             bool bodyLevelHoistedUse);
+                             Directives inheritedDirectives, Directives *newDirectives);
 
     Node unaryOpExpr(ParseNodeKind kind, JSOp op, uint32_t begin);
 
     Node condition();
 
     Node generatorComprehensionLambda(GeneratorKind comprehensionKind, unsigned begin,
                                       Node innerStmt);
 
@@ -633,22 +632,21 @@ class Parser : private JS::AutoGCRooter,
         KeyedDestructuringAssignment,
         IncDecAssignment
     };
 
     bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor);
     bool matchInOrOf(bool *isForInp, bool *isForOfp);
 
     bool checkFunctionArguments();
-    bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom, bool *pbodyLevelHoistedUse);
+    bool makeDefIntoUse(Definition *dn, Node pn, JSAtom *atom);
     bool checkFunctionDefinition(HandlePropertyName funName, Node *pn, FunctionSyntaxKind kind,
-                                 bool *pbodyProcessed, bool *pbodyLevelHoistedUse);
+                                 bool *pbodyProcessed);
     bool finishFunctionDefinition(Node pn, FunctionBox *funbox, Node prelude, Node body);
-    bool addFreeVariablesFromLazyFunction(JSFunction *fun, ParseContext<ParseHandler> *pc,
-                                          bool bodyLevelHoistedUse);
+    bool addFreeVariablesFromLazyFunction(JSFunction *fun, ParseContext<ParseHandler> *pc);
 
     bool isValidForStatementLHS(Node pn1, JSVersion version, bool forDecl, bool forEach,
                                 ParseNodeKind headKind);
     bool checkForHeadConstInitializers(Node pn1);
     bool checkAndMarkAsIncOperand(Node kid, TokenKind tt, bool preorder);
     bool checkStrictAssignment(Node lhs);
     bool checkStrictBinding(PropertyName *name, Node pn);
     bool defineArg(Node funcpn, HandlePropertyName name,
@@ -690,17 +688,17 @@ class Parser : private JS::AutoGCRooter,
 
     static Node null() { return ParseHandler::null(); }
 
     bool reportRedeclaration(Node pn, Definition::Kind redeclKind, HandlePropertyName name);
     bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);
     DefinitionNode getOrCreateLexicalDependency(ParseContext<ParseHandler> *pc, JSAtom *atom);
 
     bool leaveFunction(Node fn, ParseContext<ParseHandler> *outerpc,
-                       bool bodyLevelHoistedUse, FunctionSyntaxKind kind = Expression);
+                       FunctionSyntaxKind kind = Expression);
 
     TokenPos pos() const { return tokenStream.currentToken().pos; }
 
     bool asmJS(Node list);
 
     void accumulateTelemetry();
 
     friend class LegacyCompExprTransplanter;
deleted file mode 100644
--- a/js/src/gc/ForkJoinNursery-inl.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef gc_ForkJoinNursery_inl_h
-#define gc_ForkJoinNursery_inl_h
-
-#ifdef JSGC_FJGENERATIONAL
-
-#include "gc/ForkJoinNursery.h"
-
-#include "jsgc.h"
-
-namespace js {
-namespace gc {
-
-// For the following two predicates we can't check the attributes on
-// the chunk trailer because it's not known whether addr points into a
-// chunk.
-//
-// A couple of optimizations are possible if performance is an issue:
-//
-//  - The loop can be unrolled, and we can arrange for all array entries
-//    to be valid for this purpose so that the bound is constant.
-//  - The per-chunk test can be reduced to testing whether the high bits
-//    of the object pointer and the high bits of the chunk pointer are
-//    the same (and the latter value is essentially space[i]).
-//    Note, experiments with that do not show an improvement yet.
-//  - Taken together, those optimizations yield code that is one LOAD,
-//    one XOR, and one AND for each chunk, with the result being true
-//    iff the resulting value is zero.
-//  - We can have multiple versions of the predicates, and those that
-//    take known-good GCThing types can go directly to the attributes;
-//    it may be possible to ensure that more calls use GCThing types.
-//    Note, this requires the worker ID to be part of the chunk
-//    attribute bit vector.
-//
-// Performance may not be an issue as there may be few survivors of a
-// collection in the ForkJoinNursery and few objects will be tested.
-// If so then the bulk of the calls may come from the code that scans
-// the roots.  Behavior will be workload-dependent however.
-
-MOZ_ALWAYS_INLINE bool
-ForkJoinNursery::isInsideNewspace(const void *addr)
-{
-    uintptr_t p = reinterpret_cast<uintptr_t>(addr);
-    for (unsigned i = 0 ; i <= currentChunk_ ; i++) {
-        if (p >= newspace[i]->start() && p < newspace[i]->end())
-            return true;
-    }
-    return false;
-}
-
-MOZ_ALWAYS_INLINE bool
-ForkJoinNursery::isInsideFromspace(const void *addr)
-{
-    uintptr_t p = reinterpret_cast<uintptr_t>(addr);
-    for (unsigned i = 0 ; i < numFromspaceChunks_ ; i++) {
-        if (p >= fromspace[i]->start() && p < fromspace[i]->end())
-            return true;
-    }
-    return false;
-}
-
-MOZ_ALWAYS_INLINE bool
-ForkJoinNursery::isForwarded(Cell *cell)
-{
-    MOZ_ASSERT(isInsideFromspace(cell));
-    const RelocationOverlay *overlay = RelocationOverlay::fromCell(cell);
-    return overlay->isForwarded();
-}
-
-template <typename T>
-MOZ_ALWAYS_INLINE bool
-ForkJoinNursery::getForwardedPointer(T **ref)
-{
-    MOZ_ASSERT(ref);
-    MOZ_ASSERT(isInsideFromspace(*ref));
-    const RelocationOverlay *overlay = RelocationOverlay::fromCell(*ref);
-    if (!overlay->isForwarded())
-        return false;
-    // This static_cast from Cell* restricts T to valid (GC thing) types.
-    *ref = static_cast<T *>(overlay->forwardingAddress());
-    return true;
-}
-
-} // namespace gc
-} // namespace js
-
-#endif // JSGC_FJGENERATIONAL
-
-#endif // gc_ForkJoinNursery_inl_h
deleted file mode 100644
--- a/js/src/gc/ForkJoinNursery.cpp
+++ /dev/null
@@ -1,932 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifdef JSGC_FJGENERATIONAL
-
-#include "gc/ForkJoinNursery-inl.h"
-
-#include "mozilla/IntegerPrintfMacros.h"
-
-#include "prmjtime.h"
-
-#include "gc/Heap.h"
-#include "jit/JitFrames.h"
-#include "jit/RematerializedFrame.h"
-#include "vm/ArrayObject.h"
-#include "vm/ForkJoin.h"
-
-#include "jsgcinlines.h"
-#include "gc/Nursery-inl.h"
-#include "vm/NativeObject-inl.h"
-
-// The ForkJoinNursery provides an object nursery for movable object
-// types for one ForkJoin worker thread.  There is a one-to-one
-// correspondence between ForkJoinNursery and ForkJoinContext.
-//
-// For a general overview of how the ForkJoinNursery fits into the
-// overall PJS system, see the comment block in vm/ForkJoin.h.
-//
-//
-// Invariants on the ForkJoinNursery:
-//
-// Let "the tenured area" from the point of view of one
-// ForkJoinNursery comprise the global tenured area and the nursery's
-// owning worker's private tenured area.  Then:
-//
-// - There can be pointers from the tenured area into a ForkJoinNursery,
-//   and from the ForkJoinNursery into the tenured area
-//
-// - There *cannot* be a pointer from one ForkJoinNursery into
-//   another, or from one private tenured area into another, or from a
-//   ForkJoinNursery into another worker's private tenured are or vice
-//   versa, or from any ForkJoinNursery or private tenured area into
-//   the normal Nursery.
-//
-// For those invariants to hold the normal Nursery must be empty before
-// a ForkJoin section.
-//
-//
-// General description:
-//
-// The nursery maintains a space into which small, movable objects
-// are allocated.  Other objects are allocated directly in the private
-// tenured area for the worker.
-//
-// If an allocation request can't be satisfied because the nursery is
-// full then a /minor collection/ is triggered without bailouts.  This
-// collection copies nursery-allocated objects reachable from the
-// worker's roots into a fresh space.  Then the old space is
-// discarded.
-//
-// Nurseries are maintained in 1MB chunks.  If the live data in a
-// nursery after a collection exceeds some set fraction (currently
-// 1/3) then the nursery is grown, independently of other nurseries.
-//
-// There is an upper limit on the number of chunks in a nursery.  If
-// the live data in a nursery after a collection exceeds the set
-// fraction and the nursery can't grow, then the next collection will
-// be an /evacuating collection/.
-//
-// An evacuating collection copies nursery-allocated objects reachable
-// from the worker's roots into the worker's private tenured area.
-//
-// If an allocation request in the tenured area - whether the request
-// comes from the mutator or from the garbage collector during
-// evacuation - can't be satisified because the tenured area is full,
-// then the worker bails out and triggers a full collection in the
-// ForkJoin worker's zone.  This is expected to happen very rarely in
-// practice.
-//
-// The roots for a collection in the ForkJoinNursery are: the frames
-// of the execution stack, any registered roots on the execution
-// stack, any objects in the private tenured area, and the ForkJoin
-// result object in the common tenured area.
-//
-// The entire private tenured area is considered to be rooted in order
-// not to have to run write barriers during the ForkJoin section.
-// During a minor or evacuating collection in a worker the GC will
-// step through the worker's tenured area, examining each object for
-// pointers into the nursery.
-//
-// The ForkJoinNursery contains its own object tracing machinery for
-// most of the types that can be allocated in the nursery.  But it
-// does not handle all types, and there are two places where the code
-// in ForkJoinNursery loses control of the tracing:
-//
-// - When calling clasp->trace() in traceObject()
-// - When calling MarkForkJoinStack() in forwardFromStack()
-//
-// In both cases:
-//
-// - We pass a ForkJoinNurseryCollectionTracer object with a callback
-//   to ForkJoinNursery::MinorGCCallback
-//
-// - We should only ever end up in MarkInternal() in Marking.cpp, in
-//   the case in that code that calls back to trc->callback.  We
-//   should /never/ end up in functions that trigger use of the mark
-//   stack internal to the general GC's marker.
-//
-// - Any function along the path to MarkInternal() that asks about
-//   whether something is in the nursery or is tenured /must/ be aware
-//   that there can be multiple nursery and tenured areas; assertions
-//   get this wrong a lot of the time and must be fixed when they do.
-//   In practice, such code either must have a case for each nursery
-//   kind or must use the IsInsideNursery(Cell*) method, which looks
-//   only at the chunk tag.
-//
-//
-// Terminological note:
-//
-// - While the mutator is running it is allocating in what's known as
-//   the nursery's "newspace".  The mutator may also allocate directly
-//   in the tenured space, but the tenured space is not part of the
-//   newspace.
-//
-// - While the gc is running, the previous "newspace" has been renamed
-//   as the gc's "fromspace", and the space that objects are copied
-//   into is known as the "tospace".  The tospace may be a nursery
-//   space (during a minor collection), or it may be a tenured space
-//   (during an evacuation collection), but it's always one or the
-//   other, never a combination.  After gc the fromspace is always
-//   discarded.
-//
-// - If the gc copies objects into a nursery tospace then this tospace
-//   becomes known as the "newspace" following gc.  Otherwise, a new
-//   newspace won't be needed (if the parallel section is finished) or
-//   can be created empty (if the gc just needed to evacuate).
-//
-
-namespace js {
-namespace gc {
-
-ForkJoinNursery::ForkJoinNursery(ForkJoinContext *cx, ForkJoinGCShared *shared, Allocator *tenured)
-  : cx_(cx)
-  , tenured_(tenured)
-  , shared_(shared)
-  , evacuationZone_(nullptr)
-  , currentStart_(0)
-  , currentEnd_(0)
-  , position_(0)
-  , currentChunk_(0)
-  , numActiveChunks_(0)
-  , numFromspaceChunks_(0)
-  , mustEvacuate_(false)
-  , isEvacuating_(false)
-  , movedSize_(0)
-  , head_(nullptr)
-  , tail_(&head_)
-  , hugeSlotsNew(0)
-  , hugeSlotsFrom(1)
-{
-    for ( size_t i=0 ; i < MaxNurseryChunks ; i++ ) {
-        newspace[i] = nullptr;
-        fromspace[i] = nullptr;
-    }
-}
-
-ForkJoinNursery::~ForkJoinNursery()
-{
-    for ( size_t i=0 ; i < numActiveChunks_ ; i++ ) {
-        if (newspace[i])
-            shared_->freeNurseryChunk(newspace[i]);
-    }
-}
-
-bool
-ForkJoinNursery::initialize()
-{
-    if (!hugeSlots[hugeSlotsNew].init() || !hugeSlots[hugeSlotsFrom].init())
-        return false;
-    if (!initNewspace())
-        return false;
-    return true;
-}
-
-void
-ForkJoinNursery::minorGC()
-{
-    if (mustEvacuate_) {
-        mustEvacuate_ = false;
-        pjsCollection(Evacuate|Recreate);
-    } else {
-        pjsCollection(Collect|Recreate);
-    }
-}
-
-void
-ForkJoinNursery::evacuatingGC()
-{
-    pjsCollection(Evacuate);
-}
-
-#define TIME_START(name) int64_t timstampStart_##name = PRMJ_Now()
-#define TIME_END(name) int64_t timstampEnd_##name = PRMJ_Now()
-#define TIME_TOTAL(name) (timstampEnd_##name - timstampStart_##name)
-
-void
-ForkJoinNursery::pjsCollection(int op)
-{
-    MOZ_ASSERT((op & Collect) != (op & Evacuate));
-
-    bool evacuate = op & Evacuate;
-    bool recreate = op & Recreate;
-
-    MOZ_ASSERT(!isEvacuating_);
-    MOZ_ASSERT(!evacuationZone_);
-    MOZ_ASSERT(!head_);
-    MOZ_ASSERT(tail_ == &head_);
-
-    JSRuntime *const rt = shared_->runtime();
-    const unsigned currentNumActiveChunks_ = numActiveChunks_;
-    const char *msg = "";
-
-    MOZ_ASSERT(!rt->needsIncrementalBarrier());
-
-    TIME_START(pjsCollection);
-
-    rt->gc.incFJMinorCollecting();
-    if (evacuate) {
-        isEvacuating_ = true;
-        evacuationZone_ = shared_->zone();
-    }
-
-    flip();
-    if (recreate) {
-        if (!initNewspace())
-            CrashAtUnhandlableOOM("Cannot expand PJS nursery during GC");
-        // newspace must be at least as large as fromSpace
-        numActiveChunks_ = currentNumActiveChunks_;
-    }
-    ForkJoinNurseryCollectionTracer trc(rt, this);
-    forwardFromRoots(&trc);
-    collectToFixedPoint(&trc);
-    jit::UpdateJitActivationsForMinorGC<ForkJoinNursery>(TlsPerThreadData.get(), &trc);
-    freeFromspace();
-
-    size_t live = movedSize_;
-    computeNurserySizeAfterGC(live, &msg);
-
-    sweepHugeSlots();
-    MOZ_ASSERT(hugeSlots[hugeSlotsFrom].empty());
-    MOZ_ASSERT_IF(isEvacuating_, hugeSlots[hugeSlotsNew].empty());
-
-    isEvacuating_ = false;
-    evacuationZone_ = nullptr;
-    head_ = nullptr;
-    tail_ = &head_;
-    movedSize_ = 0;
-
-    rt->gc.decFJMinorCollecting();
-
-    TIME_END(pjsCollection);
-
-    // Note, the spew is awk-friendly, non-underlined words serve as markers:
-    //   FJGC _tag_ us _value_ copied _value_ size _value_ _message-word_ ...
-    shared_->spewGC("FJGC %s us %5" PRId64 "  copied %7" PRIu64 "  size %" PRIu64 "  %s",
-                    (evacuate ? "evacuate " : "collect  "),
-                    TIME_TOTAL(pjsCollection),
-                    (uint64_t)live,
-                    (uint64_t)numActiveChunks_*1024*1024,
-                    msg);
-}
-
-#undef TIME_START
-#undef TIME_END
-#undef TIME_TOTAL
-
-void
-ForkJoinNursery::computeNurserySizeAfterGC(size_t live, const char **msg)
-{
-    // Grow the nursery if it is too full.  Do not bother to shrink it - lazy
-    // chunk allocation means that a too-large nursery will not really be a problem,
-    // the entire nursery will be deallocated soon anyway.
-    if (live * NurseryLoadFactor > numActiveChunks_ * ForkJoinNurseryChunk::UsableSize) {
-        if (numActiveChunks_ < MaxNurseryChunks) {
-            while (numActiveChunks_ < MaxNurseryChunks &&
-                   live * NurseryLoadFactor > numActiveChunks_ * ForkJoinNurseryChunk::UsableSize)
-            {
-                ++numActiveChunks_;
-            }
-        } else {
-            // Evacuation will tend to drive us toward the cliff of a bailout GC, which
-            // is not good, probably worse than working within the thread at a higher load
-            // than desirable.
-            //
-            // Thus it's possible to be more sophisticated than this:
-            //
-            // - evacuate only after several minor GCs in a row exceeded the set load
-            // - evacuate only if significantly less space than required is available, eg,
-            //   if only 1/2 the required free space is available
-            *msg = "  Overfull, will evacuate next";
-            mustEvacuate_ = true;
-        }
-    }
-}
-
-void
-ForkJoinNursery::flip()
-{
-    size_t i;
-    for (i=0; i < numActiveChunks_; i++) {
-        if (!newspace[i])
-            break;
-        fromspace[i] = newspace[i];
-        newspace[i] = nullptr;
-        fromspace[i]->trailer.location = gc::ChunkLocationBitPJSFromspace;
-    }
-    numFromspaceChunks_ = i;
-    numActiveChunks_ = 0;
-
-    int tmp = hugeSlotsNew;
-    hugeSlotsNew = hugeSlotsFrom;
-    hugeSlotsFrom = tmp;
-
-    MOZ_ASSERT(hugeSlots[hugeSlotsNew].empty());
-}
-
-void
-ForkJoinNursery::freeFromspace()
-{
-    for (size_t i=0; i < numFromspaceChunks_; i++) {
-        shared_->freeNurseryChunk(fromspace[i]);
-        fromspace[i] = nullptr;
-    }
-    numFromspaceChunks_ = 0;
-}
-
-bool
-ForkJoinNursery::initNewspace()
-{
-    MOZ_ASSERT(newspace[0] == nullptr);
-    MOZ_ASSERT(numActiveChunks_ == 0);
-
-    numActiveChunks_ = 1;
-    return setCurrentChunk(0);
-}
-
-MOZ_ALWAYS_INLINE bool
-ForkJoinNursery::shouldMoveObject(void **thingp)
-{
-    // Note that thingp must really be a T** where T is some GCThing,
-    // ie, something that lives in a chunk (or nullptr).  This should
-    // be the case because the MinorGCCallback is only called on exact
-    // roots on the stack or slots within in tenured objects and not
-    // on slot/element arrays that can be malloc'd; they are forwarded
-    // using the forwardBufferPointer() mechanism.
-    //
-    // The main reason for that restriction is so that we can call a
-    // method here that can check the chunk trailer for the cell (a
-    // future optimization).
-    Cell **cellp = reinterpret_cast<Cell **>(thingp);
-    return isInsideFromspace(*cellp) && !getForwardedPointer(cellp);
-}
-
-/* static */ void
-ForkJoinNursery::MinorGCCallback(JSTracer *trcArg, void **thingp, JSGCTraceKind traceKind)
-{
-    // traceKind can be all sorts of things, when we're marking from stack roots
-    ForkJoinNursery *nursery = static_cast<ForkJoinNurseryCollectionTracer *>(trcArg)->nursery_;
-    if (nursery->shouldMoveObject(thingp)) {
-        // When other types of objects become nursery-allocable then the static_cast
-        // to JSObject * will no longer be valid.
-        MOZ_ASSERT(traceKind == JSTRACE_OBJECT);
-        *thingp = nursery->moveObjectToTospace(static_cast<JSObject *>(*thingp));
-    }
-}
-
-void
-ForkJoinNursery::forwardFromRoots(ForkJoinNurseryCollectionTracer *trc)
-{
-    // There should be no other roots as a result of effect-freedom.
-    forwardFromUpdatable(trc);
-    forwardFromStack(trc);
-    forwardFromTenured(trc);
-    forwardFromRematerializedFrames(trc);
-}
-
-void
-ForkJoinNursery::forwardFromUpdatable(ForkJoinNurseryCollectionTracer *trc)
-{
-    JSObject *obj = shared_->updatable();
-    if (obj)
-        traceObject(trc, obj);
-}
-
-void
-ForkJoinNursery::forwardFromStack(ForkJoinNurseryCollectionTracer *trc)
-{
-    MarkForkJoinStack(trc);
-}
-
-void
-ForkJoinNursery::forwardFromTenured(ForkJoinNurseryCollectionTracer *trc)
-{
-    JSObject *objs[ArenaCellCount];
-    ArenaLists &lists = tenured_->arenas;
-    for (size_t k=0; k < FINALIZE_LIMIT; k++) {
-        AllocKind kind = (AllocKind)k;
-        if (!IsFJNurseryAllocable(kind))
-            continue;
-
-        // When non-JSObject types become nursery-allocable the assumptions in the
-        // loops below will no longer hold; other types than JSObject must be
-        // handled.
-        MOZ_ASSERT(kind <= FINALIZE_OBJECT_LAST);
-
-        // Clear the free list that we're currently allocating out of.
-        lists.purge(kind);
-
-        // Since we only purge once, there must not currently be any partially
-        // full arenas left to allocate out of, or we would break out early.
-        MOZ_ASSERT(!lists.getArenaAfterCursor(kind));
-
-        ArenaIter ai;
-        ai.init(const_cast<Allocator *>(tenured_), kind);
-        for (; !ai.done(); ai.next()) {
-            if (isEvacuating_ && lists.arenaIsInUse(ai.get(), kind))
-                break;
-            // Use ArenaCellIterUnderFinalize, not ...UnderGC, because that side-steps
-            // some assertions in the latter that are wrong for PJS collection.
-            size_t numObjs = 0;
-            for (ArenaCellIterUnderFinalize i(ai.get()); !i.done(); i.next())
-                objs[numObjs++] = i.get<JSObject>();
-            for (size_t i=0; i < numObjs; i++)
-                traceObject(trc, objs[i]);
-        }
-    }
-}
-
-void
-ForkJoinNursery::forwardFromRematerializedFrames(ForkJoinNurseryCollectionTracer *trc)
-{
-    if (cx_->bailoutRecord->hasFrames())
-        jit::RematerializedFrame::MarkInVector(trc, cx_->bailoutRecord->frames());
-}
-
-/*static*/ void
-ForkJoinNursery::forwardBufferPointer(JSTracer *trc, HeapSlot **pSlotsElems)
-{
-    ForkJoinNursery *nursery = static_cast<ForkJoinNurseryCollectionTracer *>(trc)->nursery_;
-    HeapSlot *old = *pSlotsElems;
-
-    if (!nursery->isInsideFromspace(old))
-        return;
-
-    // If the elements buffer is zero length, the "first" item could be inside
-    // of the next object or past the end of the allocable area.  However,
-    // since we always store the runtime as the last word in a nursery chunk,
-    // isInsideFromspace will still be true, even if this zero-size allocation
-    // abuts the end of the allocable area. Thus, it is always safe to read the
-    // first word of |old| here.
-    *pSlotsElems = *reinterpret_cast<HeapSlot **>(old);
-    MOZ_ASSERT(!nursery->isInsideFromspace(*pSlotsElems));
-}
-
-void
-ForkJoinNursery::collectToFixedPoint(ForkJoinNurseryCollectionTracer *trc)
-{
-    for (RelocationOverlay *p = head_; p; p = p->next())
-        traceObject(trc, static_cast<JSObject *>(p->forwardingAddress()));
-}
-
-inline bool
-ForkJoinNursery::setCurrentChunk(int index)
-{
-    MOZ_ASSERT((size_t)index < numActiveChunks_);
-    MOZ_ASSERT(!newspace[index]);
-
-    currentChunk_ = index;
-    ForkJoinNurseryChunk *c = shared_->allocateNurseryChunk();
-    if (!c)
-        return false;
-    c->trailer.runtime = shared_->runtime();
-    c->trailer.location = gc::ChunkLocationBitPJSNewspace;
-    c->trailer.storeBuffer = nullptr;
-    currentStart_ = c->start();
-    currentEnd_ = c->end();
-    position_ = currentStart_;
-    newspace[index] = c;
-    return true;
-}
-
-void *
-ForkJoinNursery::allocate(size_t size)
-{
-    MOZ_ASSERT(position_ >= currentStart_);
-
-    if (currentEnd_ - position_ < size) {
-        if (currentChunk_ + 1 == numActiveChunks_)
-            return nullptr;
-        // Failure to allocate on growth is treated the same as exhaustion
-        // of the nursery.  If this happens during normal execution then
-        // we'll trigger a minor collection.  That collection will likely
-        // fail to obtain a block for the new tospace, and we'll go OOM
-        // immediately; that's expected and acceptable.  If we do continue
-        // to run (because some other thread or process has freed the memory)
-        // then so much the better.
-        if (!setCurrentChunk(currentChunk_ + 1))
-            return nullptr;
-    }
-
-    void *thing = reinterpret_cast<void *>(position_);
-    position_ += size;
-
-    JS_POISON(thing, JS_ALLOCATED_NURSERY_PATTERN, size);
-    return thing;
-}
-
-JSObject *
-ForkJoinNursery::allocateObject(size_t baseSize, size_t numDynamic, bool& tooLarge)
-{
-    // Ensure there's enough space to replace the contents with a RelocationOverlay.
-    MOZ_ASSERT(baseSize >= sizeof(js::gc::RelocationOverlay));
-
-    // Too-large slot arrays cannot be accomodated.
-    if (numDynamic > MaxNurserySlots) {
-        tooLarge = true;
-        return nullptr;
-    }
-
-    // Allocate slots contiguously after the object.
-    size_t totalSize = baseSize + sizeof(HeapSlot) * numDynamic;
-    JSObject *obj = static_cast<JSObject *>(allocate(totalSize));
-    if (!obj) {
-        tooLarge = false;
-        return nullptr;
-    }
-    obj->setInitialSlotsMaybeNonNative(numDynamic
-                                       ? reinterpret_cast<HeapSlot *>(size_t(obj) + baseSize)
-                                       : nullptr);
-    return obj;
-}
-
-HeapSlot *
-ForkJoinNursery::allocateSlots(JSObject *obj, uint32_t nslots)
-{
-    MOZ_ASSERT(obj);
-    MOZ_ASSERT(nslots > 0);
-
-    if (nslots & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
-        return nullptr;
-
-    if (!isInsideNewspace(obj))
-        return obj->zone()->pod_malloc<HeapSlot>(nslots);
-
-    if (nslots > MaxNurserySlots)
-        return allocateHugeSlots(obj, nslots);
-
-    size_t size = nslots * sizeof(HeapSlot);
-    HeapSlot *slots = static_cast<HeapSlot *>(allocate(size));
-    if (slots)
-        return slots;
-
-    return allocateHugeSlots(obj, nslots);
-}
-
-HeapSlot *
-ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
-                                 uint32_t oldCount, uint32_t newCount)
-{
-    if (newCount & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
-        return nullptr;
-
-    if (!isInsideNewspace(obj)) {
-        MOZ_ASSERT_IF(oldSlots, !isInsideNewspace(oldSlots));
-        return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
-    }
-
-    if (!isInsideNewspace(oldSlots))
-        return reallocateHugeSlots(obj, oldSlots, oldCount, newCount);
-
-    // No-op if we're shrinking, we can't make use of the freed portion.
-    if (newCount < oldCount)
-        return oldSlots;
-
-    HeapSlot *newSlots = allocateSlots(obj, newCount);
-    if (!newSlots)
-        return nullptr;
-
-    size_t oldSize = oldCount * sizeof(HeapSlot);
-    js_memcpy(newSlots, oldSlots, oldSize);
-    return newSlots;
-}
-
-ObjectElements *
-ForkJoinNursery::allocateElements(JSObject *obj, uint32_t nelems)
-{
-    MOZ_ASSERT(nelems >= ObjectElements::VALUES_PER_HEADER);
-    return reinterpret_cast<ObjectElements *>(allocateSlots(obj, nelems));
-}
-
-ObjectElements *
-ForkJoinNursery::reallocateElements(JSObject *obj, ObjectElements *oldHeader,
-                                    uint32_t oldCount, uint32_t newCount)
-{
-    HeapSlot *slots = reallocateSlots(obj, reinterpret_cast<HeapSlot *>(oldHeader),
-                                      oldCount, newCount);
-    return reinterpret_cast<ObjectElements *>(slots);
-}
-
-void
-ForkJoinNursery::freeSlots(HeapSlot *slots)
-{
-    if (!isInsideNewspace(slots)) {
-        hugeSlots[hugeSlotsNew].remove(slots);
-        js_free(slots);
-    }
-}
-
-HeapSlot *
-ForkJoinNursery::allocateHugeSlots(JSObject *obj, size_t nslots)
-{
-    if (nslots & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
-        return nullptr;
-
-    HeapSlot *slots = obj->zone()->pod_malloc<HeapSlot>(nslots);
-    if (!slots)
-        return slots;
-
-    // If this put fails, we will only leak the slots.
-    (void)hugeSlots[hugeSlotsNew].put(slots);
-    return slots;
-}
-
-HeapSlot *
-ForkJoinNursery::reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
-                                     uint32_t oldCount, uint32_t newCount)
-{
-    HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
-    if (!newSlots)
-        return newSlots;
-
-    if (oldSlots != newSlots) {
-        hugeSlots[hugeSlotsNew].remove(oldSlots);
-        // If this put fails, we will only leak the slots.
-        (void)hugeSlots[hugeSlotsNew].put(newSlots);
-    }
-    return newSlots;
-}
-
-void
-ForkJoinNursery::sweepHugeSlots()
-{
-    for (HugeSlotsSet::Range r = hugeSlots[hugeSlotsFrom].all(); !r.empty(); r.popFront())
-        js_free(r.front());
-    hugeSlots[hugeSlotsFrom].clear();
-}
-
-MOZ_ALWAYS_INLINE void
-ForkJoinNursery::traceObject(ForkJoinNurseryCollectionTracer *trc, JSObject *obj)
-{
-    const Class *clasp = obj->getClass();
-    if (clasp->trace)
-        clasp->trace(trc, obj);
-
-    if (!obj->isNative())
-        return;
-    NativeObject *nobj = &obj->as<NativeObject>();
-
-    if (!nobj->hasEmptyElements())
-        markSlots(nobj->getDenseElements(), nobj->getDenseInitializedLength());
-
-    HeapSlot *fixedStart, *fixedEnd, *dynStart, *dynEnd;
-    nobj->getSlotRange(0, nobj->slotSpan(), &fixedStart, &fixedEnd, &dynStart, &dynEnd);
-    markSlots(fixedStart, fixedEnd);
-    markSlots(dynStart, dynEnd);
-}
-
-MOZ_ALWAYS_INLINE void
-ForkJoinNursery::markSlots(HeapSlot *vp, uint32_t nslots)
-{
-    markSlots(vp, vp + nslots);
-}
-
-MOZ_ALWAYS_INLINE void
-ForkJoinNursery::markSlots(HeapSlot *vp, HeapSlot *end)
-{
-    for (; vp != end; ++vp)
-        markSlot(vp);
-}
-
-MOZ_ALWAYS_INLINE void
-ForkJoinNursery::markSlot(HeapSlot *slotp)
-{
-    if (!slotp->isObject())
-        return;
-
-    JSObject *obj = &slotp->toObject();
-    if (!isInsideFromspace(obj))
-        return;
-
-    if (getForwardedPointer(&obj)) {
-        slotp->unsafeGet()->setObject(*obj);
-        return;
-    }
-
-    JSObject *moved = static_cast<JSObject *>(moveObjectToTospace(obj));
-    slotp->unsafeGet()->setObject(*moved);
-}
-
-AllocKind
-ForkJoinNursery::getObjectAllocKind(JSObject *obj)
-{
-    if (obj->is<ArrayObject>()) {
-        ArrayObject *aobj = &obj->as<ArrayObject>();
-        MOZ_ASSERT(aobj->numFixedSlots() == 0);
-
-        // Use minimal size object if we are just going to copy the pointer.
-        if (!isInsideFromspace((void *)aobj->getElementsHeader()))
-            return FINALIZE_OBJECT0_BACKGROUND;
-
-        size_t nelements = aobj->getDenseCapacity();
-        return GetBackgroundAllocKind(GetGCArrayKind(nelements));
-    }
-
-    if (obj->is<JSFunction>())
-        return obj->as<JSFunction>().getAllocKind();
-
-    // Don't handle other objects with special allocation requirements.
-    MOZ_ASSERT(!obj->is<TypedArrayObject>());
-    MOZ_ASSERT(obj->isNative());
-
-    AllocKind kind = GetGCObjectFixedSlotsKind(obj->as<NativeObject>().numFixedSlots());
-    MOZ_ASSERT(!IsBackgroundFinalized(kind));
-    MOZ_ASSERT(CanBeFinalizedInBackground(kind, obj->getClass()));
-    return GetBackgroundAllocKind(kind);
-}
-
-// Nursery allocation will never fail during GC - apart from true OOM - since
-// newspace is at least as large as fromspace, ergo a nullptr return from the
-// allocator means true OOM, which we catch and signal here.
-void *
-ForkJoinNursery::allocateInTospaceInfallible(size_t thingSize)
-{
-    void *p = allocate(thingSize);
-    if (!p)
-        CrashAtUnhandlableOOM("Cannot expand PJS nursery during GC");
-    return p;
-}
-
-void *
-ForkJoinNursery::allocateInTospace(gc::AllocKind thingKind)
-{
-    size_t thingSize = Arena::thingSize(thingKind);
-    if (isEvacuating_) {
-        void *t = tenured_->arenas.allocateFromFreeList(thingKind, thingSize);
-        if (t)
-            return t;
-        tenured_->arenas.checkEmptyFreeList(thingKind);
-        // This call may return NULL but should do so only if memory
-        // is truly exhausted.  However, allocateFromArena() can fail
-        // either because memory is exhausted or if the allocation
-        // budget is used up.  There is a guard in
-        // Chunk::allocateArena() against the latter case.
-        return tenured_->arenas.allocateFromArena(evacuationZone_, thingKind);
-    }
-    return allocateInTospaceInfallible(thingSize);
-}
-
-template <typename T>
-T *
-ForkJoinNursery::allocateInTospace(size_t nelem)
-{
-    if (isEvacuating_)
-        return evacuationZone_->pod_malloc<T>(nelem);
-    return static_cast<T *>(allocateInTospaceInfallible(nelem * sizeof(T)));
-}
-
-MOZ_ALWAYS_INLINE void
-ForkJoinNursery::insertIntoFixupList(RelocationOverlay *entry)
-{
-    *tail_ = entry;
-    tail_ = &entry->next_;
-    *tail_ = nullptr;
-}
-
-void *
-ForkJoinNursery::moveObjectToTospace(JSObject *src)
-{
-    AllocKind dstKind = getObjectAllocKind(src);
-    JSObject *dst = static_cast<JSObject *>(allocateInTospace(dstKind));
-    if (!dst)
-        CrashAtUnhandlableOOM("Failed to allocate object while moving object.");
-
-    movedSize_ += copyObjectToTospace(dst, src, dstKind);
-
-    RelocationOverlay *overlay = RelocationOverlay::fromCell(src);
-    overlay->forwardTo(dst);
-    insertIntoFixupList(overlay);
-
-    return static_cast<void *>(dst);
-}
-
-size_t
-ForkJoinNursery::copyObjectToTospace(JSObject *dst, JSObject *src, AllocKind dstKind)
-{
-    size_t srcSize = Arena::thingSize(dstKind);
-    size_t movedSize = srcSize;
-
-    // Arrays do not necessarily have the same AllocKind between src and dst.
-    // We deal with this by copying elements manually, possibly re-inlining
-    // them if there is adequate room inline in dst.
-    if (src->is<ArrayObject>())
-        srcSize = movedSize = sizeof(NativeObject);
-
-    js_memcpy(dst, src, srcSize);
-    if (src->isNative()) {
-        NativeObject *ndst = &dst->as<NativeObject>(), *nsrc = &src->as<NativeObject>();
-        movedSize += copySlotsToTospace(ndst, nsrc, dstKind);
-        movedSize += copyElementsToTospace(ndst, nsrc, dstKind);
-    }
-
-    // The shape's list head may point into the old object.
-    if (&src->shape_ == dst->shape_->listp) {
-        MOZ_ASSERT(cx_->isThreadLocal(dst->shape_.get()));
-        dst->shape_->listp = &dst->shape_;
-    }
-
-    return movedSize;
-}
-
-size_t
-ForkJoinNursery::copySlotsToTospace(NativeObject *dst, NativeObject *src, AllocKind dstKind)
-{
-    // Fixed slots have already been copied over.
-    if (!src->hasDynamicSlots())
-        return 0;
-
-    if (!isInsideFromspace(src->slots_)) {
-        hugeSlots[hugeSlotsFrom].remove(src->slots_);
-        if (!isEvacuating_)
-            hugeSlots[hugeSlotsNew].put(src->slots_);
-        return 0;
-    }
-
-    size_t count = src->numDynamicSlots();
-    dst->slots_ = allocateInTospace<HeapSlot>(count);
-    if (!dst->slots_)
-        CrashAtUnhandlableOOM("Failed to allocate slots while moving object.");
-    js_memcpy(dst->slots_, src->slots_, count * sizeof(HeapSlot));
-    setSlotsForwardingPointer(src->slots_, dst->slots_, count);
-    return count * sizeof(HeapSlot);
-}
-
-size_t
-ForkJoinNursery::copyElementsToTospace(NativeObject *dst, NativeObject *src, AllocKind dstKind)
-{
-    if (src->hasEmptyElements() || src->denseElementsAreCopyOnWrite())
-        return 0;
-
-    ObjectElements *srcHeader = src->getElementsHeader();
-    ObjectElements *dstHeader;
-
-    // TODO Bug 874151: Prefer to put element data inline if we have space.
-    // (Note, not a correctness issue.)
-    if (!isInsideFromspace(srcHeader)) {
-        MOZ_ASSERT(src->elements_ == dst->elements_);
-        hugeSlots[hugeSlotsFrom].remove(reinterpret_cast<HeapSlot*>(srcHeader));
-        if (!isEvacuating_)
-            hugeSlots[hugeSlotsNew].put(reinterpret_cast<HeapSlot*>(srcHeader));
-        return 0;
-    }
-
-    size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity;
-
-    // Unlike other objects, Arrays can have fixed elements.
-    if (src->is<ArrayObject>() && nslots <= GetGCKindSlots(dstKind)) {
-        dst->as<ArrayObject>().setFixedElements();
-        dstHeader = dst->as<ArrayObject>().getElementsHeader();
-        js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
-        setElementsForwardingPointer(srcHeader, dstHeader, nslots);
-        return nslots * sizeof(HeapSlot);
-    }
-
-    MOZ_ASSERT(nslots >= 2);
-    dstHeader = reinterpret_cast<ObjectElements *>(allocateInTospace<HeapSlot>(nslots));
-    if (!dstHeader)
-        CrashAtUnhandlableOOM("Failed to allocate elements while moving object.");
-    js_memcpy(dstHeader, srcHeader, nslots * sizeof(HeapSlot));
-    setElementsForwardingPointer(srcHeader, dstHeader, nslots);
-    dst->elements_ = dstHeader->elements();
-    return nslots * sizeof(HeapSlot);
-}
-
-void
-ForkJoinNursery::setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots)
-{
-    MOZ_ASSERT(nslots > 0);
-    MOZ_ASSERT(isInsideFromspace(oldSlots));
-    MOZ_ASSERT(!isInsideFromspace(newSlots));
-    *reinterpret_cast<HeapSlot **>(oldSlots) = newSlots;
-}
-
-void
-ForkJoinNursery::setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
-                                             uint32_t nelems)
-{
-    // If the JIT has hoisted a zero length pointer, then we do not need to
-    // relocate it because reads and writes to/from this pointer are invalid.
-    if (nelems - ObjectElements::VALUES_PER_HEADER < 1)
-        return;
-    MOZ_ASSERT(isInsideFromspace(oldHeader));
-    MOZ_ASSERT(!isInsideFromspace(newHeader));
-    *reinterpret_cast<HeapSlot **>(oldHeader->elements()) = newHeader->elements();
-}
-
-ForkJoinNurseryCollectionTracer::ForkJoinNurseryCollectionTracer(JSRuntime *rt,
-                                                                 ForkJoinNursery *nursery)
-  : JSTracer(rt, ForkJoinNursery::MinorGCCallback, TraceWeakMapKeysValues)
-  , nursery_(nursery)
-{
-    MOZ_ASSERT(rt);
-    MOZ_ASSERT(nursery);
-}
-
-} // namespace gc
-} // namespace js
-
-#endif /* JSGC_FJGENERATIONAL */
deleted file mode 100644
--- a/js/src/gc/ForkJoinNursery.h
+++ /dev/null
@@ -1,297 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef gc_ForkJoinNursery_h
-#define gc_ForkJoinNursery_h
-
-#ifdef JSGC_FJGENERATIONAL
-
-#include "jsalloc.h"
-#include "jspubtd.h"
-
-#include "gc/Heap.h"
-#include "gc/Memory.h"
-#include "gc/Nursery.h"
-
-#include "js/HashTable.h"
-#include "js/TracingAPI.h"
-
-namespace js {
-class ObjectElements;
-class HeapSlot;
-class ForkJoinShared;
-}
-
-namespace js {
-namespace gc {
-
-class ForkJoinGCShared;
-class ForkJoinNursery;
-class ForkJoinNurseryCollectionTracer;
-class RelocationOverlay;
-
-// This tracer comes into play when a class has a tracer function, but
-// is otherwise unused and has no other functionality.
-//
-// It could look like this could be merged into ForkJoinNursery by
-// making the latter derive from JSTracer; I've decided to keep them
-// separate for now, since it allows for multiple instantiations of
-// this class with different parameters, for different purposes.  That
-// may change.
-
-class ForkJoinNurseryCollectionTracer : public JSTracer
-{
-    friend class ForkJoinNursery;
-
-  public:
-    ForkJoinNurseryCollectionTracer(JSRuntime *rt, ForkJoinNursery *nursery);
-
-  private:
-    ForkJoinNursery *const nursery_;
-};
-
-// The layout for a chunk used by the ForkJoinNursery.
-
-struct ForkJoinNurseryChunk
-{
-    // The amount of space in the mapped nursery available to allocations
-    static const size_t UsableSize = ChunkSize - sizeof(ChunkTrailer);
-
-    char data[UsableSize];
-    ChunkTrailer trailer;
-    uintptr_t start() { return uintptr_t(&data); }
-    uintptr_t end() { return uintptr_t(&trailer); }
-};
-
-// A GC adapter to ForkJoinShared, which is a complex class hidden
-// inside ForkJoin.cpp.
-
-class ForkJoinGCShared
-{
-  public:
-    explicit ForkJoinGCShared(ForkJoinShared *shared) : shared_(shared) {}
-
-    JSRuntime *runtime();
-    JS::Zone *zone();
-
-    // The updatable object (the ForkJoin result array), or nullptr.
-    JSObject *updatable();
-
-    // allocateNurseryChunk() returns nullptr on oom.
-    ForkJoinNurseryChunk *allocateNurseryChunk();
-
-    // p must have been obtained through allocateNurseryChunk.
-    void freeNurseryChunk(ForkJoinNurseryChunk *p);
-
-    // GC statistics output.
-    void spewGC(const char *fmt, ...);
-
-  private:
-    ForkJoinShared *const shared_;
-};
-
-// There is one ForkJoinNursery per ForkJoin worker.
-//
-// See the comment in ForkJoinNursery.cpp about how it works.
-
-class ForkJoinNursery
-{
-    friend class ForkJoinNurseryCollectionTracer;
-    friend class RelocationOverlay;
-
-    static_assert(sizeof(ForkJoinNurseryChunk) == ChunkSize,
-                  "ForkJoinNursery chunk size must match Chunk size.");
-  public:
-    ForkJoinNursery(ForkJoinContext *cx, ForkJoinGCShared *shared, Allocator *tenured);
-    ~ForkJoinNursery();
-
-    // Attempt to allocate initial storage, returns false on failure
-    bool initialize();
-
-    // Perform a collection within the nursery, and if that for some reason
-    // cannot be done then perform an evacuating collection.
-    void minorGC();
-
-    // Evacuate the live data from the nursery into the tenured area;
-    // do not recreate the nursery.
-    void evacuatingGC();
-
-    // Allocate an object with a number of dynamic slots.  Returns an
-    // object, or nullptr in one of two circumstances:
-    //
-    //  - The nursery was full, the collector must be run, and the
-    //    allocation must be retried.  tooLarge is set to 'false'.
-    //  - The number of dynamic slots requested is too large and
-    //    the object should be allocated in the tenured area.
-    //    tooLarge is set to 'true'.
-    //
-    // This method will never run the garbage collector.
-    JSObject *allocateObject(size_t size, size_t numDynamic, bool& tooLarge);
-
-    // Allocate and reallocate slot and element arrays for existing
-    // objects.  These will create or maintain the arrays within the
-    // nursery if possible and appropriate, and otherwise will fall
-    // back to allocating in the tenured area.  They will return
-    // nullptr only if memory is exhausted.  If the reallocate methods
-    // return nullptr then the old array is still live.
-    //
-    // These methods will never run the garbage collector.
-    HeapSlot *allocateSlots(JSObject *obj, uint32_t nslots);
-    HeapSlot *reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
-                              uint32_t oldCount, uint32_t newCount);
-    ObjectElements *allocateElements(JSObject *obj, uint32_t nelems);
-    ObjectElements *reallocateElements(JSObject *obj, ObjectElements *oldHeader,
-                                       uint32_t oldCount, uint32_t newCount);
-
-    // Free a slots array.
-    void freeSlots(HeapSlot *slots);
-
-    // The method embedded in a ForkJoinNurseryCollectionTracer
-    static void MinorGCCallback(JSTracer *trcArg, void **thingp, JSGCTraceKind kind);
-
-    // A method called from the JIT frame updater
-    static void forwardBufferPointer(JSTracer *trc, HeapSlot **pSlotsElems);
-
-    // Return true iff obj is inside the current newspace.
-    MOZ_ALWAYS_INLINE bool isInsideNewspace(const void *obj);
-
-    // Return true iff collection is ongoing and obj is inside the current fromspace.
-    MOZ_ALWAYS_INLINE bool isInsideFromspace(const void *obj);
-
-    MOZ_ALWAYS_INLINE bool isForwarded(Cell *cell);
-
-    template <typename T>
-    MOZ_ALWAYS_INLINE bool getForwardedPointer(T **ref);
-
-    static size_t offsetOfPosition() {
-        return offsetof(ForkJoinNursery, position_);
-    }
-
-    static size_t offsetOfCurrentEnd() {
-        return offsetof(ForkJoinNursery, currentEnd_);
-    }
-
-  private:
-    // The largest slot arrays that will be allocated in the nursery.
-    // On the one hand we want this limit to be large, to avoid
-    // managing many hugeSlots.  On the other hand, slot arrays have
-    // to be copied during GC and will induce some external
-    // fragmentation in the nursery at chunk boundaries.
-    static const size_t MaxNurserySlots = 2048;
-
-    // The fixed limit on the per-worker nursery, in chunks.
-    //
-    // For production runs, 16 may be good - programs that need it,
-    // really need it, and as allocation is lazy programs that don't
-    // need it won't suck up a lot of resources.
-    //
-    // For debugging runs, 1 or 2 may sometimes be good, because it
-    // will more easily provoke bugs in the evacuation paths.
-    static const size_t MaxNurseryChunks = 16;
-
-    // The inverse load factor in the per-worker nursery.  Grow the nursery
-    // or schedule an evacuation if more than 1/NurseryLoadFactor of the
-    // current nursery size is live after minor GC.
-    static const int NurseryLoadFactor = 3;
-
-    // Allocate an object in the nursery's newspace.  Return nullptr
-    // when allocation fails (ie the object can't fit in the current
-    // chunk and the number of chunks it at its maximum).
-    void *allocate(size_t size);
-
-    // Allocate an external slot array and register it with this nursery.
-    HeapSlot *allocateHugeSlots(JSObject *obj, size_t nslots);
-
-    // Reallocate an external slot array, unregister the old array and
-    // register the new array.  If the allocation fails then leave
-    // everything unchanged.
-    HeapSlot *reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
-                                  uint32_t oldCount, uint32_t newCount);
-
-    // Walk the list of registered slot arrays and free them all.
-    void sweepHugeSlots();
-
-    // Set the position/end pointers to correspond to the numbered
-    // chunk.  Returns false if the chunk could not be allocated, either
-    // because we're OOM or because the nursery capacity is exhausted.
-    bool setCurrentChunk(int index);
-
-    enum PJSCollectionOp {
-        Evacuate = 1,
-        Collect = 2,
-        Recreate = 4
-    };
-
-    // Misc GC internals.
-    void pjsCollection(int op /* A combination of PJSCollectionOp bits */);
-    bool initNewspace();
-    void flip();
-    void forwardFromRoots(ForkJoinNurseryCollectionTracer *trc);
-    void forwardFromUpdatable(ForkJoinNurseryCollectionTracer *trc);
-    void forwardFromStack(ForkJoinNurseryCollectionTracer *trc);
-    void forwardFromTenured(ForkJoinNurseryCollectionTracer *trc);
-    void forwardFromRematerializedFrames(ForkJoinNurseryCollectionTracer *trc);
-    void collectToFixedPoint(ForkJoinNurseryCollectionTracer *trc);
-    void freeFromspace();
-    void computeNurserySizeAfterGC(size_t live, const char **msg);
-
-    AllocKind getObjectAllocKind(JSObject *src);
-    void *allocateInTospaceInfallible(size_t thingSize);
-    void *allocateInTospace(AllocKind thingKind);
-    template <typename T> T *allocateInTospace(size_t nelem);
-    MOZ_ALWAYS_INLINE bool shouldMoveObject(void **thingp);
-    void *moveObjectToTospace(JSObject *src);
-    size_t copyObjectToTospace(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
-    size_t copyElementsToTospace(NativeObject *dst, NativeObject *src, gc::AllocKind dstKind);
-    size_t copySlotsToTospace(NativeObject *dst, NativeObject *src, gc::AllocKind dstKind);
-    MOZ_ALWAYS_INLINE void insertIntoFixupList(RelocationOverlay *entry);
-
-    void setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots);
-    void setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
-                                      uint32_t nelems);
-
-    MOZ_ALWAYS_INLINE void traceObject(ForkJoinNurseryCollectionTracer *trc, JSObject *obj);
-    MOZ_ALWAYS_INLINE void markSlots(HeapSlot *vp, uint32_t nslots);
-    MOZ_ALWAYS_INLINE void markSlots(HeapSlot *vp, HeapSlot *end);
-    MOZ_ALWAYS_INLINE void markSlot(HeapSlot *slotp);
-
-    ForkJoinContext *const cx_;      // The context that owns this nursery
-    Allocator *const tenured_;       // Private tenured area
-    ForkJoinGCShared *const shared_; // Common to all nurseries belonging to a ForkJoin instance
-    JS::Zone *evacuationZone_;       // During evacuating GC this is non-NULL: the Zone we
-                                     // allocate into
-
-    uintptr_t currentStart_;         // Start of current area in newspace
-    uintptr_t currentEnd_;           // End of current area in newspace (last byte + 1)
-    uintptr_t position_;             // Next free byte in current newspace chunk
-    unsigned currentChunk_;          // Index of current / highest numbered chunk in newspace
-    unsigned numActiveChunks_;       // Number of active chunks in newspace, not all may be allocated
-    unsigned numFromspaceChunks_;    // Number of active chunks in fromspace, all are allocated
-    bool mustEvacuate_;              // Set to true after GC when the /next/ minor GC must evacuate
-
-    bool isEvacuating_;              // Set to true when the current minor GC is evacuating
-    size_t movedSize_;               // Bytes copied during the current minor GC
-    RelocationOverlay *head_;        // First node of relocation list
-    RelocationOverlay **tail_;       // Pointer to 'next_' field of last node of relocation list
-
-    typedef HashSet<HeapSlot *, PointerHasher<HeapSlot *, 3>, SystemAllocPolicy> HugeSlotsSet;
-
-    HugeSlotsSet hugeSlots[2];       // Hash sets for huge slots
-
-    int hugeSlotsNew;                // Huge slot arrays in the newspace (index in hugeSlots)
-    int hugeSlotsFrom;               // Huge slot arrays in the fromspace (index in hugeSlots)
-
-    ForkJoinNurseryChunk *newspace[MaxNurseryChunks];  // All allocation happens here
-    ForkJoinNurseryChunk *fromspace[MaxNurseryChunks]; // Meaningful during GC: the previous newspace
-};
-
-} // namespace gc
-} // namespace js
-
-#endif // JSGC_FJGENERATIONAL
-
-#endif // gc_ForkJoinNursery_h
--- a/js/src/gc/GCInternals.h
+++ b/js/src/gc/GCInternals.h
@@ -14,23 +14,16 @@
 #include "vm/Runtime.h"
 
 namespace js {
 namespace gc {
 
 void
 MarkPersistentRootedChains(JSTracer *trc);
 
-#ifdef JSGC_FJGENERATIONAL
-class ForkJoinNurseryCollectionTracer;
-
-void
-MarkForkJoinStack(ForkJoinNurseryCollectionTracer *trc);
-#endif
-
 class AutoCopyFreeListToArenas
 {
     JSRuntime *runtime;
     ZoneSelector selector;
 
   public:
     AutoCopyFreeListToArenas(JSRuntime *rt, ZoneSelector selector);
     ~AutoCopyFreeListToArenas();
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -296,25 +296,16 @@ class GCRuntime
     bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; }
     bool isHeapCollecting() { return isHeapMajorCollecting() || isHeapMinorCollecting(); }
 #ifdef JSGC_COMPACTING
     bool isHeapCompacting() { return isHeapMajorCollecting() && state() == COMPACT; }
 #else
     bool isHeapCompacting() { return false; }
 #endif
 
-    // Performance note: if isFJMinorCollecting turns out to be slow because
-    // reading the counter is slow then we may be able to augment the counter
-    // with a volatile flag that is set iff the counter is greater than
-    // zero. (It will require some care to make sure the two variables stay in
-    // sync.)
-    bool isFJMinorCollecting() { return fjCollectionCounter > 0; }
-    void incFJMinorCollecting() { fjCollectionCounter++; }
-    void decFJMinorCollecting() { fjCollectionCounter--; }
-
     bool triggerGC(JS::gcreason::Reason reason);
     void maybeAllocTriggerZoneGC(Zone *zone, const AutoLockGC &lock);
     bool triggerZoneGC(Zone *zone, JS::gcreason::Reason reason);
     bool maybeGC(Zone *zone);
     void maybePeriodicFullGC();
     void minorGC(JS::gcreason::Reason reason) {
         gcstats::AutoPhase ap(stats, gcstats::PHASE_MINOR_GC);
         minorGCImpl(reason, nullptr);
@@ -843,26 +834,16 @@ class GCRuntime
      */
     unsigned objectsMarkedInDeadZones;
 
     bool poked;
 
     mozilla::Atomic<js::HeapState> heapState;
 
     /*
-     * ForkJoin workers enter and leave GC independently; this counter
-     * tracks the number that are currently in GC.
-     *
-     * Technically this should be #ifdef JSGC_FJGENERATIONAL but that
-     * affects the observed size of JSRuntime in problematic ways, see
-     * note in vm/ThreadPool.h.
-     */
-    mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> fjCollectionCounter;
-
-    /*
      * These options control the zealousness of the GC. The fundamental values
      * are nextScheduled and gcDebugCompartmentGC. At every allocation,
      * nextScheduled is decremented. When it reaches zero, we do either a full
      * or a compartmental GC, based on debugCompartmentGC.
      *
      * At this point, if zeal_ is one of the types that trigger periodic
      * collection, then nextScheduled is reset to the value of zealFrequency.
      * Otherwise, no additional GCs take place.
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -159,26 +159,16 @@ CheckMarkedThing(JSTracer *trc, T **thin
 
     T *thing = *thingp;
     MOZ_ASSERT(*thingp);
 
 #ifdef JSGC_COMPACTING
     thing = MaybeForwarded(thing);
 #endif
 
-# ifdef JSGC_FJGENERATIONAL
-    /*
-     * The code below (runtimeFromMainThread(), etc) makes assumptions
-     * not valid for the ForkJoin worker threads during ForkJoin GGC,
-     * so just bail.
-     */
-    if (ForkJoinContext::current())
-        return;
-# endif
-
     /* This function uses data that's not available in the nursery. */
     if (IsInsideNursery(thing))
         return;
 
 #ifdef JSGC_COMPACTING
     MOZ_ASSERT_IF(!MovingTracer::IsMovingTracer(trc) && !Nursery::IsMinorCollectionTracer(trc),
                   !IsForwarded(*thingp));
 #endif
@@ -271,26 +261,16 @@ SetMaybeAliveFlag(JSScript *thing)
 template<typename T>
 static void
 MarkInternal(JSTracer *trc, T **thingp)
 {
     CheckMarkedThing(trc, thingp);
     T *thing = *thingp;
 
     if (!trc->callback) {
-#ifdef JSGC_FJGENERATIONAL
-        /*
-         * This case should never be reached from PJS collections as
-         * those should all be using a ForkJoinNurseryCollectionTracer
-         * that carries a callback.
-         */
-        MOZ_ASSERT(!ForkJoinContext::current());
-        MOZ_ASSERT(!trc->runtime()->isFJMinorCollecting());
-#endif
-
         /*
          * We may mark a Nursery thing outside the context of the
          * MinorCollectionTracer because of a pre-barrier. The pre-barrier is
          * not needed in this case because we perform a minor collection before
          * each incremental slice.
          */
         if (IsInsideNursery(thing))
             return;
@@ -442,32 +422,20 @@ IsMarked(T **thingp)
 
 template <typename T>
 static bool
 IsMarkedFromAnyThread(T **thingp)
 {
     MOZ_ASSERT(thingp);
     MOZ_ASSERT(*thingp);
     JSRuntime* rt = (*thingp)->runtimeFromAnyThread();
-#ifdef JSGC_FJGENERATIONAL
-    // Must precede the case for GGC because IsInsideNursery()
-    // will also be true for the ForkJoinNursery.
-    if (rt->isFJMinorCollecting()) {
-        ForkJoinContext *ctx = ForkJoinContext::current();
-        ForkJoinNursery &nursery = ctx->nursery();
-        if (nursery.isInsideFromspace(*thingp))
-            return nursery.getForwardedPointer(thingp);
-    }
-    else
-#endif
-    {
-        if (IsInsideNursery(*thingp)) {
-            Nursery &nursery = rt->gc.nursery;
-            return nursery.getForwardedPointer(thingp);
-        }
+
+    if (IsInsideNursery(*thingp)) {
+        Nursery &nursery = rt->gc.nursery;
+        return nursery.getForwardedPointer(thingp);
     }
 
     Zone *zone = (*thingp)->asTenured().zoneFromAnyThread();
     if (!zone->isCollectingFromAnyThread() || zone->isGCFinished())
         return true;
 #ifdef JSGC_COMPACTING
     if (zone->isGCCompacting() && IsForwarded(*thingp))
         *thingp = Forwarded(*thingp);
@@ -493,33 +461,22 @@ IsAboutToBeFinalizedFromAnyThread(T **th
 
     T *thing = *thingp;
     JSRuntime *rt = thing->runtimeFromAnyThread();
 
     /* Permanent atoms are never finalized by non-owning runtimes. */
     if (ThingIsPermanentAtom(thing) && !TlsPerThreadData.get()->associatedWith(rt))
         return false;
 
-#ifdef JSGC_FJGENERATIONAL
-    if (rt->isFJMinorCollecting()) {
-        ForkJoinContext *ctx = ForkJoinContext::current();
-        ForkJoinNursery &nursery = ctx->nursery();
-        if (nursery.isInsideFromspace(thing))
+    Nursery &nursery = rt->gc.nursery;
+    MOZ_ASSERT_IF(!rt->isHeapMinorCollecting(), !IsInsideNursery(thing));
+    if (rt->isHeapMinorCollecting()) {
+        if (IsInsideNursery(thing))
             return !nursery.getForwardedPointer(thingp);
-    }
-    else
-#endif
-    {
-        Nursery &nursery = rt->gc.nursery;
-        MOZ_ASSERT_IF(!rt->isHeapMinorCollecting(), !IsInsideNursery(thing));
-        if (rt->isHeapMinorCollecting()) {
-            if (IsInsideNursery(thing))
-                return !nursery.getForwardedPointer(thingp);
-            return false;
-        }
+        return false;
     }
 
     Zone *zone = thing->asTenured().zoneFromAnyThread();
     if (zone->isGCSweeping()) {
         if (thing->asTenured().arenaHeader()->allocatedDuringIncremental)
             return false;
         return !thing->asTenured().isMarked();
     }
@@ -536,26 +493,16 @@ IsAboutToBeFinalizedFromAnyThread(T **th
 template <typename T>
 T *
 UpdateIfRelocated(JSRuntime *rt, T **thingp)
 {
     MOZ_ASSERT(thingp);
     if (!*thingp)
         return nullptr;
 
-#ifdef JSGC_FJGENERATIONAL
-    if (rt->isFJMinorCollecting()) {
-        ForkJoinContext *ctx = ForkJoinContext::current();
-        ForkJoinNursery &nursery = ctx->nursery();
-        if (nursery.isInsideFromspace(*thingp))
-            nursery.getForwardedPointer(thingp);
-        return *thingp;
-    }
-#endif
-
     if (rt->isHeapMinorCollecting() && IsInsideNursery(*thingp)) {
         rt->gc.nursery.getForwardedPointer(thingp);
         return *thingp;
     }
 
 #ifdef JSGC_COMPACTING
     Zone *zone = (*thingp)->zone();
     if (zone->isGCCompacting() && IsForwarded(*thingp))
--- a/js/src/gc/Memory.cpp
+++ b/js/src/gc/Memory.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gc/Memory.h"
 
+#include "mozilla/Atomics.h"
 #include "mozilla/TaggedAnonymousMemory.h"
 
 #include "js/HeapAPI.h"
 #include "vm/Runtime.h"
 
 #if defined(XP_WIN)
 
 #include "jswin.h"
@@ -40,28 +41,26 @@ namespace gc {
 // running process matches the compiled arena size.
 static size_t pageSize = 0;
 
 // The OS allocation granularity may not match the page size.
 static size_t allocGranularity = 0;
 
 #if defined(XP_UNIX)
 // The addresses handed out by mmap may grow up or down.
-static int growthDirection = 0;
+static mozilla::Atomic<int, mozilla::Relaxed> growthDirection(0);
 #endif
 
-// The maximum number of unalignable chunks to temporarily keep alive in
-// the last ditch allocation pass. OOM crash reports generally show <= 7
-// unaligned chunks available (bug 1005844 comment #16).
-static const int MaxLastDitchAttempts = 8;
+// Data from OOM crashes shows there may be up to 24 chunksized but unusable
+// chunks available in low memory situations. These chunks may all need to be
+// used up before we gain access to remaining *alignable* chunksized regions,
+// so we use a generous limit of 32 unusable chunks to ensure we reach them.
+static const int MaxLastDitchAttempts = 32;
 
-static void GetNewChunk(void **aAddress, void **aRetainedAddr, size_t *aRetainedSize, size_t size,
-                        size_t alignment);
-static bool GetNewChunkInner(void **aAddress, void **aRetainedAddr, size_t *aRetainedSize,
-                             size_t size, size_t alignment, bool addrsGrowDown);
+static void GetNewChunk(void **aAddress, void **aRetainedAddr, size_t size, size_t alignment);
 static void *MapAlignedPagesSlow(size_t size, size_t alignment);
 static void *MapAlignedPagesLastDitch(size_t size, size_t alignment);
 
 size_t
 SystemPageSize()
 {
     return pageSize;
 }
@@ -129,20 +128,19 @@ MapAlignedPages(size_t size, size_t alig
     /* Special case: If we want allocation alignment, no further work is needed. */
     if (alignment == allocGranularity)
         return p;
 
     if (OffsetFromAligned(p, alignment) == 0)
         return p;
 
     void *retainedAddr;
-    size_t retainedSize;
-    GetNewChunk(&p, &retainedAddr, &retainedSize, size, alignment);
+    GetNewChunk(&p, &retainedAddr, size, alignment);
     if (retainedAddr)
-        UnmapPages(retainedAddr, retainedSize);
+        UnmapPages(retainedAddr, size);
     if (p) {
         if (OffsetFromAligned(p, alignment) == 0)
             return p;
         UnmapPages(p, size);
     }
 
     p = MapAlignedPagesSlow(size, alignment);
     if (!p)
@@ -181,79 +179,73 @@ MapAlignedPagesSlow(size_t size, size_t 
 
         /* Failure here indicates a race with another thread, so try again. */
     } while (!p);
 
     return p;
 }
 
 /*
- * Even though there aren't any |size + alignment - pageSize| byte chunks left,
- * the allocator may still be able to give us |size| byte chunks that are
- * either already aligned, or *can* be aligned by allocating in the nearest
- * aligned location. Since we can't tell the allocator to give us a different
- * address each time, we temporarily hold onto the unaligned part of each chunk
- * until the allocator gives us a chunk that either is, or can be aligned.
+ * In a low memory or high fragmentation situation, alignable chunks of the
+ * desired size may still be available, even if there are no more contiguous
+ * free chunks that meet the |size + alignment - pageSize| requirement of
+ * MapAlignedPagesSlow. In this case, try harder to find an alignable chunk
+ * by temporarily holding onto the unaligned parts of each chunk until the
+ * allocator gives us a chunk that either is, or can be aligned.
  */
 static void *
 MapAlignedPagesLastDitch(size_t size, size_t alignment)
 {
-    void *p = nullptr;
     void *tempMaps[MaxLastDitchAttempts];
     int attempt = 0;
+    void *p = MapMemory(size, MEM_COMMIT | MEM_RESERVE);
+    if (OffsetFromAligned(p, alignment) == 0)
+        return p;
     for (; attempt < MaxLastDitchAttempts; ++attempt) {
-        size_t retainedSize;
-        GetNewChunk(&p, tempMaps + attempt, &retainedSize, size, alignment);
+        GetNewChunk(&p, tempMaps + attempt, size, alignment);
         if (OffsetFromAligned(p, alignment) == 0) {
             if (tempMaps[attempt])
-                UnmapPages(tempMaps[attempt], retainedSize);
+                UnmapPages(tempMaps[attempt], size);
             break;
         }
-        if (!tempMaps[attempt]) {
-            /* GetNewChunk failed, but we can still try the simpler method. */
-            tempMaps[attempt] = p;
-            p = nullptr;
-        }
+        if (!tempMaps[attempt])
+            break; /* Bail if GetNewChunk failed. */
     }
     if (OffsetFromAligned(p, alignment)) {
         UnmapPages(p, size);
         p = nullptr;
     }
     while (--attempt >= 0)
-        UnmapPages(tempMaps[attempt], 0);
+        UnmapPages(tempMaps[attempt], size);
     return p;
 }
 
 /*
  * On Windows, map and unmap calls must be matched, so we deallocate the
  * unaligned chunk, then reallocate the unaligned part to block off the
  * old address and force the allocator to give us a new one.
  */
 static void
-GetNewChunk(void **aAddress, void **aRetainedAddr, size_t *aRetainedSize, size_t size,
-            size_t alignment)
+GetNewChunk(void **aAddress, void **aRetainedAddr, size_t size, size_t alignment)
 {
     void *address = *aAddress;
     void *retainedAddr = nullptr;
-    size_t retainedSize = 0;
     do {
-        if (!address)
-            address = MapMemory(size, MEM_COMMIT | MEM_RESERVE);
+        size_t retainedSize;
         size_t offset = OffsetFromAligned(address, alignment);
         if (!offset)
             break;
         UnmapPages(address, size);
         retainedSize = alignment - offset;
         retainedAddr = MapMemoryAt(address, retainedSize, MEM_RESERVE);
         address = MapMemory(size, MEM_COMMIT | MEM_RESERVE);
         /* If retainedAddr is null here, we raced with another thread. */
     } while (!retainedAddr);
     *aAddress = address;
     *aRetainedAddr = retainedAddr;
-    *aRetainedSize = retainedSize;
 }
 
 void
 UnmapPages(void *p, size_t size)
 {
     MOZ_ALWAYS_TRUE(VirtualFree(p, 0, MEM_RELEASE));
 }
 
@@ -374,20 +366,18 @@ DeallocateMappedContent(void *p, size_t 
     // Not implemented.
 }
 
 #elif defined(XP_UNIX)
 
 void
 InitMemorySubsystem()
 {
-    if (pageSize == 0) {
+    if (pageSize == 0)
         pageSize = allocGranularity = size_t(sysconf(_SC_PAGESIZE));
-        growthDirection = 0;
-    }
 }
 
 static inline void *
 MapMemoryAt(void *desired, size_t length, int prot = PROT_READ | PROT_WRITE,
             int flags = MAP_PRIVATE | MAP_ANON, int fd = -1, off_t offset = 0)
 {
 #if defined(__ia64__)
     MOZ_ASSERT(0xffff800000000000ULL & (uintptr_t(desired) + length - 1) == 0);
@@ -460,20 +450,19 @@ MapAlignedPages(size_t size, size_t alig
     /* Special case: If we want page alignment, no further work is needed. */
     if (alignment == allocGranularity)
         return p;
 
     if (OffsetFromAligned(p, alignment) == 0)
         return p;
 
     void *retainedAddr;
-    size_t retainedSize;
-    GetNewChunk(&p, &retainedAddr, &retainedSize, size, alignment);
+    GetNewChunk(&p, &retainedAddr, size, alignment);
     if (retainedAddr)
-        UnmapPages(retainedAddr, retainedSize);
+        UnmapPages(retainedAddr, size);
     if (p) {
         if (OffsetFromAligned(p, alignment) == 0)
             return p;
         UnmapPages(p, size);
     }
 
     p = MapAlignedPagesSlow(size, alignment);
     if (!p)
@@ -509,148 +498,103 @@ MapAlignedPagesSlow(size_t size, size_t 
         UnmapPages(region, uintptr_t(front) - uintptr_t(region));
     if (end != regionEnd)
         UnmapPages(end, uintptr_t(regionEnd) - uintptr_t(end));
 
     return front;
 }
 
 /*
- * Even though there aren't any |size + alignment - pageSize| byte chunks left,
- * the allocator may still be able to give us |size| byte chunks that are
- * either already aligned, or *can* be aligned by allocating in the nearest
- * aligned location. Since we can't tell the allocator to give us a different
- * address each time, we temporarily hold onto the unaligned part of each chunk
- * until the allocator gives us a chunk that either is, or can be aligned.
+ * In a low memory or high fragmentation situation, alignable chunks of the
+ * desired size may still be available, even if there are no more contiguous
+ * free chunks that meet the |size + alignment - pageSize| requirement of
+ * MapAlignedPagesSlow. In this case, try harder to find an alignable chunk
+ * by temporarily holding onto the unaligned parts of each chunk until the
+ * allocator gives us a chunk that either is, or can be aligned.
  */
 static void *
 MapAlignedPagesLastDitch(size_t size, size_t alignment)
 {
-    void *p = nullptr;
     void *tempMaps[MaxLastDitchAttempts];
-    size_t tempSizes[MaxLastDitchAttempts];
     int attempt = 0;
+    void *p = MapMemory(size);
+    if (OffsetFromAligned(p, alignment) == 0)
+        return p;
     for (; attempt < MaxLastDitchAttempts; ++attempt) {
-        GetNewChunk(&p, tempMaps + attempt, tempSizes + attempt, size, alignment);
+        GetNewChunk(&p, tempMaps + attempt, size, alignment);
         if (OffsetFromAligned(p, alignment) == 0) {
             if (tempMaps[attempt])
-                UnmapPages(tempMaps[attempt], tempSizes[attempt]);
+                UnmapPages(tempMaps[attempt], size);
             break;
         }
-        if (!tempMaps[attempt]) {
-            /* GetNewChunk failed, but we can still try the simpler method. */
-            tempMaps[attempt] = p;
-            tempSizes[attempt] = size;
-            p = nullptr;
-        }
+        if (!tempMaps[attempt])
+            break; /* Bail if GetNewChunk failed. */
     }
     if (OffsetFromAligned(p, alignment)) {
         UnmapPages(p, size);
         p = nullptr;
     }
     while (--attempt >= 0)
-        UnmapPages(tempMaps[attempt], tempSizes[attempt]);
+        UnmapPages(tempMaps[attempt], size);
     return p;
 }
 
 /*
  * mmap calls don't have to be matched with calls to munmap, so we can unmap
  * just the pages we don't need. However, as we don't know a priori if addresses
  * are handed out in increasing or decreasing order, we have to try both
  * directions (depending on the environment, one will always fail).
  */
 static void
-GetNewChunk(void **aAddress, void **aRetainedAddr, size_t *aRetainedSize, size_t size,
-            size_t alignment)
+GetNewChunk(void **aAddress, void **aRetainedAddr, size_t size, size_t alignment)
 {
     void *address = *aAddress;
     void *retainedAddr = nullptr;
-    size_t retainedSize = 0;
-    do {
-        bool addrsGrowDown = growthDirection <= 0;
+    bool addrsGrowDown = growthDirection <= 0;
+    int i = 0;
+    for (; i < 2; ++i) {
         /* Try the direction indicated by growthDirection. */
-        if (GetNewChunkInner(&address, &retainedAddr, &retainedSize, size,
-                             alignment, addrsGrowDown)) {
-            break;
+        if (addrsGrowDown) {
+            size_t offset = OffsetFromAligned(address, alignment);
+            void *head = (void *)((uintptr_t)address - offset);
+            void *tail = (void *)((uintptr_t)head + size);
+            if (MapMemoryAt(head, offset)) {
+                UnmapPages(tail, offset);
+                if (growthDirection >= -8)
+                    --growthDirection;
+                address = head;
+                break;
+            }
+        } else {
+            size_t offset = alignment - OffsetFromAligned(address, alignment);
+            void *head = (void *)((uintptr_t)address + offset);
+            void *tail = (void *)((uintptr_t)address + size);
+            if (MapMemoryAt(tail, offset)) {
+                UnmapPages(address, offset);
+                if (growthDirection <= 8)
+                    ++growthDirection;
+                address = head;
+                break;
+            }
         }
-        /* If that failed, try the opposite direction. */
-        if (GetNewChunkInner(&address, &retainedAddr, &retainedSize, size,
-                             alignment, !addrsGrowDown)) {
+        /* If we're confident in the growth direction, don't try the other. */
+        if (growthDirection < -8 || growthDirection > 8)
             break;
-        }
-        /* If retainedAddr is non-null here, we raced with another thread. */
-    } while (retainedAddr);
+        /* If that failed, try the opposite direction. */
+        addrsGrowDown = !addrsGrowDown;
+    }
+    /* If our current chunk cannot be aligned, see if the next one is aligned. */
+    if (OffsetFromAligned(address, alignment)) {
+        retainedAddr = address;
+        address = MapMemory(size);
+    }
     *aAddress = address;
     *aRetainedAddr = retainedAddr;
-    *aRetainedSize = retainedSize;
 }
 
-#define SET_OUT_PARAMS_AND_RETURN(address_, retainedAddr_, retainedSize_, toReturn_)\
-    do {                                                                            \
-        *aAddress = address_; *aRetainedAddr = retainedAddr_;                       \
-        *aRetainedSize = retainedSize_; return toReturn_;                           \
-    } while(false)
-
-static bool
-GetNewChunkInner(void **aAddress, void **aRetainedAddr, size_t *aRetainedSize, size_t size,
-                 size_t alignment, bool addrsGrowDown)
-{
-    void *initial = *aAddress;
-    if (!initial)
-        initial = MapMemory(size);
-    if (OffsetFromAligned(initial, alignment) == 0)
-        SET_OUT_PARAMS_AND_RETURN(initial, nullptr, 0, true);
-    /* Set the parameters based on whether addresses grow up or down. */
-    size_t offset;
-    void *discardedAddr;
-    void *retainedAddr;
-    int delta;
-    if (addrsGrowDown) {
-        offset = OffsetFromAligned(initial, alignment);
-        discardedAddr = initial;
-        retainedAddr = (void *)(uintptr_t(initial) + size - offset);
-        delta = -1;
-    } else {
-        offset = alignment - OffsetFromAligned(initial, alignment);
-        discardedAddr = (void*)(uintptr_t(initial) + offset);
-        retainedAddr = initial;
-        delta = 1;
-    }
-    /* Keep only the |offset| unaligned bytes. */
-    UnmapPages(discardedAddr, size - offset);
-    void *address = MapMemory(size);
-    if (!address) {
-        /* Map the rest of the original chunk again in case we can recover. */
-        address = MapMemoryAt(initial, size - offset);
-        if (!address)
-            UnmapPages(retainedAddr, offset);
-        SET_OUT_PARAMS_AND_RETURN(address, nullptr, 0, false);
-    }
-    if ((addrsGrowDown && address < retainedAddr) || (!addrsGrowDown && address > retainedAddr)) {
-        growthDirection += delta;
-        SET_OUT_PARAMS_AND_RETURN(address, retainedAddr, offset, true);
-    }
-    /* If we didn't choose the right direction, reduce its score. */
-    growthDirection -= delta;
-    /* Accept an aligned address if growthDirection didn't just flip. */
-    if (OffsetFromAligned(address, alignment) == 0 && growthDirection + delta != 0)
-        SET_OUT_PARAMS_AND_RETURN(address, retainedAddr, offset, true);
-    UnmapPages(address, size);
-    /* Map the original chunk again since we chose the wrong direction. */
-    address = MapMemoryAt(initial, size - offset);
-    if (!address) {
-        /* Return non-null retainedAddr to indicate thread-related failure. */
-        UnmapPages(retainedAddr, offset);
-        SET_OUT_PARAMS_AND_RETURN(nullptr, retainedAddr, 0, false);
-    }
-    SET_OUT_PARAMS_AND_RETURN(address, nullptr, 0, false);
-}
-
-#undef SET_OUT_PARAMS_AND_RETURN
-
 void
 UnmapPages(void *p, size_t size)
 {
     if (munmap(p, size))
         MOZ_ASSERT(errno == ENOMEM);
 }
 
 bool
--- a/js/src/gc/Nursery-inl.h
+++ b/js/src/gc/Nursery-inl.h
@@ -23,15 +23,9 @@ js::Nursery::getForwardedPointer(T **ref
     const gc::RelocationOverlay *overlay = reinterpret_cast<const gc::RelocationOverlay *>(*ref);
     if (!overlay->isForwarded())
         return false;
     /* This static cast from Cell* restricts T to valid (GC thing) types. */
     *ref = static_cast<T *>(overlay->forwardingAddress());
     return true;
 }
 
-inline void
-js::Nursery::forwardBufferPointer(JSTracer* trc, HeapSlot **pSlotElems)
-{
-    trc->runtime()->gc.nursery.forwardBufferPointer(pSlotElems);
-}
-
 #endif /* gc_Nursery_inl_h */
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -820,17 +820,17 @@ js::Nursery::collect(JSRuntime *rt, JS::
     for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
         if (c->innerViews.needsSweepAfterMinorGC())
             c->innerViews.sweepAfterMinorGC(rt);
     }
     TIME_END(sweepArrayBufferViewList);
 
     // Update any slot or element pointers whose destination has been tenured.
     TIME_START(updateJitActivations);
-    js::jit::UpdateJitActivationsForMinorGC<Nursery>(&rt->mainThread, &trc);
+    js::jit::UpdateJitActivationsForMinorGC(&rt->mainThread, &trc);
     forwardedBuffers.finish();
     TIME_END(updateJitActivations);
 
     // Resize the nursery.
     TIME_START(resize);
     double promotionRate = trc.tenuredSize / double(allocationEnd() - start());
     if (promotionRate > 0.05)
         growAllocableSpace();
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -31,17 +31,16 @@ class ObjectElements;
 class NativeObject;
 class HeapSlot;
 void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
 
 namespace gc {
 struct Cell;
 class Collector;
 class MinorCollectionTracer;
-class ForkJoinNursery;
 } /* namespace gc */
 
 namespace types {
 struct TypeObject;
 }
 
 namespace jit {
 class CodeGenerator;
@@ -130,18 +129,16 @@ class Nursery
      * returns false and leaves |*ref| unset.
      */
     template <typename T>
     MOZ_ALWAYS_INLINE bool getForwardedPointer(T **ref);
 
     /* Forward a slots/elements pointer stored in an Ion frame. */
     void forwardBufferPointer(HeapSlot **pSlotsElems);
 
-    static void forwardBufferPointer(JSTracer* trc, HeapSlot **pSlotsElems);
-
     void maybeSetForwardingPointer(JSTracer *trc, void *oldData, void *newData, bool direct) {
         if (IsMinorCollectionTracer(trc) && isInside(oldData))
             setForwardingPointer(oldData, newData, direct);
     }
 
     size_t sizeOfHeapCommitted() const {
         return numActiveChunks_ * gc::ChunkSize;
     }
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -13,17 +13,16 @@
 #include "jscntxt.h"
 #include "jsgc.h"
 #include "jsprf.h"
 #include "jstypes.h"
 #include "jswatchpoint.h"
 
 #include "builtin/MapObject.h"
 #include "frontend/BytecodeCompiler.h"
-#include "gc/ForkJoinNursery.h"
 #include "gc/GCInternals.h"
 #include "gc/Marking.h"
 #include "jit/MacroAssembler.h"
 #include "js/HashTable.h"
 #include "vm/Debugger.h"
 #include "vm/JSONParser.h"
 #include "vm/PropDesc.h"
 
@@ -115,24 +114,16 @@ MarkExactStackRootsAcrossTypes(T context
     MarkExactStackRootList<Value, MarkValueRoot>(trc, context, "exact-value");
     MarkExactStackRootList<types::Type, MarkTypeRoot>(trc, context, "types::Type");
     MarkExactStackRootList<Bindings, MarkBindingsRoot>(trc, context, "Bindings");
     MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
         trc, context, "JSPropertyDescriptor");
     MarkExactStackRootList<PropDesc, MarkPropDescRoot>(trc, context, "PropDesc");
 }
 
-#ifdef JSGC_FJGENERATIONAL
-static void
-MarkExactStackRoots(ThreadSafeContext* cx, JSTracer *trc)
-{
-    MarkExactStackRootsAcrossTypes<ThreadSafeContext*>(cx, trc);
-}
-#endif
-
 static void
 MarkExactStackRoots(JSRuntime* rt, JSTracer *trc)
 {
     for (ContextIter cx(rt); !cx.done(); cx.next())
         MarkExactStackRootsAcrossTypes<ThreadSafeContext*>(cx.get(), trc);
     MarkExactStackRootsAcrossTypes<PerThreadData*>(&rt->mainThread, trc);
 }
 
@@ -414,37 +405,16 @@ js::gc::MarkPersistentRootedChains(JSTra
 
     // Mark the PersistentRooted chains of types that are never null.
     PersistentRootedMarker<jsid>::markChain<MarkIdRoot>(trc, rt->idPersistentRooteds,
                                                         "PersistentRooted<jsid>");
     PersistentRootedMarker<Value>::markChain<MarkValueRoot>(trc, rt->valuePersistentRooteds,
                                                             "PersistentRooted<Value>");
 }
 
-#ifdef JSGC_FJGENERATIONAL
-void
-js::gc::MarkForkJoinStack(ForkJoinNurseryCollectionTracer *trc)
-{
-    ForkJoinContext *cx = ForkJoinContext::current();
-    PerThreadData *ptd = cx->perThreadData;
-
-    AutoGCRooter::traceAllInContext(cx, trc);
-    MarkExactStackRoots(cx, trc);
-    jit::MarkJitActivations(ptd, trc);
-
-#ifdef DEBUG
-    // There should be only JIT activations on the stack
-    for (ActivationIterator iter(ptd); !iter.done(); ++iter) {
-        Activation *act = iter.activation();
-        MOZ_ASSERT(act->isJit());
-    }
-#endif
-}
-#endif  // JSGC_FJGENERATIONAL
-
 void
 js::gc::GCRuntime::markRuntime(JSTracer *trc,
                                TraceOrMarkRuntime traceOrMark,
                                TraceRootsOrUsedSaved rootsSource)
 {
     gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK_ROOTS);
 
     MOZ_ASSERT(trc->callback != GCMarker::GrayCallback);
deleted file mode 100644
--- a/js/src/jit-test/lib/parallelarray-helpers.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/* 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/. */
-
-// Explanation of minItemsTestingThreshold:
-//
-// If the volume of input items in a test is small, then all of them
-// may be processed during warmup alone, and the parallel-invocation
-// will trivially succeed even if we are intentionally trying to
-// detect a failure.
-//
-// The maximum number of items processed by sequential warmups for
-// ArrayBuildPar is:
-//      maxSeqItems = maxBailouts * numSlices * CHUNK_SIZE
-//
-// For maxBailouts = 3, maxSeqItems == 3 * 8 * 32 == 768
-// For maxBailouts = 5, maxSeqItems == 5 * 8 * 32 == 1280
-//
-// Our test code does not have access to the values of these constants
-// (maxBailouts, numSlices, CHUNK_SIZE).  Therefore, the value of
-// minItemsTestingThreshold should be kept in sync with some value
-// greater than maxSeqItems as calculated above.
-//
-// This is still imperfect since it assumes numSlices <= 8, but
-// numSlices is machine-dependent.
-// (TODO: consider exposing numSlices via builtin/TestingFunctions.cpp)
-
-var minItemsTestingThreshold = 1024;
-
-// The standard sequence of modes to test.
-// First mode compiles for parallel exec.
-// Second mode checks that parallel exec does not bail.
-// Final mode tests the sequential fallback path.
-var MODE_STRINGS = ["compile", "par", "seq"];
-var MODES = MODE_STRINGS.map(s => ({mode: s}));
-
-var INVALIDATE_MODE_STRINGS = ["seq", "compile", "par", "seq"];
-var INVALIDATE_MODES = INVALIDATE_MODE_STRINGS.map(s => ({mode: s}));
-
-function build(n, f) {
-  var result = [];
-  for (var i = 0; i < n; i++)
-    result.push(f(i));
-  return result;
-}
-
-function range(n, m) {
-  // Returns an array with [n..m] (include on n, exclusive on m)
-
-  var result = [];
-  for (var i = n; i < m; i++)
-    result.push(i);
-  return result;
-}
-
-function seq_scan(array, f) {
-  // Simple sequential version of scan() that operates over an array
-
-  var result = [];
-  result[0] = array[0];
-  for (var i = 1; i < array.length; i++) {
-    result[i] = f(result[i-1], array[i]);
-  }
-  return result;
-}
-
-function assertAlmostEq(v1, v2) {
-  if (v1 === v2)
-    return true;
-  // + and other fp ops can vary somewhat when run in parallel!
-  assertEq(typeof v1, "number");
-  assertEq(typeof v2, "number");
-  var diff = Math.abs(v1 - v2);
-  var percent = diff / v1 * 100.0;
-  print("v1 = " + v1);
-  print("v2 = " + v2);
-  print("% diff = " + percent);
-  assertEq(percent < 1e-10, true); // off by an less than 1e-10%...good enough.
-}
-
-function assertStructuralEq(e1, e2) {
-    if (e1 instanceof Array && e2 instanceof Array) {
-      assertEqArray(e1, e2);
-    } else if (e1 instanceof Object && e2 instanceof Object) {
-      assertEq(e1.__proto__, e2.__proto__);
-      for (prop in e1) {
-        if (e1.hasOwnProperty(prop)) {
-          assertEq(e2.hasOwnProperty(prop), true);
-          assertStructuralEq(e1[prop], e2[prop]);
-        }
-      }
-    } else {
-      assertEq(e1, e2);
-    }
-}
-
-function assertEqArray(a, b) {
-    assertEq(a.length, b.length);
-    for (var i = 0, l = a.length; i < l; i++) {
-      try {
-        assertStructuralEq(a[i], b[i]);
-      } catch (e) {
-        print("...in index", i, "of", l);
-        throw e;
-      }
-    }
-}
-
-// Checks that whenever we execute this in parallel mode,
-// it bails out. `opFunction` should be a closure that takes a
-// mode parameter and performs some parallel array operation.
-// This closure will be invoked repeatedly.
-//
-// Here is an example of the expected usage:
-//
-//    assertParallelExecWillBail(function(m) {
-//        Array.buildPar(..., m)
-//    });
-//
-// where the `Array.buildPar(...)` is a stand-in
-// for some parallel array operation.
-function assertParallelExecWillBail(opFunction) {
-  opFunction({mode:"compile"}); // get the script compiled
-  opFunction({mode:"bailout"}); // check that it bails when executed
-}
-
-// Checks that when we execute this in parallel mode,
-// some bailouts will occur but we will recover and
-// return to parallel execution mode. `opFunction` is a closure
-// that expects a mode, just as in `assertParallelExecWillBail`.
-function assertParallelExecWillRecover(opFunction) {
-  opFunction({mode:"compile"}); // get the script compiled
-  opFunction({mode:"recover"}); // check that it bails when executed
-}
-
-// Checks that we will (eventually) be able to compile and exection
-// `opFunction` in parallel mode. Invokes `cmpFunction` with the
-// result.  For some tests, it takes many compile rounds to reach a TI
-// fixed point. So this function will repeatedly attempt to invoke
-// `opFunction` with `compile` and then `par` mode until getting a
-// successful `par` run.  After enough tries, of course, we give up
-// and declare a test failure.
-function assertParallelExecSucceeds(opFunction, cmpFunction) {
-  var failures = 0;
-  while (true) {
-    print("Attempting compile #", failures);
-    var result = opFunction({mode:"compile"});
-    cmpFunction(result);
-
-    try {
-      print("Attempting parallel run #", failures);
-      var result = opFunction({mode:"par"});
-      cmpFunction(result);
-      break;
-    } catch (e) {
-      failures++;
-      if (failures > 5) {
-        throw e; // doesn't seem to be reaching a fixed point!
-      } else {
-        print(e);
-      }
-    }
-  }
-
-  print("Attempting sequential run");
-  var result = opFunction({mode:"seq"});
-  cmpFunction(result);
-}
-
-// Compares an Array constructed in parallel against one constructed
-// sequentially. `func` should be the closure to provide as argument. For
-// example:
-//
-//    assertArraySeqParResultsEq([1, 2, 3], "map", i => i + 1)
-//
-// would check that `[1, 2, 3].map(i => i+1)` and `[1, 2, 3].mapPar(i => i+1)`
-// yield the same result.
-//
-// Based on `assertParallelExecSucceeds`
-function assertArraySeqParResultsEq(arr, op, func, cmpFunc) {
-  if (!cmpFunc)
-    cmpFunc = assertStructuralEq;
-  var expected = arr[op].apply(arr, [func]);
-  assertParallelExecSucceeds(
-    function (m) { return arr[op + "Par"].apply(arr, [func, m]); },
-    function (r) { cmpFunc(expected, r); });
-}
-
-// Similar to `compareAgainstArray`, but for the `scan` method which
-// does not appear on array.
-function testArrayScanPar(jsarray, func, cmpFunction) {
-  if (!cmpFunction)
-    cmpFunction = assertStructuralEq;
-  var expected = seq_scan(jsarray, func);
-
-  // Unfortunately, it sometimes happens that running 'par' twice in a
-  // row causes bailouts and other unfortunate things!
-
-  assertParallelExecSucceeds(
-    function(m) {
-      print(m.mode + " " + m.expect);
-      var p = jsarray.scanPar(func, m);
-      return p;
-    },
-    function(r) {
-      cmpFunction(expected, r);
-    });
-}
-
-// Checks that `opFunction`, when run with each of the modes
-// in `modes`, returns the same value each time.
-function assertParallelModesCommute(modes, opFunction) {
-  var expected = undefined;
-  var acc = opFunction(modes[0]);
-  assertParallelExecSucceeds(
-    opFunction,
-    function(r) {
-      if (expected === undefined)
-        expected = r;
-      else
-        assertStructuralEq(expected, r);
-    });
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/asm.js/testBug978714.js
+++ /dev/null
@@ -1,9 +0,0 @@
-if (!getBuildConfiguration().parallelJS)
-    quit();
-
-var y = Array.buildPar(9, function() {});
-Array.prototype.every.call(y, (function() {
-    "use asm";
-    function f() {}
-    return f
-}))
deleted file mode 100644
--- a/js/src/jit-test/tests/auto-regress/bug784015.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// |jit-test| error:Error
-
-// Binary: cache/js-dbg-64-c676b554c7bb-linux
-// Flags:
-//
-
-if (getBuildConfiguration().parallelJS) {
-  var p = new ParallelArray([1,25e8 ,3,4]);
-  var pp = p.partition(.34 );
-} else {
-  throw new Error();
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/collections/Array-build-basic.js
+++ /dev/null
@@ -1,22 +0,0 @@
-// Array.build basics
-
-if (getBuildConfiguration().parallelJS) {
-  load(libdir + "asserts.js");
-  load(libdir + "eqArrayHelper.js");
-
-  function myBuild(l, f) {
-    var a = [];
-    for (var i = 0; i < l; i++)
-      a.push(f(i));
-    return a;
-  }
-
-  // Test that build returns an identical, but new array.
-  var a1 = [];
-  for (var i = 0; i < 100; i++)
-    a1[i] = Math.random();
-  var a2 = Array.build(a1.length, (i) => a1[i]);
-
-  assertEq(a1 === a2, false);
-  assertEqArray(a2, a1);
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/collections/Array-build-surfaces.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Check superficial features of Array.build.
-
-if (getBuildConfiguration().parallelJS) {
-  load(libdir + "asserts.js");
-
-  var desc = Object.getOwnPropertyDescriptor(Array, "build");
-  assertEq(desc.configurable, true);
-  assertEq(desc.enumerable, false);
-  assertEq(desc.writable, true);
-  assertEq(Array.build.length, 2);
-  assertThrowsInstanceOf(() => new Array.build(), TypeError);  // not a constructor
-
-  // Must pass a function to second argument.
-  for (let v of [undefined, null, false, "cow"])
-    assertThrowsInstanceOf(() => Array.build(1, v), TypeError);
-
-  // The first argument must be a legal length.
-  assertThrowsInstanceOf(() => Array.build(-1, function() {}), RangeError);
-
-  // When the this-value passed in is not a constructor, the result is an array.
-  for (let v of [undefined, null, false, "cow"])
-    assertEq(Array.isArray(Array.build.call(v, 1, function() {})), true);
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-1014972.js
+++ /dev/null
@@ -1,14 +0,0 @@
-if (getBuildConfiguration().parallelJS) {
-    Function("\
-        Array.buildPar(6947, (function() {\
-            return {\
-                a: new Function,\
-                b1: function() {},\
-                b2: function() {},\
-                b3: function() {},\
-                b4: function() {}\
-            }\
-        }));\
-        selectforgc(new Object);\
-    ")()
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-1055034.js
+++ /dev/null
@@ -1,14 +0,0 @@
-function range(n, m) {
-  var result = [];
-  for (var i = n; i < m; i++)
-    result.push(i);
-  return result;
-}
-function run(arr, func) {
-  var expected = arr["map"].apply(arr, [func]);
-  function f(m) { return arr["mapPar"].apply(arr, [func, m]); }
-    f({mode:"compile"});
-    f({mode:"seq"});
- }
-if (getBuildConfiguration().parallelJS)
-  run(range(0, 1024), function (i) { var a = []; a.length = i; });
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-975959.js
+++ /dev/null
@@ -1,20 +0,0 @@
-if (!getBuildConfiguration().parallelJS)
-  quit(0);
-
-try {
-    y = z = [];
-    y[1] = x
-    for (var e, x = [];; d) {}
-} catch (e) {}
-try {
-    Object.defineProperty(this, "y", {
-        get: function() {
-            z.filterPar(function() {})
-        }
-    })(1 instanceof 2)
-} catch (e) {}
-y
-verifyprebarriers()
-y
-verifyprebarriers()
-y
deleted file mode 100644
--- a/js/src/jit-test/tests/gc/bug-992866.js
+++ /dev/null
@@ -1,15 +0,0 @@
-if (!getBuildConfiguration().parallelJS)
-  quit(0);
-
-test([0], "map", function (... Object)  {
-  var x = [];
-  for (var i = 0; i < 10; i++) {
-      x[i] = {};
-  }
-});
-
-function test(arr, op, func) {
-  for (var i = 0; i < 1000; i++) {
-    arr[op + "Par"].apply(arr, [func, undefined]);
-  }
-}
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/900683.js
+++ /dev/null
@@ -1,37 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-ParallelArray(11701, function() {
-    return /x/
-}).reduce(function(a) {
-    if (a % 9) {
-        for (var y = 0; y; ++y) {}
-        return []
-    }
-})
-
-function foo() {
-  return "foo";
-}
-
-function test() {
-var a = [1, 2, 3];
-var s = '';
-for (var x of a)
-  for (var i of 'y')
-    s += '' + foo()
-} test();
-
-ignoreComments = [];
-
-function bug909276() {
-var actual = '';
-for (var next of ignoreComments) {
-  actual += a;
-  for (var b in x) {
-    actual += b.eval("args = [-0, NaN, -1/0]; this.f(-0, NaN, -1/0);");
-  }
-}
-var y = Iterator([1,2,3], true);
-for (var c in y) {}
-} bug909276();
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug905989.js
+++ /dev/null
@@ -1,13 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-function TestCase(n, d, e, a) {};
-function reportCompare() {
-  new TestCase();
-}
-reportCompare();
-TestCase = ParallelArray;
-try {
-  reportCompare();
-} catch(exc1) {}
-reportCompare();
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug906885.js
+++ /dev/null
@@ -1,8 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-ParallelArray([57], function() {
-    return (Math.max(2207764374, (function() {
-        return 1
-    })()))
-})
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug908867.js
+++ /dev/null
@@ -1,42 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-x = ParallelArray()
-y = x.shape
-Object.defineProperty(this, "z", {
-    get: function() {
-        return x.flatten()
-    }
-})
-Object.defineProperty(y, 5, {
-    value: this
-});
-y[8] = z
-valueOf = (function() {
-    function f() {
-        (.9 % 1) > f
-    }
-    return f
-})(this, {})
-x.shape.join()
-
-
-assertArraySeqParResultsEq(range(0, 1024), "filter", function(e, i) { return (i % (1.1)) != 0; });
-function range(n, m) {
-  var result = [];
-  for (var i = n; i < m; i++)
-    result.push(i);
-  return result;
-}
-function assertArraySeqParResultsEq(arr, op, func) {
-  arr[op].apply(arr, [func]);
-}
-
-
-function foo(v) {
-  if (v < -200) return 0;
-  if (v > 200) return 0;
-  return v % 1;
-}
-assertEq(foo(0.9), 0.9);
-assertEq(foo(0.9), 0.9);
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug911708.js
+++ /dev/null
@@ -1,11 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-function x() {
-    yield x
-}
-new(x)
-ParallelArray([7247], function() {
-    --x
-    eval("")
-})
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug916761.js
+++ /dev/null
@@ -1,11 +0,0 @@
-if (typeof ParallelArray === "undefined")
-    quit();
-
-function toString(r) {
-    var result = "";
-    for (var i = 0; i < 5; i++)
-	result += r.get(i);
-    return result;
-}
-Array.prototype[2] = 'y';
-assertEq(toString(new ParallelArray(['x', 'x'])), "xxyundefinedundefined");
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug936361.js
+++ /dev/null
@@ -1,5 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-x = ParallelArray([1942], function() {})
-x + watch.call(x, "length", (function() {}));
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug938431.js
+++ /dev/null
@@ -1,9 +0,0 @@
-if (typeof ParallelArray === "undefined")
-  quit();
-
-function x() {}
-ParallelArray(3385, function(y) {
-    Object.defineProperty([], 8, {
-        e: (y ? x : Math.fround(1))
-    })
-})
deleted file mode 100644
--- a/js/src/jit-test/tests/ion/bug977674.js
+++ /dev/null
@@ -1,41 +0,0 @@
-if (!getBuildConfiguration().parallelJS)
-  quit(0);
-
-function testReduce() {
-  function sum(a, b) {
-    var r = a + b;
-  }
-  var array = build(8 * 0X0aaec , function() { return 1; });
-  var parResult = array.reducePar(sum);
-}
-for (var ix = 0; ix < 3; ++ix) {
-  testReduce();
-}
-function build(n, f) {
-  var result = [];
-  for (var i = 0; i < n; i++)
-    result.push(f(i));
-  return result;
-}
-function seq_scan(array, f) {
-  for (var i = 1; i < array.length; i++) {
-  }
-}
-function assertAlmostEq(v1, v2) {
-    if (e1 instanceof Array && e2 instanceof Array) {
-      for (prop in e1) {
-        if (e1.hasOwnProperty(prop)) {        }
-      }
-    }
-}
-function assertEqArray(a, b) {
-    for (var i = 0, l = a.length; i < l; i++) {
-      try {      } catch (e) {      }
-    }
-}
-function assertParallelExecWillRecover(opFunction) {
-assertParallelExecSucceeds(
-    function(m) {},
-    function(r) {}
-);
-}
--- a/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js
+++ b/js/src/jit-test/tests/ion/inlining/TypedObject-TypeDescrIsArrayType-unknown.js
@@ -30,19 +30,26 @@ if (!this.TypedObject) {
 
 var T = TypedObject;
 var AT = new T.ArrayType(T.int32, 100);
 
 function check(v) {
     return v.map(x => x+1);
 }
 
+function Array_build(n, f) {
+  var a = new Array(n);
+  for ( var i=0 ; i < n ; i++ )
+    a[i] = f(i);
+  return a;
+}
+
 function test() {
     var w1 = AT.build(x => x+1);
-    var w2 = Array.build(100, x => x+1);
+    var w2 = Array_build(100, x => x+1);
     w2.map = w1.map;
     var a = [ w1, w2 ];
     for ( var i=0 ; i < 2000 ; i++ )
 	try { a[i%2] = check(a[i%2]); } catch (e) { assertEq( i%2, 1 ); }
     return a[0];
 }
 
 var w = test();
--- a/js/src/jit-test/tests/ion/testFloat32.js
+++ b/js/src/jit-test/tests/ion/testFloat32.js
@@ -22,21 +22,16 @@
         for (var i = 0; i < v.length; ++i)
         v[i] = i;
     var t = (false  );
     for (var i = 0; i < i .length; ++i)
         t += v[i];
     })();
     //
     (function() {
-        if (typeof ParallelArray !== "undefined")
-        ParallelArray([1606], Math.fround)
-    })();
-    //
-    (function() {
         x = y = {};
         z = new Float32Array(6)
         for (c in this) {
             Array.prototype.unshift.call(x, new ArrayBuffer())
         }
         Array.prototype.sort.call(x, (function (j) {
             y.s = z[2]
         }))
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-buildPar-in-loop.js
+++ /dev/null
@@ -1,20 +0,0 @@
-// |jit-test| slow;
-
-load(libdir + "parallelarray-helpers.js")
-
-function buildComprehension() {
-  var pa1 = Array.buildPar(256, function (idx) { return idx; });
-  for (var i = 0; i < 20000; i++) {
-    print(i);
-    buildAndCompare();
-  }
-
-  function buildAndCompare() {
-    // this will be ion-generated:
-    var pa2 = Array.buildPar(256, function (idx) { return idx; });
-    assertStructuralEq(pa1, pa2);
-  }
-}
-
-if (getBuildConfiguration().parallelJS)
-  buildComprehension();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-buildPar-nested.js
+++ /dev/null
@@ -1,17 +0,0 @@
-load(libdir + "parallelarray-helpers.js")
-
-function test() {
-  var pa1 = Array.buildPar(256, function (x) {
-    return Array.buildPar(256, function(y) { return x*1000 + y; });
-  });
-
-  for (var x = 0; x < 256; x++) {
-    var pax = pa1[x];
-    for (var y = 0; y < 256; y++) {
-      assertEq(pax[y], x * 1000 + y);
-    }
-  }
-}
-
-if (getBuildConfiguration().parallelJS)
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-buildPar.js
+++ /dev/null
@@ -1,11 +0,0 @@
-load(libdir + "parallelarray-helpers.js")
-
-function buildComprehension() {
-  // 1D comprehension
-  var p = Array.buildPar(10, function (idx) { return idx; });
-  var a = [0,1,2,3,4,5,6,7,8,9];
-  assertEqArray(p, a);
-}
-
-if (getBuildConfiguration().parallelJS)
-  buildComprehension();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-all.js
+++ /dev/null
@@ -1,3 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 1024), "filter", function() { return true; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-every-third-element.js
+++ /dev/null
@@ -1,6 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 1024), "filter", function(e, i) {
-    return (i % 3) != 0;
-  });
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-non-divisible.js
+++ /dev/null
@@ -1,7 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-// since we divide things into chunks of 32, and filter uses some
-// bitsets, test that all that logic works fine if the number of items
-// is not evenly divisible by 32:
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 617), "filter", function(i) { return (i % 2) == 0; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-none.js
+++ /dev/null
@@ -1,3 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 1024), "filter", function() { return false; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-short.js
+++ /dev/null
@@ -1,3 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 4), "filter", function(i) { return i % 2; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-truthy.js
+++ /dev/null
@@ -1,19 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testFilterMisc() {
-  function truthy(e, i, c) {
-    switch (i % 6) {
-      case 0: return 1;
-      case 1: return "";
-      case 2: return {};
-      case 3: return [];
-      case 4: return false;
-      case 5: return true;
-    }
-  }
-
-  assertArraySeqParResultsEq(range(0, 1024), "filter", truthy);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testFilterMisc();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-filterPar-very-few.js
+++ /dev/null
@@ -1,3 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 1024), "filter", function(i) { return i <= 1 || i >= 1022; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-add-from-upvar-field.js
+++ /dev/null
@@ -1,13 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-var SIZE = 4096;
-
-function testMap() {
-  var q = {f: 22};
-  assertArraySeqParResultsEq(range(0, SIZE), "map", function(e) {
-    return e + q.f;
-  });
-}
-
-if (getBuildConfiguration().parallelJS)
-  testMap();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-assign-to-def-prop.js
+++ /dev/null
@@ -1,10 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function wrapInObject(v) {
-    var obj = {f: 2};
-    obj.f += v;
-    return obj;
-}
-
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 64), "map", wrapInObject);
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-factorial.js
+++ /dev/null
@@ -1,10 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function factorial(n) {
-  if (n == 0)
-    return 1;
-  return n * factorial(n - 1);
-}
-
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 64), "map", factorial);
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-fn-args.js
+++ /dev/null
@@ -1,19 +0,0 @@
-function testMap() {
-  // Test map elemental fun args
-  var p = [1,2,3,4];
-  var m = p.mapPar(function(e) {
-    assertEq(e >= 1 && e <= 4, true);
-  });
-  var m = p.mapPar(function(e,i) {
-    assertEq(e >= 1 && e <= 4, true);
-    assertEq(i >= 0 && i < 4, true);
-  });
-  var m = p.mapPar(function(e,i,c) {
-    assertEq(e >= 1 && e <= 4, true);
-    assertEq(i >= 0 && i < 4, true);
-    assertEq(c, p);
-  });
-}
-
-if (getBuildConfiguration().parallelJS)
-  testMap();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-inc.js
+++ /dev/null
@@ -1,4 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-if (getBuildConfiguration().parallelJS)
-  assertArraySeqParResultsEq(range(0, 512), "map", function(e) { return e+1; });
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-nested.js
+++ /dev/null
@@ -1,21 +0,0 @@
-load(libdir + "parallelarray-helpers.js")
-
-function test() {
-  var pa0 = range(0, 256);
-
-  var pa1;
-  for (var i in MODES)
-    pa1 = Array.buildPar(256, function (x) {
-      return pa0.mapPar(function(y) { return x * 1000 + y; });
-    }, MODES[i]);
-
-  for (var x = 0; x < 256; x++) {
-    var pax = pa1[x];
-    for (var y = 0; y < 256; y++) {
-      assertEq(pax[y], x * 1000 + y);
-    }
-  }
-}
-
-if (getBuildConfiguration().parallelJS)
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-mapPar-short.js
+++ /dev/null
@@ -1,12 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function test() {
-  // Test what happens if the length of the array is very short (i.e.,
-  // less than the number of cores).  There used to be a bug in this
-  // case that led to crashes or other undefined behavior.
-  var makeadd1 = function (v) { return [v]; }
-  assertArraySeqParResultsEq(range(1, 3), "map", makeadd1);
-}
-
-if (getBuildConfiguration().parallelJS)
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-bail.js
+++ /dev/null
@@ -1,32 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-// Tests that reduce saves its intermediate state correctly by
-// inducing a bailout in the middle of the reduction.  This test may
-// fail to test what it is intended to test if the wrong number of
-// worker threads etc are present.  It reproduced an existing bug when
-// used with 8 worker threads.
-
-function testReduce() {
-  var aCounter = 0;
-  function sum(a, b) {
-    var r = a + b;
-    if (r == 234) // occurs once per slice
-      aCounter++;
-    return r;
-  }
-
-  // We use a big array, to make sure that the test runs with 64 slices.
-  var array = build(8 * 4096, function() { return 1; });
-  var seqResult = array.reduce(sum);
-  var seqCounter = aCounter;
-
-  aCounter = 0;
-  var parResult = array.reducePar(sum);
-  var parCounter = aCounter;
-
-  assertEq(true, parCounter >= seqCounter);
-  assertStructuralEq(parResult, seqResult);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduce();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-fn-args.js
+++ /dev/null
@@ -1,16 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testReduce() {
-  // Test reduce elemental fun args
-  var N = 64;
-  var p = range(1, N+1);
-  var r = p.reducePar(function (a, b) {
-    assertEq(a >= 1 && a <= N, true);
-    assertEq(b >= 1 && b <= N, true);
-    return a;
-  });
-  assertEq(r >= 1 && r <= N, true);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduce();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-length-one.js
+++ /dev/null
@@ -1,10 +0,0 @@
-function testReduceOne() {
-    // Note: parallel execution with only 1 element will generally
-    // bailout, so don't use assertParallelArrayModesEq() here.
-    var p = [1];
-    var r = p.reducePar(function (v, p) { return v*p; });
-    assertEq(r, 1);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduceOne();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-mul-short.js
+++ /dev/null
@@ -1,16 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testReduce() {
-  // This test is interesting because during warmup v*p remains an
-  // integer but this ceases to be true once real execution proceeds.
-  // By the end, it will just be some double value.
-
-  function mul(v, p) { return v*p; }
-
-  // Ensure that the array only contains values between 1 and 4.
-  var array = range(1, 513).map(function(v) { return (v % 4) + 1; });
-  assertArraySeqParResultsEq(array, "reduce", mul, assertAlmostEq);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduce();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-mul.js
+++ /dev/null
@@ -1,15 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testReduce() {
-  // This test is interesting because during warmup v*p remains an
-  // integer but this ceases to be true once real execution proceeds.
-  // By the end, it will just be infinity. Note that this is a case
-  // where the non-commutative of floating point becomes relevant,
-  // so we must use assertAlmostEq.
-  function mul(v, p) { return v*p; }
-  var array = range(1, 513);
-  assertArraySeqParResultsEq(array, "reduce", mul, assertAlmostEq);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduce();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-nested-sum-each-row.js
+++ /dev/null
@@ -1,23 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function test() {
-  var array1 = range(0, 512);
-  var array2 = Array.build(512, function(i) {
-    return i*1000000 + array1.reduce(sum);
-  });
-
-  assertParallelExecSucceeds(
-    function (m) {
-      return  Array.buildPar(512, function(i) {
-        return i*1000000 + array1.reducePar(sum);
-      });
-    },
-    function (r) {
-      assertStructuralEq(array2, r);
-    });
-
-  function sum(a, b) { return a+b; }
-}
-
-if (getBuildConfiguration().parallelJS)
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-reducePar-sum.js
+++ /dev/null
@@ -1,9 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testReduce() {
-  function sum(v, p) { return v+p; }
-  assertArraySeqParResultsEq(range(1, 513), "reduce", sum);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testReduce();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-scanPar-fn-args.js
+++ /dev/null
@@ -1,12 +0,0 @@
-function testScan() {
-  // Test reduce elemental fun args
-  var p = [1,2,3,4];
-  var r = p.scanPar(function (a, b) {
-    assertEq(a >= 1 && a <= 4, true);
-    assertEq(b >= 1 && b <= 4, true);
-    return a;
-  });
-}
-
-if (getBuildConfiguration().parallelJS)
-  testScan();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-scanPar-one.js
+++ /dev/null
@@ -1,10 +0,0 @@
-function testScanOne() {
-  function f(v, p) { throw "This should never be called."; }
-  var p = [1];
-  var s = p.scanPar(f);
-  assertEq(s[0], 1);
-  assertEq(s[0], p.reducePar(f));
-}
-
-if (getBuildConfiguration().parallelJS)
-  testScanOne();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-scanPar-sorted.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// |jit-test| slow;
-
-load(libdir + "parallelarray-helpers.js");
-
-function mergeSorted(l1, l2) {
-  var result = [];
-  var i1 = 0, i2 = 0, j = 0;
-  while (i1 < l1.length && i2 < l2.length) {
-    if (l1[i1] < l2[i2])
-      result[j++] = l1[i1++];
-    else
-      result[j++] = l2[i2++];
-  }
-  while (i1 < l1.length) {
-    result[j++] = l1[i1++];
-  }
-  while (i2 < l2.length) {
-    result[j++] = l2[i2++];
-  }
-  return result;
-}
-
-function test() {
-  var elts = [];
-  var ints = range(1, 5), c = 0;
-
-  // Using 2048 as the length of elts induces bailouts due to GC.
-  // This exposed various bugs.
-  for (var i = 0; i < 2048; i++)
-    elts[i] = ints;
-
-  var scanned1 = seq_scan(elts, mergeSorted);
-  var scanned2 = elts.scanPar(mergeSorted);
-  assertStructuralEq(scanned1, scanned2);
-}
-
-if (getBuildConfiguration().parallelJS)
-  test();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-scanPar-sum.js
+++ /dev/null
@@ -1,4 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-function sum(a, b) { return a+b; }
-if (getBuildConfiguration().parallelJS)
-  testArrayScanPar(range(1, 1024), sum);
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/Array-throws.js
+++ /dev/null
@@ -1,54 +0,0 @@
-load(libdir + "asserts.js");
-
-function testArrayThrows() {
-  // Test kernel not being callable.
-  var a = [1,2,3,4,5,6,7,8];
-  for (var [opName, args] in ["mapPar", [{}],
-                              "filterPar", [{}],
-                              "reducePar", [{}],
-                              "scanPar", [{}]])
-  {
-    assertThrowsInstanceOf(function () { a[opName].apply(a, args); }, TypeError);
-  }
-
-  assertThrowsInstanceOf(function () {
-    a.scatterPar(a, 0, {});
-  }, TypeError);
-
-  assertThrowsInstanceOf(function () {
-    Array.buildPar(1024, {});
-  }, TypeError);
-
-  // Test bad lengths.
-  assertThrowsInstanceOf(function () {
-    Array.buildPar(0xffffffff + 1, function () {});
-  }, RangeError);
-
-  assertThrowsInstanceOf(function () {
-    a.scatterPar(a, 0, function () {}, 0xffffffff + 1);
-  }, RangeError);
-
-  // Test empty reduction.
-  for (var opName in ["reducePar", "scanPar"]) {
-    assertThrowsInstanceOf(function () {
-      var a = [];
-      a[opName](function (v, p) { return v * p; });
-    }, TypeError);
-  }
-
-  // Test scatter:
-  //  - no conflict function.
-  //  - out of bounds
-  var p = [1,2,3,4,5];
-
-  assertThrowsInstanceOf(function () {
-    p.scatterPar([0,1,0,3,4]);
-  }, Error);
-
-  assertThrowsInstanceOf(function () {
-    p.scatterPar([0,1,0,3,11]);
-  }, Error);
-}
-
-if (getBuildConfiguration().parallelJS)
-  testArrayThrows();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-outpointer-struct.js
+++ /dev/null
@@ -1,36 +0,0 @@
-// Test basic fromPar parallel execution using an out
-// pointer to generate a struct return.
-
-if (!getBuildConfiguration().parallelJS)
-  quit();
-
-load(libdir + "parallelarray-helpers.js")
-
-var { ArrayType, StructType, uint32 } = TypedObject;
-
-function test() {
-  var L = minItemsTestingThreshold;
-
-  var Matrix = uint32.array(L, 2);
-  var matrix = new Matrix();
-  for (var i = 0; i < L; i++)
-    matrix[i][0] = i;
-
-  var Point = new StructType({x: uint32, y: uint32});
-  var Points = Point.array(L);
-
-  assertParallelExecSucceeds(
-    // FIXME Bug 983692 -- no where to pass `m` to
-    function(m) Points.fromPar(matrix, function(p, i, c, out) { out.y = p[0]; }),
-    function(points) {
-      for (var i = 0; i < L; i++) {
-        assertEq(matrix[i][0], i);
-        assertEq(matrix[i][1], 0);
-        assertEq(points[i].x, 0);
-        assertEq(points[i].y, i);
-      }
-    });
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/TypedObj-fromPar-return-scalar.js
+++ /dev/null
@@ -1,27 +0,0 @@
-// Test basic fromPar parallel execution using a scalar return value.
-
-if (!getBuildConfiguration().parallelJS)
-  quit();
-
-load(libdir + "parallelarray-helpers.js")
-
-var { uint8, uint32 } = TypedObject;
-
-function test() {
-  var L = minItemsTestingThreshold;
-  var Uints = uint32.array(L);
-  var Uint8s = uint8.array(L);
-
-  var uint32s = new Uints();
-
-  assertParallelExecSucceeds(
-    // FIXME Bug 983692 -- no where to pass `m` to
-    function(m) Uint8s.fromPar(uint32s, function(e) e + 1),
-    function(uint8s) {
-      for (var i = 0; i < L; i++)
-        assertEq((uint32s[i] + 1) & 0xFF, uint8s[i]);
-    });
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/TypedObj-mapPar-outpointer-struct.js
+++ /dev/null
@@ -1,33 +0,0 @@
-// Test basic mapPar parallel execution using an out
-// pointer to generate a struct return.
-
-if (!this.hasOwnProperty("TypedObject"))
-  quit();
-
-load(libdir + "parallelarray-helpers.js")
-
-var { ArrayType, StructType, uint32 } = TypedObject;
-
-function test() {
-  var L = minItemsTestingThreshold;
-  var Point = new StructType({x: uint32, y: uint32});
-  var Points = Point.array(L);
-  var points = new Points();
-  for (var i = 0; i < L; i++)
-    points[i].x = i;
-
-  assertParallelExecSucceeds(
-    // FIXME Bug 983692 -- no where to pass `m` to
-    function(m) points.mapPar(function(p, i, c, out) { out.y = p.x; }),
-    function(points2) {
-      for (var i = 0; i < L; i++) {
-        assertEq(points[i].x, i);
-        assertEq(points[i].y, 0);
-        assertEq(points2[i].x, 0);
-        assertEq(points2[i].y, i);
-      }
-    });
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/TypedObj-mapPar-return-scalar.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// Test basic mapPar parallel execution.
-
-if (!this.hasOwnProperty("TypedObject"))
-  quit();
-
-load(libdir + "parallelarray-helpers.js")
-
-var { ArrayType, StructType, uint32 } = TypedObject;
-
-function test() {
-  var L = minItemsTestingThreshold;
-  var Uints = uint32.array(L);
-  var uints1 = new Uints();
-  assertParallelExecSucceeds(
-    // FIXME Bug 983692 -- no where to pass `m` to
-    function(m) uints1.mapPar(function(e) e + 1),
-    function(uints2) {
-      for (var i = 0; i < L; i++)
-        assertEq(uints1[i] + 1, uints2[i]);
-    });
-}
-
-test();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-array-nonwritable.js
+++ /dev/null
@@ -1,40 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function buildSimple()
-{
-  var subarr = [];
-  for (var i = 0; i < 100; i++)
-    subarr[i] = 3;
-  subarr[100] = 0;
-
-  var expected = [];
-  for (var i = 0; i < 256; i++)
-    expected[i] = subarr;
-
-  var pa = Array.buildPar(256, function(_) {
-    var arrs = [];
-    for (var i = 0; i < 100; i++)
-      arrs[i] = [0, 1, 2, 3, 4, 5, 6];
-
-    arrs[100] =
-      Object.defineProperty([0, 1, 2, 3, 4, 5, 6, 7],
-                            "length",
-                            { writable: false, value: 7 });
-
-    for (var i = 0; i < 101; i++)
-      arrs[i][7] = 7;
-
-    var x = [];
-    for (var i = 0; i < 101; i++) {
-      var a = arrs[i];
-      x[i] = +(a.length === 8) + 2 * +("7" in a);
-    }
-
-    return x;
-  });
-
-  assertEqArray(pa, expected);
-}
-
-if (getBuildConfiguration().parallelJS)
-  buildSimple();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-array.js
+++ /dev/null
@@ -1,33 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function buildSimple() {
-
-    assertParallelModesCommute(["seq", "par"], function(m) {
-        return Array.buildPar(256, function(i) {
-            return [i, i+1, i+2, i+3];
-        }, m);
-    });
-
-    assertParallelModesCommute(["seq", "par"], function(m) {
-        return Array.buildPar(256, function(i) {
-            var x = [];
-            for (var i = 0; i < 4; i++) {
-                x[i] = i;
-            }
-            return x;
-        }, m);
-    });
-
-    assertParallelModesCommute(["seq", "par"], function(m) {
-        return Array.buildPar(256, function(i) {
-            var x = [];
-            for (var i = 0; i < 99; i++) {
-                x[i] = i;
-            }
-            return x;
-        }, m);
-    });
-}
-
-if (getBuildConfiguration().parallelJS)
-  buildSimple();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-different-objs.js
+++ /dev/null
@@ -1,22 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testMap() {
-  assertArraySeqParResultsEq(range(0, 64), "map", function (v) {
-    var x = [];
-    var N = 2;
-    for (var i = 0; i < 10; i++) {
-      if ((i % N) == 0) {
-        x[i] = {f1: v};
-      } else if ((i % N) == 1) {
-        x[i] = {f1: v, f2: v, f3: v,
-                f4: v, f5: v, f6: v,
-                f7: v, f8: v, f9: v};
-      }
-    }
-    return x;
-  });
-}
-
-if (getBuildConfiguration().parallelJS)
-  testMap();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-many-objs.js
+++ /dev/null
@@ -1,24 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testMap() {
-  // At least on my machine, this test is successful, whereas
-  // `alloc-too-many-objs.js` fails to run in parallel because of
-  // issues around GC.
-
-  var nums = range(0, 10);
-
-  assertParallelModesCommute(["seq", "par"], function(m) {
-    print(m.mode+" "+m.expect);
-    nums.mapPar(function (v) {
-      var x = [];
-      for (var i = 0; i < 20000; i++) {
-        x[i] = {from: v};
-      }
-      return x;
-    }, m)
-  });
-}
-
-if (getBuildConfiguration().parallelJS)
-  testMap();
-
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-obj.js
+++ /dev/null
@@ -1,12 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function buildSimple() {
-    assertParallelModesCommute(["seq", "par"], function(m) {
-        return Array.buildPar(256, function(i) {
-            return { x: i, y: i + 1, z: i + 2 };
-        }, m);
-    });
-}
-
-if (getBuildConfiguration().parallelJS)
-  buildSimple();
deleted file mode 100644
--- a/js/src/jit-test/tests/parallel/alloc-too-many-objs.js
+++ /dev/null
@@ -1,37 +0,0 @@
-load(libdir + "parallelarray-helpers.js");
-
-function testMap() {
-
-  // Note: This is the same kernel function as `alloc-many-objs`, but
-  // with a larger bound.  This often fails par. exec. because it
-  // triggers GC at inconvenient times.  But let's just test that it