merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 28 Feb 2017 11:24:33 +0100
changeset 490433 1bc2ad020aee2830e0a7941f10958dbec108c254
parent 490431 682ee6f4802745005eccdb88f831828051ae4c1b (current diff)
parent 490432 22974497e57e814c3119a30b483842c793067434 (diff)
child 490434 063c77665cd3ef054175dbbd3c69daeb54ffeb0c
child 490436 ea8ea5f6a1dd078eff540455fb9fc474b79a4b3c
child 490451 4d3e8107cea50422450398e18b00c6d7b5cab93b
child 490453 110ce9bee70adc2ad314b8927385b851f1ce67b7
child 490454 65d0a93c36b175dc366c85b097344ed7e80103f3
child 490457 d5f662dff0bddbfdee76254ee3b236b385db18d3
child 490459 7c6799ecb0c8334d6ad37e207708918c86be5d08
child 490460 1df8360b30a1c30d898f19ded7836d2b4b28421e
child 490461 53e3374689734477507bdb217b13036240e0d182
child 490466 b5bda8c7ac745d2205b0c7381686dfa6fdf213af
child 490476 c245c00fe456318b8ebcb76016335849b9927ad3
child 490480 6a164b64f4d001c5235ed0bb30b8fb769766f959
child 490481 9be48d8708cbeaa60b767881d969a901d6861ecf
child 490489 fb50b669e464c5dc7b4f9f76feff63ba25043483
child 490505 0d6ca3d14e5b4e0a6ace7e72f074e2b29e8400f6
child 490529 217283972c4fea27f5588f028be206b6807478af
child 490538 9dfc2a7c3ef6af786cb976b29418e63ea7db0bf4
child 490563 13e3ffc64949a2498298c636b15edc672d4c654e
child 490567 4542b047e219aba35cb15f0908a4c5e67f044bfc
child 490569 b3bf05858c77041cb9766f127033d11bd553bdd0
child 490571 0b6445f594200f1b1624a24dcd8d928c65066894
child 490573 37d29dd16e12bfdd9950810f7e38f9b27412d91f
child 490582 2c81cab73f0829b1c20f688679421b33089a16c5
child 490584 be8c202361fcef0a47983371d370b1ace27cecbe
child 490595 697dbeae416bf99e4a43b60ee246d68b576be330
child 490625 1412772e9dbae2d854abda9c432cca938e602ed3
child 490628 e1703e1b061c443964786031491b0497dfeca354
child 490632 a243a278d184216be511f5fd04479d758ec61420
child 490634 c9354bc45e6e95e0c42158045906c18db20fd48d
child 490637 af102d53de3407908b15b69ba0263747561a1627
child 490638 6e8b09cf0a9acadb5afc0a4a586b76d1f883952b
child 490641 7653d2f8957c859b22ebc1e53f9fec2ea5db6265
child 490646 f322207e8cf103761419fc011458a596c28a7093
child 490649 ba3d20d8031a34d446483c0642014f84231c8298
child 490652 0f2597225e96ee1e2815a9ebf9659c2597fb5e45
child 490653 71121dca647bdf5807b26754707ef3b3cf3b1884
child 490654 e7cd9a53064e01bbaf314163ef5f93638a014516
child 490655 06c373934bc9290ab8f0a07dd986c954c3155b23
child 490658 21aa6c5cb0548c080a6fc2d1980b807f14237743
child 490660 720089f6e16cb4c65ce98c8050a3faffa94b894a
child 490661 2f60b1b5b5e2971a11db50093a65b75c761625cf
child 490662 3efa123a8074ae1b60e9d986adeccc747cd0dab5
child 490663 aab7fad00ac245cac50f9225ac45f2917df4b3e4
child 490664 3f3ca1e99c63e9ca4e5d1937641275aee8ae3900
child 490666 1f31246ac9801baadb702a7bba9234f72e342748
child 490668 bd061e720fd383cc1a0687c785dcbe2aebc21048
child 490669 dd53612eb979c1d464fbd1b28f42c696546b2ec4
child 490674 0c1e7e989c1eaeffea3b890103be095402241db3
child 490675 6146c7a8dd007621afb3cadd256ef12dba97124c
child 490710 95480a61674b3bb87b358d09c81e1f2f06d57545
child 490721 144b81bf94259b4755db231989822db84a7c37f2
child 490724 673f9b911d1781d8071033e78d772f435b16fd7f
child 490736 92fcce340a8ed6250dc292f6b8851baf64f9ebcd
child 490741 0bbc31e5cbf4f6fe47bc10dae249a6e452c4659c
child 490745 17fa9e2bd8a2bd3e2065c5e0afd04e06e7ba01d2
child 490762 aa3cadb8d78697a5cac0b53e3c8910239d074ece
child 490780 716bb6df434acc245721d15a7ee14c5bfae0f44a
child 490790 7d18fa187f831c68435bdbe006af065cd7a625cb
child 490799 005e450d6c4e2e182ec8a05abd7ef722384c0554
child 490801 14705ad9e26a3c71730b932439af84f31dffd24c
child 490803 7ff0cbedceb00849e37dcf14dc881eaef84d3c67
child 490815 cbdbbcbba85e4a2cb9fdb7d87dee86c9435cd204
child 490819 564ed5df5a5800a89d112430adbdb24f2c491878
child 490820 57fe18923985cd18e36cd030bb844b20298abf05
child 490821 855cda9296a56f7914f0e8509da336a654cdb06f
child 490823 59555eadd075d273d823ad5d4fd55f650b7e2520
child 490824 2dd1560c92b61fff1fd1809ead53a92d456ceed7
child 490827 948a2b462886714b1fd172c8d42b32fe1d7b0ed9
child 490830 7be0dbbc51a373f534244c28ba2ba72a2bc65bd1
child 490832 c595ed0d28da33dbfe07398394201269f9702030
child 490880 3d45f15d4c720e619738f7d649f55dd3306f93c1
child 490899 3418de94ce3d820d4eba9db5a83cb1d91c4bab1e
child 490907 a78b5a95067a97043ee0623edc9b74ec9fe5dc10
child 490909 66a66ffe4b90bbdb20d4f79fe74fe02b8b0c2c81
child 490914 9147f9d83f41b4c5e3dd69ae6d34ddc0f3cb157f
child 490929 45640b81ed5009dfa2628bae05d5f66da9e3e7bf
child 490934 5fe280d7a536896eb11d918a69456a72c5594761
child 490936 f6b6546f56f3233ccf336984645ad6d1d2123a69
child 490972 409f4b19ff3225f796a2b5579a1c80124ff4b62b
child 490986 3835ccfc30ceb2739837913a425356198f6bacac
child 490993 cf61ae1a4e47b2857cb75cf77f102113abbd433b
child 490995 ad88284ef743520a363975972d2c4f69590cb7d3
child 491001 3d491c6747ec1d2f87526c1f98e99485908c84cc
child 491121 30629978e190c8ece3b73ed3eff60485812e09d3
child 491593 1c52f8d62e325dcfd22f18ca7e32363832b75d57
child 491598 b941fe115410a56b59075f52fe68f0501716964f
child 491623 50d55483531a3486d5f3c425b8403ef6ff78809b
child 491727 eb514d63a5e03f290c64117d307c63860e25c46a
child 491738 e760a0b75b45f22560c6d0d8d0eef980766d4efe
child 491741 370e95132711766ccc41e0b1f17cf55eb3a20ca7
child 491742 bf8ef7ad50a5d624f25bd39dc5839a2342bfd480
child 491771 442fac5cc8a6518054c5d2c0ef42e4ed44546b66
child 491802 b2d507c4a83ff47a67f7045715fcebaa95b215cf
child 491813 aecdffe13ade75c6da4eed6d3b46f0aa822cd90e
child 491814 f1517de576d4d34c5496b943ad7195fd3c12e141
child 491817 8edb9cb5b6fd2c391593200443cef65890aab8ca
child 491819 386c1d1a29a547c288f4d366460e73f797b1bf2b
child 491826 506068a33fa0d55b848c3dcc1eea11e7b57410c7
child 491834 bc3b8e8e45d64d7a629da31f4f0bdc3add8c65b0
child 491859 272920bc2633472836aa090662ace68a03b8823c
child 491997 2ad767df5bfd1fa61309161ce6f1e6fbbefbfddd
child 492038 7a4512b683b9e7ed5d72ac8e050cc0d659b6447d
child 492039 6b9fef87bb5a3db752aaf36747f554ffc69484c5
child 492043 c01e4623c6c7689cdb6377364870b5279fc3db60
child 492140 b0488c7b7d3e7914e42eebf8fd4e18a7e25ff641
child 492622 bf271760bbc851f49cfe7276e279ddf648a290a7
child 492638 2ded5e85ddabd3b9df75f5be7e6c2539763260bc
child 493198 21a259aa0f24b46ff259ec7fc057aa44b3e7e4c6
child 493279 c2f40aabcf869420d43fda6f3fd928e66ffa84d9
child 493303 2d4aecf051a45a10ce591793b21fefac040db3fb
child 493309 44247441ff7aa6f70cc07de74e32578a54175918
child 493621 e550aeabafd98c50ab739a60454c3017ece40fee
child 493733 f3f1971f33d8fe6b560c1a9aca307219725713c6
child 493875 1f45d92fcda242ca0c74bbdc173f849529ea8a93
child 494046 f62a455522429be8d349f1c06f7b48e2593fb2d5
child 494072 7c71e437c5a099be4eacbbce4576d6ce42c07eca
child 494084 be8b2fd4e162d5273464d7c6f95328bc506911e0
child 494090 ede97914cfd194f6a7dab25e4a5ca7b87c2821b7
child 494195 3b04f7e2dd7a51e05c6f5f9c56e520ad507186a7
child 494200 db7e5baabd8bc5c7608ced7add5b0f5bd3e64f84
child 494321 78d4a74ce9d6db154df44cbf0ffe813f8fae6be7
child 494425 ef57642efc5b6967d0e18d375d40399c5e9023e4
child 495067 b38ff7eb10d82f45643d6f393af74f4a97a6586e
child 495116 b684c7a78c67d5713bc11d407a2c8361733eb328
child 495117 0629691405b0cc164cc27bd0acfbedcfc7c5e0c3
child 495368 3b5ae9ec279b127e0bb69a7578791bfdfea762b6
child 495371 ac0010c2da41309abbf81dabf52fed1eddf736f7
child 495390 6833df97135751bb2830b9cf3bd8ab88382f20ce
child 497181 6b6f70e91b9641f15487666e92216894edad781d
child 497859 dbf72fad4fba90f572e2843e69d6509608599d10
child 499961 df6af3b3c0d694ee3574ad3f07464e3056d3f7a4
push id47088
push userbmo:sledru@mozilla.com
push dateTue, 28 Feb 2017 11:05:49 +0000
reviewersmerge
milestone54.0a1
merge mozilla-inbound to mozilla-central a=merge
testing/mozharness/configs/partner_repacks/staging_release_mozilla-esr52_desktop.py
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -515,16 +515,19 @@
 @RESPATH@/components/NotificationStorage.manifest
 @RESPATH@/components/Push.js
 @RESPATH@/components/Push.manifest
 @RESPATH@/components/PushComponents.js
 
 @RESPATH@/components/remotebrowserutils.manifest
 @RESPATH@/components/RemoteWebNavigation.js
 
+@RESPATH@/components/ProcessSelector.js
+@RESPATH@/components/ProcessSelector.manifest
+
 @RESPATH@/components/SlowScriptDebug.manifest
 @RESPATH@/components/SlowScriptDebug.js
 
 #ifdef MOZ_WEBRTC
 @RESPATH@/components/PeerConnection.js
 @RESPATH@/components/PeerConnection.manifest
 #endif
 
new file mode 100644
--- /dev/null
+++ b/dom/base/ProcessSelector.js
@@ -0,0 +1,62 @@
+/* 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 { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import('resource://gre/modules/Services.jsm');
+
+const BASE_PREF = "dom.ipc.processCount"
+const PREF_BRANCH = BASE_PREF + ".";
+
+// Utilities:
+function getMaxContentParents(processType) {
+  let maxContentParents = -1;
+  try {
+    maxContentParents = Services.prefs.getIntPref(PREF_BRANCH + processType);
+  } catch (e) {
+    // Pref probably didn't exist, get the default number of processes.
+    try {
+      maxContentParents = Services.prefs.getIntPref(BASE_PREF);
+    } catch (e) {
+      // No prefs? That's odd, use only one process.
+      maxContentParents = 1;
+    }
+  }
+
+  return maxContentParents;
+}
+
+// Fills up aProcesses until max and then selects randomly from the available
+// ones.
+function RandomSelector() {
+}
+
+RandomSelector.prototype = {
+  classID:          Components.ID("{c616fcfd-9737-41f1-aa74-cee72a38f91b}"),
+  QueryInterface:   XPCOMUtils.generateQI([Ci.nsIContentProcessProvider]),
+
+  provideProcess(aType, aOpener, aProcesses, aCount) {
+    let maxContentParents = getMaxContentParents(aType);
+    if (aCount < maxContentParents) {
+      return Ci.nsIContentProcessProvider.NEW_PROCESS;
+    }
+
+    let startIdx = Math.floor(Math.random() * maxContentParents);
+    let curIdx = startIdx;
+
+    do {
+      if (aProcesses[curIdx].opener === aOpener) {
+        return curIdx;
+      }
+
+      curIdx = (curIdx + 1) % maxContentParents;
+    } while (curIdx !== startIdx);
+
+    return Ci.nsIContentProcessProvider.NEW_PROCESS;
+  },
+};
+
+var components = [RandomSelector];
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/dom/base/ProcessSelector.manifest
@@ -0,0 +1,2 @@
+component {c616fcfd-9737-41f1-aa74-cee72a38f91b} ProcessSelector.js
+contract @mozilla.org/ipc/processselector;1 {c616fcfd-9737-41f1-aa74-cee72a38f91b}
--- a/dom/base/TimeoutManager.cpp
+++ b/dom/base/TimeoutManager.cpp
@@ -66,16 +66,21 @@ static int32_t gTimeoutBucketingStrategy
 // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
 // nsTimerImpl.h for details.
 #define DOM_MAX_TIMEOUT_VALUE    DELAY_INTERVAL_LIMIT
 
 uint32_t TimeoutManager::sNestingLevel = 0;
 
 namespace {
 
+// The maximum number of timer callbacks we will try to run in a single event
+// loop runnable.
+#define DEFAULT_TARGET_MAX_CONSECUTIVE_CALLBACKS 5
+uint32_t gTargetMaxConsecutiveCallbacks;
+
 // The number of queued runnables within the TabGroup ThrottledEventQueue
 // at which to begin applying back pressure to the window.
 #define DEFAULT_THROTTLED_EVENT_QUEUE_BACK_PRESSURE 5000
 static uint32_t gThrottledEventQueueBackPressure;
 
 // The amount of delay to apply to timers when back pressure is triggered.
 // As the length of the ThrottledEventQueue grows delay is increased.  The
 // delay is scaled such that every kThrottledEventQueueBackPressure runnables
@@ -177,16 +182,20 @@ TimeoutManager::Initialize()
                                "dom.timeout.back_pressure_delay_ms",
                                DEFAULT_BACK_PRESSURE_DELAY_MS);
   Preferences::AddUintVarCache(&gBackPressureDelayReductionThresholdMS,
                                "dom.timeout.back_pressure_delay_reduction_threshold_ms",
                                DEFAULT_BACK_PRESSURE_DELAY_REDUCTION_THRESHOLD_MS);
   Preferences::AddUintVarCache(&gBackPressureDelayMinimumMS,
                                "dom.timeout.back_pressure_delay_minimum_ms",
                                DEFAULT_BACK_PRESSURE_DELAY_MINIMUM_MS);
+
+  Preferences::AddUintVarCache(&gTargetMaxConsecutiveCallbacks,
+                               "dom.timeout.max_consecutive_callbacks",
+                               DEFAULT_TARGET_MAX_CONSECUTIVE_CALLBACKS);
 }
 
 uint32_t
 TimeoutManager::GetTimeoutId(Timeout::Reason aReason)
 {
   switch (aReason) {
     case Timeout::Reason::eIdleCallbackTimeout:
       return ++mIdleCallbackTimeoutCounter;
@@ -439,16 +448,20 @@ TimeoutManager::RunTimeout(Timeout* aTim
   // nothing past that point is expired.
   {
     // Use a nested scope in order to make sure the strong references held by
     // the iterator are freed after the loop.
     OrderedTimeoutIterator expiredIter(mNormalTimeouts,
                                        mTrackingTimeouts,
                                        nullptr,
                                        nullptr);
+
+    uint32_t numTimersToRun = 0;
+    bool targetTimerSeen = false;
+
     while (true) {
       Timeout* timeout = expiredIter.Next();
       if (!timeout || timeout->When() > deadline) {
         break;
       }
 
       if (timeout->mFiringDepth == 0) {
         // Mark any timeouts that are on the list to be fired with the
@@ -456,29 +469,39 @@ TimeoutManager::RunTimeout(Timeout* aTim
         timeout->mFiringDepth = firingDepth;
         last_expired_timeout_is_normal = expiredIter.PickedNormalIter();
         if (last_expired_timeout_is_normal) {
           last_expired_normal_timeout = timeout;
         } else {
           last_expired_tracking_timeout = timeout;
         }
 
-        // Run available timers until we see our target timer.  After
-        // that, however, stop coalescing timers so we can yield the
-        // main thread.  Further timers that are ready will get picked
-        // up by their own nsITimer runnables when they execute.
+        // Note that we have seen our target timer.  This means we can now
+        // stop processing timers once we hit our threshold below.
+        if (timeout == aTimeout) {
+          targetTimerSeen = true;
+        }
+
+        // Run only a limited number of timers based on the configured
+        // maximum.  Note, we must always run our target timer however.
+        // Further timers that are ready will get picked up by their own
+        // nsITimer runnables when they execute.
         //
         // For chrome windows, however, we do coalesce all timers and
         // do not yield the main thread.  This is partly because we
         // trust chrome windows not to misbehave and partly because a
         // number of browser chrome tests have races that depend on this
         // coalescing.
-        if (timeout == aTimeout && !mWindow.IsChromeWindow()) {
+        if (targetTimerSeen &&
+            numTimersToRun >= gTargetMaxConsecutiveCallbacks &&
+            !mWindow.IsChromeWindow()) {
           break;
         }
+
+        numTimersToRun += 1;
       }
 
       expiredIter.UpdateIterator();
     }
   }
 
   // Maybe the timeout that the event was fired for has been deleted
   // and there are no others timeouts with deadlines that make them
--- a/dom/base/UseCounters.conf
+++ b/dom/base/UseCounters.conf
@@ -57,16 +57,22 @@ attribute OfflineResourceList.onchecking
 attribute OfflineResourceList.onerror
 attribute OfflineResourceList.onnoupdate
 attribute OfflineResourceList.ondownloading
 attribute OfflineResourceList.onprogress
 attribute OfflineResourceList.onupdateready
 attribute OfflineResourceList.oncached
 attribute OfflineResourceList.onobsolete
 
+// Non-standard IndexedDB API
+method IDBDatabase.createMutableFile
+method IDBDatabase.mozCreateFileHandle
+method IDBMutableFile.open
+method IDBMutableFile.getFile
+
 // DataTransfer API (gecko-only methods)
 method DataTransfer.addElement
 attribute DataTransfer.mozItemCount
 attribute DataTransfer.mozCursor
 method DataTransfer.mozTypesAt
 method DataTransfer.mozClearDataAt
 method DataTransfer.mozSetDataAt
 method DataTransfer.mozGetDataAt
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -396,16 +396,18 @@ if CONFIG['INTEL_ARCHITECTURE']:
     SOURCES += ['nsTextFragmentSSE2.cpp']
     SOURCES['nsTextFragmentSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
 
 EXTRA_COMPONENTS += [
     'contentAreaDropListener.js',
     'contentAreaDropListener.manifest',
     'messageWakeupService.js',
     'messageWakeupService.manifest',
+    'ProcessSelector.js',
+    'ProcessSelector.manifest',
     'SlowScriptDebug.js',
     'SlowScriptDebug.manifest',
 ]
 
 # Firefox for Android provides an alternate version of this component
 if CONFIG['MOZ_BUILD_APP'] != 'mobile/android':
     EXTRA_COMPONENTS += [
         'SiteSpecificUserAgent.js',
--- a/dom/interfaces/base/moz.build
+++ b/dom/interfaces/base/moz.build
@@ -6,16 +6,17 @@
 
 XPIDL_SOURCES += [
     'domstubs.idl',
     'nsIBrowser.idl',
     'nsIBrowserDOMWindow.idl',
     'nsIContentPermissionPrompt.idl',
     'nsIContentPrefService.idl',
     'nsIContentPrefService2.idl',
+    'nsIContentProcess.idl',
     'nsIContentURIGrouper.idl',
     'nsIDOMChromeWindow.idl',
     'nsIDOMClientRect.idl',
     'nsIDOMClientRectList.idl',
     'nsIDOMConstructor.idl',
     'nsIDOMCrypto.idl',
     'nsIDOMGlobalPropertyInitializer.idl',
     'nsIDOMHistory.idl',
new file mode 100644
--- /dev/null
+++ b/dom/interfaces/base/nsIContentProcess.idl
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+interface nsIDOMElement;
+interface nsIMessageSender;
+interface nsIURI;
+
+[scriptable, builtinclass, uuid(456f58be-29dd-4973-885b-95aece1c9a8a)]
+interface nsIContentProcessInfo : nsISupports
+{
+  /**
+   * Is this content process alive?
+   */
+  readonly attribute boolean isAlive;
+
+  /**
+   * The content process's PID.
+   * Throws if the process is not alive.
+   */
+  readonly attribute int32_t processId;
+
+  /**
+   * This content process's opener.
+   */
+  readonly attribute nsIContentProcessInfo opener;
+
+  /**
+   * The process manager for this ContentParent (so a process message manager
+   * as opposed to a frame message manager.
+   */
+  readonly attribute nsIMessageSender messageManager;
+};
+
+[scriptable, uuid(83ffb063-5f65-4c45-ae07-3f553e0809bb)]
+interface nsIContentProcessProvider : nsISupports
+{
+  /**
+   * Return this from provideProcess to create a new process.
+   */
+  const int32_t NEW_PROCESS = -1;
+
+  /**
+   * Given aAliveProcesses (with an opener aOpener), choose which process of
+   * aType to use. Return nsIContentProcessProvider.NEW_PROCESS to ask the
+   * caller to create a new content process.
+   */
+  int32_t provideProcess(in AString aType, in nsIContentProcessInfo aOpener,
+                         [array, size_is(aCount)] in nsIContentProcessInfo aAliveProcesses,
+                         in uint32_t aCount);
+};
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -107,16 +107,17 @@
 #include "nsContentUtils.h"
 #include "nsDebugImpl.h"
 #include "nsFrameLoader.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashPropertyBag.h"
 #include "nsIAlertsService.h"
 #include "nsIClipboard.h"
 #include "nsContentPermissionHelper.h"
+#include "nsIContentProcess.h"
 #include "nsICycleCollectorListener.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocument.h"
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPositionError.h"
 #include "nsIDragService.h"
 #include "mozilla/dom/WakeLock.h"
 #include "nsIDOMWindow.h"
@@ -430,16 +431,100 @@ ContentParentsMemoryReporter::CollectRep
                             KIND_OTHER, UNITS_COUNT,
                             numQueuedMessages, desc, aData);
   }
 
   return NS_OK;
 }
 
 nsClassHashtable<nsStringHashKey, nsTArray<ContentParent*>>* ContentParent::sBrowserContentParents;
+
+namespace {
+
+class ScriptableCPInfo final : public nsIContentProcessInfo
+{
+public:
+  explicit ScriptableCPInfo(ContentParent* aParent)
+    : mContentParent(aParent)
+  {
+    MOZ_ASSERT(mContentParent);
+  }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSICONTENTPROCESSINFO
+
+  void ProcessDied()
+  {
+    mContentParent = nullptr;
+  }
+
+private:
+  ~ScriptableCPInfo()
+  {
+    MOZ_ASSERT(!mContentParent, "must call ProcessDied");
+  }
+
+  ContentParent* mContentParent;
+};
+
+NS_IMPL_ISUPPORTS(ScriptableCPInfo, nsIContentProcessInfo)
+
+NS_IMETHODIMP
+ScriptableCPInfo::GetIsAlive(bool* aIsAlive)
+{
+  *aIsAlive = mContentParent != nullptr;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ScriptableCPInfo::GetProcessId(int32_t* aPID)
+{
+  if (!mContentParent) {
+    *aPID = -1;
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  *aPID = mContentParent->Pid();
+  if (*aPID == -1) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ScriptableCPInfo::GetOpener(nsIContentProcessInfo** aInfo)
+{
+  *aInfo = nullptr;
+  if (!mContentParent) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  if (ContentParent* opener = mContentParent->Opener()) {
+    nsCOMPtr<nsIContentProcessInfo> info = opener->ScriptableHelper();
+    info.forget(aInfo);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ScriptableCPInfo::GetMessageManager(nsIMessageSender** aMessenger)
+{
+  *aMessenger = nullptr;
+  if (!mContentParent) {
+    return NS_ERROR_NOT_INITIALIZED;
+  }
+
+  nsCOMPtr<nsIMessageSender> manager = mContentParent->GetMessageManager();
+  manager.forget(aMessenger);
+  return NS_OK;
+}
+
+} // anonymous namespace
+
 nsTArray<ContentParent*>* ContentParent::sPrivateContent;
 StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
 #if defined(XP_LINUX) && defined(MOZ_CONTENT_SANDBOX)
 UniquePtr<SandboxBrokerPolicyFactory> ContentParent::sSandboxBrokerPolicyFactory;
 #endif
 
 // This is true when subprocess launching is enabled.  This is the
 // case between StartUp() and ShutDown() or JoinAllSubprocesses().
@@ -692,47 +777,74 @@ ContentParent::RandomSelect(const nsTArr
 }
 
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
                                           ProcessPriority aPriority,
                                           ContentParent* aOpener)
 {
   nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
-
   uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
 
-  RefPtr<ContentParent> p;
-  if (contentParents.Length() >= maxContentParents) {
+  if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
     // We never want to re-use Large-Allocation processes.
-    if (aRemoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
+    if (contentParents.Length() >= maxContentParents) {
       return GetNewOrUsedBrowserProcess(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
                                         aPriority,
                                         aOpener);
     }
-
-    if ((p = RandomSelect(contentParents, aOpener, maxContentParents))) {
+  } else {
+    nsTArray<nsIContentProcessInfo*> infos(contentParents.Length());
+    for (auto* cp : contentParents) {
+      infos.AppendElement(cp->mScriptableHelper);
+    }
+
+    nsCOMPtr<nsIContentProcessProvider> cpp =
+      do_GetService("@mozilla.org/ipc/processselector;1");
+    nsIContentProcessInfo* openerInfo = aOpener ? aOpener->mScriptableHelper.get() : nullptr;
+    int32_t index;
+    if (cpp &&
+        NS_SUCCEEDED(cpp->ProvideProcess(aRemoteType, openerInfo,
+                                         infos.Elements(), infos.Length(),
+                                         &index))) {
+      // If the provider returned an existing ContentParent, use that one.
+      if (0 <= index && static_cast<uint32_t>(index) <= maxContentParents) {
+        RefPtr<ContentParent> retval = contentParents[index];
+        return retval.forget();
+      }
+    } else {
+      // If there was a problem with the JS chooser, fall back to a random
+      // selection.
+      NS_WARNING("nsIContentProcessProvider failed to return a process");
+      RefPtr<ContentParent> random;
+      if (contentParents.Length() >= maxContentParents &&
+          (random = RandomSelect(contentParents, aOpener, maxContentParents))) {
+        return random.forget();
+      }
+    }
+
+    // Try to take the preallocated process only for the default process type.
+    RefPtr<ContentParent> p;
+    if (aRemoteType.EqualsLiteral(DEFAULT_REMOTE_TYPE) &&
+        (p = PreallocatedProcessManager::Take())) {
+      // For pre-allocated process we have not set the opener yet.
+      p->mOpener = aOpener;
+      contentParents.AppendElement(p);
       return p.forget();
     }
   }
 
-  // Try to take the preallocated process only for the default process type.
-  if (aRemoteType.Equals(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE)) &&
-      (p = PreallocatedProcessManager::Take())) {
-    // For pre-allocated process we have not set the opener yet.
-    p->mOpener = aOpener;
-  } else {
-    p = new ContentParent(aOpener, aRemoteType);
-
-    if (!p->LaunchSubprocess(aPriority)) {
-      return nullptr;
-    }
-
-    p->Init();
-  }
+  // Create a new process from scratch.
+  RefPtr<ContentParent> p = new ContentParent(aOpener, aRemoteType);
+
+  if (!p->LaunchSubprocess(aPriority)) {
+    return nullptr;
+  }
+
+  p->Init();
 
   contentParents.AppendElement(p);
   return p.forget();
 }
 
 /*static*/ ProcessPriority
 ContentParent::GetInitialProcessPriority(Element* aFrameElement)
 {
@@ -1199,16 +1311,18 @@ ContentParent::Init()
     mIsProfilerActive = true;
 
     StartProfiler(currentProfilerParams);
   }
 #endif
 
   RefPtr<GeckoMediaPluginServiceParent> gmps(GeckoMediaPluginServiceParent::GetSingleton());
   gmps->UpdateContentProcessGMPCapabilities();
+
+  mScriptableHelper = new ScriptableCPInfo(this);
 }
 
 namespace {
 
 class RemoteWindowContext final : public nsIRemoteWindowContext
                                 , public nsIInterfaceRequestor
 {
 public:
@@ -1269,16 +1383,21 @@ ContentParent::SetPriorityAndCheckIsAliv
 #endif
 
   return true;
 }
 
 void
 ContentParent::ShutDownProcess(ShutDownMethod aMethod)
 {
+  if (mScriptableHelper) {
+    static_cast<ScriptableCPInfo*>(mScriptableHelper.get())->ProcessDied();
+    mScriptableHelper = nullptr;
+  }
+
   // Shutting down by sending a shutdown message works differently than the
   // other methods. We first call Shutdown() in the child. After the child is
   // ready, it calls FinishShutdown() on us. Then we close the channel.
   if (aMethod == SEND_SHUTDOWN_MESSAGE) {
     if (mIPCOpen && !mShutdownPending && SendShutdown()) {
       mShutdownPending = true;
       // Start the force-kill timer if we haven't already.
       StartForceKillTimer();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -40,16 +40,17 @@
 #define DEFAULT_REMOTE_TYPE "web"
 #define FILE_REMOTE_TYPE "file"
 #define EXTENSION_REMOTE_TYPE "extension"
 
 // This must start with the DEFAULT_REMOTE_TYPE above.
 #define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"
 
 class nsConsoleService;
+class nsIContentProcessInfo;
 class nsICycleCollectorLogSink;
 class nsIDumpGCAndCCLogsCallback;
 class nsITabParent;
 class nsITimer;
 class ParentIdleListener;
 class nsIWidget;
 
 namespace mozilla {
@@ -366,16 +367,20 @@ public:
   {
     return mSubprocess;
   }
 
   ContentParent* Opener() const
   {
     return mOpener;
   }
+  nsIContentProcessInfo* ScriptableHelper() const
+  {
+    return mScriptableHelper;
+  }
 
   bool NeedsPermissionsUpdate() const
   {
     return mSendPermissionUpdates;
   }
 
   /**
    * Kill our subprocess and make sure it dies.  Should only be used
@@ -1168,16 +1173,17 @@ private:
   bool mCalledClose;
   bool mCalledKillHard;
   bool mCreatedPairedMinidumps;
   bool mShutdownPending;
   bool mIPCOpen;
 
   RefPtr<nsConsoleService>  mConsoleService;
   nsConsoleService* GetConsoleService();
+  nsCOMPtr<nsIContentProcessInfo> mScriptableHelper;
 
   nsTArray<nsCOMPtr<nsIObserver>> mIdleListeners;
 
 #ifdef MOZ_X11
   // Dup of child's X socket, used to scope its resources to this
   // object instead of the child process's lifetime.
   ScopedClose mChildXSocketFdDup;
 #endif
--- a/dom/webidl/IDBDatabase.webidl
+++ b/dom/webidl/IDBDatabase.webidl
@@ -34,15 +34,15 @@ interface IDBDatabase : EventTarget {
                 attribute EventHandler       onerror;
                 attribute EventHandler       onversionchange;
 };
 
 partial interface IDBDatabase {
     [Func="mozilla::dom::IndexedDatabaseManager::ExperimentalFeaturesEnabled"]
     readonly    attribute StorageType        storage;
 
-    [Exposed=Window, Throws]
+    [Exposed=Window, Throws, UseCounter]
     IDBRequest createMutableFile (DOMString name, optional DOMString type);
 
     // this is deprecated due to renaming in the spec
-    [Exposed=Window, Throws]
+    [Exposed=Window, Throws, UseCounter]
     IDBRequest mozCreateFileHandle (DOMString name, optional DOMString type); // now createMutableFile
 };
--- a/dom/webidl/IDBMutableFile.webidl
+++ b/dom/webidl/IDBMutableFile.webidl
@@ -5,17 +5,17 @@
 
 [Exposed=(Window,System)]
 interface IDBMutableFile : EventTarget {
   readonly attribute DOMString name;
   readonly attribute DOMString type;
 
   readonly attribute IDBDatabase database;
 
-  [Throws]
+  [Throws, UseCounter]
   IDBFileHandle open(optional FileMode mode = "readonly");
 
-  [Throws]
+  [Throws, UseCounter]
   DOMRequest getFile();
 
   attribute EventHandler onabort;
   attribute EventHandler onerror;
 };
new file mode 100755
--- /dev/null
+++ b/intl/hyphenation/hyphen/NEWS
@@ -0,0 +1,106 @@
+2014-09-18 Hyphen 2.8.8:
+  - remove last coverity warning, 0 remaining
+
+2014-06-27 Hyphen 2.8.7:
+  - various clang scan-build warning fixes
+
+2012-09-13 Hyphen 2.8.6:
+  - righthyphenmin fix for 3-byte or more UTF-8
+    multibyte characters by Steven Dickson
+  - fix for fdo#43931 (removing hard hyphen hyphenation for LibreOffice)
+
+2012-07-12 Hyphen 2.8.5:
+  - fix short alloc
+
+2012-06-29 Hyphen 2.8.4:
+  - coverity warnings
+
+2011-10-10 Hyphen 2.8.3:
+  - fix NOHYPHEN
+  - fix unbalanced hyphenation of LibreOffice/OOo
+  - set default COMPOUNDHYPHENMIN=3 at hyphens and apostrophes
+  - fix VERBOSE in hyphen.c
+  - new ./example option: -n to print hyphenation vector
+
+2011-10-07 Hyphen 2.8.2:
+  - fix for explicite COMPOUNDHYPHENMIN values
+
+2011-10-06 Hyphen 2.8.1:
+  - force minimal lefthyphenmin and righthyphenmin values of the dictionary
+    (eg. righthyphenmin=3 of English dictionaries in LibreOffice/OOo,
+    also the original TeX hyphenation patterns are correct only with this
+    righthyphenmin value).
+
+2011-10-04 Hyphen 2.8:
+  - Ignore leading and ending numbers (eg. manual/field based indexes
+    in LibreOffice/OOo)
+
+  - Fix LibreOffice/OpenOffice.org hyphenation errors at apostrophes and
+    hyphens, n-dashes with default NOHYPHEN separators.
+    Eg. *o'c=lock -> o'clock.
+
+2010-12-01 Hyphen 2.7.1 bug fix release
+
+2010-11-27 Hyphen 2.7 release:
+  - The new hyphenation problem of OpenOffice.org 3.2, related to its
+    modified word breaking of words with hyphen characters, can be fixed
+    with the new NOHYPHEN feature. Also it's possible to solve the similar old
+    problem with apostrophes. More information: README.compound.
+
+  - improved English dictionaries
+
+2010-08-10 Hyphen 2.6 release:
+  - maintainance release, fix all warnings, tidy up
+    make check with VALGRIND=memcheck, etc.
+
+2010-02-23 Hyphen 2.5 release:
+  - add Unicode ligature support for correct hyphenmin calculation
+    (ff, fi, fl, St, st are 1-character, ffi and ffl are 2-character length for
+    hyphenation)
+  - fix lefthyphenmin calculation for UTF-8 encoded input
+
+  - en_US hyphenation dictionary:
+      - add OpenOffice.org patch to fix apostrophe handling
+      - add correct hyphenation for words with Unicode f-ligatures
+        (NOTE: hyphenation within ligatures is not supported yet
+        because of an implementation problem of OpenOffice.org,
+        see OOo issue 71608.)
+
+    - small patches from OpenOffice.org
+
+2008-05-01 Hyphen 2.4 release:
+  - compound word hyphenation support by recursive pattern matching
+    based on two hyphenation pattern sets, see README.compound.
+    Especially useful for languages with arbitrary number of compounds (Danish,
+    Dutch, Finnish, German, Hungarian, Icelandic, Norwegian, Swedish etc.).
+
+  - new dictionary parameters (minimal character numbers for hyph. distances):
+    LEFTHYPHENMIN: minimal hyphenation distance from the left end of the word
+    RIGHTHYPHENMIN: minimal hyphenation distance from the right end of the word
+    COMPOUNDLEFTHYPHENMIN: min. hyph. dist. from the left compound word boundary
+    COMPOUNDRIGHTHYPHENMIN: min. hyph. dist. from the right comp. word boundary
+
+  - new API function: hnj_hyphen_hyphenate3() (like hyphenate2(), but
+    with hyphenmin options)
+
+en_US hyphenation patterns:
+
+  - extended hyph_en_US.dic with TugBoat hyphenation log (fix thousand 
+    incompletely or badly hyphenated words, for example acad-e-my, acro-nym,
+    acryl-amide, adren-a-line, aero-space, am-phet-a-mine, anom-aly etc.)
+
+  - fixed hyph_en_US.dic: set the right default hyphenation distance of
+    the original TeX hyphenation patterns:
+    LEFTHYPHENMIN 2
+    RIGHTHYPHENMIN 3 (not 2!)
+    It is not only a typographical issue. It seems, TeX hyphenation
+    patterns are right only with these settings, for example,
+    the bad "anoma-ly" is restricted in TeX only by the default
+    \righthyphenmin=3 (but not restricted in OpenOffice.org, until now).
+
+  - documentation (README_hyph_en_US.dic)
+
+  - fixes for automake configuration, compiling and checking, see ChangeLog
+
+2008-02-19: Hyphen 2.3.1 release:
+  - fix obsolete API function hnj_hyphen_hyphenate()
--- a/js/src/frontend/NameAnalysisTypes.h
+++ b/js/src/frontend/NameAnalysisTypes.h
@@ -73,16 +73,17 @@ enum class DeclarationKind : uint8_t
     FormalParameter,
     CoverArrowParameter,
     Var,
     ForOfVar,
     Let,
     Const,
     Import,
     BodyLevelFunction,
+    ModuleBodyLevelFunction,
     LexicalFunction,
     VarForAnnexBLexicalFunction,
     SimpleCatchParameter,
     CatchParameter
 };
 
 static inline BindingKind
 DeclarationKindToBindingKind(DeclarationKind kind)
@@ -90,16 +91,17 @@ DeclarationKindToBindingKind(Declaration
     switch (kind) {
       case DeclarationKind::PositionalFormalParameter:
       case DeclarationKind::FormalParameter:
       case DeclarationKind::CoverArrowParameter:
         return BindingKind::FormalParameter;
 
       case DeclarationKind::Var:
       case DeclarationKind::BodyLevelFunction:
+      case DeclarationKind::ModuleBodyLevelFunction:
       case DeclarationKind::VarForAnnexBLexicalFunction:
       case DeclarationKind::ForOfVar:
         return BindingKind::Var;
 
       case DeclarationKind::Let:
       case DeclarationKind::LexicalFunction:
       case DeclarationKind::SimpleCatchParameter:
       case DeclarationKind::CatchParameter:
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -112,16 +112,17 @@ DeclarationKindString(DeclarationKind ki
         return "var";
       case DeclarationKind::Let:
         return "let";
       case DeclarationKind::Const:
         return "const";
       case DeclarationKind::Import:
         return "import";
       case DeclarationKind::BodyLevelFunction:
+      case DeclarationKind::ModuleBodyLevelFunction:
       case DeclarationKind::LexicalFunction:
         return "function";
       case DeclarationKind::VarForAnnexBLexicalFunction:
         return "annex b var";
       case DeclarationKind::ForOfVar:
         return "var in for-of";
       case DeclarationKind::SimpleCatchParameter:
       case DeclarationKind::CatchParameter:
@@ -1374,16 +1375,34 @@ Parser<ParseHandler>::noteDeclaredName(H
         if (redeclaredKind) {
             reportRedeclaration(name, *redeclaredKind, pos, prevPos);
             return false;
         }
 
         break;
       }
 
+      case DeclarationKind::ModuleBodyLevelFunction: {
+          MOZ_ASSERT(pc->atModuleLevel());
+
+          AddDeclaredNamePtr p = pc->varScope().lookupDeclaredNameForAdd(name);
+          if (p) {
+              reportRedeclaration(name, p->value()->kind(), pos, p->value()->pos());
+              return false;
+          }
+
+          if (!pc->varScope().addDeclaredName(pc, p, name, kind, pos.begin))
+              return false;
+
+          // Body-level functions in modules are always closed over.
+          pc->varScope().lookupDeclaredName(name)->value()->setClosedOver();
+
+          break;
+      }
+
       case DeclarationKind::FormalParameter: {
         // It is an early error if any non-positional formal parameter name
         // (e.g., destructuring formal parameter) is duplicated.
 
         AddDeclaredNamePtr p = pc->functionScope().lookupDeclaredNameForAdd(name);
         if (p) {
             error(JSMSG_BAD_DUP_ARGS);
             return false;
@@ -3713,22 +3732,21 @@ Parser<ParseHandler>::functionStmt(Yield
             // the start of the block.
             if (!tryDeclareVarForAnnexBLexicalFunction(name, pos().begin, &tryAnnexB))
                 return null();
         }
 
         if (!noteDeclaredName(name, DeclarationKind::LexicalFunction, pos()))
             return null();
     } else {
-        if (!noteDeclaredName(name, DeclarationKind::BodyLevelFunction, pos()))
-            return null();
-
-        // Body-level functions in modules are always closed over.
-        if (pc->atModuleLevel())
-            pc->varScope().lookupDeclaredName(name)->value()->setClosedOver();
+        DeclarationKind kind = pc->atModuleLevel()
+                               ? DeclarationKind::ModuleBodyLevelFunction
+                               : DeclarationKind::BodyLevelFunction;
+        if (!noteDeclaredName(name, kind, pos()))
+            return null();
     }
 
     Node pn = handler.newFunctionStatement();
     if (!pn)
         return null();
 
     YieldHandling newYieldHandling = GetYieldHandling(generatorKind, asyncKind);
     return functionDefinition(pn, InAllowed, newYieldHandling, name, Statement, generatorKind,
--- a/js/src/jit-test/modules/export-default-async-asi.js
+++ b/js/src/jit-test/modules/export-default-async-asi.js
@@ -1,4 +1,2 @@
-function async() { return 42; } // overwritten by subsequent declaration
-
 export default async // ASI occurs here due to the [no LineTerminator here] restriction on default-exporting an async function
 function async() { return 17; }
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/modules/function-redeclaration.js
@@ -0,0 +1,94 @@
+load(libdir + "asserts.js");
+
+var functionDeclarations = [
+    "function f(){}",
+    "function* f(){}",
+    "async function f(){}",
+];
+
+var varDeclarations = [
+    "var f",
+    "{ var f; }",
+    "for (var f in null);",
+    "for (var f of null);",
+    "for (var f; ;);",
+];
+
+var lexicalDeclarations = [
+    "let f;",
+    "const f = 0;",
+    "class f {};",
+];
+
+var imports = [
+    "import f from '';",
+    "import f, {} from '';",
+    "import d, {f} from '';",
+    "import d, {f as f} from '';",
+    "import d, {foo as f} from '';",
+    "import f, * as d from '';",
+    "import d, * as f from '';",
+    "import {f} from '';",
+    "import {f as f} from '';",
+    "import {foo as f} from '';",
+    "import* as f from '';",
+];
+
+var exports = [
+    "export var f;",
+    ...functionDeclarations.map(fn => `export ${fn};`),
+    ...lexicalDeclarations.map(ld => `export ${ld};`),
+    ...functionDeclarations.map(fn => `export default ${fn};`),
+    "export default class f {};",
+];
+
+var redeclarations = [
+    ...functionDeclarations,
+    ...varDeclarations,
+    ...lexicalDeclarations,
+    ...imports,
+    ...exports,
+];
+
+var noredeclarations = [
+    ...functionDeclarations.map(fn => `{ ${fn} }`),
+    ...lexicalDeclarations.map(ld => `{ ${ld} }`),
+    ...["let", "const"].map(ld => `for (${ld} f in null);`),
+    ...["let", "const"].map(ld => `for (${ld} f of null);`),
+    ...["let", "const"].map(ld => `for (${ld} f = 0; ;);`),
+    "export {f};",
+    "export {f as f};",
+    "export {foo as f}; var foo;",
+    "export {f} from '';",
+    "export {f as f} from '';",
+    "export {foo as f} from '';",
+];
+
+for (var decl of functionDeclarations) {
+    for (var redecl of redeclarations) {
+        assertThrowsInstanceOf(() => {
+            parseModule(`
+                ${decl}
+                ${redecl}
+            `);
+        }, SyntaxError);
+
+        assertThrowsInstanceOf(() => {
+            parseModule(`
+                ${redecl}
+                ${decl}
+            `);
+        }, SyntaxError);
+    }
+
+    for (var redecl of noredeclarations) {
+        parseModule(`
+            ${decl}
+            ${redecl}
+        `);
+        parseModule(`
+            ${redecl}
+            ${decl}
+        `);
+    }
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/import-export-sigs.js
@@ -0,0 +1,88 @@
+// Tests that function imports and function exports descriptors have
+// signatures, in the test mode only, for fuzzers.
+
+var module = new WebAssembly.Module(wasmTextToBinary(`(module
+  (import $vv "env" "v_v")
+  (export "v_v" $vv)
+
+  (import $vi "env" "v_i" (param i32))
+  (export "v_i" $vi)
+
+  (import $vI "env" "v_I" (param i64))
+  (export "v_I" $vI)
+
+  (import $vf "env" "v_f" (param f32))
+  (export "v_f" $vf)
+
+  (import $mem "env" "memory" (memory 0))
+  (export "mem" (memory $mem))
+
+  (import $vd "env" "v_d" (param f64))
+  (export "v_d" $vd)
+
+  (import $vfd "env" "v_fd" (param f32) (param f64))
+  (export "v_fd" $vfd)
+
+  (import $vIfifd "env" "v_Ififd" (param i64) (param f32) (param i32) (param f32) (param f64))
+  (export "v_Ififd" $vIfifd)
+
+  (import $iv "env" "i_v" (result i32))
+  (export "i_v" $iv)
+
+  (import $Ii "env" "I_i" (result i64) (param i32))
+  (export "I_i" $Ii)
+
+  (import $table "env" "table" (table 0 anyfunc))
+  (export "table" (table $table))
+
+  (import $fd "env" "f_d" (result f32) (param f64))
+  (export "f_d" $fd)
+
+  (import $dffd "env" "d_ffd" (result f64) (param f32) (param f32) (param f64))
+  (export "d_ffd" $dffd)
+)`));
+
+for (let desc of WebAssembly.Module.imports(module)) {
+    assertEq(typeof desc.signature, 'undefined');
+}
+for (let desc of WebAssembly.Module.exports(module)) {
+    assertEq(typeof desc.signature, 'undefined');
+}
+
+setJitCompilerOption('wasm.test-mode', 1);
+
+function shortToType(s) {
+    switch (s) {
+        case 'v': return "";
+        case 'i': return "i32";
+        case 'I': return "i64";
+        case 'f': return "f32";
+        case 'd': return "f64";
+    }
+    throw new Error("unexpected shorthand type");
+}
+
+function expectedSignature(name) {
+    let [ret, args] = name.split('_');
+
+    args = args.split('').map(shortToType).join(', ');
+    ret = shortToType(ret);
+
+    return `(${args}) -> (${ret})`;
+}
+
+for (let desc of WebAssembly.Module.imports(module)) {
+    if (desc.kind !== 'function') {
+        assertEq(typeof desc.signature, 'undefined');
+    } else {
+        assertEq(desc.signature, expectedSignature(desc.name))
+    }
+}
+
+for (let desc of WebAssembly.Module.exports(module)) {
+    if (desc.kind !== 'function') {
+        assertEq(typeof desc.signature, 'undefined');
+    } else {
+        assertEq(desc.signature, expectedSignature(desc.name))
+    }
+}
--- a/js/src/tests/test262-intl-extras.js
+++ b/js/src/tests/test262-intl-extras.js
@@ -1,7 +1,14 @@
 // 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/.
 
 // Call the shell helper to add experimental features to the Intl object.
-if (typeof addIntlExtras === "function")
-    addIntlExtras(Intl);
+if (typeof addIntlExtras === "function") {
+    let intlExtras = {};
+    addIntlExtras(intlExtras);
+
+    Object.defineProperty(Intl, "PluralRules", {
+        value: intlExtras.PluralRules,
+        writable: true, enumerable: false, configurable: true
+    });
+}
--- a/js/src/tests/test262/intl402/PluralRules/shell.js
+++ b/js/src/tests/test262/intl402/PluralRules/shell.js
@@ -1,8 +1,15 @@
 // file: test262-intl-extras.js
 // 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/.
 
 // Call the shell helper to add experimental features to the Intl object.
-if (typeof addIntlExtras === "function")
-    addIntlExtras(Intl);
+if (typeof addIntlExtras === "function") {
+    let intlExtras = {};
+    addIntlExtras(intlExtras);
+
+    Object.defineProperty(Intl, "PluralRules", {
+        value: intlExtras.PluralRules,
+        writable: true, enumerable: false, configurable: true
+    });
+}
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1495,18 +1495,29 @@ SetObjectElementOperation(JSContext* cx,
         int32_t i = JSID_TO_INT(id);
         if ((uint32_t)i >= length) {
             // Annotate script if provided with information (e.g. baseline)
             if (script && script->hasBaselineScript() && IsSetElemPC(pc))
                 script->baselineScript()->noteHasDenseAdd(script->pcToOffset(pc));
         }
     }
 
-    if (obj->isNative() && !JSID_IS_INT(id) && !JSObject::setHadElementsAccess(cx, obj))
-        return false;
+    // Set the HadElementsAccess flag on the object if needed. This flag is
+    // used to do more eager dictionary-mode conversion for objects that are
+    // used as hashmaps. Set this flag only for objects with many properties,
+    // to avoid unnecessary Shape changes.
+    if (obj->isNative() &&
+        JSID_IS_ATOM(id) &&
+        !obj->as<NativeObject>().inDictionaryMode() &&
+        !obj->hadElementsAccess() &&
+        obj->as<NativeObject>().slotSpan() > PropertyTree::MAX_HEIGHT_WITH_ELEMENTS_ACCESS / 3)
+    {
+        if (!JSObject::setHadElementsAccess(cx, obj))
+            return false;
+    }
 
     ObjectOpResult result;
     return SetProperty(cx, obj, id, value, receiver, result) &&
            result.checkStrictErrorOrWarning(cx, obj, id, strict);
 }
 
 /*
  * Get the innermost enclosing function that has a 'this' binding.
--- a/js/src/wasm/WasmJS.cpp
+++ b/js/src/wasm/WasmJS.cpp
@@ -23,16 +23,17 @@
 #include "mozilla/RangedPtr.h"
 
 #include "jsprf.h"
 
 #include "builtin/Promise.h"
 #include "jit/JitOptions.h"
 #include "vm/Interpreter.h"
 #include "vm/String.h"
+#include "vm/StringBuffer.h"
 #include "wasm/WasmCompile.h"
 #include "wasm/WasmInstance.h"
 #include "wasm/WasmModule.h"
 #include "wasm/WasmSignalHandlers.h"
 #include "wasm/WasmValidate.h"
 
 #include "jsobjinlines.h"
 
@@ -549,18 +550,19 @@ GetModuleArg(JSContext* cx, CallArgs arg
     return true;
 }
 
 struct KindNames
 {
     RootedPropertyName kind;
     RootedPropertyName table;
     RootedPropertyName memory;
+    RootedPropertyName signature;
 
-    explicit KindNames(JSContext* cx) : kind(cx), table(cx), memory(cx) {}
+    explicit KindNames(JSContext* cx) : kind(cx), table(cx), memory(cx), signature(cx) {}
 };
 
 static bool
 InitKindNames(JSContext* cx, KindNames* names)
 {
     JSAtom* kind = Atomize(cx, "kind", strlen("kind"));
     if (!kind)
         return false;
@@ -571,16 +573,21 @@ InitKindNames(JSContext* cx, KindNames* 
         return false;
     names->table = table->asPropertyName();
 
     JSAtom* memory = Atomize(cx, "memory", strlen("memory"));
     if (!memory)
         return false;
     names->memory = memory->asPropertyName();
 
+    JSAtom* signature = Atomize(cx, "signature", strlen("signature"));
+    if (!signature)
+        return false;
+    names->signature = signature->asPropertyName();
+
     return true;
 }
 
 static JSString*
 KindToString(JSContext* cx, const KindNames& names, DefinitionKind kind)
 {
     switch (kind) {
       case DefinitionKind::Function:
@@ -592,16 +599,50 @@ KindToString(JSContext* cx, const KindNa
       case DefinitionKind::Global:
         return cx->names().global;
     }
 
     MOZ_CRASH("invalid kind");
 }
 
 static JSString*
+SigToString(JSContext* cx, const Sig& sig)
+{
+    StringBuffer buf(cx);
+    if (!buf.append('('))
+        return nullptr;
+
+    bool first = true;
+    for (ValType arg : sig.args()) {
+        if (!first && !buf.append(", ", strlen(", ")))
+            return nullptr;
+
+        const char* argStr = ToCString(arg);
+        if (!buf.append(argStr, strlen(argStr)))
+            return nullptr;
+
+        first = false;
+    }
+
+    if (!buf.append(") -> (", strlen(") -> (")))
+        return nullptr;
+
+    if (sig.ret() != ExprType::Void) {
+        const char* retStr = ToCString(sig.ret());
+        if (!buf.append(retStr, strlen(retStr)))
+            return nullptr;
+    }
+
+    if (!buf.append(')'))
+        return nullptr;
+
+    return buf.finishString();
+}
+
+static JSString*
 UTF8CharsToString(JSContext* cx, const char* chars)
 {
     return NewStringCopyUTF8Z<CanGC>(cx, JS::ConstUTF8CharsZ(chars, strlen(chars)));
 }
 
 /* static */ bool
 WasmModuleObject::imports(JSContext* cx, unsigned argc, Value* vp)
 {
@@ -614,16 +655,17 @@ WasmModuleObject::imports(JSContext* cx,
     KindNames names(cx);
     if (!InitKindNames(cx, &names))
         return false;
 
     AutoValueVector elems(cx);
     if (!elems.reserve(module->imports().length()))
         return false;
 
+    size_t numFuncImport = 0;
     for (const Import& import : module->imports()) {
         Rooted<IdValueVector> props(cx, IdValueVector(cx));
         if (!props.reserve(3))
             return false;
 
         JSString* moduleStr = UTF8CharsToString(cx, import.module.get());
         if (!moduleStr)
             return false;
@@ -634,16 +676,24 @@ WasmModuleObject::imports(JSContext* cx,
             return false;
         props.infallibleAppend(IdValuePair(NameToId(cx->names().name), StringValue(nameStr)));
 
         JSString* kindStr = KindToString(cx, names, import.kind);
         if (!kindStr)
             return false;
         props.infallibleAppend(IdValuePair(NameToId(names.kind), StringValue(kindStr)));
 
+        if (JitOptions.wasmTestMode && import.kind == DefinitionKind::Function) {
+            JSString* sigStr = SigToString(cx, module->metadata().funcImports[numFuncImport++].sig());
+            if (!sigStr)
+                return false;
+            if (!props.append(IdValuePair(NameToId(names.signature), StringValue(sigStr))))
+                return false;
+        }
+
         JSObject* obj = ObjectGroup::newPlainObject(cx, props.begin(), props.length(), GenericObject);
         if (!obj)
             return false;
 
         elems.infallibleAppend(ObjectValue(*obj));
     }
 
     JSObject* arr = NewDenseCopiedArray(cx, elems.length(), elems.begin());
@@ -666,31 +716,40 @@ WasmModuleObject::exports(JSContext* cx,
     KindNames names(cx);
     if (!InitKindNames(cx, &names))
         return false;
 
     AutoValueVector elems(cx);
     if (!elems.reserve(module->exports().length()))
         return false;
 
+    size_t numFuncExport = 0;
     for (const Export& exp : module->exports()) {
         Rooted<IdValueVector> props(cx, IdValueVector(cx));
         if (!props.reserve(2))
             return false;
 
         JSString* nameStr = UTF8CharsToString(cx, exp.fieldName());
         if (!nameStr)
             return false;
         props.infallibleAppend(IdValuePair(NameToId(cx->names().name), StringValue(nameStr)));
 
         JSString* kindStr = KindToString(cx, names, exp.kind());
         if (!kindStr)
             return false;
         props.infallibleAppend(IdValuePair(NameToId(names.kind), StringValue(kindStr)));
 
+        if (JitOptions.wasmTestMode && exp.kind() == DefinitionKind::Function) {
+            JSString* sigStr = SigToString(cx, module->metadata().funcExports[numFuncExport++].sig());
+            if (!sigStr)
+                return false;
+            if (!props.append(IdValuePair(NameToId(names.signature), StringValue(sigStr))))
+                return false;
+        }
+
         JSObject* obj = ObjectGroup::newPlainObject(cx, props.begin(), props.length(), GenericObject);
         if (!obj)
             return false;
 
         elems.infallibleAppend(ObjectValue(*obj));
     }
 
     JSObject* arr = NewDenseCopiedArray(cx, elems.length(), elems.begin());
--- a/layout/base/crashtests/1338772-1.html
+++ b/layout/base/crashtests/1338772-1.html
@@ -16,15 +16,27 @@ function loadHandler() {
     outer.remove();
     document.documentElement.removeAttribute("class");
   };
 
   // Trigger the resize handler:
   inner.height = "5px";
   inner.offsetTop;
 }
+
+// This function is a hack to avoid sporadic test-failures with...
+//   "...timed out waiting for reftest-wait to be removed".
+// Occasionally, it seems this test loses a race condition of some sort, and
+// its resize handler isn't invoked. When that happens (and specifically, when
+// the test runs for longer than 500ms), we clear reftest-wait and call the
+// run a "pass" (which is kind of valid, because we didn't crash!) and move on.
+function setupFailsafe() {
+  setTimeout(() => {
+    document.documentElement.removeAttribute("class");
+  }, 500);
+}
 </script>
-<body>
+<body onload="setupFailsafe()">
   <iframe id="outer"
           src="data:text/html,<html><body>"
           onload="loadHandler()">
   </iframe>
 </body>
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was 25b593fa59d0c284ff2de54b10db927d48579f5e.
+The git commit ID used was 25b593fa59d0c284ff2de54b10db927d48579f5e (2017-02-23 14:05:03 +0200)
--- a/media/libcubeb/update.sh
+++ b/media/libcubeb/update.sh
@@ -43,22 +43,23 @@ cp $1/test/test_resampler.cpp gtest
 cp $1/test/test_ring_array.cpp gtest
 cp $1/test/test_sanity.cpp gtest
 cp $1/test/test_tone.cpp gtest
 cp $1/test/test_utils.cpp gtest
 cp $1/test/test_mixer.cpp gtest
 
 if [ -d $1/.git ]; then
   rev=$(cd $1 && git rev-parse --verify HEAD)
+  date=$(cd $1 && git show -s --format=%ci HEAD)
   dirty=$(cd $1 && git diff-index --name-only HEAD)
 fi
 
 if [ -n "$rev" ]; then
   version=$rev
   if [ -n "$dirty" ]; then
     version=$version-dirty
     echo "WARNING: updating from a dirty git repository."
   fi
-  sed -i.bak -e "/The git commit ID used was/ s/[0-9a-f]\{40\}\(-dirty\)\{0,1\}\./$version./" README_MOZILLA
+  sed -i.bak -e "/The git commit ID used was/ s/[0-9a-f]\{40\}\(-dirty\)\{0,1\} .\{1,100\}/$version ($date)/" README_MOZILLA
   rm README_MOZILLA.bak
 else
   echo "Remember to update README_MOZILLA with the version details."
 fi
--- a/mobile/android/base/java/org/mozilla/gecko/FilePicker.java
+++ b/mobile/android/base/java/org/mozilla/gecko/FilePicker.java
@@ -1,19 +1,21 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.GeckoAppShell;
+import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
+import android.Manifest;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.Parcelable;
@@ -56,25 +58,52 @@ public class FilePicker implements Bundl
             final String title = message.getString("title", "");
 
             if ("mimeType".equals(mode)) {
                 mimeType = message.getString("mimeType", "");
             } else if ("extension".equals(mode)) {
                 mimeType = GeckoAppShell.getMimeTypeFromExtensions(message.getString("extensions", ""));
             }
 
-            showFilePickerAsync(title, mimeType, new ResultHandler() {
-                @Override
-                public void gotFile(final String filename) {
-                    callback.sendSuccess(filename);
-                }
-            }, tabId);
+            final String[] requiredPermission = getPermissionsForMimeType(mimeType);
+            final String finalMimeType = mimeType;
+            // Use activity context cause we want to prompt for runtime permission. (bug 1337692)
+            Permissions.from(GeckoAppShell.getGeckoInterface().getActivity())
+                    .withPermissions(requiredPermission)
+                    .andFallback(new Runnable() {
+                        @Override
+                        public void run() {
+                            callback.sendError(null);
+                        }
+                    })
+                    .run(new Runnable() {
+                        @Override
+                        public void run() {
+                            showFilePickerAsync(title, finalMimeType, new ResultHandler() {
+                                @Override
+                                public void gotFile(final String filename) {
+                                    callback.sendSuccess(filename);
+                                }
+                            }, tabId);
+                        }
+                    });
         }
     }
 
+    private static String[] getPermissionsForMimeType(final String mimeType) {
+        if (mimeType.startsWith("audio/")) {
+            return new String[] { Manifest.permission.RECORD_AUDIO };
+        } else if (mimeType.startsWith("image/")) {
+            return new String[] { Manifest.permission.CAMERA };
+        } else if (mimeType.startsWith("video/")) {
+            return new String[] { Manifest.permission.CAMERA };
+        }
+        return new String[] { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO };
+    }
+
     private void addActivities(Intent intent, HashMap<String, Intent> intents, HashMap<String, Intent> filters) {
         PackageManager pm = context.getPackageManager();
         List<ResolveInfo> lri = pm.queryIntentActivities(intent, 0);
         for (ResolveInfo ri : lri) {
             ComponentName cn = new ComponentName(ri.activityInfo.applicationInfo.packageName, ri.activityInfo.name);
             if (filters != null && !filters.containsKey(cn.toString())) {
                 Intent rintent = new Intent(intent);
                 rintent.setComponent(cn);
--- a/mobile/android/base/java/org/mozilla/gecko/PresentationView.java
+++ b/mobile/android/base/java/org/mozilla/gecko/PresentationView.java
@@ -12,16 +12,16 @@ import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.ScreenManagerHelper;
 
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 
 public class PresentationView extends GeckoView {
     private static final String LOGTAG = "PresentationView";
-    private static final String presentationViewURI = "chrome://browser/content/PresentationView.xul";
+    private static final String PRESENTATION_VIEW_URI = "chrome://browser/content/PresentationView.xul";
 
     public PresentationView(Context context, String deviceId, int screenId) {
         super(context);
-        this.chromeURI = presentationViewURI + "#" + deviceId;
-        this.screenId = screenId;
+        this.mChromeUri = PRESENTATION_VIEW_URI + "#" + deviceId;
+        this.mScreenId = screenId;
     }
 }
--- a/mobile/android/chrome/content/GeckoViewContent.js
+++ b/mobile/android/chrome/content/GeckoViewContent.js
@@ -2,40 +2,39 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {}).AndroidLog.d.bind(null, "ViewContent");
 
-var DEBUG = false;
+function debug(aMsg) {
+  // dump(aMsg);
+}
 
 // This is copied from desktop's tab-content.js. See bug 1153485 about sharing this code somehow.
 var DOMTitleChangedListener = {
   init: function() {
     addEventListener("DOMTitleChanged", this, false);
   },
 
-  receiveMessage: function(message) {
-    if (DEBUG) {
-      dump("receiveMessage " + message.name);
-    }
+  receiveMessage: function(aMsg) {
+    debug("receiveMessage " + aMsg.name);
   },
 
   handleEvent: function(aEvent) {
     if (aEvent.originalTarget.defaultView != content) {
       return;
     }
 
-    if (DEBUG) {
-      dump("handleEvent " + aEvent.type);
-    }
+    debug("handleEvent " + aEvent.type);
 
     switch (aEvent.type) {
       case "DOMTitleChanged":
-        sendAsyncMessage("GeckoView:DOMTitleChanged", { title: content.document.title });
+        sendAsyncMessage("GeckoView:DOMTitleChanged",
+                         { title: content.document.title });
         break;
     }
   },
 };
 
 DOMTitleChangedListener.init();
--- a/mobile/android/chrome/content/geckoview.js
+++ b/mobile/android/chrome/content/geckoview.js
@@ -24,29 +24,30 @@ var dump = Cu.import("resource://gre/mod
 // and remove by calling
 //   remove(<type name>)
 var ModuleManager = {
   init: function() {
     this.browser = document.getElementById("content");
     this.modules = {};
   },
 
-  add: function(resource, type, ...args) {
-    this.remove(type);
+  add: function(aResource, aType, ...aArgs) {
+    this.remove(aType);
     let scope = {};
-    Cu.import(resource, scope);
-    this.modules[type] = new scope[type](
-      window, this.browser, WindowEventDispatcher, ...args);
+    Cu.import(aResource, scope);
+    this.modules[aType] = new scope[aType](
+      window, this.browser, WindowEventDispatcher, ...aArgs
+    );
   },
 
-  remove: function(type) {
-    if (!(type in this.modules)) {
+  remove: function(aType) {
+    if (!(aType in this.modules)) {
       return;
     }
-    delete this.modules[type];
+    delete this.modules[aType];
   }
 };
 
 function startup() {
   ModuleManager.init();
   ModuleManager.add("resource://gre/modules/GeckoViewSettings.jsm",
                     "GeckoViewSettings");
   ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoView.java
@@ -38,38 +38,38 @@ import android.view.inputmethod.InputCon
 public class GeckoView extends LayerView
     implements ContextGetter {
 
     private static final String DEFAULT_SHARED_PREFERENCES_FILE = "GeckoView";
     private static final String LOGTAG = "GeckoView";
 
     private static final boolean DEBUG = false;
 
-    private final EventDispatcher eventDispatcher = new EventDispatcher();
+    private final EventDispatcher mEventDispatcher = new EventDispatcher();
 
     private ChromeDelegate mChromeDelegate;
     /* package */ ContentListener mContentListener;
     /* package */ NavigationListener mNavigationListener;
     /* package */ ProgressListener mProgressListener;
     private InputConnectionListener mInputConnectionListener;
 
     private GeckoViewSettings mSettings;
 
-    protected boolean onAttachedToWindowCalled;
-    protected String chromeURI;
-    protected int screenId = 0; // default to the primary screen
+    protected boolean mOnAttachedToWindowCalled;
+    protected String mChromeUri;
+    protected int mScreenId = 0; // default to the primary screen
 
     @WrapForJNI(dispatchTo = "proxy")
     protected static final class Window extends JNIObject {
         @WrapForJNI(skip = true)
         /* package */ Window() {}
 
         static native void open(Window instance, GeckoView view,
                                 Object compositor, EventDispatcher dispatcher,
-                                String chromeURI, GeckoBundle settings,
+                                String chromeUri, GeckoBundle settings,
                                 int screenId);
 
         @Override protected native void disposeNative();
         native void close();
         native void reattach(GeckoView view, Object compositor, EventDispatcher dispatcher);
         native void loadUri(String uri, int flags);
     }
 
@@ -137,17 +137,17 @@ public class GeckoView extends LayerView
 
             if ("GeckoView:DOMTitleChanged".equals(event)) {
                 if (mContentListener != null) {
                     mContentListener.onTitleChanged(GeckoView.this, message.getString("title"));
                 }
             } else if ("GeckoView:LocationChange".equals(event)) {
                 if (mNavigationListener == null) {
                     // We shouldn't be getting this event.
-                    eventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
+                    mEventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
                 } else {
                     mNavigationListener.onLocationChange(GeckoView.this, message.getString("uri"));
                     mNavigationListener.onCanGoBack(GeckoView.this, message.getBoolean("canGoBack"));
                     mNavigationListener.onCanGoForward(GeckoView.this, message.getBoolean("canGoForward"));
                 }
             } else if ("GeckoView:PageStart".equals(event)) {
                 if (mProgressListener != null) {
                     mProgressListener.onPageStart(GeckoView.this, message.getString("uri"));
@@ -195,94 +195,90 @@ public class GeckoView extends LayerView
 
         initializeView();
         listener.registerListeners();
 
         mSettings = new GeckoViewSettings(getEventDispatcher());
     }
 
     @Override
-    protected Parcelable onSaveInstanceState()
-    {
+    protected Parcelable onSaveInstanceState() {
         final Parcelable superState = super.onSaveInstanceState();
         stateSaved = true;
         return new StateBinder(superState, this.window);
     }
 
     @Override
-    protected void onRestoreInstanceState(final Parcelable state)
-    {
+    protected void onRestoreInstanceState(final Parcelable state) {
         final StateBinder stateBinder = (StateBinder) state;
 
         if (stateBinder.window != null) {
             this.window = stateBinder.window;
         }
         stateSaved = false;
 
-        if (onAttachedToWindowCalled) {
+        if (mOnAttachedToWindowCalled) {
             reattachWindow();
         }
 
         // We have to always call super.onRestoreInstanceState because View keeps
         // track of these calls and throws an exception when we don't call it.
         super.onRestoreInstanceState(stateBinder.superState);
     }
 
     protected void openWindow() {
-        if (chromeURI == null) {
-            chromeURI = getGeckoInterface().getDefaultChromeURI();
+        if (mChromeUri == null) {
+            mChromeUri = getGeckoInterface().getDefaultChromeURI();
         }
 
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
-            Window.open(window, this, getCompositor(), eventDispatcher,
-                        chromeURI, mSettings.asBundle(), screenId);
+            Window.open(window, this, getCompositor(), mEventDispatcher,
+                        mChromeUri, mSettings.asBundle(), mScreenId);
         } else {
             GeckoThread.queueNativeCallUntil(
                 GeckoThread.State.PROFILE_READY,
                 Window.class, "open", window,
                 GeckoView.class, this,
                 Object.class, getCompositor(),
-                EventDispatcher.class, eventDispatcher,
-                String.class, chromeURI,
+                EventDispatcher.class, mEventDispatcher,
+                String.class, mChromeUri,
                 GeckoBundle.class, mSettings.asBundle(),
-                screenId);
+                mScreenId);
         }
     }
 
     protected void reattachWindow() {
         if (GeckoThread.isStateAtLeast(GeckoThread.State.PROFILE_READY)) {
-            window.reattach(this, getCompositor(), eventDispatcher);
+            window.reattach(this, getCompositor(), mEventDispatcher);
         } else {
             GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                     window, "reattach", GeckoView.class, this,
-                    Object.class, getCompositor(), EventDispatcher.class, eventDispatcher);
+                    Object.class, getCompositor(), EventDispatcher.class, mEventDispatcher);
         }
     }
 
     @Override
-    public void onAttachedToWindow()
-    {
+    public void onAttachedToWindow() {
         final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
 
         if (window == null) {
             // Open a new nsWindow if we didn't have one from before.
             window = new Window();
             openWindow();
         } else {
             reattachWindow();
         }
 
         super.onAttachedToWindow();
 
-        onAttachedToWindowCalled = true;
+        mOnAttachedToWindowCalled = true;
     }
 
     @Override
-    public void onDetachedFromWindow()
-    {
+    public void onDetachedFromWindow() {
         super.onDetachedFromWindow();
         super.destroy();
 
         if (stateSaved) {
             // If we saved state earlier, we don't want to close the nsWindow.
             return;
         }
 
@@ -291,17 +287,17 @@ public class GeckoView extends LayerView
             window.disposeNative();
         } else {
             GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                     window, "close");
             GeckoThread.queueNativeCallUntil(GeckoThread.State.PROFILE_READY,
                     window, "disposeNative");
         }
 
-        onAttachedToWindowCalled = false;
+        mOnAttachedToWindowCalled = false;
     }
 
     @WrapForJNI public static final int LOAD_DEFAULT = 0;
     @WrapForJNI public static final int LOAD_NEW_TAB = 1;
     @WrapForJNI public static final int LOAD_SWITCH_TAB = 2;
 
     /**
     * Load the given URI.
@@ -315,32 +311,39 @@ public class GeckoView extends LayerView
 
         if (GeckoThread.isRunning()) {
             window.loadUri(uri, flags);
         }  else {
             GeckoThread.queueNativeCall(window, "loadUri", String.class, uri, flags);
         }
     }
 
+    /**
+    * Reload the current URI.
+    */
+    public void reload() {
+        mEventDispatcher.dispatch("GeckoView:Reload", null);
+    }
+
     /* package */ void setInputConnectionListener(final InputConnectionListener icl) {
         mInputConnectionListener = icl;
     }
 
     /**
     * Go back in history.
     */
     public void goBack() {
-        eventDispatcher.dispatch("GeckoView:GoBack", null);
+        mEventDispatcher.dispatch("GeckoView:GoBack", null);
     }
 
     /**
     * Go forward in history.
     */
     public void goForward() {
-        eventDispatcher.dispatch("GeckoView:GoForward", null);
+        mEventDispatcher.dispatch("GeckoView:GoForward", null);
     }
 
     public GeckoViewSettings getSettings() {
         return mSettings;
     }
 
     @Override
     public Handler getHandler() {
@@ -465,19 +468,19 @@ public class GeckoView extends LayerView
     * This will replace the current handler.
     * @param navigation An implementation of NavigationListener.
     */
     public void setNavigationDelegate(NavigationListener listener) {
         if (mNavigationListener == listener) {
             return;
         }
         if (listener == null) {
-            eventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
+            mEventDispatcher.dispatch("GeckoViewNavigation:Inactive", null);
         } else if (mNavigationListener == null) {
-            eventDispatcher.dispatch("GeckoViewNavigation:Active", null);
+            mEventDispatcher.dispatch("GeckoViewNavigation:Active", null);
         }
 
         mNavigationListener = listener;
     }
 
     /**
     * Get the navigation callback handler.
     * @return The current navigation callback handler.
@@ -499,17 +502,17 @@ public class GeckoView extends LayerView
     }
 
     @Override
     public SharedPreferences getSharedPreferences() {
         return getContext().getSharedPreferences(getSharedPreferencesFile(), 0);
     }
 
     public EventDispatcher getEventDispatcher() {
-        return eventDispatcher;
+        return mEventDispatcher;
     }
 
     /* Provides a means for the client to indicate whether a JavaScript
      * dialog request should proceed. An instance of this class is passed to
      * various GeckoViewChrome callback actions.
      */
     public class PromptResult {
         public PromptResult() {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewFragment.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewFragment.java
@@ -12,41 +12,41 @@ import android.util.Log;
 import android.util.SparseArray;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
 public class GeckoViewFragment extends android.support.v4.app.Fragment {
     private static final String LOGTAG = "GeckoViewFragment";
 
-    private static Parcelable state = null;
-    private static GeckoViewFragment lastUsed = null;
-    private GeckoView geckoView = null;
+    private static Parcelable mSavedState = null;
+    private static GeckoViewFragment mLastUsed = null;
+    private GeckoView mGeckoView = null;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         setRetainInstance(true);
         super.onCreate(savedInstanceState);
     }
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        geckoView = new GeckoView(getContext());
-        return geckoView;
+        mGeckoView = new GeckoView(getContext());
+        return mGeckoView;
     }
 
     @Override
     public void onResume() {
-        if (state != null && lastUsed != this) {
+        if (mSavedState != null && mLastUsed != this) {
             // "Restore" the window from the previously used GeckoView to this GeckoView and attach it
-            geckoView.onRestoreInstanceState(state);
-            state = null;
+            mGeckoView.onRestoreInstanceState(mSavedState);
+            mSavedState = null;
         }
         super.onResume();
     }
 
     @Override
     public void onPause() {
-        state = geckoView.onSaveInstanceState();
-        lastUsed = this;
+        mSavedState = mGeckoView.onSaveInstanceState();
+        mLastUsed = this;
         super.onPause();
     }
 }
--- a/mobile/android/modules/GeckoViewContent.jsm
+++ b/mobile/android/modules/GeckoViewContent.jsm
@@ -8,37 +8,38 @@ this.EXPORTED_SYMBOLS = ["GeckoViewConte
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/GeckoViewModule.jsm");
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewContent");
 
-var DEBUG = false;
+function debug(aMsg) {
+  // dump(aMsg);
+}
 
 class GeckoViewContent extends GeckoViewModule {
   init() {
     this.window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = this;
 
     this.messageManager.loadFrameScript("chrome://browser/content/GeckoViewContent.js", true);
     this.messageManager.addMessageListener("GeckoView:DOMTitleChanged", this);
   }
 
-  handleEvent(event) {
-    if (DEBUG) {
-      dump("handleEvent: event.type=" + event.type);
-    }
+  handleEvent(aEvent) {
+    debug("handleEvent: aEvent.type=" + aEvent.type);
   }
 
   // Message manager event handler.
-  receiveMessage(msg) {
-    if (DEBUG) {
-      dump("receiveMessage " + msg.name);
-    }
+  receiveMessage(aMsg) {
+    debug("receiveMessage " + aMsg.name);
 
-    switch (msg.name) {
+    switch (aMsg.name) {
       case "GeckoView:DOMTitleChanged":
-        this.eventDispatcher.sendRequest({ type: "GeckoView:DOMTitleChanged", title: msg.data.title });
+        this.eventDispatcher.sendRequest({
+          type: "GeckoView:DOMTitleChanged",
+          title: aMsg.data.title
+        });
         break;
     }
   }
 }
--- a/mobile/android/modules/GeckoViewModule.jsm
+++ b/mobile/android/modules/GeckoViewModule.jsm
@@ -6,25 +6,25 @@
 
 this.EXPORTED_SYMBOLS = ["GeckoViewModule"];
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewModule");
 
-function debug(msg) {
-  // dump(msg);
+function debug(aMsg) {
+  // dump(aMsg);
 }
 
 class GeckoViewModule {
-  constructor(window, browser, eventDispatcher) {
-    this.window = window;
-    this.browser = browser;
-    this.eventDispatcher = eventDispatcher;
+  constructor(aWindow, aBrowser, aEventDispatcher) {
+    this.window = aWindow;
+    this.browser = aBrowser;
+    this.eventDispatcher = aEventDispatcher;
 
     this.eventDispatcher.registerListener(
       () => this.onSettingsUpdate(),
       "GeckoView:UpdateSettings");
 
     this.init();
     this.onSettingsUpdate();
   }
--- a/mobile/android/modules/GeckoViewNavigation.jsm
+++ b/mobile/android/modules/GeckoViewNavigation.jsm
@@ -12,18 +12,18 @@ Cu.import("resource://gre/modules/GeckoV
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
   "resource://gre/modules/Messaging.jsm");
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewNavigation");
 
-function debug(msg) {
-  // dump(msg);
+function debug(aMsg) {
+  // dump(aMsg);
 }
 
 // Handles navigation requests between Gecko and a GeckoView.
 // Implements GeckoView.loadUri via openURI.
 // Handles GeckoView:GoBack and :GoForward requests dispatched by
 // GeckoView.goBack and .goForward.
 // Dispatches GeckoView:LocationChange to the GeckoView on location change when
 // active.
@@ -37,49 +37,53 @@ class GeckoViewNavigation extends GeckoV
     // event may be dispatched before this object is constructed.
     this.registerProgressListener();
 
     this.eventDispatcher.registerListener(this, [
       "GeckoViewNavigation:Active",
       "GeckoViewNavigation:Inactive",
       "GeckoView:GoBack",
       "GeckoView:GoForward",
+      "GeckoView:Reload",
     ]);
   }
 
   // Bundle event handler.
-  onEvent(event, data, callback) {
-    debug("onEvent: event=" + event + ", data=" + JSON.stringify(data));
+  onEvent(aEvent, aData, aCallback) {
+    debug("onEvent: aEvent=" + aEvent + ", aData=" + JSON.stringify(aData));
 
-    switch (event) {
+    switch (aEvent) {
       case "GeckoViewNavigation:Active":
         this.registerProgressListener();
         break;
       case "GeckoViewNavigation:Inactive":
         this.unregisterProgressListener();
         break;
       case "GeckoView:GoBack":
         this.browser.goBack();
         break;
       case "GeckoView:GoForward":
         this.browser.goForward();
         break;
+      case "GeckoView:Reload":
+        this.browser.reload();
+        break;
     }
   }
 
   // Message manager event handler.
-  receiveMessage(msg) {
-    debug("receiveMessage " + msg.name);
+  receiveMessage(aMsg) {
+    debug("receiveMessage " + aMsg.name);
   }
 
   // nsIBrowserDOMWindow::openURI implementation.
-  openURI(uri, opener, where, flags) {
-    debug("openURI: uri.spec=" + uri.spec);
+  openURI(aUri, aOpener, aWhere, aFlags) {
+    debug("openURI: aUri.spec=" + aUri.spec);
     // nsIWebNavigation::loadURI(URI, loadFlags, referrer, postData, headers).
-    this.browser.loadURI(uri.spec, null, null, null);
+    this.browser.loadURI(aUri.spec, null, null, null);
   }
 
   // nsIBrowserDOMWindow::canClose implementation.
   canClose() {
     debug("canClose");
     return false;
   }
 
@@ -98,23 +102,23 @@ class GeckoViewNavigation extends GeckoV
     if (!this.progressFilter) {
       return;
     }
     this.progressFilter.removeProgressListener(this);
     this.browser.removeProgressListener(this.progressFilter);
   }
 
   // WebProgress event handler.
-  onLocationChange(webProgress, request, locationURI, flags) {
+  onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
     debug("onLocationChange");
 
-    let fixedURI = locationURI;
+    let fixedURI = aLocationURI;
 
     try {
-      fixedURI = URIFixup.createExposableURI(locationURI);
+      fixedURI = URIFixup.createExposableURI(aLocationURI);
     } catch (ex) { }
 
     let message = {
       type: "GeckoView:LocationChange",
       uri: fixedURI.spec,
       canGoBack: this.browser.canGoBack,
       canGoForward: this.browser.canGoForward,
     };
--- a/mobile/android/modules/GeckoViewProgress.jsm
+++ b/mobile/android/modules/GeckoViewProgress.jsm
@@ -12,69 +12,66 @@ Cu.import("resource://gre/modules/GeckoV
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "EventDispatcher",
   "resource://gre/modules/Messaging.jsm");
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewNavigation");
 
-var DEBUG = false;
+function debug(aMsg) {
+  // dump(aMsg);
+}
 
 class GeckoViewProgress extends GeckoViewModule {
   init() {
     this.window.QueryInterface(Ci.nsIDOMChromeWindow).browserDOMWindow = this;
 
     this.registerProgressListener();
   }
 
   registerProgressListener() {
-    if (DEBUG) {
-      dump("registerProgressListeners()");
-    }
+    debug("registerProgressListeners()");
 
     let flags = Ci.nsIWebProgress.NOTIFY_STATE_NETWORK | Ci.nsIWebProgress.NOTIFY_SECURITY;
     this.progressFilter =
       Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
       .createInstance(Ci.nsIWebProgress);
     this.progressFilter.addProgressListener(this, flags);
     this.browser.addProgressListener(this.progressFilter, flags);
   }
 
   onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
-    if (DEBUG) {
-      dump("onStateChange()");
-    }
+    debug("onStateChange()");
 
     if (!aWebProgress.isTopLevel) {
       return;
     }
 
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
       let uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
       let message = {
         type: "GeckoView:PageStart",
         uri: uri.spec,
       };
 
       this.eventDispatcher.sendRequest(message);
-    } else if ((aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) && !aWebProgress.isLoadingDocument) {
+    } else if ((aStateFlags & Ci.nsIWebProgressListener.STATE_STOP) &&
+               !aWebProgress.isLoadingDocument) {
       let message = {
         type: "GeckoView:PageStop",
         success: aStatus ? false : true
       };
 
       this.eventDispatcher.sendRequest(message);
     }
   }
 
   onSecurityChange(aWebProgress, aRequest, aState) {
-    if (DEBUG) {
-      dump("onSecurityChange()");
-    }
+    debug("onSecurityChange()");
 
     let message = {
       type: "GeckoView:SecurityChanged",
       status: aState
     };
 
     this.eventDispatcher.sendRequest(message);
   }
--- a/mobile/android/modules/GeckoViewSettings.jsm
+++ b/mobile/android/modules/GeckoViewSettings.jsm
@@ -12,18 +12,18 @@ Cu.import("resource://gre/modules/GeckoV
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
   "resource://gre/modules/SafeBrowsing.jsm");
 
 var dump = Cu.import("resource://gre/modules/AndroidLog.jsm", {})
            .AndroidLog.d.bind(null, "ViewSettings");
 
-function debug(msg) {
-  // dump(msg);
+function debug(aMsg) {
+  // dump(aMsg);
 }
 
 // Handles GeckoView settings including:
 // * tracking protection
 class GeckoViewSettings extends GeckoViewModule {
   init() {
     this._isSafeBrowsingInit = false;
     this._useTrackingProtection = false;
@@ -34,22 +34,22 @@ class GeckoViewSettings extends GeckoVie
 
     this.useTrackingProtection = !!this.settings.useTrackingProtection;
   }
 
   get useTrackingProtection() {
     return this._useTrackingProtection;
   }
 
-  set useTrackingProtection(use) {
-    if (use && !this._isSafeBrowsingInit) {
+  set useTrackingProtection(aUse) {
+    if (aUse && !this._isSafeBrowsingInit) {
       SafeBrowsing.init();
       this._isSafeBrowsingInit = true;
     }
-    if (use != this._useTrackingProtection) {
+    if (aUse != this._useTrackingProtection) {
       this.messageManager.loadFrameScript('data:,' +
-        'docShell.useTrackingProtection = ' + use,
+        'docShell.useTrackingProtection = ' + aUse,
         true
       );
-      this._useTrackingProtection = use;
+      this._useTrackingProtection = aUse;
     }
   }
 }
--- a/mobile/android/tests/background/junit4/src/org/mozilla/gecko/util/TestStringUtils.java
+++ b/mobile/android/tests/background/junit4/src/org/mozilla/gecko/util/TestStringUtils.java
@@ -53,16 +53,31 @@ public class TestStringUtils {
 
         assertEquals(StringUtils.stripRef("??AAABBBCCC"), "??AAABBBCCC");
         assertEquals(StringUtils.stripRef("https://mozilla.org"), "https://mozilla.org");
         assertEquals(StringUtils.stripRef("https://mozilla.org#BBBB"), "https://mozilla.org");
         assertEquals(StringUtils.stripRef("https://mozilla.org/#BBBB"), "https://mozilla.org/");
     }
 
     @Test
+    public void testStripScheme() {
+        assertEquals("mozilla.org", StringUtils.stripScheme("http://mozilla.org"));
+        assertEquals("mozilla.org", StringUtils.stripScheme("http://mozilla.org/"));
+        assertEquals("https://mozilla.org", StringUtils.stripScheme("https://mozilla.org"));
+        assertEquals("https://mozilla.org", StringUtils.stripScheme("https://mozilla.org/"));
+        assertEquals("mozilla.org", StringUtils.stripScheme("https://mozilla.org/", StringUtils.UrlFlags.STRIP_HTTPS));
+        assertEquals("mozilla.org", StringUtils.stripScheme("https://mozilla.org", StringUtils.UrlFlags.STRIP_HTTPS));
+        assertEquals("", StringUtils.stripScheme("http://"));
+        assertEquals("", StringUtils.stripScheme("https://", StringUtils.UrlFlags.STRIP_HTTPS));
+        // This edge case is not handled properly yet
+//        assertEquals(StringUtils.stripScheme("https://"), "");
+        assertEquals(null, StringUtils.stripScheme(null));
+    }
+
+    @Test
     public void testIsRTL() {
         assertFalse(StringUtils.isRTL("mozilla.org"));
         assertFalse(StringUtils.isRTL("something.عربي"));
 
         assertTrue(StringUtils.isRTL("عربي"));
         assertTrue(StringUtils.isRTL("عربي.org"));
 
         // Text with LTR mark
--- a/netwerk/protocol/http/Http2Stream.cpp
+++ b/netwerk/protocol/http/Http2Stream.cpp
@@ -1475,18 +1475,18 @@ Http2Stream::MapStreamToHttpConnection()
 // -----------------------------------------------------------------------------
 // mirror nsAHttpTransaction
 // -----------------------------------------------------------------------------
 
 bool
 Http2Stream::Do0RTT()
 {
   MOZ_ASSERT(mTransaction);
-  mAttempting0RTT = true;
-  return mTransaction->Do0RTT();
+  mAttempting0RTT = mTransaction->Do0RTT();
+  return mAttempting0RTT;
 }
 
 nsresult
 Http2Stream::Finish0RTT(bool aRestart, bool aAlpnChanged)
 {
   MOZ_ASSERT(mTransaction);
   mAttempting0RTT = false;
   return mTransaction->Finish0RTT(aRestart, aAlpnChanged);
rename from testing/mozharness/configs/partner_repacks/staging_release_mozilla-esr52_desktop.py
rename to testing/mozharness/configs/partner_repacks/release_mozilla-esr52_desktop.py
--- a/tools/profiler/core/ProfilerBacktrace.cpp
+++ b/tools/profiler/core/ProfilerBacktrace.cpp
@@ -14,19 +14,17 @@ ProfilerBacktrace::ProfilerBacktrace(Syn
 {
   MOZ_COUNT_CTOR(ProfilerBacktrace);
   MOZ_ASSERT(aProfile);
 }
 
 ProfilerBacktrace::~ProfilerBacktrace()
 {
   MOZ_COUNT_DTOR(ProfilerBacktrace);
-  if (mProfile->ShouldDestroy()) {
-    delete mProfile;
-  }
+  delete mProfile;
 }
 
 void
 ProfilerBacktrace::StreamJSON(SpliceableJSONWriter& aWriter,
                               UniqueStacks& aUniqueStacks)
 {
   mozilla::MutexAutoLock lock(mProfile->GetMutex());
   mProfile->StreamJSON(aWriter, aUniqueStacks);
--- a/tools/profiler/core/SyncProfile.cpp
+++ b/tools/profiler/core/SyncProfile.cpp
@@ -4,52 +4,25 @@
  * 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 "SyncProfile.h"
 
 SyncProfile::SyncProfile(int aThreadId, PseudoStack* aStack)
   : ThreadInfo("SyncProfile", aThreadId, /* isMainThread = */ false, aStack,
                /* stackTop = */ nullptr)
-  , mOwnerState(REFERENCED)
 {
   MOZ_COUNT_CTOR(SyncProfile);
   SetProfile(new ProfileBuffer(GET_BACKTRACE_DEFAULT_ENTRIES));
 }
 
 SyncProfile::~SyncProfile()
 {
   MOZ_COUNT_DTOR(SyncProfile);
 }
 
-bool
-SyncProfile::ShouldDestroy()
-{
-  mozilla::MutexAutoLock lock(GetMutex());
-  if (mOwnerState == OWNED) {
-    mOwnerState = OWNER_DESTROYING;
-    return true;
-  }
-  mOwnerState = ORPHANED;
-  return false;
-}
-
-void
-SyncProfile::EndUnwind()
-{
-  if (mOwnerState != ORPHANED) {
-    mOwnerState = OWNED;
-  }
-  // Save mOwnerState before we release the mutex
-  OwnerState ownerState = mOwnerState;
-  ThreadInfo::EndUnwind();
-  if (ownerState == ORPHANED) {
-    delete this;
-  }
-}
-
 // SyncProfiles' stacks are deduplicated in the context of the containing
 // profile in which the backtrace is as a marker payload.
 void
 SyncProfile::StreamJSON(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks)
 {
   ThreadInfo::StreamSamplesAndMarkers(aWriter, /* aSinceTime = */ 0, aUniqueStacks);
 }
--- a/tools/profiler/core/SyncProfile.h
+++ b/tools/profiler/core/SyncProfile.h
@@ -14,28 +14,14 @@ class SyncProfile : public ThreadInfo
 public:
   SyncProfile(int aThreadId, PseudoStack* aStack);
   ~SyncProfile();
 
   // SyncProfiles' stacks are deduplicated in the context of the containing
   // profile in which the backtrace is as a marker payload.
   void StreamJSON(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks);
 
-  virtual void EndUnwind();
-
 private:
   friend class ProfilerBacktrace;
-
-  enum OwnerState
-  {
-    REFERENCED,       // ProfilerBacktrace has a pointer to this but doesn't own
-    OWNED,            // ProfilerBacktrace is responsible for destroying this
-    OWNER_DESTROYING, // ProfilerBacktrace owns this and is destroying
-    ORPHANED          // No owner, we must destroy ourselves
-  };
-
-  bool ShouldDestroy();
-
-  OwnerState mOwnerState;
 };
 
 #endif // __SYNCPROFILE_H
 
--- a/tools/profiler/core/ThreadInfo.cpp
+++ b/tools/profiler/core/ThreadInfo.cpp
@@ -232,28 +232,16 @@ ThreadInfo::FlushSamplesAndMarkers()
     mSavedStreamedMarkers = b.WriteFunc()->CopyData();
   }
 
   // Reset the buffer. Attempting to symbolicate JS samples after mContext has
   // gone away will crash.
   mBuffer->reset();
 }
 
-void
-ThreadInfo::BeginUnwind()
-{
-  mMutex->Lock();
-}
-
-void
-ThreadInfo::EndUnwind()
-{
-  mMutex->Unlock();
-}
-
 mozilla::Mutex&
 ThreadInfo::GetMutex()
 {
   return *mMutex.get();
 }
 
 void
 ThreadInfo::DuplicateLastSample(const TimeStamp& aStartTime)
--- a/tools/profiler/core/ThreadInfo.h
+++ b/tools/profiler/core/ThreadInfo.h
@@ -65,19 +65,16 @@ public:
   void addStoredMarker(ProfilerMarker* aStoredMarker);
   mozilla::Mutex& GetMutex();
   void StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime = 0);
 
   // Call this method when the JS entries inside the buffer are about to
   // become invalid, i.e., just before JS shutdown.
   void FlushSamplesAndMarkers();
 
-  void BeginUnwind();
-  virtual void EndUnwind();
-
   void DuplicateLastSample(const mozilla::TimeStamp& aStartTime);
 
   ThreadResponsiveness* GetThreadResponsiveness() { return &mRespInfo; }
 
   void UpdateThreadResponsiveness() {
     mRespInfo.Update(mIsMainThread, mThread);
   }
 
--- a/tools/profiler/core/platform-linux-android.cpp
+++ b/tools/profiler/core/platform-linux-android.cpp
@@ -176,28 +176,27 @@ static void SetSampleContext(TickSample*
 }
 
 static void
 SigprofHandler(int signal, siginfo_t* info, void* context)
 {
   // Avoid TSan warning about clobbering errno.
   int savedErrno = errno;
 
-  TickSample sample_obj;
-  TickSample* sample = &sample_obj;
-  sample->context = context;
+  TickSample sample;
+  sample.context = context;
 
   // Extract the current pc and sp.
-  SetSampleContext(sample, context);
-  sample->threadInfo = gCurrentThreadInfo;
-  sample->timestamp = mozilla::TimeStamp::Now();
-  sample->rssMemory = gRssMemory;
-  sample->ussMemory = gUssMemory;
+  SetSampleContext(&sample, context);
+  sample.threadInfo = gCurrentThreadInfo;
+  sample.timestamp = mozilla::TimeStamp::Now();
+  sample.rssMemory = gRssMemory;
+  sample.ussMemory = gUssMemory;
 
-  Tick(sample);
+  Tick(&sample);
 
   sem_post(&gSignalHandlingDone);
   errno = savedErrno;
 }
 
 #if defined(GP_OS_android)
 #define SYS_tgkill __NR_tgkill
 #endif
--- a/tools/profiler/core/platform-macos.cpp
+++ b/tools/profiler/core/platform-macos.cpp
@@ -185,25 +185,24 @@ public:
     }
   }
 
   void SampleContext(ThreadInfo* aThreadInfo, bool isFirstProfiledThread)
   {
     thread_act_t profiled_thread =
       aThreadInfo->GetPlatformData()->profiled_thread();
 
-    TickSample sample_obj;
-    TickSample* sample = &sample_obj;
+    TickSample sample;
 
     // Unique Set Size is not supported on Mac.
-    sample->ussMemory = 0;
-    sample->rssMemory = 0;
+    sample.ussMemory = 0;
+    sample.rssMemory = 0;
 
     if (isFirstProfiledThread && gProfileMemory) {
-      sample->rssMemory = nsMemoryReporterManager::ResidentFast();
+      sample.rssMemory = nsMemoryReporterManager::ResidentFast();
     }
 
     // We're using thread_suspend on OS X because pthread_kill (which is what
     // we're using on Linux) has less consistent performance and causes
     // strange crashes, see bug 1166778 and bug 1166808.
 
     if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
 
@@ -228,25 +227,25 @@ public:
 #else
 #error Unsupported Mac OS X host architecture.
 #endif  // GP_ARCH_*
 
     if (thread_get_state(profiled_thread,
                          flavor,
                          reinterpret_cast<natural_t*>(&state),
                          &count) == KERN_SUCCESS) {
-      sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
-      sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
-      sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
-      sample->timestamp = mozilla::TimeStamp::Now();
-      sample->threadInfo = aThreadInfo;
+      sample.pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
+      sample.sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
+      sample.fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
+      sample.timestamp = mozilla::TimeStamp::Now();
+      sample.threadInfo = aThreadInfo;
 
 #undef REGISTER_FIELD
 
-      Tick(sample);
+      Tick(&sample);
     }
     thread_resume(profiled_thread);
   }
 
 private:
   pthread_t mThread;
 
   int mIntervalMicro;
--- a/tools/profiler/core/platform-win32.cpp
+++ b/tools/profiler/core/platform-win32.cpp
@@ -197,31 +197,30 @@ class SamplerThread
     HANDLE profiled_thread = reinterpret_cast<HANDLE>(thread);
     if (profiled_thread == NULL)
       return;
 
     // Context used for sampling the register state of the profiled thread.
     CONTEXT context;
     memset(&context, 0, sizeof(context));
 
-    TickSample sample_obj;
-    TickSample* sample = &sample_obj;
+    TickSample sample;
 
     // Grab the timestamp before pausing the thread, to avoid deadlocks.
-    sample->timestamp = mozilla::TimeStamp::Now();
-    sample->threadInfo = aThreadInfo;
+    sample.timestamp = mozilla::TimeStamp::Now();
+    sample.threadInfo = aThreadInfo;
 
     if (isFirstProfiledThread && gProfileMemory) {
-      sample->rssMemory = nsMemoryReporterManager::ResidentFast();
+      sample.rssMemory = nsMemoryReporterManager::ResidentFast();
     } else {
-      sample->rssMemory = 0;
+      sample.rssMemory = 0;
     }
 
     // Unique Set Size is not supported on Windows.
-    sample->ussMemory = 0;
+    sample.ussMemory = 0;
 
     static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
     if (SuspendThread(profiled_thread) == kSuspendFailed)
       return;
 
     // SuspendThread is asynchronous, so the thread may still be running.
     // Call GetThreadContext first to ensure the thread is really suspended.
     // See https://blogs.msdn.microsoft.com/oldnewthing/20150205-00/?p=44743.
@@ -234,28 +233,28 @@ class SamplerThread
     context.ContextFlags = CONTEXT_CONTROL;
 #endif
     if (!GetThreadContext(profiled_thread, &context)) {
       ResumeThread(profiled_thread);
       return;
     }
 
 #if defined(GP_ARCH_amd64)
-    sample->pc = reinterpret_cast<Address>(context.Rip);
-    sample->sp = reinterpret_cast<Address>(context.Rsp);
-    sample->fp = reinterpret_cast<Address>(context.Rbp);
+    sample.pc = reinterpret_cast<Address>(context.Rip);
+    sample.sp = reinterpret_cast<Address>(context.Rsp);
+    sample.fp = reinterpret_cast<Address>(context.Rbp);
 #else
-    sample->pc = reinterpret_cast<Address>(context.Eip);
-    sample->sp = reinterpret_cast<Address>(context.Esp);
-    sample->fp = reinterpret_cast<Address>(context.Ebp);
+    sample.pc = reinterpret_cast<Address>(context.Eip);
+    sample.sp = reinterpret_cast<Address>(context.Esp);
+    sample.fp = reinterpret_cast<Address>(context.Ebp);
 #endif
 
-    sample->context = &context;
+    sample.context = &context;
 
-    Tick(sample);
+    Tick(&sample);
 
     ResumeThread(profiled_thread);
   }
 
 private:
   HANDLE mThread;
   Thread::tid_t mThreadId;
 
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -2454,19 +2454,17 @@ profiler_get_backtrace()
 #else
 # error "unknown platform"
 #endif
 #endif
 
   sample.isSamplingCurrentThread = true;
   sample.timestamp = mozilla::TimeStamp::Now();
 
-  profile->BeginUnwind();
   Tick(&sample);
-  profile->EndUnwind();
 
   return UniqueProfilerBacktrace(new ProfilerBacktrace(profile));
 }
 
 void
 ProfilerBacktraceDestructor::operator()(ProfilerBacktrace* aBacktrace)
 {
   delete aBacktrace;