Merge mozilla-central to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 28 Apr 2015 14:00:20 +0200
changeset 271250 c00ef0ced828a39ecae97abc6574724cdbfe155f
parent 271249 cdf65dcd35ea2dfcf3aa3236227efd495ca2c64e (current diff)
parent 271220 e0299ad29b855f798ee5db8257cbb459894c1b29 (diff)
child 271251 4084f5eca1c6f3987e552436064b59d20f552859
push id4830
push userjlund@mozilla.com
push dateMon, 29 Jun 2015 20:18:48 +0000
treeherdermozilla-beta@4c2175bb0420 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone40.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to fx-team
new file mode 100644
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,27 @@
+# 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/.
+
+import imp
+import os
+from StringIO import StringIO
+import shlex
+
+path = os.path.join(os.path.dirname(__file__), 'mach')
+
+if not os.path.exists(path):
+    path = os.path.join(os.path.dirname(__file__), 'config.status')
+    config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
+    path = os.path.join(config.topsrcdir, 'mach')
+mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE))
+
+def FlagsForFile(filename):
+    mach = mach_module.get_mach()
+    out = StringIO()
+    out.encoding = None
+    mach.run(['compileflags', filename], stdout=out, stderr=out)
+
+    return {
+        'flags': shlex.split(out.getvalue()),
+        'do_cache': True
+    }
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,12 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1038068: Check add-on signatures and refuse to install unsigned or broken add-ons
-
-Not sure why this needs a clobber but tests perma-failed when they don't on
-try (2).
+Bug 1154356: escape variable name in Declaration::AppendVariableAndValueToString;
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -118,30 +118,26 @@ static const GInterfaceInfo atk_if_infos
     {(GInterfaceInitFunc)textInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)documentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)imageInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}
 };
 
-// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
-// proxy.
-static const uintptr_t IS_PROXY = 1;
-
 static GQuark quark_mai_hyperlink = 0;
 
 AtkHyperlink*
 MaiAtkObject::GetAtkHyperlink()
 {
   NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
   MaiHyperlink* maiHyperlink =
     (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
   if (!maiHyperlink) {
-    maiHyperlink = new MaiHyperlink(reinterpret_cast<Accessible*>(accWrap));
+    maiHyperlink = new MaiHyperlink(accWrap);
     g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, maiHyperlink);
   }
 
   return maiHyperlink->GetAtkHyperlink();
 }
 
 void
 MaiAtkObject::Shutdown()
--- a/accessible/atk/nsMai.h
+++ b/accessible/atk/nsMai.h
@@ -46,16 +46,20 @@ extern int atkMajorVersion, atkMinorVers
  */
 static inline bool
 IsAtkVersionAtLeast(int aMajor, int aMinor)
 {
   return aMajor < atkMajorVersion ||
          (aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
 }
 
+// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
+// proxy.
+static const uintptr_t IS_PROXY = 1;
+
 /**
  * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
  */
 struct MaiAtkObject
 {
   AtkObject parent;
   /*
    * The AccessibleWrap whose properties and features are exported
--- a/accessible/atk/nsMaiHyperlink.cpp
+++ b/accessible/atk/nsMaiHyperlink.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsIURI.h"
 #include "nsMaiHyperlink.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 
 using namespace mozilla::a11y;
 
 /* MaiAtkHyperlink */
 
 #define MAI_TYPE_ATK_HYPERLINK      (mai_atk_hyperlink_get_type ())
 #define MAI_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
                                      MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
@@ -56,18 +57,27 @@ static gchar *getUriCB(AtkHyperlink *aLi
 static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
 static gint getEndIndexCB(AtkHyperlink *aLink);
 static gint getStartIndexCB(AtkHyperlink *aLink);
 static gboolean isValidCB(AtkHyperlink *aLink);
 static gint getAnchorCountCB(AtkHyperlink *aLink);
 G_END_DECLS
 
 static gpointer parent_class = nullptr;
-static Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink);
+
+static MaiHyperlink*
+GetMaiHyperlink(AtkHyperlink *aHyperlink)
+{
+    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
+    MaiHyperlink * maiHyperlink =
+        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
+    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
+    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
+    return maiHyperlink;
+}
 
 GType
 mai_atk_hyperlink_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
@@ -85,23 +95,20 @@ mai_atk_hyperlink_get_type(void)
 
         type = g_type_register_static(ATK_TYPE_HYPERLINK,
                                       "MaiAtkHyperlink",
                                       &tinfo, GTypeFlags(0));
     }
     return type;
 }
 
-MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) :
+MaiHyperlink::MaiHyperlink(uintptr_t aHyperLink) :
     mHyperlink(aHyperLink),
     mMaiAtkHyperlink(nullptr)
 {
-  if (!mHyperlink->IsLink())
-    return;
-
     mMaiAtkHyperlink =
         reinterpret_cast<AtkHyperlink *>
                         (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
     NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
     if (!mMaiAtkHyperlink)
       return;
 
     MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
@@ -148,84 +155,107 @@ finalizeCB(GObject *aObj)
     /* call parent finalize function */
     if (G_OBJECT_CLASS (parent_class)->finalize)
         G_OBJECT_CLASS (parent_class)->finalize(aObj);
 }
 
 gchar *
 getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
+  nsAutoCString cautoStr;
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
     nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
     if (!uri)
-        return nullptr;
+      return nullptr;
 
-    nsAutoCString cautoStr;
     nsresult rv = uri->GetSpec(cautoStr);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return g_strdup(cautoStr.get());
+  }
+
+  bool valid;
+  maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
+  if (!valid)
+    return nullptr;
+
+  return g_strdup(cautoStr.get());
 }
 
 AtkObject *
 getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
-    Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
-    NS_ENSURE_TRUE(anchor, nullptr);
+    if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
+      Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
+      NS_ENSURE_TRUE(anchor, nullptr);
 
-    AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor);
-    //no need to add ref it, because it is "get" not "ref"
-    return atkObj;
+      return AccessibleWrap::GetAtkObject(anchor);
+    }
+
+    ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
+    return anchor ? GetWrapperFor(anchor) : nullptr;
 }
 
 gint
 getEndIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->EndOffset());
+
+  bool valid = false;
+  uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
+  return valid ? static_cast<gint>(endIdx) : -1;
 }
 
 gint
 getStartIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (maiLink)
+    return -1;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->StartOffset());
+
+  bool valid = false;
+  uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
+  return valid ? static_cast<gint>(startIdx) : -1;
 }
 
 gboolean
 isValidCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, FALSE);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gboolean>(hyperlink->IsLinkValid());
+
+  return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
 }
 
 gint
 getAnchorCountCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
-
-    return static_cast<gint>(hyperlink->AnchorCount());
-}
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return -1;
 
-// Check if aHyperlink is a valid MaiHyperlink, and return the
-// HyperLinkAccessible related.
-Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink)
-{
-    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
-    MaiHyperlink * maiHyperlink =
-        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
-    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
-    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
-    return maiHyperlink->GetAccHyperlink();
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
+    return static_cast<gint>(hyperlink->AnchorCount());
+
+  bool valid = false;
+  uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
+  return valid ? static_cast<gint>(anchorCount) : -1;
 }
--- a/accessible/atk/nsMaiHyperlink.h
+++ b/accessible/atk/nsMaiHyperlink.h
@@ -18,25 +18,40 @@ namespace a11y {
 
 /*
  * MaiHyperlink is a auxiliary class for MaiInterfaceHyperText.
  */
 
 class MaiHyperlink
 {
 public:
-  explicit MaiHyperlink(Accessible* aHyperLink);
+  explicit MaiHyperlink(uintptr_t aHyperLink);
   ~MaiHyperlink();
 
 public:
   AtkHyperlink* GetAtkHyperlink() const { return mMaiAtkHyperlink; }
   Accessible* GetAccHyperlink()
-    { return mHyperlink && mHyperlink->IsLink() ? mHyperlink : nullptr; }
+    {
+      if (!mHyperlink || mHyperlink & IS_PROXY)
+        return nullptr;
+
+      Accessible* link = reinterpret_cast<Accessible*>(mHyperlink);
+      NS_ASSERTION(link->IsLink(), "Why isn't it a link!");
+      return link;
+    }
+
+  ProxyAccessible* Proxy() const
+  {
+    if (!(mHyperlink & IS_PROXY))
+      return nullptr;
+
+    return reinterpret_cast<ProxyAccessible*>(mHyperlink & ~IS_PROXY);
+  }
 
 protected:
-  Accessible* mHyperlink;
+  uintptr_t mHyperlink;
   AtkHyperlink* mMaiAtkHyperlink;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif /* __MAI_HYPERLINK_H__ */
--- a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
+++ b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
@@ -11,20 +11,21 @@
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkHyperlink*
 getHyperlinkCB(AtkHyperlinkImpl* aImpl)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImpl));
-  if (!accWrap)
+  if (!accWrap || !GetProxy(ATK_OBJECT(aImpl)))
     return nullptr;
 
-  NS_ENSURE_TRUE(accWrap->IsLink(), nullptr);
+  if (accWrap)
+    NS_ASSERTION(accWrap->IsLink(), "why isn't it a link!");
 
   return MAI_ATK_OBJECT(aImpl)->GetAtkHyperlink();
 }
 }
 
 void
 hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface)
 {
--- a/accessible/atk/nsMaiInterfaceHypertext.cpp
+++ b/accessible/atk/nsMaiInterfaceHypertext.cpp
@@ -17,41 +17,37 @@
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static AtkHyperlink*
 getLinkCB(AtkHypertext *aText, gint aLinkIndex)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  AtkObject* atkHyperLink = nullptr;
   if (accWrap) {
     HyperTextAccessible* hyperText = accWrap->AsHyperText();
     NS_ENSURE_TRUE(hyperText, nullptr);
 
     Accessible* hyperLink = hyperText->LinkAt(aLinkIndex);
-    if (!hyperLink) {
+    if (!hyperLink || !hyperLink->IsLink()) {
       return nullptr;
     }
 
-    AtkObject* hyperLinkAtkObj = AccessibleWrap::GetAtkObject(hyperLink);
-    NS_ENSURE_TRUE(IS_MAI_OBJECT(hyperLinkAtkObj), nullptr);
+    atkHyperLink = AccessibleWrap::GetAtkObject(hyperLink);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex);
+    if (!proxyLink)
+      return nullptr;
 
-    return MAI_ATK_OBJECT(hyperLinkAtkObj)->GetAtkHyperlink();
+    atkHyperLink = GetWrapperFor(proxyLink);
   }
 
-  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
-    ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex);
-    if (proxyLink) {
-      NS_WARNING("IMPLEMENT ME! See bug 1146518.");
-      // We should somehow get from ProxyAccessible* to AtkHyperlink*.
-    }
-    return nullptr;
-  }
-
-  return nullptr;
+    NS_ENSURE_TRUE(IS_MAI_OBJECT(atkHyperLink), nullptr);
+    return MAI_ATK_OBJECT(atkHyperLink)->GetAtkHyperlink();
 }
 
 static gint
 getLinkCountCB(AtkHypertext *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (accWrap) {
     HyperTextAccessible* hyperText = accWrap->AsHyperText();
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
@@ -129,16 +129,16 @@
   <project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
   <!-- dolphin specific things -->
   <project name="device/sprd" path="device/sprd" revision="a26ba0ab998133ad590102be1e5950818b86ce82"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="39a5b5bcadad745df3e6882316fce426f98b1669"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="8bb69db127112fc66da75f8ca7a1158614b919f6"/>
   <project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
   <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
-  <project name="kernel/common" path="kernel" revision="65d2a18bd4ab0f1ed36a76c1e3c4f9ae98f345b9"/>
+  <project name="kernel/common" path="kernel" revision="0be9cc12cd81b145e1471016c19722429ff9285e"/>
   <project name="platform/system/core" path="system/core" revision="7992618bd4ee33ce96897675a5c0a9b619122f13"/>
   <project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
   <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>
   <project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="e503b1d14d7fdee532b8f391407299da193c1b2d"/>
   <project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
   <project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
 </manifest>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "0636405f0844bf32451a375b2d61a2b16fe33348", 
+        "git_revision": "e5c1905b0144a855537fd857d62ec7a3393bb334", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "d4ec6c8c9cfc10a495e5c6cfddeb71871be73106", 
+    "revision": "97f0671809608b83775857fce9a7f7eba056d5d3", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="0636405f0844bf32451a375b2d61a2b16fe33348"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="e5c1905b0144a855537fd857d62ec7a3393bb334"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="bdd03caf084e1b9279155bd232bc718a38c47cbc"/>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -37,16 +37,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
                                   "resource:///modules/AboutHome.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
+                                  "resource://gre/modules/UpdateChannel.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
                                    "@mozilla.org/browser/favicon-service;1",
                                    "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
@@ -2753,17 +2755,17 @@ let BrowserOnClick = {
       port: location.port,
       timestamp: Math.round(Date.now() / 1000),
       errorCode: transportSecurityInfo.errorCode,
       failedCertChain: asciiCertChain,
       userAgent: window.navigator.userAgent,
       version: 1,
       build: gAppInfo.appBuildID,
       product: gAppInfo.name,
-      channel: Services.prefs.getCharPref("app.update.channel")
+      channel: UpdateChannel.get()
     }
 
     let reportURL = Services.prefs.getCharPref("security.ssl.errorReporting.url");
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
         .createInstance(Ci.nsIXMLHttpRequest);
     try {
       xhr.open("POST", reportURL);
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -48,16 +48,23 @@ LLDBINIT_OBJDIR := .lldbinit.in
 LLDBINIT_OBJDIR_PATH = $(DEPTH)
 LLDBINIT_OBJDIR_FLAGS += -Dtopsrcdir=$(abspath $(topsrcdir))
 PP_TARGETS += LLDBINIT_OBJDIR
 
 LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
 LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
 INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
 
+# Put the .ycm_extra_conf.py file at the root of the objdir. It is used by
+# the vim plugin YouCompleteMe.
+YCM_FILES := $(topsrcdir)/.ycm_extra_conf.py
+YCM_DEST := $(abspath $(DEPTH))
+YCM_TARGET := export
+INSTALL_TARGETS += YCM
+
 ifdef MOZTTDIR
 # Install the Firefox OS fonts.
 include $(MOZTTDIR)/fonts.mk
 MOZTT_DEST = $(FINAL_TARGET)/fonts
 MOZTT_FILES = $(patsubst external/moztt/%,$(MOZTTDIR)/%,$(filter external/moztt/%,$(subst :, ,$(PRODUCT_COPY_FILES))))
 INSTALL_TARGETS += MOZTT
 endif
 
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -78,16 +78,17 @@ MACH_MODULES = [
     'dom/bindings/mach_commands.py',
     'layout/tools/reftest/mach_commands.py',
     'python/mach_commands.py',
     'python/mach/mach/commands/commandinfo.py',
     'python/compare-locales/mach_commands.py',
     'python/mozboot/mozboot/mach_commands.py',
     'python/mozbuild/mozbuild/mach_commands.py',
     'python/mozbuild/mozbuild/backend/mach_commands.py',
+    'python/mozbuild/mozbuild/compilation/codecomplete.py',
     'python/mozbuild/mozbuild/frontend/mach_commands.py',
     'services/common/tests/mach_commands.py',
     'testing/luciddream/mach_commands.py',
     'testing/mach_commands.py',
     'testing/taskcluster/mach_commands.py',
     'testing/marionette/mach_commands.py',
     'testing/mochitest/mach_commands.py',
     'testing/xpcshell/mach_commands.py',
--- a/caps/moz.build
+++ b/caps/moz.build
@@ -25,18 +25,16 @@ UNIFIED_SOURCES += [
     'nsJSPrincipals.cpp',
     'nsNullPrincipal.cpp',
     'nsNullPrincipalURI.cpp',
     'nsPrincipal.cpp',
     'nsScriptSecurityManager.cpp',
     'nsSystemPrincipal.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/js/xpconnect/src',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/chrome/moz.build
+++ b/chrome/moz.build
@@ -19,18 +19,16 @@ EXPORTS.mozilla.chrome += [
 
 UNIFIED_SOURCES += [
     'nsChromeProtocolHandler.cpp',
     'nsChromeRegistry.cpp',
     'nsChromeRegistryChrome.cpp',
     'nsChromeRegistryContent.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_INCLUDES += [
     '/xpcom',
 ]
 
--- a/docshell/base/moz.build
+++ b/docshell/base/moz.build
@@ -60,18 +60,16 @@ UNIFIED_SOURCES += [
     'nsDSURIContentListener.cpp',
     'nsWebNavigationInfo.cpp',
     'SerializedLoadContext.cpp',
     'TimelineMarker.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../shistory/src',
     '/dom/base',
     '/layout/base',
     '/layout/generic',
--- a/docshell/shistory/src/moz.build
+++ b/docshell/shistory/src/moz.build
@@ -12,15 +12,13 @@ UNIFIED_SOURCES += [
     'nsSHEntry.cpp',
     'nsSHEntryShared.cpp',
     'nsSHistory.cpp',
     'nsSHTransaction.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/docshell/base',
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/dom/asmjscache/moz.build
+++ b/dom/asmjscache/moz.build
@@ -13,15 +13,13 @@ SOURCES += [
 ]
 
 IPDL_SOURCES += [
     'PAsmJSCacheEntry.ipdl'
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 MOCHITEST_MANIFESTS += ['test/mochitest.ini']
--- a/dom/base/moz.build
+++ b/dom/base/moz.build
@@ -397,18 +397,16 @@ if CONFIG['MOZ_BUILD_APP'] != 'mobile/an
 
 EXTRA_JS_MODULES += [
     'DOMRequestHelper.jsm',
     'IndexedDBHelper.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '../battery',
     '../bluetooth',
     '../events',
     '../media',
     '../network',
     '../time',
     '/caps',
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -20,16 +20,19 @@
 #include "nsRefreshDriver.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/PendingAnimationTracker.h"
 #include "nsIObjectLoadingContent.h"
 #include "nsFrame.h"
 #include "mozilla/layers/ShadowLayers.h"
 #include "ClientLayerManager.h"
 #include "nsQueryObject.h"
+#ifdef MOZ_FMP4
+#include "MP4Reader.h"
+#endif
 
 #include "nsIScrollableFrame.h"
 
 #include "nsContentUtils.h"
 
 #include "nsIFrame.h"
 #include "nsIWidget.h"
 #include "nsCharsetSource.h"
@@ -2232,16 +2235,37 @@ nsDOMWindowUtils::GetLayerManagerRemote(
   if (!mgr)
     return NS_ERROR_FAILURE;
 
   *retval = !!mgr->AsShadowForwarder();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMWindowUtils::GetSupportsHardwareH264Decoding(bool* retval)
+{
+  MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
+
+#ifdef MOZ_FMP4
+  nsCOMPtr<nsIWidget> widget = GetWidget();
+  if (!widget)
+    return NS_ERROR_FAILURE;
+
+  LayerManager *mgr = widget->GetLayerManager();
+  if (!mgr)
+    return NS_ERROR_FAILURE;
+
+  *retval = MP4Reader::IsVideoAccelerated(mgr->GetCompositorBackendType());
+#else
+  *retval = false;
+#endif
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMWindowUtils::StartFrameTimeRecording(uint32_t *startIndex)
 {
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   NS_ENSURE_ARG_POINTER(startIndex);
 
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget)
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2467,17 +2467,18 @@ nsFrameLoader::DoSendAsyncMessage(JSCont
   TabParent* tabParent = mRemoteBrowser;
   if (tabParent) {
     ClonedMessageData data;
     nsIContentParent* cp = tabParent->Manager();
     if (!BuildClonedMessageDataForParent(cp, aData, data)) {
       return false;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
-    if (aCpows && !cp->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+    jsipc::CPOWManager* mgr = cp->GetCPOWManager();
+    if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
       return false;
     }
     return tabParent->SendAsyncMessage(nsString(aMessage), data, cpows,
                                        IPC::Principal(aPrincipal));
   }
 
   if (mChildMessageManager) {
     nsCOMPtr<nsIRunnable> ev = new nsAsyncMessageToChild(aCx, this, aMessage,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1434,16 +1434,18 @@ nsGlobalWindow::DropOuterWindowDocs()
 void
 nsGlobalWindow::CleanUp()
 {
   // Guarantee idempotence.
   if (mCleanedUp)
     return;
   mCleanedUp = true;
 
+  StartDying();
+
   mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr);
   mEventTargetObjects.Clear();
 
   if (mObserver) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
       os->RemoveObserver(mObserver, "dom-storage2-changed");
@@ -2615,16 +2617,22 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       // nsGlobalWindow, so GetWrapperPreserveColor() on that outer
       // nsGlobalWindow doesn't return null and nsGlobalWindow::OuterObject
       // works correctly.
       JS::Rooted<JS::Value> unused(cx);
       if (!JS_GetProperty(cx, newInnerGlobal, "window", &unused)) {
         NS_ERROR("can't create the 'window' property");
         return NS_ERROR_FAILURE;
       }
+
+      // And same thing for the "self" property.
+      if (!JS_GetProperty(cx, newInnerGlobal, "self", &unused)) {
+        NS_ERROR("can't create the 'self' property");
+        return NS_ERROR_FAILURE;
+      }
     }
   }
 
   JSAutoCompartment ac(cx, GetWrapperPreserveColor());
 
   if (!aState && !reUseInnerWindow) {
     // Loading a new page and creating a new inner window, *not*
     // restoring from session history.
@@ -3528,32 +3536,32 @@ nsGlobalWindow::GetWindow(nsIDOMWindow**
   FORWARD_TO_OUTER_OR_THROW(GetWindow, (aWindow), rv, rv.StealNSResult());
 
   nsCOMPtr<nsIDOMWindow> window = Window();
   window.forget(aWindow);
 
   return NS_OK;
 }
 
-nsIDOMWindow*
-nsGlobalWindow::GetSelf(ErrorResult& aError)
-{
-  FORWARD_TO_OUTER_OR_THROW(GetSelf, (aError), aError, nullptr);
-
+nsGlobalWindow*
+nsGlobalWindow::Self()
+{
   return this;
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow)
 {
   ErrorResult rv;
-  nsCOMPtr<nsIDOMWindow> window = GetSelf(rv);
+  FORWARD_TO_OUTER_OR_THROW(GetSelf, (aWindow), rv, rv.StealNSResult());
+
+  nsCOMPtr<nsIDOMWindow> window = Self();
   window.forget(aWindow);
 
-  return rv.StealNSResult();
+  return NS_OK;
 }
 
 Navigator*
 nsGlobalWindow::GetNavigator(ErrorResult& aError)
 {
   FORWARD_TO_INNER_OR_THROW(GetNavigator, (aError), aError, nullptr);
 
   if (!mNavigator) {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -833,17 +833,17 @@ public:
   {
     return nullptr;
   }
 
   static JSObject*
     CreateNamedPropertiesObject(JSContext *aCx, JS::Handle<JSObject*> aProto);
 
   nsGlobalWindow* Window();
-  nsIDOMWindow* GetSelf(mozilla::ErrorResult& aError);
+  nsGlobalWindow* Self();
   nsIDocument* GetDocument()
   {
     return GetDoc();
   }
   void GetName(nsAString& aName, mozilla::ErrorResult& aError);
   void SetName(const nsAString& aName, mozilla::ErrorResult& aError);
   nsLocation* GetLocation(mozilla::ErrorResult& aError);
   nsHistory* GetHistory(mozilla::ErrorResult& aError);
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -12,21 +12,55 @@
 #define NS_IGLOBALOBJECT_IID \
 { 0xe2538ded, 0x13ef, 0x4f4d, \
 { 0x94, 0x6b, 0x65, 0xd3, 0x33, 0xb4, 0xf0, 0x3c } }
 
 class nsIPrincipal;
 
 class nsIGlobalObject : public nsISupports
 {
+  bool mIsDying;
+
+protected:
+  nsIGlobalObject()
+   : mIsDying(false)
+  {}
+
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
 
+  /**
+   * This check is added to deal with Promise microtask queues. On the main
+   * thread, we do not impose restrictions about when script stops running or
+   * when runnables can no longer be dispatched to the main thread. This means
+   * it is possible for a Promise chain to keep resolving an infinite chain of
+   * promises, preventing the browser from shutting down. See Bug 1058695. To
+   * prevent this, the nsGlobalWindow subclass sets this flag when it is
+   * closed. The Promise implementation checks this and prohibits new runnables
+   * from being dispatched.
+   *
+   * We pair this with checks during processing the promise microtask queue
+   * that pops up the slow script dialog when the Promise queue is preventing
+   * a window from going away.
+   */
+  bool
+  IsDying() const
+  {
+    return mIsDying;
+  }
+
   virtual JSObject* GetGlobalJSObject() = 0;
 
   // This method is not meant to be overridden.
   nsIPrincipal* PrincipalOrNull();
+
+protected:
+  void
+  StartDying()
+  {
+    mIsDying = true;
+  }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject,
                               NS_IGLOBALOBJECT_IID)
 
 #endif // nsIGlobalObject_h__
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -590,17 +590,16 @@ nsPerformance::AddEntry(nsIHttpChannel* 
   MOZ_ASSERT(NS_IsMainThread());
   // Check if resource timing is prefed off.
   if (!nsContentUtils::IsResourceTimingEnabled()) {
     return;
   }
 
   // Don't add the entry if the buffer is full
   if (mEntries.Length() >= mPrimaryBufferSize) {
-    NS_WARNING("Performance Entry buffer size maximum reached!");
     return;
   }
 
   if (channel && timedChannel) {
     nsAutoCString name;
     nsAutoString initiatorType;
     nsCOMPtr<nsIURI> originalURI;
 
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3550,21 +3550,22 @@ class CGUpdateMemberSlotsMethod(CGAbstra
                 Argument(descriptor.nativeType + '*', 'aObject')]
         CGAbstractStaticMethod.__init__(self, descriptor, 'UpdateMemberSlots', 'bool', args)
 
     def definition_body(self):
         body = ("JS::Rooted<JS::Value> temp(aCx);\n"
                 "JSJitGetterCallArgs args(&temp);\n")
         for m in self.descriptor.interface.members:
             if m.isAttr() and m.getExtendedAttribute("StoreInSlot"):
-                # Skip doing this for the "window" attribute on the Window
-                # interface, because that can't be gotten safely until we have
-                # hooked it up correctly to the outer window.
+                # Skip doing this for the "window" and "self" attributes on the
+                # Window interface, because those can't be gotten safely until
+                # we have hooked it up correctly to the outer window.  The
+                # window code handles doing the get itself.
                 if (self.descriptor.interface.identifier.name == "Window" and
-                    m.identifier.name == "window"):
+                    (m.identifier.name == "window" or m.identifier.name == "self")):
                     continue
                 body += fill(
                     """
 
                     if (!get_${member}(aCx, aWrapper, aObject, args)) {
                       return false;
                     }
                     // Getter handled setting our reserved slots
--- a/dom/bindings/moz.build
+++ b/dom/bindings/moz.build
@@ -37,18 +37,16 @@ EXPORTS.mozilla.dom += [
     'StructuredClone.h',
     'ToJSValue.h',
     'TypedArray.h',
     'UnionMember.h',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/battery',
     '/dom/bluetooth',
     '/dom/camera',
     '/dom/canvas',
     '/dom/geolocation',
     '/dom/html',
--- a/dom/canvas/moz.build
+++ b/dom/canvas/moz.build
@@ -128,18 +128,16 @@ UNIFIED_SOURCES += [
     'WebGLVertexArrayGL.cpp',
 ]
 LOCAL_INCLUDES += [
     '/js/xpconnect/wrappers',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
     '/dom/svg',
     '/dom/xul',
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -121,18 +121,16 @@ SOURCES += [
     'EventStateManager.cpp',
 ]
 
 if CONFIG['MOZ_WEBSPEECH']:
     UNIFIED_SOURCES += ['SpeechRecognitionError.cpp']
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/html',
     '/dom/settings',
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -28,10 +28,9 @@ UNIFIED_SOURCES += [
 
 LOCAL_INCLUDES += [
     '../workers',
     # For nsDataHandler.h
     '/netwerk/protocol/data',
 ]
 
 FAIL_ON_WARNINGS = True
-MSVC_ENABLE_PGO = True
 FINAL_LIBRARY = 'xul'
--- a/dom/html/moz.build
+++ b/dom/html/moz.build
@@ -217,18 +217,16 @@ SOURCES += [
 
 EXTRA_COMPONENTS += [
     'htmlMenuBuilder.js',
     'htmlMenuBuilder.manifest'
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/caps',
     '/docshell/base',
     '/dom/base',
     '/dom/canvas',
     '/dom/media/',
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -46,17 +46,17 @@ interface nsIDOMClientRect;
 interface nsIURI;
 interface nsIDOMEventTarget;
 interface nsIRunnable;
 interface nsITranslationNodeList;
 interface nsIJSRAIIHelper;
 interface nsIContentPermissionRequest;
 interface nsIObserver;
 
-[scriptable, uuid(7ecfd6e7-120a-4567-85f7-14277f4c6d9f)]
+[scriptable, uuid(55d6b97f-0717-449d-ac6c-cdaba0a9b698)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -1323,16 +1323,23 @@ interface nsIDOMWindowUtils : nsISupport
   /**
    * True if the layer manager for the widget associated with this window is
    * forwarding layers to a remote compositor, false otherwise. Throws an
    * error if there is no widget associated with this window.
    */
   readonly attribute boolean layerManagerRemote;
 
   /**
+   * True if we can initialize a hardware-backed h264 decoder for a simple
+   * test video, does not mean that all h264 video decoding will be done
+   * in hardware.
+   */
+  readonly attribute boolean supportsHardwareH264Decoding;
+
+  /**
    * Record (and return) frame-intervals for frames which were presented
    *   between calling StartFrameTimeRecording and StopFrameTimeRecording.
    *
    * - Uses a cyclic buffer and serves concurrent consumers, so if Stop is called too late
    *     (elements were overwritten since Start), result is considered invalid and hence empty.
    * - Buffer is capable of holding 10 seconds @ 60fps (or more if frames were less frequent).
    *     Can be changed (up to 1 hour) via pref: toolkit.framesRecording.bufferSize.
    * - Note: the first frame-interval may be longer than expected because last frame
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -49,16 +49,17 @@
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "mozilla/layers/PCompositorChild.h"
 #include "mozilla/layers/SharedBufferManagerChild.h"
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginModuleParent.h"
+#include "mozilla/media/webrtc/WebrtcGlobalChild.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 
 #if defined(MOZ_CONTENT_SANDBOX)
 #if defined(XP_WIN)
 #define TARGET_SANDBOX_EXPORTS
 #include "mozilla/sandboxTarget.h"
 #elif defined(XP_LINUX)
 #include "mozilla/Sandbox.h"
@@ -809,16 +810,19 @@ ContentChild::InitXPCOM()
     ClipboardCapabilities clipboardCaps;
     DomainPolicyClone domainPolicy;
 
     SendGetXPCOMProcessAttributes(&isOffline, &isLangRTL, &mAvailableDictionaries,
                                   &clipboardCaps, &domainPolicy);
     RecvSetOffline(isOffline);
     RecvBidiKeyboardNotify(isLangRTL);
 
+    // Create the CPOW manager as soon as possible.
+    SendPJavaScriptConstructor();
+
     if (domainPolicy.active()) {
         nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
         MOZ_ASSERT(ssm);
         ssm->ActivateDomainPolicyInternal(getter_AddRefs(mPolicy));
         if (!mPolicy) {
             MOZ_CRASH("Failed to activate domain policy.");
         }
         mPolicy->ApplyClone(&domainPolicy);
@@ -1821,16 +1825,31 @@ ContentChild::DeallocPSpeechSynthesisChi
 #ifdef MOZ_WEBSPEECH
     delete aActor;
     return true;
 #else
     return false;
 #endif
 }
 
+PWebrtcGlobalChild *
+ContentChild::AllocPWebrtcGlobalChild()
+{
+    WebrtcGlobalChild *child = new WebrtcGlobalChild();
+    return child;
+}
+
+bool
+ContentChild::DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor)
+{
+    delete static_cast<WebrtcGlobalChild*>(aActor);
+    return true;
+}
+
+
 bool
 ContentChild::RecvRegisterChrome(InfallibleTArray<ChromePackage>&& packages,
                                  InfallibleTArray<ResourceMapping>&& resources,
                                  InfallibleTArray<OverrideMapping>&& overrides,
                                  const nsCString& locale,
                                  const bool& reset)
 {
     nsCOMPtr<nsIChromeRegistry> registrySvc = nsChromeRegistry::GetService();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -452,16 +452,19 @@ public:
     virtual POfflineCacheUpdateChild* AllocPOfflineCacheUpdateChild(
             const URIParams& manifestURI,
             const URIParams& documentURI,
             const bool& stickDocument,
             const TabId& aTabId) override;
     virtual bool
     DeallocPOfflineCacheUpdateChild(POfflineCacheUpdateChild* offlineCacheUpdate) override;
 
+    virtual PWebrtcGlobalChild* AllocPWebrtcGlobalChild() override;
+    virtual bool DeallocPWebrtcGlobalChild(PWebrtcGlobalChild *aActor) override;
+
     virtual PContentPermissionRequestChild*
     AllocPContentPermissionRequestChild(const InfallibleTArray<PermissionRequest>& aRequests,
                                         const IPC::Principal& aPrincipal,
                                         const TabId& aTabId) override;
     virtual bool
     DeallocPContentPermissionRequestChild(PContentPermissionRequestChild* actor) override;
 
     virtual bool RecvGamepadUpdate(const GamepadChangeEvent& aGamepadEvent) override;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -82,16 +82,17 @@
 #include "mozilla/plugins/PluginBridge.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ProcessHangMonitor.h"
 #include "mozilla/ProcessHangMonitorIPC.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/unused.h"
+#include "mozilla/media/webrtc/WebrtcGlobalParent.h"
 #include "nsAnonymousTemporaryFile.h"
 #include "nsAppRunner.h"
 #include "nsAutoPtr.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsCExternalHandlerService.h"
 #include "nsCOMPtr.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsConsoleMessage.h"
@@ -2602,17 +2603,17 @@ ContentParent::RecvSetClipboard(const IP
           static_cast<mozilla::gfx::SourceSurfaceRawData*>(image.get());
         raw->InitWrappingData(
           reinterpret_cast<uint8_t*>(const_cast<nsCString&>(text).BeginWriting()),
           size, imageDetails.stride(),
           static_cast<mozilla::gfx::SurfaceFormat>(imageDetails.format()), false);
         raw->GuaranteePersistance();
 
         nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(image, size);
-        nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable)); 
+        nsCOMPtr<imgIContainer> imageContainer(image::ImageOps::CreateFromDrawable(drawable));
 
         nsCOMPtr<nsISupportsInterfacePointer>
           imgPtr(do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID, &rv));
 
         rv = imgPtr->SetData(imageContainer);
         NS_ENSURE_SUCCESS(rv, true);
 
         trans->SetTransferData(item.flavor().get(), imgPtr, sizeof(nsISupports*));
@@ -4383,17 +4384,18 @@ ContentParent::DoSendAsyncMessage(JSCont
                                   JS::Handle<JSObject *> aCpows,
                                   nsIPrincipal* aPrincipal)
 {
     ClonedMessageData data;
     if (!BuildClonedMessageDataForParent(this, aData, data)) {
         return false;
     }
     InfallibleTArray<CpowEntry> cpows;
-    if (aCpows && !GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+    jsipc::CPOWManager* mgr = GetCPOWManager();
+    if (aCpows && (!mgr || !mgr->Wrap(aCx, aCpows, &cpows))) {
         return false;
     }
 #ifdef MOZ_NUWA_PROCESS
     if (IsNuwaProcess() && IsNuwaReady()) {
         // Nuwa won't receive frame messages after it is frozen.
         return true;
     }
 #endif
@@ -4901,16 +4903,29 @@ bool
 ContentParent::DeallocPOfflineCacheUpdateParent(POfflineCacheUpdateParent* aActor)
 {
     // Reclaim the IPDL reference.
     nsRefPtr<mozilla::docshell::OfflineCacheUpdateParent> update =
         dont_AddRef(static_cast<mozilla::docshell::OfflineCacheUpdateParent*>(aActor));
     return true;
 }
 
+PWebrtcGlobalParent *
+ContentParent::AllocPWebrtcGlobalParent()
+{
+    return WebrtcGlobalParent::Alloc();
+}
+
+bool
+ContentParent::DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor)
+{
+    WebrtcGlobalParent::Dealloc(static_cast<WebrtcGlobalParent*>(aActor));
+    return true;
+}
+
 bool
 ContentParent::RecvSetOfflinePermission(const Principal& aPrincipal)
 {
     nsIPrincipal* principal = aPrincipal;
     nsContentUtils::MaybeAllowOfflineAppByDefault(principal, nullptr);
     return true;
 }
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -838,16 +838,20 @@ private:
                           int32_t* aSliceRefCnt,
                           bool* aResult) override;
 
     virtual PDocAccessibleParent* AllocPDocAccessibleParent(PDocAccessibleParent*, const uint64_t&) override;
     virtual bool DeallocPDocAccessibleParent(PDocAccessibleParent*) override;
     virtual bool RecvPDocAccessibleConstructor(PDocAccessibleParent* aDoc,
                                                PDocAccessibleParent* aParentDoc, const uint64_t& aParentID) override;
 
+    virtual PWebrtcGlobalParent* AllocPWebrtcGlobalParent() override;
+    virtual bool DeallocPWebrtcGlobalParent(PWebrtcGlobalParent *aActor) override;
+
+
     virtual bool RecvUpdateDropEffect(const uint32_t& aDragAction,
                                       const uint32_t& aDropEffect) override;
 
     virtual bool RecvGetBrowserConfiguration(const nsCString& aURI, BrowserConfiguration* aConfig) override;
 
     virtual bool RecvGamepadListenerAdded() override;
     virtual bool RecvGamepadListenerRemoved() override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -45,16 +45,17 @@ include protocol PSharedBufferManager;
 include protocol PSms;
 include protocol PSpeechSynthesis;
 include protocol PStorage;
 include protocol PTelephony;
 include protocol PTestShell;
 include protocol PVoicemail;
 include protocol PJavaScript;
 include protocol PRemoteSpellcheckEngine;
+include protocol PWebrtcGlobal;
 include DOMTypes;
 include JavaScriptTypes;
 include InputStreamParams;
 include PTabContext;
 include URIParams;
 include PluginTypes;
 include ProtocolTypes;
 include PContentPermission;
@@ -438,16 +439,17 @@ prio(normal upto urgent) sync protocol P
     manages PSms;
     manages PSpeechSynthesis;
     manages PStorage;
     manages PTelephony;
     manages PTestShell;
     manages PVoicemail;
     manages PJavaScript;
     manages PRemoteSpellcheckEngine;
+    manages PWebrtcGlobal;
 
 both:
     // Depending on exactly how the new browser is being created, it might be
     // created from either the child or parent process!
     //
     // The child creates the PBrowser as part of
     // TabChild::BrowserFrameProvideWindow (which happens when the child's
     // content calls window.open()), and the parent creates the PBrowser as part
@@ -758,16 +760,18 @@ parent:
     PVoicemail();
 
     PBluetooth();
 
     PFMRadio();
 
     PAsmJSCacheEntry(OpenMode openMode, WriteParams write, Principal principal);
 
+    PWebrtcGlobal();
+
     // Services remoting
 
     async StartVisitedQuery(URIParams uri);
     async VisitURI(URIParams uri, OptionalURIParams referrer, uint32_t flags);
     async SetURITitle(URIParams uri, nsString title);
 
     async LoadURIExternal(URIParams uri);
 
--- a/dom/media/MP3FrameParser.cpp
+++ b/dom/media/MP3FrameParser.cpp
@@ -173,53 +173,88 @@ MP3Parser::GetSamplesPerFrame()
   return mpeg_frame_samples[frame.mVersion][frame.mLayer];
 }
 
 
 /** ID3Parser methods **/
 
 const char sID3Head[3] = { 'I', 'D', '3' };
 const uint32_t ID3_HEADER_LENGTH = 10;
+const uint32_t ID3_FOOTER_LENGTH = 10;
+const uint8_t ID3_FOOTER_PRESENT = 0x10;
 
 ID3Parser::ID3Parser()
   : mCurrentChar(0)
+  , mVersion(0)
+  , mFlags(0)
   , mHeaderLength(0)
 { }
 
 void
 ID3Parser::Reset()
 {
-  mCurrentChar = mHeaderLength = 0;
+  mCurrentChar = mVersion = mFlags = mHeaderLength = 0;
 }
 
 bool
 ID3Parser::ParseChar(char ch)
 {
-  // First three bytes of an ID3v2 header must match the string "ID3".
-  if (mCurrentChar < sizeof(sID3Head) / sizeof(*sID3Head)
-      && ch != sID3Head[mCurrentChar]) {
-    goto fail;
-  }
-
-  // The last four bytes of the header is a 28-bit unsigned integer with the
-  // high bit of each byte unset.
-  if (mCurrentChar >= 6 && mCurrentChar < ID3_HEADER_LENGTH) {
-    if (ch & 0x80) {
-      goto fail;
-    } else {
+  switch (mCurrentChar) {
+    // The first three bytes of an ID3v2 header must match the string "ID3".
+    case 0: case 1: case 2:
+      if (ch != sID3Head[mCurrentChar]) {
+        goto fail;
+      }
+      break;
+    // The fourth and fifth bytes give the version, between 2 and 4.
+    case 3:
+      if (ch < '\2' || ch > '\4') {
+        goto fail;
+      }
+      mVersion = uint8_t(ch);
+      break;
+    case 4:
+      if (ch != '\0') {
+        goto fail;
+      }
+      break;
+    // The sixth byte gives the flags; valid flags depend on the version.
+    case 5:
+      if ((ch & (0xff >> mVersion)) != '\0') {
+        goto fail;
+      }
+      mFlags = uint8_t(ch);
+      break;
+    // Bytes seven through ten give the sum of the byte length of the extended
+    // header, the padding and the frames after unsynchronisation.
+    // These bytes form a 28-bit integer, with the high bit of each byte unset.
+    case 6: case 7: case 8: case 9:
+      if (ch & 0x80) {
+        goto fail;
+      }
       mHeaderLength <<= 7;
       mHeaderLength |= ch;
-    }
+      if (mCurrentChar == 9) {
+        mHeaderLength += ID3_HEADER_LENGTH;
+        mHeaderLength += (mFlags & ID3_FOOTER_PRESENT) ? ID3_FOOTER_LENGTH : 0;
+      }
+      break;
+    default:
+      MOZ_CRASH("Header already fully parsed!");
   }
 
   mCurrentChar++;
 
   return IsParsed();
 
 fail:
+  if (mCurrentChar) {
+    Reset();
+    return ParseChar(ch);
+  }
   Reset();
   return false;
 }
 
 bool
 ID3Parser::IsParsed() const
 {
   return mCurrentChar >= ID3_HEADER_LENGTH;
--- a/dom/media/MP3FrameParser.h
+++ b/dom/media/MP3FrameParser.h
@@ -24,16 +24,18 @@ public:
 
   void Reset();
   bool ParseChar(char ch);
   bool IsParsed() const;
   uint32_t GetHeaderLength() const;
 
 private:
   uint32_t mCurrentChar;
+  uint8_t mVersion;
+  uint8_t mFlags;
   uint32_t mHeaderLength;
 };
 
 struct MP3Frame {
   uint16_t mSync1 : 8;      // Always all set
   uint16_t mProtected : 1;  // Ignored
   uint16_t mLayer : 2;
   uint16_t mVersion : 2;
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -1052,17 +1052,16 @@ void MediaDecoder::PlaybackEnded()
       mPlayState == PLAY_STATE_LOADING) {
     return;
   }
 
   PlaybackPositionChanged();
   ChangeState(PLAY_STATE_ENDED);
   InvalidateWithFlags(VideoFrameContainer::INVALIDATE_FORCE);
 
-  mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary?
   if (mOwner)  {
     mOwner->PlaybackEnded();
   }
 
   // This must be called after |mOwner->PlaybackEnded()| call above, in order
   // to fire the required durationchange.
   if (IsInfinite()) {
     SetInfinite(false);
@@ -1246,34 +1245,32 @@ void MediaDecoder::OnSeekResolved(SeekRe
         ChangeState(aVal.mAtEnd ? PLAY_STATE_ENDED : mNextState);
       }
     }
   }
 
   PlaybackPositionChanged(aVal.mEventVisibility);
 
   if (mOwner) {
-    mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary?
     if (!seekWasAborted && (aVal.mEventVisibility != MediaDecoderEventVisibility::Suppressed)) {
       mOwner->SeekCompleted();
       if (fireEnded) {
         mOwner->PlaybackEnded();
       }
     }
   }
 }
 
 void MediaDecoder::SeekingStarted(MediaDecoderEventVisibility aEventVisibility)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (mShuttingDown)
     return;
 
   if (mOwner) {
-    mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary?
     if (aEventVisibility != MediaDecoderEventVisibility::Suppressed) {
       mOwner->SeekStarted();
     }
   }
 }
 
 void MediaDecoder::ChangeState(PlayState aState)
 {
@@ -1646,17 +1643,16 @@ size_t MediaDecoder::SizeOfAudioQueue() 
   }
   return 0;
 }
 
 void MediaDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {
   if (mDecoderStateMachine) {
     mDecoderStateMachine->NotifyDataArrived(aBuffer, aLength, aOffset);
   }
-  mReadyStateWatchTarget->Notify(); // XXXbholley - Still necessary?
 }
 
 // Provide access to the state machine object
 MediaDecoderStateMachine* MediaDecoder::GetStateMachine() const {
   return mDecoderStateMachine;
 }
 
 void
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -200,21 +200,22 @@ static uint32_t sVideoQueueHWAccelSize =
 
 MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
                                                    MediaDecoderReader* aReader,
                                                    bool aRealTime) :
   mDecoder(aDecoder),
   mRealTime(aRealTime),
   mDispatchedStateMachine(false),
   mDelayedScheduler(this),
-  mState(DECODER_STATE_DECODING_NONE),
+  mState(DECODER_STATE_DECODING_NONE, "MediaDecoderStateMachine::mState"),
   mPlayDuration(0),
   mStartTime(-1),
   mEndTime(-1),
   mDurationSet(false),
+  mNextFrameStatusUpdater("MediaDecoderStateMachine::mNextFrameStatusUpdater"),
   mFragmentEndTime(-1),
   mReader(aReader),
   mCurrentFrameTime(0),
   mAudioStartTime(-1),
   mAudioEndTime(-1),
   mDecodedAudioEndTime(-1),
   mVideoFrameEndTime(-1),
   mDecodedVideoEndTime(-1),
@@ -223,17 +224,17 @@ MediaDecoderStateMachine::MediaDecoderSt
   mPreservesPitch(true),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
   mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
   mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
   mIsAudioPrerolling(false),
   mIsVideoPrerolling(false),
   mAudioCaptured(false),
   mPositionChangeQueued(false),
-  mAudioCompleted(false),
+  mAudioCompleted(false, "MediaDecoderStateMachine::mAudioCompleted"),
   mGotDurationFromMetaData(false),
   mDispatchedEventToDecode(false),
   mStopAudioThread(true),
   mQuickBuffering(false),
   mMinimizePreroll(false),
   mDecodeThreadWaiting(false),
   mDropAudioUntilNextDiscontinuity(false),
   mDropVideoUntilNextDiscontinuity(false),
@@ -252,16 +253,22 @@ MediaDecoderStateMachine::MediaDecoderSt
   // Set up our task queue.
   RefPtr<SharedThreadPool> pool(GetMediaThreadPool());
   MOZ_DIAGNOSTIC_ASSERT(pool);
   mTaskQueue = new MediaTaskQueue(pool.forget(), /* aAssertTailDispatch = */ true);
 
   mNextFrameStatus.Init(mTaskQueue, MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED,
                         "MediaDecoderStateMachine::mNextFrameStatus (Canonical)");
 
+  // Skip the initial notification we get when we Watch the value, since we're
+  // not on the right thread yet.
+  mNextFrameStatusUpdater->Watch(mState, /* aSkipInitialNotify = */ true);
+  mNextFrameStatusUpdater->Watch(mAudioCompleted, /* aSkipInitialNotify = */ true);
+  mNextFrameStatusUpdater->AddWeakCallback(this, &MediaDecoderStateMachine::UpdateNextFrameStatus);
+
   static bool sPrefCacheInit = false;
   if (!sPrefCacheInit) {
     sPrefCacheInit = true;
     Preferences::AddUintVarCache(&sVideoQueueDefaultSize,
                                  "media.video-queue.default-size",
                                  MAX_VIDEO_QUEUE_SIZE);
     Preferences::AddUintVarCache(&sVideoQueueHWAccelSize,
                                  "media.video-queue.hw-accel-size",
@@ -538,17 +545,16 @@ void MediaDecoderStateMachine::SendStrea
     }
     break;
   }
 
   // To be consistent with AudioSink, |mAudioCompleted| is not set
   // until all samples are drained.
   if (finished && AudioQueue().GetSize() == 0) {
     mAudioCompleted = true;
-    UpdateNextFrameStatus();
   }
 }
 
 MediaDecoderStateMachine::WakeDecoderRunnable*
 MediaDecoderStateMachine::GetWakeDecoderRunnable()
 {
   AssertCurrentThreadInMonitor();
 
@@ -935,19 +941,16 @@ MediaDecoderStateMachine::OnNotDecoded(M
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_BUFFERING:
     case DECODER_STATE_DECODING: {
       CheckIfDecodeComplete();
-      // The ready state can change when we've decoded data, so update the
-      // ready state, so that DOM events can fire.
-      UpdateNextFrameStatus();
       mDecoder->GetReentrantMonitor().NotifyAll();
       // Schedule the state machine to notify track ended as soon as possible.
       if (mAudioCaptured) {
         ScheduleStateMachine();
       }
       return;
     }
     case DECODER_STATE_SEEKING: {
@@ -1862,21 +1865,16 @@ MediaDecoderStateMachine::InitiateSeek()
   mCurrentTimeBeforeSeek = GetMediaTime();
 
   // Stop playback now to ensure that while we're outside the monitor
   // dispatching SeekingStarted, playback doesn't advance and mess with
   // mCurrentFrameTime that we've setting to seekTime here.
   StopPlayback();
   UpdatePlaybackPositionInternal(mCurrentSeek.mTarget.mTime);
 
-
-  // Make sure the main thread decoder gets notified of the seek only after
-  // we've updated the mirrored NextFrameStatus, which has special behavior
-  // when we're in DECODER_STATE_SEEKING.
-  UpdateNextFrameStatus();
   nsCOMPtr<nsIRunnable> startEvent =
       NS_NewRunnableMethodWithArg<MediaDecoderEventVisibility>(
         mDecoder,
         &MediaDecoder::SeekingStarted,
         mCurrentSeek.mTarget.mEventVisibility);
   AbstractThread::MainThread()->Dispatch(startEvent.forget());
 
   // Reset our state machine and decoding pipeline before seeking.
@@ -2672,17 +2670,16 @@ nsresult MediaDecoderStateMachine::RunSt
       }
 
       DECODER_LOG("Changed state from BUFFERING to DECODING");
       DECODER_LOG("Buffered for %.3lfs", (now - mBufferingStart).ToSeconds());
       StartDecoding();
 
       // Notify to allow blocked decoder thread to continue
       mDecoder->GetReentrantMonitor().NotifyAll();
-      UpdateNextFrameStatus();
       MaybeStartPlayback();
       NS_ASSERTION(IsStateMachineScheduled(), "Must have timer scheduled");
       return NS_OK;
     }
 
     case DECODER_STATE_SEEKING: {
       if (mPendingSeek.Exists()) {
         InitiateSeek();
@@ -3026,22 +3023,16 @@ void MediaDecoderStateMachine::AdvanceFr
       return;
     }
     MediaDecoder::FrameStatistics& frameStats = mDecoder->GetFrameStatistics();
     frameStats.NotifyPresentedFrame();
     remainingTime = currentFrame->GetEndTime() - clock_time;
     currentFrame = nullptr;
   }
 
-  // If the number of audio/video frames queued has changed, either by
-  // this function popping and playing a video frame, or by the audio
-  // thread popping and playing an audio frame, we may need to update our
-  // ready state. Post an update to do so.
-  UpdateNextFrameStatus();
-
   int64_t delay = remainingTime / mPlaybackRate;
   if (delay > 0) {
     ScheduleStateMachineIn(delay);
   } else {
     ScheduleStateMachine();
   }
 }
 
@@ -3191,17 +3182,17 @@ void MediaDecoderStateMachine::SetStartT
   // first actual audio frame we have, we'll inject silence during playback
   // to ensure the audio starts at the correct time.
   mAudioStartTime = mStartTime;
   DECODER_LOG("Set media start time to %lld", mStartTime);
 }
 
 void MediaDecoderStateMachine::UpdateNextFrameStatus() {
   MOZ_ASSERT(OnTaskQueue());
-  AssertCurrentThreadInMonitor();
+  ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
 
   MediaDecoderOwner::NextFrameStatus status;
   const char* statusString;
   if (IsBuffering()) {
     status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING;
     statusString = "NEXT_FRAME_UNAVAILABLE_BUFFERING";
   } else if (IsSeeking()) {
     status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_SEEKING;
@@ -3251,17 +3242,16 @@ void MediaDecoderStateMachine::StartBuff
   // a "quick exit". This stops us flip-flopping between playing and buffering
   // when the download speed is similar to the decode speed.
   mQuickBuffering =
     !JustExitedQuickBuffering() &&
     decodeDuration < UsecsToDuration(QUICK_BUFFER_THRESHOLD_USECS);
   mBufferingStart = TimeStamp::Now();
 
   SetState(DECODER_STATE_BUFFERING);
-  UpdateNextFrameStatus();
   DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs",
               decodeDuration.ToSeconds());
 #ifdef PR_LOGGING
   MediaDecoder::Statistics stats = mDecoder->GetStatistics();
   DECODER_LOG("Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
               stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
               stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)");
 #endif
@@ -3434,17 +3424,16 @@ void MediaDecoderStateMachine::OnAudioSi
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   if (mAudioCaptured) {
     return;
   }
   ResyncAudioClock();
   mAudioCompleted = true;
-  UpdateNextFrameStatus();
   // Kick the decode thread; it may be sleeping waiting for this to finish.
   mDecoder->GetReentrantMonitor().NotifyAll();
 }
 
 void MediaDecoderStateMachine::OnAudioSinkError()
 {
   MOZ_ASSERT(OnTaskQueue());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -839,17 +839,17 @@ public:
   // Queue of video frames. This queue is threadsafe, and is accessed from
   // the decoder, state machine, and main threads.
   MediaQueue<VideoData> mVideoQueue;
 
   // The decoder monitor must be obtained before modifying this state.
   // NotifyAll on the monitor must be called when the state is changed so
   // that interested threads can wake up and alter behaviour if appropriate
   // Accessed on state machine, audio, main, and AV thread.
-  State mState;
+  Watchable<State> mState;
 
   // The task queue in which we run decode tasks. This is referred to as
   // the "decode thread", though in practise tasks can run on a different
   // thread every time they're called.
   MediaTaskQueue* DecodeTaskQueue() const { return mReader->GetTaskQueue(); }
 
   // The time that playback started from the system clock. This is used for
   // timing the presentation of video frames when there's no audio.
@@ -882,16 +882,17 @@ public:
 
   // Will be set when SetDuration has been called with a value != -1
   // mDurationSet false doesn't indicate that we do not have a valid duration
   // as mStartTime and mEndTime could have been set separately.
   bool mDurationSet;
 
   // The status of our next frame. Mirrored on the main thread and used to
   // compute ready state.
+  WatcherHolder mNextFrameStatusUpdater;
   Canonical<NextFrameStatus>::Holder mNextFrameStatus;
 public:
   AbstractCanonical<NextFrameStatus>* CanonicalNextFrameStatus() { return &mNextFrameStatus; }
 protected:
 
   struct SeekJob {
     void Steal(SeekJob& aOther)
     {
@@ -1150,17 +1151,17 @@ protected:
 
   // True if the audio playback thread has finished. It is finished
   // when either all the audio frames have completed playing, or we've moved
   // into shutdown state, and the threads are to be
   // destroyed. Written by the audio playback thread and read and written by
   // the state machine thread. Synchronised via decoder monitor.
   // When data is being sent to a MediaStream, this is true when all data has
   // been written to the MediaStream.
-  bool mAudioCompleted;
+  Watchable<bool> mAudioCompleted;
 
   // True if mDuration has a value obtained from an HTTP header, or from
   // the media index/metadata. Accessed on the state machine thread.
   bool mGotDurationFromMetaData;
 
   // True if we've dispatched an event to the decode task queue to call
   // DecodeThreadRun(). We use this flag to prevent us from dispatching
   // unneccessary runnables, since the decode thread runs in a loop.
--- a/dom/media/StateWatching.h
+++ b/dom/media/StateWatching.h
@@ -65,17 +65,17 @@ void EnsureStateWatchingLog();
   PR_LOG(gStateWatchingLog, PR_LOG_DEBUG, (x, ##__VA_ARGS__))
 
 /*
  * AbstractWatcher is a superclass from which all watchers must inherit.
  */
 class AbstractWatcher
 {
 public:
-  NS_INLINE_DECL_REFCOUNTING(AbstractWatcher)
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractWatcher)
   AbstractWatcher() : mDestroyed(false) {}
   bool IsDestroyed() { return mDestroyed; }
   virtual void Notify() = 0;
 
 protected:
   virtual ~AbstractWatcher() {}
   virtual void CustomDestroy() {}
 
@@ -99,21 +99,23 @@ private:
  * The functionality that this class provides is not threadsafe, and should only
  * be used on the thread that owns that WatchTarget.
  */
 class WatchTarget
 {
 public:
   explicit WatchTarget(const char* aName) : mName(aName) {}
 
-  void AddWatcher(AbstractWatcher* aWatcher)
+  void AddWatcher(AbstractWatcher* aWatcher, bool aSkipInitialNotify)
   {
     MOZ_ASSERT(!mWatchers.Contains(aWatcher));
     mWatchers.AppendElement(aWatcher);
-    aWatcher->Notify();
+    if (!aSkipInitialNotify) {
+      aWatcher->Notify();
+    }
   }
 
   void RemoveWatcher(AbstractWatcher* aWatcher)
   {
     MOZ_ASSERT(mWatchers.Contains(aWatcher));
     mWatchers.RemoveElement(aWatcher);
   }
 
@@ -199,17 +201,17 @@ public:
     }
     mNotifying = true;
 
     // Queue up our notification jobs to run in a stable state.
     nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethod(this, &Watcher::DoNotify);
     AbstractThread::GetCurrent()->TailDispatcher().AddDirectTask(r.forget());
   }
 
-  void Watch(WatchTarget& aTarget) { aTarget.AddWatcher(this); }
+  void Watch(WatchTarget& aTarget, bool aSkipInitialNotify = false) { aTarget.AddWatcher(this, aSkipInitialNotify); }
   void Unwatch(WatchTarget& aTarget) { aTarget.RemoveWatcher(this); }
 
   template<typename ThisType>
   void AddWeakCallback(ThisType* aThisVal, void(ThisType::*aMethod)())
   {
     mCallbacks.AppendElement(NS_NewNonOwningRunnableMethod(aThisVal, aMethod));
   }
 
--- a/dom/media/apple/AppleMP3Reader.cpp
+++ b/dom/media/apple/AppleMP3Reader.cpp
@@ -534,19 +534,23 @@ AppleMP3Reader::NotifyDataArrived(const 
                                   int64_t aOffset)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (!mMP3FrameParser.NeedsData()) {
     return;
   }
 
   mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
+  if (!mMP3FrameParser.IsMP3()) {
+    return;
+  }
 
   uint64_t duration = mMP3FrameParser.GetDuration();
   if (duration != mDuration) {
     LOGD("Updating media duration to %lluus\n", duration);
+    MOZ_ASSERT(mDecoder);
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mDuration = duration;
-    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mDecoder->UpdateEstimatedMediaDuration(duration);
   }
 }
 
 } // namespace mozilla
--- a/dom/media/directshow/DirectShowReader.cpp
+++ b/dom/media/directshow/DirectShowReader.cpp
@@ -404,22 +404,27 @@ DirectShowReader::SeekInternal(int64_t a
 
   return NS_OK;
 }
 
 void
 DirectShowReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  if (!mMP3FrameParser.NeedsData()) {
+    return;
+  }
+
+  mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
   if (!mMP3FrameParser.IsMP3()) {
     return;
   }
-  mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
+
   int64_t duration = mMP3FrameParser.GetDuration();
   if (duration != mDuration) {
-    mDuration = duration;
     MOZ_ASSERT(mDecoder);
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    mDuration = duration;
     mDecoder->UpdateEstimatedMediaDuration(mDuration);
   }
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -25,16 +25,17 @@
 #include <algorithm>
 
 #ifdef MOZ_EME
 #include "mozilla/CDMProxy.h"
 #endif
 
 using mozilla::layers::Image;
 using mozilla::layers::LayerManager;
+using mozilla::layers::ImageContainer;
 using mozilla::layers::LayersBackend;
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetDemuxerLog() {
   static PRLogModuleInfo* log = nullptr;
   if (!log) {
     log = PR_NewLogModule("MP4Demuxer");
   }
@@ -65,16 +66,53 @@ TrackTypeToStr(TrackType aTrack)
   case kVideo:
     return "Video";
   default:
     return "Unknown";
   }
 }
 #endif
 
+uint8_t sTestExtraData[40] = { 0x01, 0x64, 0x00, 0x0a, 0xff, 0xe1, 0x00, 0x17, 0x67, 0x64, 0x00, 0x0a, 0xac, 0xd9, 0x44, 0x26, 0x84, 0x00, 0x00, 0x03,
+                               0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x96, 0x58, 0x01, 0x00, 0x06, 0x68, 0xeb, 0xe3, 0xcb, 0x22, 0xc0 };
+
+/* static */ bool
+MP4Reader::IsVideoAccelerated(LayersBackend aBackend)
+{
+  VideoInfo config;
+  config.mMimeType = "video/avc";
+  config.mId = 1;
+  config.mDuration = 40000;
+  config.mMediaTime = 0;
+  config.mDisplay = config.mImage = nsIntSize(64, 64);
+  config.mExtraData = new MediaByteBuffer();
+  config.mExtraData->AppendElements(sTestExtraData, 40);
+
+  PlatformDecoderModule::Init();
+
+  nsRefPtr<PlatformDecoderModule> platform = PlatformDecoderModule::Create();
+  if (!platform) {
+    return false;
+  }
+
+  nsRefPtr<MediaDataDecoder> decoder =
+    platform->CreateDecoder(config, nullptr, nullptr, aBackend, nullptr);
+  if (!decoder) {
+    return false;
+  }
+  nsresult rv = decoder->Init();
+  NS_ENSURE_SUCCESS(rv, false);
+
+  bool result = decoder->IsHardwareAccelerated();
+
+  decoder->Shutdown();
+
+  return result;
+}
+
 bool
 AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
 {
   SPSData spsdata;
   if (H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
                          (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
                          (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -83,16 +83,18 @@ public:
   virtual nsRefPtr<ShutdownPromise> Shutdown() override;
 
   virtual bool IsAsync() const override { return true; }
 
   virtual bool VideoIsHardwareAccelerated() const override;
 
   virtual void DisableHardwareAcceleration() override;
 
+  static bool IsVideoAccelerated(layers::LayersBackend aBackend);
+
 private:
 
   bool InitDemuxer();
   void ReturnOutput(MediaData* aData, TrackType aTrack);
 
   bool EnsureDecodersSetup();
 
   bool CheckIfDecoderSetup();
--- a/dom/media/fmp4/PlatformDecoderModule.cpp
+++ b/dom/media/fmp4/PlatformDecoderModule.cpp
@@ -113,18 +113,17 @@ PlatformDecoderModule::CreateCDMWrapper(
   return emepdm.forget();
 }
 #endif
 
 /* static */
 already_AddRefed<PlatformDecoderModule>
 PlatformDecoderModule::Create()
 {
-  // Note: This runs on the decode thread.
-  MOZ_ASSERT(!NS_IsMainThread());
+  // Note: This (usually) runs on the decode thread.
 
   nsRefPtr<PlatformDecoderModule> m(CreatePDM());
 
   if (m && NS_SUCCEEDED(m->Startup())) {
     return m.forget();
   }
   return nullptr;
 }
--- a/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/fmp4/gonk/GonkVideoDecoderManager.cpp
@@ -49,18 +49,16 @@ GonkVideoDecoderManager::GonkVideoDecode
   const VideoInfo& aConfig)
   : GonkDecoderManager(aTaskQueue)
   , mImageContainer(aImageContainer)
   , mReaderCallback(nullptr)
   , mColorConverterBufferSize(0)
   , mNativeWindow(nullptr)
   , mPendingVideoBuffersLock("GonkVideoDecoderManager::mPendingVideoBuffersLock")
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
-  MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
   mMimeType = aConfig.mMimeType;
   mVideoWidth  = aConfig.mDisplay.width;
   mVideoHeight = aConfig.mDisplay.height;
   mDisplayWidth = aConfig.mDisplay.width;
   mDisplayHeight = aConfig.mDisplay.height;
   mInfo.mVideo = aConfig;
 
--- a/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
+++ b/dom/media/fmp4/wmf/WMFMediaDataDecoder.cpp
@@ -44,18 +44,22 @@ WMFMediaDataDecoder::Init()
   NS_ENSURE_TRUE(mDecoder, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 nsresult
 WMFMediaDataDecoder::Shutdown()
 {
-  mTaskQueue->Dispatch(
-    NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
+  if (mTaskQueue) {
+    mTaskQueue->Dispatch(
+      NS_NewRunnableMethod(this, &WMFMediaDataDecoder::ProcessShutdown));
+  } else {
+    ProcessShutdown();
+  }
 #ifdef DEBUG
   {
     MonitorAutoLock mon(mMonitor);
     // The MP4Reader should have flushed before calling Shutdown().
     MOZ_ASSERT(!mIsDecodeTaskDispatched);
   }
 #endif
   return NS_OK;
--- a/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/fmp4/wmf/WMFVideoMFTManager.cpp
@@ -73,18 +73,16 @@ WMFVideoMFTManager::WMFVideoMFTManager(
                             mozilla::layers::ImageContainer* aImageContainer,
                             bool aDXVAEnabled)
   : mImageContainer(aImageContainer)
   , mDXVAEnabled(aDXVAEnabled)
   , mLayersBackend(aLayersBackend)
   // mVideoStride, mVideoWidth, mVideoHeight, mUseHwAccel are initialized in
   // Init().
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Should not be on main thread.");
-  MOZ_ASSERT(mImageContainer);
   MOZ_COUNT_CTOR(WMFVideoMFTManager);
 
   // Need additional checks/params to check vp8/vp9
   if (aConfig.mMimeType.EqualsLiteral("video/mp4") ||
       aConfig.mMimeType.EqualsLiteral("video/avc")) {
     mStreamType = H264;
   } else if (aConfig.mMimeType.EqualsLiteral("video/webm; codecs=vp8")) {
     mStreamType = VP8;
@@ -160,17 +158,22 @@ WMFVideoMFTManager::InitializeDXVA()
       (mLayersBackend != LayersBackend::LAYERS_D3D9 &&
        mLayersBackend != LayersBackend::LAYERS_D3D10 &&
        mLayersBackend != LayersBackend::LAYERS_D3D11)) {
     return false;
   }
 
   // The DXVA manager must be created on the main thread.
   nsRefPtr<CreateDXVAManagerEvent> event(new CreateDXVAManagerEvent(mLayersBackend));
-  NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+
+  if (NS_IsMainThread()) {
+    event->Run();
+  } else {
+    NS_DispatchToMainThread(event, NS_DISPATCH_SYNC);
+  }
   mDXVA2Manager = event->mDXVA2Manager;
 
   return mDXVA2Manager != nullptr;
 }
 
 TemporaryRef<MFTDecoder>
 WMFVideoMFTManager::Init()
 {
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -1273,29 +1273,31 @@ GStreamerReader::AutoplugSortCb(GstEleme
  * If this is an MP3 stream, pass any new data we get to the MP3 frame parser
  * for duration estimation.
  */
 void GStreamerReader::NotifyDataArrived(const char *aBuffer,
                                         uint32_t aLength,
                                         int64_t aOffset)
 {
   MOZ_ASSERT(NS_IsMainThread());
-
   if (HasVideo()) {
     return;
   }
-
   if (!mMP3FrameParser.NeedsData()) {
     return;
   }
 
   mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
+  if (!mMP3FrameParser.IsMP3()) {
+    return;
+  }
 
   int64_t duration = mMP3FrameParser.GetDuration();
   if (duration != mLastParserDuration && mUseParserDuration) {
+    MOZ_ASSERT(mDecoder);
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
     mLastParserDuration = duration;
     mDecoder->UpdateEstimatedMediaDuration(mLastParserDuration);
   }
 }
 
 #if GST_VERSION_MAJOR >= 1
 GstCaps* GStreamerReader::BuildAudioSinkCaps()
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -263,18 +263,16 @@ EXTRA_COMPONENTS += [
 EXTRA_JS_MODULES.media += [
     'IdpSandbox.jsm',
     'PeerConnectionIdp.jsm',
     'RTCStatsReport.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/camera',
     '/layout/generic',
     '/layout/xul',
     '/netwerk/base',
 ]
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -486,25 +486,28 @@ void MediaOmxReader::NotifyDataArrived(c
   MOZ_ASSERT(NS_IsMainThread());
   nsRefPtr<AbstractMediaDecoder> decoder = SafeGetDecoder();
   if (!decoder) { // reader has shut down
     return;
   }
   if (HasVideo()) {
     return;
   }
-
   if (!mMP3FrameParser.NeedsData()) {
     return;
   }
 
   mMP3FrameParser.Parse(aBuffer, aLength, aOffset);
+  if (!mMP3FrameParser.IsMP3()) {
+    return;
+  }
+
   int64_t duration = mMP3FrameParser.GetDuration();
-  ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
   if (duration != mLastParserDuration && mUseParserDuration) {
+    ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor());
     mLastParserDuration = duration;
     decoder->UpdateEstimatedMediaDuration(mLastParserDuration);
   }
 }
 
 bool MediaOmxReader::DecodeAudioData()
 {
   MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/standalone/moz.build
+++ b/dom/media/standalone/moz.build
@@ -12,18 +12,16 @@ UNIFIED_SOURCES += [
     '../AudioSegment.cpp',
     '../SimpleImageBuffer.cpp',
     '../VideoSegment.cpp',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += ['../systemservices/OSXRunLoopSingleton.cpp']
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/camera',
     '/layout/generic',
     '/layout/xul',
     '/netwerk/base',
 ]
--- a/dom/mobilemessage/moz.build
+++ b/dom/mobilemessage/moz.build
@@ -69,17 +69,15 @@ IPDL_SOURCES += [
     'ipc/PMobileMessageCursor.ipdl',
     'ipc/PSms.ipdl',
     'ipc/PSmsRequest.ipdl',
     'ipc/SmsTypes.ipdlh',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/dom/plugins/base/moz.build
+++ b/dom/plugins/base/moz.build
@@ -85,18 +85,16 @@ else:
         ]
     else:
         UNIFIED_SOURCES += [
             'nsPluginNativeWindow.cpp',
         ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/plugins/ipc',
     '/layout/generic',
     '/layout/xul',
     '/netwerk/base',
     '/widget',
     '/widget/android',
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -532,16 +532,18 @@ PluginModuleChromeParent::OnProcessLaunc
 
     Preferences::RegisterCallback(TimeoutChanged, kChildTimeoutPref, this);
     Preferences::RegisterCallback(TimeoutChanged, kParentTimeoutPref, this);
 #ifdef XP_WIN
     Preferences::RegisterCallback(TimeoutChanged, kHangUITimeoutPref, this);
     Preferences::RegisterCallback(TimeoutChanged, kHangUIMinDisplayPref, this);
 #endif
 
+    RegisterSettingsCallbacks();
+
 #ifdef MOZ_CRASHREPORTER
     // If this fails, we're having IPC troubles, and we're doomed anyways.
     if (!CrashReporterParent::CreateCrashReporter(this)) {
         mShutdown = true;
         Close();
         OnInitFailure();
         return;
     }
@@ -688,18 +690,16 @@ PluginModuleChromeParent::PluginModuleCh
     , mAsyncInitRv(NS_ERROR_NOT_INITIALIZED)
     , mAsyncInitError(NPERR_NO_ERROR)
     , mContentParent(nullptr)
 {
     NS_ASSERTION(mSubprocess, "Out of memory!");
     sInstantiated = true;
     mRunID = sNextRunID++;
 
-    RegisterSettingsCallbacks();
-
 #ifdef MOZ_ENABLE_PROFILER_SPS
     InitPluginProfiling();
 #endif
 
     mozilla::HangMonitor::RegisterAnnotator(*this);
 }
 
 PluginModuleChromeParent::~PluginModuleChromeParent()
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -258,17 +258,17 @@ protected:
 
         mPromise->RejectInternal(cx, exn);
       }
       // At least one of resolveFunc or rejectFunc have been called, so ignore
       // the exception. FIXME(nsm): This should be reported to the error
       // console though, for debugging.
     }
 
-    return NS_OK;
+    return rv.StealNSResult();
   }
 
 private:
   nsRefPtr<Promise> mPromise;
   JS::PersistentRooted<JSObject*> mThenable;
   nsRefPtr<PromiseInit> mThen;
   NS_DECL_OWNINGTHREAD;
 };
@@ -484,23 +484,34 @@ Promise::PerformMicroTaskCheckpoint()
   CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
   nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue =
     runtime->GetPromiseMicroTaskQueue();
 
   if (microtaskQueue.IsEmpty()) {
     return false;
   }
 
+  Maybe<AutoSafeJSContext> cx;
+  if (NS_IsMainThread()) {
+    cx.emplace();
+  }
+
   do {
     nsCOMPtr<nsIRunnable> runnable = microtaskQueue.ElementAt(0);
     MOZ_ASSERT(runnable);
 
     // This function can re-enter, so we remove the element before calling.
     microtaskQueue.RemoveElementAt(0);
-    runnable->Run();
+    nsresult rv = runnable->Run();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return false;
+    }
+    if (cx.isSome()) {
+      JS_CheckForInterrupt(cx.ref());
+    }
   } while (!microtaskQueue.IsEmpty());
 
   return true;
 }
 
 /* static */ bool
 Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
 {
@@ -1066,16 +1077,20 @@ Promise::Compartment() const
 {
   return js::GetObjectCompartment(GlobalJSObject());
 }
 
 void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
+  if (mGlobal->IsDying()) {
+    return;
+  }
+
   MOZ_ASSERT(aResolveCallback);
   MOZ_ASSERT(aRejectCallback);
 
   if (mIsLastInChain && mState == PromiseState::Rejected) {
     // This rejection is now consumed.
     PromiseDebugging::AddConsumedRejection(*this);
     // Note that we may not have had the opportunity to call
     // RunResolveTask() yet, so we may never have called
@@ -1292,17 +1307,22 @@ Promise::RejectInternal(JSContext* aCx,
   mResolvePending = true;
 
   MaybeSettle(aValue, Rejected);
 }
 
 void
 Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
 {
+  if (mGlobal->IsDying()) {
+    return;
+  }
+
   mSettlementTimestamp = TimeStamp::Now();
+
   SetResult(aValue);
   SetState(aState);
 
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
   JS::RootedObject wrapper(cx, GetWrapper());
   MOZ_ASSERT(wrapper); // We preserved it
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -66,30 +66,31 @@ ResolvePromiseCallback::ResolvePromiseCa
   HoldJSObjects(this);
 }
 
 ResolvePromiseCallback::~ResolvePromiseCallback()
 {
   DropJSObjects(this);
 }
 
-void
+nsresult
 ResolvePromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
-    return;
+    return NS_ERROR_FAILURE;
   }
 
   mPromise->ResolveInternal(aCx, value);
+  return NS_OK;
 }
 
 // RejectPromiseCallback
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
                                                 PromiseCallback)
@@ -124,31 +125,32 @@ RejectPromiseCallback::RejectPromiseCall
   HoldJSObjects(this);
 }
 
 RejectPromiseCallback::~RejectPromiseCallback()
 {
   DropJSObjects(this);
 }
 
-void
+nsresult
 RejectPromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
-    return;
+    return NS_ERROR_FAILURE;
   }
 
 
   mPromise->RejectInternal(aCx, value);
+  return NS_OK;
 }
 
 // WrapperPromiseCallback
 NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
                                                 PromiseCallback)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
@@ -185,25 +187,25 @@ WrapperPromiseCallback::WrapperPromiseCa
   HoldJSObjects(this);
 }
 
 WrapperPromiseCallback::~WrapperPromiseCallback()
 {
   DropJSObjects(this);
 }
 
-void
+nsresult
 WrapperPromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> aValue)
 {
   JSAutoCompartment ac(aCx, mGlobal);
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!JS_WrapValue(aCx, &value)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
-    return;
+    return NS_ERROR_FAILURE;
   }
 
   ErrorResult rv;
 
   // PromiseReactionTask step 6
   JS::Rooted<JS::Value> retValue(aCx);
   mCallback->Call(value, &retValue, rv, "promise callback",
                   CallbackObject::eRethrowExceptions,
@@ -214,30 +216,30 @@ WrapperPromiseCallback::Call(JSContext* 
   // PromiseReactionTask step 7
   if (rv.Failed()) {
     JS::Rooted<JS::Value> value(aCx);
     if (rv.IsJSException()) {
       rv.StealJSException(aCx, &value);
 
       if (!JS_WrapValue(aCx, &value)) {
         NS_WARNING("Failed to wrap value into the right compartment.");
-        return;
+        return NS_ERROR_FAILURE;
       }
     } else {
       // Convert the ErrorResult to a JS exception object that we can reject
       // ourselves with.  This will be exactly the exception that would get
       // thrown from a binding method whose ErrorResult ended up with whatever
       // is on "rv" right now.
       JSAutoCompartment ac(aCx, mNextPromise->GlobalJSObject());
       DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
       MOZ_ASSERT(conversionResult);
     }
 
     mNextPromise->RejectInternal(aCx, value);
-    return;
+    return NS_OK;
   }
 
   // If the return value is the same as the promise itself, throw TypeError.
   if (retValue.isObject()) {
     JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
     Promise* returnedPromise;
     nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise);
 
@@ -265,48 +267,49 @@ WrapperPromiseCallback::Call(JSContext* 
         }
       }
 
       // We're back in aValue's compartment here.
       JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
       if (!fn) {
         // Out of memory. Promise will stay unresolved.
         JS_ClearPendingException(aCx);
-        return;
+        return NS_ERROR_OUT_OF_MEMORY;
       }
 
       JS::Rooted<JSString*> message(aCx,
         JS_NewStringCopyZ(aCx,
           "then() cannot return same Promise that it resolves."));
       if (!message) {
         // Out of memory. Promise will stay unresolved.
         JS_ClearPendingException(aCx);
-        return;
+        return NS_ERROR_OUT_OF_MEMORY;
       }
 
       JS::Rooted<JS::Value> typeError(aCx);
       if (!JS::CreateError(aCx, JSEXN_TYPEERR, JS::NullPtr(), fn, lineNumber, 0,
                            nullptr, message, &typeError)) {
         // Out of memory. Promise will stay unresolved.
         JS_ClearPendingException(aCx);
-        return;
+        return NS_ERROR_OUT_OF_MEMORY;
       }
 
       mNextPromise->RejectInternal(aCx, typeError);
-      return;
+      return NS_OK;
     }
   }
 
   // Otherwise, run resolver's resolve with value.
   if (!JS_WrapValue(aCx, &retValue)) {
     NS_WARNING("Failed to wrap value into the right compartment.");
-    return;
+    return NS_ERROR_FAILURE;
   }
 
   mNextPromise->ResolveInternal(aCx, retValue);
+  return NS_OK;
 }
 
 // NativePromiseCallback
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
                                    PromiseCallback, mHandler)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
@@ -322,31 +325,32 @@ NativePromiseCallback::NativePromiseCall
 {
   MOZ_ASSERT(aHandler);
 }
 
 NativePromiseCallback::~NativePromiseCallback()
 {
 }
 
-void
+nsresult
 NativePromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
 {
   if (mState == Promise::Resolved) {
     mHandler->ResolvedCallback(aCx, aValue);
-    return;
+    return NS_OK;
   }
 
   if (mState == Promise::Rejected) {
     mHandler->RejectedCallback(aCx, aValue);
-    return;
+    return NS_OK;
   }
 
   NS_NOTREACHED("huh?");
+  return NS_ERROR_FAILURE;
 }
 
 /* static */ PromiseCallback*
 PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
                          AnyCallback* aCallback, Task aTask)
 {
   MOZ_ASSERT(aNextPromise);
 
--- a/dom/promise/PromiseCallback.h
+++ b/dom/promise/PromiseCallback.h
@@ -21,18 +21,18 @@ protected:
   virtual ~PromiseCallback();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
 
   PromiseCallback();
 
-  virtual void Call(JSContext* aCx,
-                    JS::Handle<JS::Value> aValue) = 0;
+  virtual nsresult Call(JSContext* aCx,
+                        JS::Handle<JS::Value> aValue) = 0;
 
   // Return the Promise that this callback will end up resolving or
   // rejecting, if any.
   virtual Promise* GetDependentPromise() = 0;
 
   enum Task {
     Resolve,
     Reject
@@ -49,18 +49,18 @@ public:
 // aNextPromise->RejectFunction() if the JS Callback throws.
 class WrapperPromiseCallback final : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback,
                                                          PromiseCallback)
 
-  void Call(JSContext* aCx,
-            JS::Handle<JS::Value> aValue) override;
+  nsresult Call(JSContext* aCx,
+                JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mNextPromise;
   }
 
   WrapperPromiseCallback(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
                          AnyCallback* aCallback);
@@ -77,18 +77,18 @@ private:
 // received by Call().
 class ResolvePromiseCallback final : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback,
                                                          PromiseCallback)
 
-  void Call(JSContext* aCx,
-            JS::Handle<JS::Value> aValue) override;
+  nsresult Call(JSContext* aCx,
+                JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mPromise;
   }
 
   ResolvePromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
 
@@ -103,18 +103,18 @@ private:
 // received by Call().
 class RejectPromiseCallback final : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback,
                                                          PromiseCallback)
 
-  void Call(JSContext* aCx,
-            JS::Handle<JS::Value> aValue) override;
+  nsresult Call(JSContext* aCx,
+                JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mPromise;
   }
 
   RejectPromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
 
@@ -128,18 +128,18 @@ private:
 // NativePromiseCallback wraps a PromiseNativeHandler.
 class NativePromiseCallback final : public PromiseCallback
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
                                            PromiseCallback)
 
-  void Call(JSContext* aCx,
-            JS::Handle<JS::Value> aValue) override;
+  nsresult Call(JSContext* aCx,
+                JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return nullptr;
   }
 
   NativePromiseCallback(PromiseNativeHandler* aHandler,
                         Promise::PromiseState aState);
--- a/dom/quota/moz.build
+++ b/dom/quota/moz.build
@@ -32,17 +32,15 @@ EXPORTS.mozilla.dom.quota += [
 UNIFIED_SOURCES += [
     'FileStreams.cpp',
     'QuotaManager.cpp',
     'QuotaObject.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/caps',
 ]
 
--- a/dom/storage/moz.build
+++ b/dom/storage/moz.build
@@ -19,18 +19,16 @@ UNIFIED_SOURCES += [
 ]
 
 IPDL_SOURCES += [
     'PStorage.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
 if CONFIG['ENABLE_TESTS']:
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -24,18 +24,18 @@ interface nsIDOMCrypto;
 typedef any Transferable;
 
 // http://www.whatwg.org/specs/web-apps/current-work/
 [PrimaryGlobal, NeedResolve]
 /*sealed*/ interface Window : EventTarget {
   // the current browsing context
   [Unforgeable, Constant, StoreInSlot,
    CrossOriginReadable] readonly attribute Window window;
-  [Replaceable, Throws,
-   CrossOriginReadable] readonly attribute WindowProxy self;
+  [Replaceable, Constant, StoreInSlot,
+   CrossOriginReadable] readonly attribute Window self;
   [Unforgeable, StoreInSlot, Pure] readonly attribute Document? document;
   [Throws] attribute DOMString name; 
   [PutForwards=href, Unforgeable, Throws,
    CrossOriginReadable, CrossOriginWritable] readonly attribute Location? location;
   [Throws] readonly attribute History history;
   [Replaceable, Throws] readonly attribute BarProp locationbar;
   [Replaceable, Throws] readonly attribute BarProp menubar;
   [Replaceable, Throws] readonly attribute BarProp personalbar;
--- a/dom/webidl/WorkerGlobalScope.webidl
+++ b/dom/webidl/WorkerGlobalScope.webidl
@@ -9,16 +9,17 @@
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and Opera
  * Software ASA.
  * You are granted a license to use, reproduce and create derivative works of
  * this document.
  */
 
 [Exposed=(Worker)]
 interface WorkerGlobalScope : EventTarget {
+  [Constant, Cached]
   readonly attribute WorkerGlobalScope self;
 
   [Replaceable]
   readonly attribute Console console;
 
   readonly attribute WorkerLocation location;
 
   [Throws]
--- a/dom/workers/WorkerScope.h
+++ b/dom/workers/WorkerScope.h
@@ -75,20 +75,20 @@ public:
   {
     return GetWrapper();
   }
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WorkerGlobalScope,
                                                          DOMEventTargetHelper)
 
-  already_AddRefed<WorkerGlobalScope>
+  WorkerGlobalScope*
   Self()
   {
-    return nsRefPtr<WorkerGlobalScope>(this).forget();
+    return this;
   }
 
   Console*
   GetConsole();
 
   already_AddRefed<WorkerLocation>
   Location();
 
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -86,18 +86,16 @@ UNIFIED_SOURCES += [
 ]
 
 IPDL_SOURCES += [
     'ServiceWorkerRegistrarTypes.ipdlh',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '../base',
     '../system',
     '/dom/base',
     '/xpcom/build',
     '/xpcom/threads',
 ]
 
--- a/dom/workers/test/serviceworkers/mochitest.ini
+++ b/dom/workers/test/serviceworkers/mochitest.ini
@@ -75,17 +75,16 @@ support-files =
   periodic.sjs
   periodic/frame.html
   periodic/register.html
   periodic/unregister.html
 
 [test_unregister.html]
 [test_installation_simple.html]
 [test_fetch_event.html]
-skip-if = os != "linux" # Bug 1136780
 [test_https_fetch.html]
 [test_https_fetch_cloned_response.html]
 [test_match_all.html]
 [test_match_all_advanced.html]
 [test_install_event.html]
 [test_navigator.html]
 [test_scopes.html]
 [test_controller.html]
--- a/dom/xbl/moz.build
+++ b/dom/xbl/moz.build
@@ -33,18 +33,16 @@ UNIFIED_SOURCES += [
     'nsXBLSerialize.cpp',
     'nsXBLService.cpp',
     'nsXBLWindowKeyHandler.cpp',
     'XBLChildrenElement.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
     '/dom/xml',
     '/dom/xul',
     '/layout/style',
 ]
 
--- a/dom/xml/moz.build
+++ b/dom/xml/moz.build
@@ -28,18 +28,16 @@ UNIFIED_SOURCES += [
     'nsXMLPrettyPrinter.cpp',
     'ProcessingInstruction.cpp',
     'XMLDocument.cpp',
     'XMLStylesheetProcessingInstruction.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/base',
     '/dom/html',
     '/dom/xul',
     '/layout/style',
--- a/dom/xul/moz.build
+++ b/dom/xul/moz.build
@@ -37,18 +37,16 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'xul'
 
 UNIFIED_SOURCES += [
     'nsXULControllers.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/dom/html',
     '/dom/xbl',
     '/dom/xml',
     '/dom/xul/templates',
     '/layout/base',
--- a/dom/xul/templates/moz.build
+++ b/dom/xul/templates/moz.build
@@ -41,18 +41,16 @@ UNIFIED_SOURCES += [
     'nsXULTemplateQueryProcessorXML.cpp',
     'nsXULTemplateResultRDF.cpp',
     'nsXULTemplateResultSetRDF.cpp',
     'nsXULTemplateResultStorage.cpp',
     'nsXULTemplateResultXML.cpp',
     'nsXULTreeBuilder.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/xul',
     '/layout/xul/tree/',
 ]
 
 FINAL_LIBRARY = 'xul'
 
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/crashtests/1158452.html
@@ -0,0 +1,10 @@
+
+<div>
+<div>
+aaaaaaa
+</script>
+<script type="text/javascript"> 
+document.designMode = "on"
+window.getSelection().modify("extend", "backward", "line")
+document.execCommand("increasefontsize","",null);
+</script>
new file mode 100644
--- /dev/null
+++ b/editor/libeditor/crashtests/1158651.html
@@ -0,0 +1,18 @@
+<script>
+onload = function() {
+  var testContainer = document.createElement("span");
+  testContainer.contentEditable = true;
+  document.body.appendChild(testContainer);
+
+  function queryFormatBlock(content)
+  {
+    testContainer.innerHTML = content;
+    while (testContainer.firstChild)
+        testContainer = testContainer.firstChild;
+    window.getSelection().collapse(testContainer, 0);
+    document.queryCommandValue('formatBlock');
+  }
+
+  queryFormatBlock('<ol>hello</ol>');
+};
+</script>
--- a/editor/libeditor/crashtests/crashtests.list
+++ b/editor/libeditor/crashtests/crashtests.list
@@ -56,8 +56,10 @@ load 768748.html
 load 768765.html
 needs-focus load 771749.html
 load 772282.html
 load 776323.html
 needs-focus load 793866.html
 load 1057677.html
 needs-focus load 1128787.html
 load 1134545.html
+load 1158452.html
+load 1158651.html
--- a/editor/libeditor/nsHTMLEditRules.cpp
+++ b/editor/libeditor/nsHTMLEditRules.cpp
@@ -6030,16 +6030,17 @@ nsHTMLEditRules::GetParagraphFormatNodes
 
   // Pre-process our list of nodes
   for (int32_t i = outArrayOfNodes.Length() - 1; i >= 0; i--) {
     OwningNonNull<nsINode> testNode = outArrayOfNodes[i];
 
     // Remove all non-editable nodes.  Leave them be.
     if (!mHTMLEditor->IsEditable(testNode)) {
       outArrayOfNodes.RemoveElementAt(i);
+      continue;
     }
 
     // Scan for table elements.  If we find table elements other than table,
     // replace it with a list of any editable non-table content.  Ditto for
     // list elements.
     if (nsHTMLEditUtils::IsTableElement(testNode) ||
         nsHTMLEditUtils::IsList(testNode) ||
         nsHTMLEditUtils::IsListItem(testNode)) {
--- a/editor/libeditor/nsHTMLEditorStyle.cpp
+++ b/editor/libeditor/nsHTMLEditorStyle.cpp
@@ -1497,21 +1497,18 @@ nsHTMLEditor::RelativeFontChange(FontSiz
       // the subtree iterator works - it will not have reported them).
       if (IsTextNode(startNode) && IsEditable(startNode)) {
         res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
             static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
             range->StartOffset(), startNode->Length());
         NS_ENSURE_SUCCESS(res, res);
       }
       if (IsTextNode(endNode) && IsEditable(endNode)) {
-        nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
-        int32_t endOffset;
-        range->GetEndOffset(&endOffset);
         res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
-            static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
+            static_cast<nsIDOMCharacterData*>(endNode->AsDOMNode()),
             0, range->EndOffset());
         NS_ENSURE_SUCCESS(res, res);
       }
     }
   }
 
   return NS_OK;
 }
--- a/editor/libeditor/tests/test_bug1154791.html
+++ b/editor/libeditor/tests/test_bug1154791.html
@@ -31,22 +31,24 @@ SimpleTest.waitForFocus(function() {
   synthesizeKey("VK_LEFT", {});
   synthesizeKey("VK_LEFT", {});
 
   setTimeout(function() {
     synthesizeKey("VK_BACK_SPACE", {});
     setTimeout(function() {
       synthesizeKey(" ", {});
 
-      var sel = getSpellCheckSelection();
-      is(sel.rangeCount, 2, "We should have two misspelled words");
-      is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word");
-      is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word");
+      setTimeout(function() {
+        var sel = getSpellCheckSelection();
+        is(sel.rangeCount, 2, "We should have two misspelled words");
+        is(String(sel.getRangeAt(0)), "thiss", "Correct misspelled word");
+        is(String(sel.getRangeAt(1)), "onee", "Correct misspelled word");
 
-      SimpleTest.finish();
+        SimpleTest.finish();
+      },0);
     },0);
   },0);
 
 });
 
 function getSpellCheckSelection() {
   var Ci = Components.interfaces;
   var editingSession = window.QueryInterface(Ci.nsIInterfaceRequestor)
--- a/extensions/cookie/moz.build
+++ b/extensions/cookie/moz.build
@@ -17,15 +17,13 @@ UNIFIED_SOURCES += [
     'nsCookieModule.cpp',
     'nsCookiePermission.cpp',
     'nsCookiePromptService.cpp',
     'nsPermission.cpp',
     'nsPermissionManager.cpp',
     'nsPopupWindowManager.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -142,18 +142,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
     ]
 
 if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
     SOURCES += ['BlurNEON.cpp']
     SOURCES['BlurNEON.cpp'].flags += ['-mfpu=neon']
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 for var in ('USE_CAIRO', 'MOZ2D_HAS_MOZ_CAIRO'):
     DEFINES[var] = True
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('android', 'gtk2', 'gtk3', 'gonk', 'qt'):
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -122,18 +122,16 @@ DEFINES['EGLAPI'] = ""
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DIRS += [ 'src/libGLESv2', 'src/libEGL' ]
 
 EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ]
 EXPORTS.angle.KHR += [ 'include/KHR/khrplatform.h' ]
 
 LOCAL_INCLUDES += [ 'include', 'src' ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 # This tells ANGLE to build the translator with declspec(dllexport) on Windows
 # which we need to get these symbols exported from gkmedias
 DEFINES['COMPONENT_BUILD'] = True
 DEFINES['ANGLE_TRANSLATOR_IMPLEMENTATION'] = True
 
--- a/gfx/cairo/cairo/src/moz.build
+++ b/gfx/cairo/cairo/src/moz.build
@@ -180,18 +180,16 @@ UNIFIED_SOURCES += [
     'cairo-traps.c',
     'cairo-unicode.c',
     'cairo-user-font.c',
     'cairo-version.c',
     'cairo-wideint.c',
     'cairo.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 
 for var in ('CAIRO_HAS_PTHREAD', '_GNU_SOURCE'):
     DEFINES[var] = True
 
--- a/gfx/cairo/libpixman/src/moz.build
+++ b/gfx/cairo/libpixman/src/moz.build
@@ -53,18 +53,16 @@ SOURCES += [
     'pixman-region32.c',
     'pixman-solid-fill.c',
     'pixman-trap.c',
     'pixman-utils.c',
     'pixman-x86.c',
     'pixman.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     '../../cairo/src',
 ]
 
 if CONFIG['MOZ_USE_PTHREADS']:
     DEFINES['HAVE_PTHREAD_SETSPECIFIC'] = True
 
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -137,18 +137,16 @@ UNIFIED_SOURCES += [
     'SharedSurfaceGL.cpp',
     'SurfaceTypes.cpp',
     'TextureGarbageBin.cpp',
     'TextureImageEGL.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
     DEFINES['MOZ_D3DCOMPILER_VISTA_DLL'] = CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']
 if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
     DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
--- a/gfx/graphite2/src/moz.build
+++ b/gfx/graphite2/src/moz.build
@@ -50,18 +50,16 @@ UNIFIED_SOURCES += [
     'Segment.cpp',
     'Silf.cpp',
     'Slot.cpp',
     'Sparse.cpp',
     'TtfUtil.cpp',
     'UtfCodec.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
     DEFINES['GRAPHITE2_EXPORTING'] = True
 else:
     # tell graphite2 not to export symbols, we'll be linking it directly with
     # thebes
     DEFINES['GRAPHITE2_STATIC'] = True
 
--- a/gfx/harfbuzz/src/moz.build
+++ b/gfx/harfbuzz/src/moz.build
@@ -53,17 +53,15 @@ UNIFIED_SOURCES += [
     'hb-ot-tag.cc',
     'hb-set.cc',
     'hb-shape.cc',
     'hb-shaper.cc',
     'hb-unicode.cc',
     'hb-warning.cc',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 DEFINES['HAVE_OT'] = 1
 DEFINES['HB_NO_MT'] = True
 DEFINES['HB_NO_UNICODE_FUNCS'] = True
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2342,29 +2342,24 @@ CalculateDisplayPortSize(const CSSSize& 
  * Attempts to redistribute any area in the displayport that would get clipped
  * by the scrollable rect, or be inaccessible due to disabled scrolling, to the
  * other axis, while maintaining total displayport area.
  */
 static void
 RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize,
                               const CSSRect& aScrollableRect)
 {
-  float xSlack = std::max(0.0f, aDisplayPortSize.width - aScrollableRect.width);
-  float ySlack = std::max(0.0f, aDisplayPortSize.height - aScrollableRect.height);
-
-  if (ySlack > 0) {
-    // Reassign wasted y-axis displayport to the x-axis
-    aDisplayPortSize.height -= ySlack;
-    float xExtra = ySlack * aDisplayPortSize.width / aDisplayPortSize.height;
-    aDisplayPortSize.width += xExtra;
-  } else if (xSlack > 0) {
-    // Reassign wasted x-axis displayport to the y-axis
-    aDisplayPortSize.width -= xSlack;
-    float yExtra = xSlack * aDisplayPortSize.height / aDisplayPortSize.width;
-    aDisplayPortSize.height += yExtra;
+  // As aDisplayPortSize.height * aDisplayPortSize.width does not change,
+  // we are just scaling by the ratio and its inverse.
+  if (aDisplayPortSize.height > aScrollableRect.height) {
+    aDisplayPortSize.width *= (aDisplayPortSize.height / aScrollableRect.height);
+    aDisplayPortSize.height = aScrollableRect.height;
+  } else if (aDisplayPortSize.width > aScrollableRect.width) {
+    aDisplayPortSize.height *= (aDisplayPortSize.width / aScrollableRect.width);
+    aDisplayPortSize.width = aScrollableRect.width;
   }
 }
 
 /* static */
 const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
   const FrameMetrics& aFrameMetrics,
   const ParentLayerPoint& aVelocity,
   double aEstimatedPaintDuration)
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -359,18 +359,16 @@ IPDL_SOURCES = [
     'ipc/PLayer.ipdl',
     'ipc/PLayerTransaction.ipdl',
     'ipc/PSharedBufferManager.ipdl',
     'ipc/PTexture.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/docshell/base',  # for nsDocShell.h
     '/layout/base',    # for TouchManager.h
 ]
 
 FINAL_LIBRARY = 'xul'
--- a/gfx/ots/src/moz.build
+++ b/gfx/ots/src/moz.build
@@ -42,18 +42,16 @@ UNIFIED_SOURCES += [
     'ots.cc',
     'post.cc',
     'prep.cc',
     'vhea.cc',
     'vmtx.cc',
     'woff2.cc',
 ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['PACKAGE_VERSION'] = '"moz"'
 DEFINES['PACKAGE_BUGREPORT'] = '"http://bugzilla.mozilla.org/"'
 DEFINES['NOMINMAX'] = True
--- a/gfx/qcms/moz.build
+++ b/gfx/qcms/moz.build
@@ -12,18 +12,16 @@ EXPORTS += [
 SOURCES += [
     'chain.c',
     'iccread.c',
     'matrix.c',
     'transform.c',
     'transform_util.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 if CONFIG['GNU_CC']:
     CFLAGS += ['-Wno-missing-field-initializers']
 
 use_sse1 = False
 use_sse2 = False
 use_altivec = False
--- a/gfx/skia/generate_mozbuild.py
+++ b/gfx/skia/generate_mozbuild.py
@@ -43,18 +43,16 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONF
         SOURCES += [
             'trunk/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
         ]
     else:
         SOURCES += [
             'trunk/src/opts/SkBlitRow_opts_SSE4_asm.S',
         ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
     'trunk/include/pathops',
--- a/gfx/skia/moz.build
+++ b/gfx/skia/moz.build
@@ -875,18 +875,16 @@ if CONFIG['INTEL_ARCHITECTURE'] and CONF
         SOURCES += [
             'trunk/src/opts/SkBlitRow_opts_SSE4_x64_asm.S',
         ]
     else:
         SOURCES += [
             'trunk/src/opts/SkBlitRow_opts_SSE4_asm.S',
         ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 LOCAL_INCLUDES += [
     'trunk/include/config',
     'trunk/include/core',
     'trunk/include/effects',
     'trunk/include/gpu',
     'trunk/include/images',
     'trunk/include/pathops',
--- a/gfx/src/moz.build
+++ b/gfx/src/moz.build
@@ -66,18 +66,16 @@ UNIFIED_SOURCES += [
 
 # nsDeviceContext.cpp cannot be built in unified mode because it pulls in OS X system headers.
 SOURCES += [
     'nsDeviceContext.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 
 if CONFIG['MOZ_WIDGET_GTK']:
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -1755,16 +1755,32 @@ gfxPlatform::GetBackendPref(const char* 
         }
     }
 
     aBackendBitmask = allowedBackends;
     return result;
 }
 
 bool
+gfxPlatform::InSafeMode()
+{
+  static bool sSafeModeInitialized = false;
+  static bool sInSafeMode = false;
+
+  if (!sSafeModeInitialized) {
+    sSafeModeInitialized = true;
+    nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
+    if (xr) {
+      xr->GetInSafeMode(&sInSafeMode);
+    }
+  }
+  return sInSafeMode;
+}
+
+bool
 gfxPlatform::OffMainThreadCompositingEnabled()
 {
   return UsesOffMainThreadCompositing();
 }
 
 eCMSMode
 gfxPlatform::GetCMSMode()
 {
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -486,16 +486,19 @@ public:
     // these are *possible* matches, no cmap-checking is done at this level
     virtual void GetCommonFallbackFonts(uint32_t /*aCh*/, uint32_t /*aNextCh*/,
                                         int32_t /*aRunScript*/,
                                         nsTArray<const char*>& /*aFontList*/)
     {
         // platform-specific override, by default do nothing
     }
 
+    // Are we in safe mode?
+    static bool InSafeMode();
+
     static bool OffMainThreadCompositingEnabled();
 
     static bool CanUseDirect3D9();
     static bool CanUseDirect3D11();
     static bool CanUseHardwareVideoDecoding();
     static bool CanUseDirect3D11ANGLE();
 
     /**
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -489,21 +489,16 @@ gfxWindowsPlatform::UpdateRenderMode()
 
       didReset = true;
     }
 
     mRenderMode = RENDER_GDI;
 
     bool isVistaOrHigher = IsVistaOrLater();
 
-    bool safeMode = false;
-    nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
-    if (xr)
-      xr->GetInSafeMode(&safeMode);
-
     mUseDirectWrite = Preferences::GetBool("gfx.font_rendering.directwrite.enabled", false);
 
 #ifdef CAIRO_HAS_D2D_SURFACE
     bool d2dDisabled = false;
     bool d2dForceEnabled = false;
     bool d2dBlocked = false;
 
     nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
@@ -530,17 +525,17 @@ gfxWindowsPlatform::UpdateRenderMode()
 
     // Do not ever try if d2d is explicitly disabled,
     // or if we're not using DWrite fonts.
     if (d2dDisabled || mUsingGDIFonts) {
         tryD2D = false;
     }
 
     ID3D11Device *device = GetD3D11Device();
-    if (isVistaOrHigher && !safeMode && tryD2D &&
+    if (isVistaOrHigher && !InSafeMode() && tryD2D &&
         device &&
         device->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 &&
         DoesD3D11TextureSharingWork(device)) {
 
         VerifyD2DDevice(d2dForceEnabled);
         if (mD2DDevice && GetD3D11Device()) {
             mRenderMode = RENDER_DIRECT2D;
             mUseDirectWrite = true;
@@ -1864,35 +1859,30 @@ gfxWindowsPlatform::InitD3D11Devices()
   // blacklisted, then this function will abort if WARP is disabled, causing us
   // to fallback to D3D9 or Basic layers. If WARP is not disabled it will use
   // a WARP device which should always be available on Windows 7 and higher.
 
   mD3D11DeviceInitialized = true;
 
   MOZ_ASSERT(!mD3D11Device); 
 
-  bool safeMode = false;
-  nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
-  if (xr) {
-    xr->GetInSafeMode(&safeMode);
-  }
-
-  if (safeMode) {
+  if (InSafeMode()) {
     return;
   }
 
   bool useWARP = false;
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     int32_t status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DIRECT3D_11_LAYERS, &status))) {
       if (status != nsIGfxInfo::FEATURE_STATUS_OK) {
 
-        if (gfxPrefs::LayersD3D11DisableWARP()) {
+        // It seems like nvdxgiwrapper makes a mess of WARP. See bug 1154703 for more.
+        if (gfxPrefs::LayersD3D11DisableWARP() || GetModuleHandleA("nvdxgiwrapper.dll")) {
           return;
         }
 
         useWARP = true;
       }
     }
   }
 
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -250,18 +250,16 @@ UNIFIED_SOURCES += [
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     UNIFIED_SOURCES += [
         'gfxMacPlatformFontList.mm',
     ]
 
 FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'DeprecatedPremultiplyTables.h',
 ]
 
--- a/gfx/vr/moz.build
+++ b/gfx/vr/moz.build
@@ -20,14 +20,12 @@ UNIFIED_SOURCES += [
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CXXFLAGS += CONFIG['TK_CFLAGS']
 CFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 CFLAGS += CONFIG['TK_CFLAGS']
 
 FAIL_ON_WARNINGS = not CONFIG['_MSC_VER']
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
--- a/intl/hyphenation/moz.build
+++ b/intl/hyphenation/moz.build
@@ -15,18 +15,16 @@ UNIFIED_SOURCES += [
 ]
 
 # These files cannot be built in unified mode because they include hnjalloc.h.
 SOURCES += [
     'hnjstdio.cpp',
     'hyphen.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CC']:
     CFLAGS += [
         '-Wno-sign-compare',
         '-Wno-type-limits',
     ]
--- a/intl/locale/moz.build
+++ b/intl/locale/moz.build
@@ -43,18 +43,16 @@ UNIFIED_SOURCES += [
     'nsScriptableDateFormat.cpp',
     'nsUConvPropertySearch.cpp',
 ]
 
 EXTRA_JS_MODULES += [
     'PluralForm.jsm',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/intl/uconv',
 ]
 
 RESOURCE_FILES += [
     'langGroups.properties',
--- a/intl/lwbrk/moz.build
+++ b/intl/lwbrk/moz.build
@@ -39,16 +39,14 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
 else:
     SOURCES += [
         'nsRuleBreaker.cpp',
     ]
     SOURCES += [
         'rulebrk.c',
     ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_WIDGET_GTK']:
     CXXFLAGS += CONFIG['MOZ_PANGO_CFLAGS']
 
 FAIL_ON_WARNINGS = True
--- a/intl/strres/moz.build
+++ b/intl/strres/moz.build
@@ -13,13 +13,11 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'intl'
 
 UNIFIED_SOURCES += [
     'nsStringBundle.cpp',
     'nsStringBundleTextOverride.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
--- a/intl/uconv/moz.build
+++ b/intl/uconv/moz.build
@@ -152,18 +152,16 @@ UNIFIED_SOURCES += [
     'util/umap.c',
     'util/uscan.c',
 ]
 
 if CONFIG['INTEL_ARCHITECTURE']:
     SOURCES += ['nsUTF8ToUnicodeSSE2.cpp']
     SOURCES['nsUTF8ToUnicodeSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
 
-MSVC_ENABLE_PGO = True
-
 LOCAL_INCLUDES += [
     'ucvcn',
     'ucvja',
     'ucvko',
     'ucvlatin',
     'ucvtw',
     'util',
 ]
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -1261,18 +1261,19 @@ MessageChannel::DispatchInterruptMessage
     // Race detection: see the long comment near mRemoteStackDepthGuess in
     // MessageChannel.h. "Remote" stack depth means our side, and "local" means
     // the other side.
     if (aMsg.interrupt_remote_stack_depth_guess() != RemoteViewOfStackDepth(stackDepth)) {
         // Interrupt in-calls have raced. The winner, if there is one, gets to defer
         // processing of the other side's in-call.
         bool defer;
         const char* winner;
-        switch (mListener->MediateInterruptRace((mSide == ChildSide) ? aMsg : mInterruptStack.top(),
-                                          (mSide != ChildSide) ? mInterruptStack.top() : aMsg))
+        const Message& parentMsg = (mSide == ChildSide) ? aMsg : mInterruptStack.top();
+        const Message& childMsg = (mSide == ChildSide) ? mInterruptStack.top() : aMsg;
+        switch (mListener->MediateInterruptRace(parentMsg, childMsg))
         {
           case RIPChildWins:
             winner = "child";
             defer = (mSide == ChildSide);
             break;
           case RIPParentWins:
             winner = "parent";
             defer = (mSide != ChildSide);
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -18,20 +18,16 @@
 #include "nsDebug.h"
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 #include "nsThreadUtils.h"
 #include "nsTimerImpl.h"
 #include "nsXULAppAPI.h"
 #include "prthread.h"
 
-#ifdef MOZ_WIDGET_ANDROID
-#include "AndroidBridge.h"
-#endif
-
 #ifdef MOZ_NUWA_PROCESS
 #include "ipc/Nuwa.h"
 #endif
 
 using base::TimeTicks;
 using namespace mozilla::ipc;
 
 NS_DEFINE_NAMED_CID(NS_TIMER_CID);
@@ -100,25 +96,16 @@ MessagePump::Run(MessagePump::Delegate* 
     if (!keep_running_)
       break;
 
     // NB: it is crucial *not* to directly call |aDelegate->DoWork()|
     // here.  To ensure that MessageLoop tasks and XPCOM events have
     // equal priority, we sensitively rely on processing exactly one
     // Task per DoWorkRunnable XPCOM event.
 
-#ifdef MOZ_WIDGET_ANDROID
-    // This processes messages in the Android Looper. Note that we only
-    // get here if the normal Gecko event loop has been awoken above.
-    // Bug 750713
-    if (MOZ_LIKELY(AndroidBridge::HasEnv())) {
-        did_work |= mozilla::widget::GeckoAppShell::PumpMessageLoop();
-    }
-#endif
-
     did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
 
 if (did_work && delayed_work_time_.is_null()
 #ifdef MOZ_NUWA_PROCESS
     && (!IsNuwaReady() || !IsNuwaProcess())
 #endif
    )
       mDelayedWorkTimer->Cancel();
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -4967,17 +4967,16 @@ class _GenerateProtocolActorCode(ipdl.as
         return helper
 
 
     def genAsyncDtor(self, md):
         actor = md.actorDecl()
         actorvar = actor.var()
         method = MethodDefn(self.makeDtorMethodDecl(md))
 
-        method.addstmts(self.dtorPrologue(actor.var()))
         method.addstmts(self.dtorPrologue(actorvar))
 
         msgvar, stmts = self.makeMessage(md, errfnSendDtor, actorvar)
         sendok, sendstmts = self.sendAsync(md, msgvar, actorvar)
         method.addstmts(
             stmts
             + sendstmts
             + [ Whitespace.NL ]
--- a/js/public/Class.h
+++ b/js/public/Class.h
@@ -608,17 +608,17 @@ struct JSClass {
 //
 // Implementing this efficiently requires that global objects have classes
 // with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
 // previously allowed, but is now an ES5 violation and thus unsupported.
 //
 // JSCLASS_GLOBAL_APPLICATION_SLOTS is the number of slots reserved at
 // the beginning of every global object's slots for use by the
 // application.
-#define JSCLASS_GLOBAL_APPLICATION_SLOTS 4
+#define JSCLASS_GLOBAL_APPLICATION_SLOTS 5
 #define JSCLASS_GLOBAL_SLOT_COUNT      (JSCLASS_GLOBAL_APPLICATION_SLOTS + JSProto_LIMIT * 3 + 31)
 #define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n)                                    \
     (JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
 #define JSCLASS_GLOBAL_FLAGS                                                  \
     JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(0)
 #define JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(clasp)                              \
   (((clasp)->flags & JSCLASS_IS_GLOBAL)                                       \
    && JSCLASS_RESERVED_SLOTS(clasp) >= JSCLASS_GLOBAL_SLOT_COUNT)
--- a/js/public/UbiNode.h
+++ b/js/public/UbiNode.h
@@ -8,16 +8,17 @@
 #define js_UbiNode_h
 
 #include "mozilla/Alignment.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
+#include "mozilla/UniquePtr.h"
 
 #include "jspubtd.h"
 
 #include "js/GCAPI.h"
 #include "js/HashTable.h"
 #include "js/TracingAPI.h"
 #include "js/TypeDecls.h"
 #include "js/Vector.h"
@@ -137,16 +138,17 @@
 // If this restriction prevents us from implementing interesting tools, we may
 // teach the GC how to root ubi::Nodes, fix up hash tables that use them as
 // keys, etc.
 
 namespace JS {
 namespace ubi {
 
 using mozilla::Maybe;
+using mozilla::UniquePtr;
 
 class Edge;
 class EdgeRange;
 
 // The base class implemented by each ubi::Node referent type. Subclasses must
 // not add data members to this class.
 class Base {
     friend class Node;
@@ -201,21 +203,36 @@ class Base {
     virtual JS::Zone* zone() const { return nullptr; }
 
     // Return the compartment for this node. Some ubi::Node referents are not
     // associated with JSCompartments, such as JSStrings (which are associated
     // with Zones). When the referent is not associated with a compartment,
     // nullptr is returned.
     virtual JSCompartment* compartment() const { return nullptr; }
 
-    // If this node references a JSObject in the live heap, or represents a
-    // previously existing JSObject from some deserialized heap snapshot, return
-    // the object's [[Class]]'s name. Otherwise, return nullptr.
+    // Methods for JSObject Referents
+    //
+    // These methods are only semantically valid if the referent is either a
+    // JSObject in the live heap, or represents a previously existing JSObject
+    // from some deserialized heap snapshot.
+
+    // Return the object's [[Class]]'s name.
     virtual const char* jsObjectClassName() const { return nullptr; }
 
+    // If this object was constructed with `new` and we have the data available,
+    // place the contructor function's display name in the out parameter.
+    // Otherwise, place nullptr in the out parameter. Caller maintains ownership
+    // of the out parameter. True is returned on success, false is returned on
+    // OOM.
+    virtual bool jsObjectConstructorName(JSContext* cx,
+                                         UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+        outName.reset(nullptr);
+        return true;
+    }
+
   private:
     Base(const Base& rhs) = delete;
     Base& operator=(const Base& rhs) = delete;
 };
 
 // A traits template with a specialization for each referent type that
 // ubi::Node supports. The specialization must be the concrete subclass of
 // Base that represents a pointer to the referent type. It must also
@@ -331,16 +348,20 @@ class Node {
     // Otherwise return UndefinedValue(). JSStrings, JS::Symbols, and some (but
     // not all!) JSObjects can be exposed.
     JS::Value exposeToJS() const;
 
     const char16_t* typeName()      const { return base()->typeName(); }
     JS::Zone* zone()                const { return base()->zone(); }
     JSCompartment* compartment()    const { return base()->compartment(); }
     const char* jsObjectClassName() const { return base()->jsObjectClassName(); }
+    bool jsObjectConstructorName(JSContext* cx,
+                                 UniquePtr<char16_t[], JS::FreePolicy>& outName) const {
+        return base()->jsObjectConstructorName(cx, outName);
+    }
 
     size_t size(mozilla::MallocSizeOf mallocSizeof) const {
         return base()->size(mallocSizeof);
     }
 
     EdgeRange* edges(JSContext* cx, bool wantNames = true) const {
         return base()->edges(cx, wantNames);
     }
@@ -569,16 +590,18 @@ class TracerConcreteWithCompartment : pu
 // These can use the generic templates above.
 template<> struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { };
 template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> { };
 
 // The JSObject specialization.
 template<>
 class Concrete<JSObject> : public TracerConcreteWithCompartment<JSObject> {
     const char* jsObjectClassName() const override;
+    bool jsObjectConstructorName(JSContext* cx,
+                                 UniquePtr<char16_t[], JS::FreePolicy>& outName) const override;
     size_t size(mozilla::MallocSizeOf mallocSizeOf) const override;
 
   protected:
     explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
 
   public:
     static void construct(void* storage, JSObject* ptr) {
         new (storage) Concrete(ptr);
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2549,16 +2549,42 @@ SetDiscardSource(JSContext* cx, unsigned
 
     bool discard = !args.hasDefined(0) || ToBoolean(args[0]);
     JS::CompartmentOptionsRef(cx->compartment()).setDiscardSource(discard);
 
     args.rval().setUndefined();
     return true;
 }
 
+static bool
+GetConstructorName(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!args.requireAtLeast(cx, "getConstructorName", 1))
+        return false;
+
+    if (!args[0].isObject()) {
+        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_NOT_EXPECTED_TYPE,
+                             "getConstructorName", "Object",
+                             InformalValueTypeName(args[0]));
+        return false;
+    }
+
+    RootedAtom name(cx);
+    if (!args[0].toObject().constructorDisplayAtom(cx, &name))
+        return false;
+
+    if (name) {
+        args.rval().setString(name);
+    } else {
+        args.rval().setNull();
+    }
+    return true;
+}
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc.\n"
 "  If 'shrinking' is passed as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
@@ -2955,16 +2981,21 @@ gc::ZealModeHelpText),
 "  Explicitly disable lazy parsing in the current compartment.  The default is that lazy "
 "  parsing is not explicitly disabled."),
 
     JS_FN_HELP("setDiscardSource", SetDiscardSource, 1, 0,
 "setDiscardSource(bool)",
 "  Explicitly enable source discarding in the current compartment.  The default is that "
 "  source discarding is not explicitly enabled."),
 
+    JS_FN_HELP("getConstructorName", GetConstructorName, 1, 0,
+"getConstructorName(object)",
+"  If the given object was created with `new Ctor`, return the constructor's display name. "
+"  Otherwise, return null."),
+
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
--- a/js/src/devtools/automation/autospider.sh
+++ b/js/src/devtools/automation/autospider.sh
@@ -7,17 +7,17 @@ ABSDIR="$(cd $DIR; pwd)"
 SOURCE="$(cd $DIR/../../../..; pwd)"
 
 function usage() {
   echo "Usage: $0 [--dep] <variant>"
 }
 
 clean=1
 platform=""
-TIMEOUT=7200
+TIMEOUT=3h
 while [ $# -gt 1 ]; do
     case "$1" in
         --dep)
             shift
             clean=""
             ;;
         --platform)
             shift
--- a/js/src/doc/Debugger/Debugger.Memory.md
+++ b/js/src/doc/Debugger/Debugger.Memory.md
@@ -194,25 +194,36 @@ Function Properties of the `Debugger.Mem
     method effectively clears the log.
 
     Objects in the array are of the form:
 
     <pre class='language-js'><code>
     {
       "timestamp": <i>timestamp</i>,
       "frame": <i>allocationSite</i>,
-      "class": <i>className</i>
+      "class": <i>className</i>,
+      "constructor": <i>constructorName</i>
     }
     </code></pre>
 
-    Here <i>timestamp</i> is the [timestamp][timestamps] of the allocation
-    event, <i>allocationSite</i> is an allocation site (as a
-    [captured stack][saved-frame]), and <i>className</i> is the string name of
-    the allocated object's internal `[[Class]]` property.  <i>allocationSite</i>
-    is `null` for objects allocated with no JavaScript frames on the stack.
+    Where
+
+    * *timestamp* is the [timestamp][timestamps] of the allocation event.
+
+    * *allocationSite* is an allocation site (as a
+      [captured stack][saved-frame]). Note that this property can be null if the
+      object was allocated with no JavaScript frames on the stack.
+
+    * *className* is the string name of the allocated object's internal
+    `[[Class]]` property, for example "Array", "Date", "RegExp", or (most
+    commonly) "Object".
+
+    * *constructorName* is the constructor function's display name for objects
+      created by `new Ctor`. If that data is not available, or the object was
+      not created with a `new` expression, this property is `null`.
 
     When `trackingAllocationSites` is `false`, `drainAllocationsLog()` throws an
     `Error`.
 
 <code id='take-census'>takeCensus()</code>
 :   Carry out a census of the debuggee compartments' contents. A *census* is a
     complete traversal of the graph of all reachable memory items belonging to a
     particular `Debugger`'s debuggees. The census produces a count of those
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -33,16 +33,79 @@
 using namespace js;
 using namespace js::gc;
 
 using mozilla::DebugOnly;
 using mozilla::IsBaseOf;
 using mozilla::IsSame;
 using mozilla::MakeRange;
 
+// Tracing Overview
+// ================
+//
+// Tracing, in this context, refers to an abstract visitation of some or all of
+// the GC-controlled heap. The effect of tracing an edge of the graph depends
+// on the subclass of the JSTracer on whose behalf we are tracing.
+//
+// Marking
+// -------
+//
+// The primary JSTracer is the GCMarker. The marking tracer causes the target
+// of each traversed edge to be marked black and the target edge's children to
+// be marked either gray (in the gc algorithm sense) or immediately black.
+//
+// Callback
+// --------
+//
+// The secondary JSTracer is the CallbackTracer. This simply invokes a callback
+// on each edge in a child.
+//
+// The following is a rough outline of the general struture of the tracing
+// internals.
+//
+//                                                                                              //
+//   .---------.    .---------.    .--------------------------.       .----------.              //
+//   |TraceEdge|    |TraceRoot|    |TraceManuallyBarrieredEdge|  ...  |TraceRange|   ... etc.   //
+//   '---------'    '---------'    '--------------------------'       '----------'              //
+//        \              \                        /                        /                    //
+//         \              \  .----------------.  /                        /                     //
+//          o------------->o-|DispatchToTracer|-o<-----------------------o                      //
+//                           '----------------'                                                 //
+//                              /          \                                                    //
+//                             /            \                                                   //
+//                       .---------.   .----------.         .-----------------.                 //
+//                       |DoMarking|   |DoCallback|-------> |<JSTraceCallback>|----------->     //
+//                       '---------'   '----------'         '-----------------'                 //
+//                            |                                                                 //
+//                            |                                                                 //
+//                        .--------.                                                            //
+//      o---------------->|traverse| .                                                          //
+//     /_\                '--------'   ' .                                                      //
+//      |                     .     .      ' .                                                  //
+//      |                     .       .        ' .                                              //
+//      |                     .         .          ' .                                          //
+//      |             .-----------.    .-----------.   ' .     .--------------------.           //
+//      |             |markAndScan|    |markAndPush|       ' - |markAndTraceChildren|---->      //
+//      |             '-----------'    '-----------'           '--------------------'           //
+//      |                   |                  \                                                //
+//      |                   |                   \                                               //
+//      |       .----------------------.     .----------------.                                 //
+//      |       |T::eagerlyMarkChildren|     |pushMarkStackTop|<===Oo                           //
+//      |       '----------------------'     '----------------'    ||                           //
+//      |                  |                         ||            ||                           //
+//      |                  |                         ||            ||                           //
+//      |                  |                         ||            ||                           //
+//      o<-----------------o<========================OO============Oo                           //
+//                                                                                              //
+//                                                                                              //
+//   Legend:                                                                                    //
+//     ------  Direct calls                                                                     //
+//     . . .   Static dispatch                                                                  //
+//     ======  Dispatch through a manual stack.                                                 //
+//                                                                                              //
 void * const js::NullPtr::constNullValue = nullptr;
 
 JS_PUBLIC_DATA(void * const) JS::NullPtr::constNullValue = nullptr;
 
 #if defined(DEBUG)
 template<typename T>
 static inline bool
 IsThingPoisoned(T* thing)
@@ -67,23 +130,16 @@ IsThingPoisoned(T* thing)
         const uint32_t pw = pb | (pb << 8) | (pb << 16) | (pb << 24);
         if (*p == pw)
             return true;
     }
     return false;
 }
 #endif
 
-static GCMarker*
-AsGCMarker(JSTracer* trc)
-{
-    MOZ_ASSERT(trc->isMarkingTracer());
-    return static_cast<GCMarker*>(trc);
-}
-
 template <typename T> bool ThingIsPermanentAtomOrWellKnownSymbol(T* thing) { return false; }
 template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSString>(JSString* str) {
     return str->isPermanentAtom();
 }
 template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSFlatString>(JSFlatString* str) {
     return str->isPermanentAtom();
 }
 template <> bool ThingIsPermanentAtomOrWellKnownSymbol<JSLinearString>(JSLinearString* str) {
@@ -188,16 +244,66 @@ CheckTracedThing<jsid>(JSTracer* trc, js
 }
 
 #define IMPL_CHECK_TRACED_THING(_, type, __) \
     template void CheckTracedThing<type*>(JSTracer*, type*);
 FOR_EACH_GC_LAYOUT(IMPL_CHECK_TRACED_THING);
 #undef IMPL_CHECK_TRACED_THING
 } // namespace js
 
+static bool
+ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell)
+{
+    if (!trc->isMarkingTracer())
+        return true;
+
+    uint32_t color = static_cast<GCMarker*>(trc)->markColor();
+    MOZ_ASSERT(color == BLACK || color == GRAY);
+
+    if (!cell->isTenured()) {
+        MOZ_ASSERT(color == BLACK);
+        return false;
+    }
+    TenuredCell& tenured = cell->asTenured();
+
+    JS::Zone* zone = tenured.zone();
+    if (color == BLACK) {
+        /*
+         * Having black->gray edges violates our promise to the cycle
+         * collector. This can happen if we're collecting a compartment and it
+         * has an edge to an uncollected compartment: it's possible that the
+         * source and destination of the cross-compartment edge should be gray,
+         * but the source was marked black by the conservative scanner.
+         */
+        if (tenured.isMarked(GRAY)) {
+            MOZ_ASSERT(!zone->isCollecting());
+            trc->runtime()->gc.setFoundBlackGrayEdges();
+        }
+        return zone->isGCMarking();
+    } else {
+        if (zone->isGCMarkingBlack()) {
+            /*
+             * The destination compartment is being not being marked gray now,
+             * but it will be later, so record the cell so it can be marked gray
+             * at the appropriate time.
+             */
+            if (!tenured.isMarked())
+                DelayCrossCompartmentGrayMarking(src);
+            return false;
+        }
+        return zone->isGCMarkingGray();
+    }
+}
+
+static bool
+ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val)
+{
+    return val.isMarkable() && ShouldMarkCrossCompartment(trc, src, (Cell*)val.toGCThing());
+}
+
 #define JS_ROOT_MARKING_ASSERT(trc) \
     MOZ_ASSERT_IF(trc->isMarkingTracer(), \
                   trc->runtime()->gc.state() == NO_INCREMENTAL || \
                   trc->runtime()->gc.state() == MARK_ROOTS);
 
 // A C++ version of JSGCTraceKind
 enum class TraceKind {
 #define NAMES(name, _, __) name,
@@ -281,18 +387,16 @@ typename PtrBaseGCType<T>::type*
 ConvertToBase(T* thingp)
 {
     return reinterpret_cast<typename PtrBaseGCType<T>::type*>(thingp);
 }
 
 template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name);
 template <typename T> T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name);
 template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
-static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell);
-static bool ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val);
 
 template <typename T>
 void
 js::TraceEdge(JSTracer* trc, BarrieredBase<T>* thingp, const char* name)
 {
     DispatchToTracer(trc, ConvertToBase(thingp->unsafeGet()), name);
 }
 
@@ -485,30 +589,33 @@ DoMarking<Value>(GCMarker* gcmarker, Val
 
 template <>
 void
 DoMarking<jsid>(GCMarker* gcmarker, jsid id)
 {
     DispatchIdTyped(DoMarkingFunctor<jsid>(), id, gcmarker);
 }
 
-// The default traversal calls out to the fully generic traceChildren function
-// to visit the child edges. In the absense of other traversal mechanisms, this
+// The simplest traversal calls out to the fully generic traceChildren function
+// to visit the child edges. In the absence of other traversal mechanisms, this
 // function will rapidly grow the stack past its bounds and crash the process.
 // Thus, this generic tracing should only be used in cases where subsequent
 // tracing will not recurse.
 template <typename T>
 void
-js::GCMarker::traverse(T* thing)
+js::GCMarker::markAndTraceChildren(T* thing)
 {
-    auto asBase = static_cast<typename BaseGCType<T>::type*>(thing);
-    MOZ_ASSERT(!ThingIsPermanentAtomOrWellKnownSymbol(asBase));
-    if (mark(asBase))
+    MOZ_ASSERT(!ThingIsPermanentAtomOrWellKnownSymbol(thing));
+    if (mark(thing))
         thing->traceChildren(this);
 }
+namespace js {
+template <> void GCMarker::traverse(LazyScript* thing) { markAndTraceChildren(thing); }
+template <> void GCMarker::traverse(JSScript* thing) { markAndTraceChildren(thing); }
+} // namespace js
 
 // Shape, BaseShape, String, and Symbol are extremely common, but have simple
 // patterns of recursion. We traverse trees of these edges immediately, with
 // aggressive, manual inlining, implemented by eagerlyTraceChildren.
 template <typename T>
 void
 js::GCMarker::markAndScan(T* thing)
 {
@@ -536,28 +643,91 @@ js::GCMarker::markAndPush(StackTag tag, 
         pushTaggedPtr(tag, thing);
 }
 namespace js {
 template <> void GCMarker::traverse(JSObject* thing) { markAndPush(ObjectTag, thing); }
 template <> void GCMarker::traverse(ObjectGroup* thing) { markAndPush(GroupTag, thing); }
 template <> void GCMarker::traverse(jit::JitCode* thing) { markAndPush(JitCodeTag, thing); }
 } // namespace js
 
+namespace js {
+template <>
+void
+GCMarker::traverse(AccessorShape* thing) {
+    MOZ_CRASH("AccessorShape must be marked as a Shape");
+}
+} // namespace js
+
+template <typename S, typename T>
+void
+js::GCMarker::traverse(S source, T target)
+{
+    MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(target),
+                  runtime()->isAtomsZone(target->zone()) || target->zone() == source->zone());
+    traverse(target);
+}
+
+template <typename V, typename S> struct TraverseFunctor : public VoidDefaultAdaptor<V> {
+    template <typename T> void operator()(T t, GCMarker* gcmarker, S s) {
+        return gcmarker->traverse(s, t);
+    }
+};
+
+template <typename S>
+void
+js::GCMarker::traverse(S source, jsid id)
+{
+    DispatchIdTyped(TraverseFunctor<jsid, S>(), id, this, source);
+}
+
 template <typename T>
 bool
 js::GCMarker::mark(T* thing)
 {
     CheckTracedThing(this, thing);
     JS_COMPARTMENT_ASSERT(runtime(), thing);
     MOZ_ASSERT(!IsInsideNursery(gc::TenuredCell::fromPointer(thing)));
     return gc::ParticipatesInCC<T>::value
            ? gc::TenuredCell::fromPointer(thing)->markIfUnmarked(markColor())
            : gc::TenuredCell::fromPointer(thing)->markIfUnmarked(gc::BLACK);
 }
 
+inline void
+Shape::traceChildren(JSTracer* trc)
+{
+    TraceEdge(trc, &base_, "base");
+    TraceEdge(trc, &propidRef(), "propid");
+    if (parent)
+        TraceEdge(trc, &parent, "parent");
+
+    if (hasGetterObject())
+        TraceManuallyBarrieredEdge(trc, &asAccessorShape().getterObj, "getter");
+    if (hasSetterObject())
+        TraceManuallyBarrieredEdge(trc, &asAccessorShape().setterObj, "setter");
+}
+inline void
+js::GCMarker::eagerlyMarkChildren(Shape* shape)
+{
+    MOZ_ASSERT(shape->isMarked(this->markColor()));
+    do {
+        traverse(shape, shape->base());
+        traverse(shape, shape->propidRef().get());
+
+        // When triggered between slices on belhalf of a barrier, these
+        // objects may reside in the nursery, so require an extra check.
+        // FIXME: Bug 1157967 - remove the isTenured checks.
+        if (shape->hasGetterObject() && shape->getterObject()->isTenured())
+            traverse(shape, shape->getterObject());
+        if (shape->hasSetterObject() && shape->setterObject()->isTenured())
+            traverse(shape, shape->setterObject());
+
+        shape = shape->previous();
+    } while (shape && mark(shape));
+}
+
 template <typename T>
 static inline void
 CheckIsMarkedThing(T* thingp)
 {
 #define IS_SAME_TYPE_OR(name, type, _) mozilla::IsSame<type*, T>::value ||
     static_assert(
             FOR_EACH_GC_LAYOUT(IS_SAME_TYPE_OR)
             false, "Only the base cell layout types are allowed into marking/tracing internals");
@@ -828,66 +998,16 @@ gc::MarkObjectSlots(JSTracer* trc, Nativ
     for (uint32_t i = start; i < (start + nslots); ++i) {
         HeapSlot& slot = obj->getSlotRef(i);
         if (InternalGCMethods<Value>::isMarkable(slot))
             DispatchToTracer(trc, slot.unsafeGet(), "object slot");
         ++index;
     }
 }
 
-static bool
-ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Cell* cell)
-{
-    if (!trc->isMarkingTracer())
-        return true;
-
-    uint32_t color = AsGCMarker(trc)->markColor();
-    MOZ_ASSERT(color == BLACK || color == GRAY);
-
-    if (IsInsideNursery(cell)) {
-        MOZ_ASSERT(color == BLACK);
-        return false;
-    }
-    TenuredCell& tenured = cell->asTenured();
-
-    JS::Zone* zone = tenured.zone();
-    if (color == BLACK) {
-        /*
-         * Having black->gray edges violates our promise to the cycle
-         * collector. This can happen if we're collecting a compartment and it
-         * has an edge to an uncollected compartment: it's possible that the
-         * source and destination of the cross-compartment edge should be gray,
-         * but the source was marked black by the conservative scanner.
-         */
-        if (tenured.isMarked(GRAY)) {
-            MOZ_ASSERT(!zone->isCollecting());
-            trc->runtime()->gc.setFoundBlackGrayEdges();
-        }
-        return zone->isGCMarking();
-    } else {
-        if (zone->isGCMarkingBlack()) {
-            /*
-             * The destination compartment is being not being marked gray now,
-             * but it will be later, so record the cell so it can be marked gray
-             * at the appropriate time.
-             */
-            if (!tenured.isMarked())
-                DelayCrossCompartmentGrayMarking(src);
-            return false;
-        }
-        return zone->isGCMarkingGray();
-    }
-}
-
-static bool
-ShouldMarkCrossCompartment(JSTracer* trc, JSObject* src, Value val)
-{
-    return val.isMarkable() && ShouldMarkCrossCompartment(trc, src, (Cell*)val.toGCThing());
-}
-
 /*** Special Marking ***/
 
 void
 gc::MarkValueForBarrier(JSTracer* trc, Value* valuep, const char* name)
 {
     MOZ_ASSERT(!trc->runtime()->isHeapCollecting());
     TraceManuallyBarrieredEdge(trc, valuep, name);
 }
@@ -895,75 +1015,35 @@ gc::MarkValueForBarrier(JSTracer* trc, V
 void
 gc::MarkIdForBarrier(JSTracer* trc, jsid* idp, const char* name)
 {
     TraceManuallyBarrieredEdge(trc, idp, name);
 }
 
 /*** Push Mark Stack ***/
 
-/*
- * GCMarker::traverse for BaseShape unpacks its children directly onto the mark
- * stack. For a pre-barrier between incremental slices, this may result in
- * objects in the nursery getting pushed onto the mark stack. It is safe to
- * ignore these objects because they will be marked by the matching
- * post-barrier during the minor GC at the start of each incremental slice.
- */
-static void
-MaybePushMarkStackBetweenSlices(GCMarker* gcmarker, JSObject* thing)
-{
-    MOZ_ASSERT_IF(gcmarker->runtime()->isHeapBusy(), !IsInsideNursery(thing));
-
-    if (!IsInsideNursery(thing))
-        gcmarker->traverse(thing);
-}
-
 void
 BaseShape::traceChildren(JSTracer* trc)
 {
     if (isOwned())
         TraceEdge(trc, &unowned_, "base");
 
     JSObject* global = compartment()->unsafeUnbarrieredMaybeGlobal();
     if (global)
         TraceManuallyBarrieredEdge(trc, &global, "global");
 }
-
-inline void
-GCMarker::eagerlyMarkChildren(Shape* shape)
-{
-  restart:
-    traverse(shape->base());
-
-    const BarrieredBase<jsid>& id = shape->propidRef();
-    if (JSID_IS_STRING(id))
-        traverse(JSID_TO_STRING(id));
-    else if (JSID_IS_SYMBOL(id))
-        traverse(JSID_TO_SYMBOL(id));
-
-    if (shape->hasGetterObject())
-        MaybePushMarkStackBetweenSlices(this, shape->getterObject());
-
-    if (shape->hasSetterObject())
-        MaybePushMarkStackBetweenSlices(this, shape->setterObject());
-
-    shape = shape->previous();
-    if (shape && shape->markIfUnmarked(this->markColor()))
-        goto restart;
-}
-
 inline void
 GCMarker::eagerlyMarkChildren(BaseShape* base)
 {
     base->assertConsistency();
 
     base->compartment()->mark();
 
     if (GlobalObject* global = base->compartment()->unsafeUnbarrieredMaybeGlobal())
-        traverse(global);
+        traverse(static_cast<JSObject*>(global));
 
     /*
      * All children of the owned base shape are consistent with its
      * unowned one, thus we do not need to trace through children of the
      * unowned base shape.
      */
     if (base->isOwned()) {
         UnownedBaseShape* unowned = base->baseUnowned();
@@ -1195,35 +1275,35 @@ ScanObjectGroup(GCMarker* gcmarker, Obje
     }
 
     if (group->proto().isObject())
         gcmarker->traverse(group->proto().toObject());
 
     group->compartment()->mark();
 
     if (GlobalObject* global = group->compartment()->unsafeUnbarrieredMaybeGlobal())
-        gcmarker->traverse(global);
+        gcmarker->traverse(static_cast<JSObject*>(global));
 
     if (group->newScript())
         group->newScript()->trace(gcmarker);
 
     if (group->maybePreliminaryObjects())
         group->maybePreliminaryObjects()->trace(gcmarker);
 
     if (group->maybeUnboxedLayout())
         group->unboxedLayout().trace(gcmarker);
 
     if (ObjectGroup* unboxedGroup = group->maybeOriginalUnboxedGroup())
         gcmarker->traverse(unboxedGroup);
 
     if (TypeDescr* descr = group->maybeTypeDescr())
-        gcmarker->traverse(descr);
+        gcmarker->traverse(static_cast<JSObject*>(descr));
 
     if (JSFunction* fun = group->maybeInterpretedFunction())
-        gcmarker->traverse(fun);
+        gcmarker->traverse(static_cast<JSObject*>(fun));
 }
 
 void
 js::ObjectGroup::traceChildren(JSTracer* trc)
 {
     unsigned count = getPropertyCount();
     for (unsigned i = 0; i < count; i++) {
         if (ObjectGroup::Property* prop = getProperty(i))
@@ -1432,38 +1512,16 @@ GCMarker::processMarkStackOther(uintptr_
             pushValueArray(obj, vp, end);
         else
             repush(obj);
     } else if (tag == JitCodeTag) {
         reinterpret_cast<jit::JitCode*>(addr)->traceChildren(this);
     }
 }
 
-MOZ_ALWAYS_INLINE void
-GCMarker::markAndScanString(JSObject* source, JSString* str)
-{
-    if (!str->isPermanentAtom()) {
-        JS_COMPARTMENT_ASSERT(runtime(), str);
-        MOZ_ASSERT(runtime()->isAtomsZone(str->zone()) || str->zone() == source->zone());
-        if (str->markIfUnmarked())
-            eagerlyMarkChildren(str);
-    }
-}
-
-MOZ_ALWAYS_INLINE void
-GCMarker::markAndScanSymbol(JSObject* source, JS::Symbol* sym)
-{
-    if (!sym->isWellKnownSymbol()) {
-        JS_COMPARTMENT_ASSERT(runtime(), sym);
-        MOZ_ASSERT(runtime()->isAtomsZone(sym->zone()) || sym->zone() == source->zone());
-        if (sym->markIfUnmarked())
-            eagerlyMarkChildren(sym);
-    }
-}
-
 inline void
 GCMarker::processMarkStackTop(SliceBudget& budget)
 {
     /*
      * The function uses explicit goto and implements the scanning of the
      * object directly. It allows to eliminate the tail recursion and
      * significantly improve the marking performance, see bug 641025.
      */
@@ -1506,59 +1564,59 @@ GCMarker::processMarkStackTop(SliceBudge
         budget.step();
         if (budget.isOverBudget()) {
             pushValueArray(obj, vp, end);
             return;
         }
 
         const Value& v = *vp++;
         if (v.isString()) {
-            markAndScanString(obj, v.toString());
+            traverse(obj, v.toString());
         } else if (v.isObject()) {
             JSObject* obj2 = &v.toObject();
             MOZ_ASSERT(obj->compartment() == obj2->compartment());
             if (mark(obj2)) {
                 // Save the rest of this value array for later and start scanning obj2's children.N
                 pushValueArray(obj, vp, end);
                 obj = obj2;
                 goto scan_obj;
             }
         } else if (v.isSymbol()) {
-            markAndScanSymbol(obj, v.toSymbol());
+            traverse(obj, v.toSymbol());
         }
     }
     return;
 
   scan_unboxed:
     {
         while (*unboxedTraceList != -1) {
             JSString* str = *reinterpret_cast<JSString**>(unboxedMemory + *unboxedTraceList);
-            markAndScanString(obj, str);
+            traverse(obj, str);
             unboxedTraceList++;
         }
         unboxedTraceList++;
         while (*unboxedTraceList != -1) {
             JSObject* obj2 = *reinterpret_cast<JSObject**>(unboxedMemory + *unboxedTraceList);
             MOZ_ASSERT_IF(obj2, obj->compartment() == obj2->compartment());
             if (obj2 && mark(obj2))
                 repush(obj2);
             unboxedTraceList++;
         }
         unboxedTraceList++;
         while (*unboxedTraceList != -1) {
             const Value& v = *reinterpret_cast<Value*>(unboxedMemory + *unboxedTraceList);
             if (v.isString()) {
-                markAndScanString(obj, v.toString());
+                traverse(obj, v.toString());
             } else if (v.isObject()) {
                 JSObject* obj2 = &v.toObject();
                 MOZ_ASSERT(obj->compartment() == obj2->compartment());
                 if (mark(obj2))
                     repush(obj2);
             } else if (v.isSymbol()) {
-                markAndScanSymbol(obj, v.toSymbol());
+                traverse(obj, v.toSymbol());
             }
             unboxedTraceList++;
         }
         return;
     }
 
   scan_obj:
     {
--- a/js/src/gc/Tracer.h
+++ b/js/src/gc/Tracer.h
@@ -153,17 +153,23 @@ class GCMarker : public JSTracer
     void setMaxCapacity(size_t maxCap) { stack.setMaxCapacity(maxCap); }
     size_t maxCapacity() const { return stack.maxCapacity(); }
 
     void start();
     void stop();
     void reset();
 
     // Mark the given GC thing and traverse its children at some point.
-    template <typename T> void traverse(T* thing);
+    template <typename T> void traverse(T thing);
+
+    // Calls traverse on target after making additional assertions.
+    template <typename S, typename T> void traverse(S source, T target);
+
+    // C++ requires explicit declarations of partial template instantiations.
+    template <typename S> void traverse(S source, jsid target);
 
     /*
      * Care must be taken changing the mark color from gray to black. The cycle
      * collector depends on the invariant that there are no black to gray edges
      * in the GC heap. This invariant lets the CC not trace through black
      * objects. If this invariant is violated, the cycle collector may free
      * objects that are still reachable.
      */
@@ -231,16 +237,17 @@ class GCMarker : public JSTracer
 
     // Push an object onto the stack for later tracing and assert that it has
     // already been marked.
     void repush(JSObject* obj) {
         MOZ_ASSERT(gc::TenuredCell::fromPointer(obj)->isMarked(markColor()));
         pushTaggedPtr(ObjectTag, obj);
     }
 
+    template <typename T> void markAndTraceChildren(T* thing);
     template <typename T> void markAndPush(StackTag tag, T* thing);
     template <typename T> void markAndScan(T* thing);
     void eagerlyMarkChildren(Shape* shape);
     void eagerlyMarkChildren(BaseShape* base);
     void eagerlyMarkChildren(JSString* str);
     void eagerlyMarkChildren(JS::Symbol* sym);
 
     // We may not have concrete types yet, so this has to be out of the header.
@@ -280,19 +287,16 @@ class GCMarker : public JSTracer
         return stack.isEmpty();
     }
 
     bool restoreValueArray(NativeObject* obj, void** vpp, void** endp);
     void saveValueRanges();
     inline void processMarkStackTop(SliceBudget& budget);
     void processMarkStackOther(uintptr_t tag, uintptr_t addr);
 
-    void markAndScanString(JSObject* source, JSString* str);
-    void markAndScanSymbol(JSObject* source, JS::Symbol* sym);
-
     /* The color is only applied to objects and functions. */
     uint32_t color;
 
     /* Pointer to the top of the stack of arenas we are delaying marking on. */
     js::gc::ArenaHeader* unmarkedArenaStackTop;
 
     /* Count of arenas that are currently in the stack. */
     mozilla::DebugOnly<size_t> markLaterArenas;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/constructor-name.js
@@ -0,0 +1,28 @@
+function Ctor() {}
+
+var nested = {};
+nested.Ctor = function () {};
+nested.object = {};
+
+function makeInstance() {
+  let LexicalCtor = function () {};
+  return new LexicalCtor;
+}
+
+function makeObject() {
+  let object = {};
+  return object;
+}
+
+let tests = [
+  { name: "Ctor",                     object: new Ctor        },
+  { name: "nested.Ctor",              object: new nested.Ctor },
+  { name: "makeInstance/LexicalCtor", object: makeInstance()  },
+  { name: null,                       object: {}              },
+  { name: null,                       object: nested.object   },
+  { name: null,                       object: makeObject()    },
+];
+
+for (let { name, object } of tests) {
+  assertEq(getConstructorName(object), name);
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Memory-drainAllocationsLog-16.js
@@ -0,0 +1,47 @@
+// Test drainAllocationsLog() and constructor names.
+
+const root = newGlobal();
+const dbg = new Debugger();
+const wrappedRoot = dbg.addDebuggee(root);
+
+root.eval(
+  `
+  function Ctor() {}
+
+  var nested = {};
+  nested.Ctor = function () {};
+
+  function makeInstance() {
+    let LexicalCtor = function () {};
+    return new LexicalCtor;
+  }
+
+  function makeObject() {
+    let object = {};
+    return object;
+  }
+
+  this.tests = [
+    { name: "Ctor",                     fn: () => new Ctor             },
+    { name: "nested.Ctor",              fn: () => new nested.Ctor      },
+    { name: "makeInstance/LexicalCtor", fn: () => makeInstance()       },
+    { name: null,                       fn: () => ({})                 },
+    { name: null,                       fn: () => (nested.object = {}) },
+    { name: null,                       fn: () => makeObject()         },
+  ];
+  `
+);
+
+for (let { name, fn } of root.tests) {
+  print(name);
+
+  dbg.memory.trackingAllocationSites = true;
+
+  fn();
+
+  let entries = dbg.memory.drainAllocationsLog();
+  let ctors = entries.map(e => e.constructor);
+  assertEq(ctors.some(ctor => ctor === name), true);
+
+  dbg.memory.trackingAllocationSites = false;
+}
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/incremental-AccessorShape-barrier.js
@@ -0,0 +1,15 @@
+var o = {};
+function foo() {
+    var i = 0;
+    startgc(0);
+    Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; },
+                                                         set: function s() { return i; }});
+    Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; },
+                                                         set: function s() { return i; }});
+    Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; },
+                                                         set: function s() { return i; }});
+    Object.defineProperty(o, 'foo', {configurable: true, get: function g() { return i; },
+                                                         set: function s() { return i; }});
+    abortgc();
+}
+foo();
--- a/js/src/jsapi-tests/testUbiNode.cpp
+++ b/js/src/jsapi-tests/testUbiNode.cpp
@@ -83,8 +83,23 @@ BEGIN_TEST(test_ubiNodeCompartment)
 
         CHECK(JS::ubi::Node(script1).compartment() == global1->compartment());
         CHECK(JS::ubi::Node(script2).compartment() == global2->compartment());
     }
 
     return true;
 }
 END_TEST(test_ubiNodeCompartment)
+
+BEGIN_TEST(test_ubiNodeJSObjectConstructorName)
+{
+    JS::RootedValue val(cx);
+    EVAL("this.Ctor = function Ctor() {}; new Ctor", &val);
+    CHECK(val.isObject());
+
+    mozilla::UniquePtr<char16_t[], JS::FreePolicy> ctorName;
+    CHECK(JS::ubi::Node(&val.toObject()).jsObjectConstructorName(cx, ctorName));
+    CHECK(ctorName);
+    CHECK(js_strcmp(ctorName.get(), MOZ_UTF16("Ctor")) == 0);
+
+    return true;
+}
+END_TEST(test_ubiNodeJSObjectConstructorName)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4457,16 +4457,22 @@ JS_New(JSContext* cx, HandleObject ctor,
     RootedObject obj(cx);
     {
         AutoLastFrameCheck lfc(cx);
         obj = JS_NewHelper(cx, ctor, inputArgs);
     }
     return obj;
 }
 
+JS_PUBLIC_API(bool)
+JS_CheckForInterrupt(JSContext* cx)
+{
+    return js::CheckForInterrupt(cx);
+}
+
 JS_PUBLIC_API(JSInterruptCallback)
 JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback)
 {
     JSInterruptCallback old = rt->interruptCallback;
     rt->interruptCallback = callback;
     return old;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3943,19 +3943,21 @@ Call(JSContext* cx, JS::HandleValue this
     JS::RootedValue fun(cx, JS::ObjectValue(*funObj));
     return Call(cx, thisv, fun, args, rval);
 }
 
 extern JS_PUBLIC_API(bool)
 Construct(JSContext* cx, JS::HandleValue fun,
           const JS::HandleValueArray& args,
           MutableHandleValue rval);
-
 } /* namespace JS */
 
+extern JS_PUBLIC_API(bool)
+JS_CheckForInterrupt(JSContext* cx);
+
 /*
  * These functions allow setting an interrupt callback that will be called
  * from the JS thread some time after any thread triggered the callback using
  * JS_RequestInterruptCallback(rt).
  *
  * To schedule the GC and for other activities the engine internally triggers
  * interrupt callbacks. The embedding should thus not rely on callbacks being
  * triggered through the external API only.
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -4101,8 +4101,37 @@ JSObject::traceChildren(JSTracer* trc)
 
             TraceRange(trc,
                        nobj->getDenseInitializedLength(),
                        static_cast<HeapSlot*>(nobj->getDenseElementsAllowCopyOnWrite()),
                        "objectElements");
         } while (false);
     }
 }
+
+static JSAtom*
+displayAtomFromObjectGroup(ObjectGroup& group)
+{
+    TypeNewScript* script = group.newScript();
+    if (!script)
+        return nullptr;
+
+    return script->function()->displayAtom();
+}
+
+bool
+JSObject::constructorDisplayAtom(JSContext* cx, js::MutableHandleAtom name)
+{
+    ObjectGroup *g = getGroup(cx);
+    if (!g)
+        return false;
+
+    name.set(displayAtomFromObjectGroup(*g));
+    return true;
+}
+
+JSAtom*
+JSObject::maybeConstructorDisplayAtom() const
+{
+    if (hasLazyGroup())
+        return nullptr;
+    return displayAtomFromObjectGroup(*group());
+}
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -249,16 +249,30 @@ class JSObject : public js::gc::Cell
     }
 
     /*
      * Whether there may be indexed properties on this object, excluding any in
      * the object's elements.
      */
     inline bool isIndexed() const;
 
+    /*
+     * If this object was instantiated with `new Ctor`, return the constructor's
+     * display atom. Otherwise, return nullptr.
+     */
+    bool constructorDisplayAtom(JSContext* cx, js::MutableHandleAtom name);
+
+    /*
+     * The same as constructorDisplayAtom above, however if this object has a
+     * lazy group, nullptr is returned. This allows for use in situations that
+     * cannot GC and where having some information, even if it is inconsistently
+     * available, is better than no information.
+     */
+    JSAtom* maybeConstructorDisplayAtom() const;
+
     /* GC support. */
 
     void traceChildren(JSTracer* trc);
 
     void fixupAfterMovingGC();
 
     static js::ThingRootKind rootKind() { return js::THING_ROOT_OBJECT; }
     static const size_t MaxTagBits = 3;
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -463,18 +463,16 @@ if CONFIG['HAVE_LINUX_PERF_EVENT_H']:
         'perf/pm_linux.cpp'
     ]
     SOURCES['perf/pm_linux.cpp'].flags += [CONFIG['LINUX_HEADERS_INCLUDES']]
 else:
     SOURCES += [
         'perf/pm_stub.cpp'
     ]
 
-MSVC_ENABLE_PGO = True
-
 HostSimplePrograms([
     'host_jskwgen',
 ])
 
 # JavaScript must be built shared, even for static builds, as it is used by
 # other modules which are always built shared. Failure to do so results in
 # the js code getting copied into xpinstall and jsd as well as mozilla-bin,
 # and then the static data cells used for locking no longer work.
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -1650,26 +1650,48 @@ Debugger::slowPathOnLogAllocationSite(JS
 
 bool
 Debugger::isDebuggee(const JSCompartment* compartment) const
 {
     MOZ_ASSERT(compartment);
     return compartment->isDebuggee() && debuggees.has(compartment->maybeGlobal());
 }
 
+/* static */ Debugger::AllocationSite*
+Debugger::AllocationSite::create(JSContext* cx, HandleObject frame, int64_t when, HandleObject obj)
+{
+    assertSameCompartment(cx, frame);
+
+    RootedAtom ctorName(cx);
+    {
+        AutoCompartment ac(cx, obj);
+        if (!obj->constructorDisplayAtom(cx, &ctorName))
+            return nullptr;
+    }
+
+    AllocationSite* allocSite = cx->new_<AllocationSite>(frame, when);
+    if (!allocSite)
+        return nullptr;
+
+    allocSite->className = obj->getClass()->name;
+    allocSite->ctorName = ctorName.get();
+    return allocSite;
+}
+
+
 bool
 Debugger::appendAllocationSite(JSContext* cx, HandleObject obj, HandleSavedFrame frame,
                                int64_t when)
 {
     AutoCompartment ac(cx, object);
     RootedObject wrappedFrame(cx, frame);
     if (!cx->compartment()->wrap(cx, &wrappedFrame))
         return false;
 
-    AllocationSite* allocSite = cx->new_<AllocationSite>(wrappedFrame, when, obj->getClass()->name);
+    AllocationSite* allocSite = AllocationSite::create(cx, wrappedFrame, when, obj);
     if (!allocSite)
         return false;
 
     allocationsLog.insertBack(allocSite);
 
     if (allocationsLogLength >= maxAllocationsLogLength) {
         js_delete(allocationsLog.getFirst());
         allocationsLogOverflowed = true;
@@ -2319,16 +2341,18 @@ Debugger::trace(JSTracer* trc)
     }
 
     /*
      * Mark every allocation site in our allocation log.
      */
     for (AllocationSite* s = allocationsLog.getFirst(); s; s = s->getNext()) {
         if (s->frame)
             TraceEdge(trc, &s->frame, "allocation log SavedFrame");
+        if (s->ctorName)
+            TraceEdge(trc, &s->ctorName, "allocation log constructor name");
     }
 
     /* Trace the weak map from JSScript instances to Debugger.Script objects. */
     scripts.trace(trc);
 
     /* Trace the referent ->Debugger.Source weak map */
     sources.trace(trc);
 
--- a/js/src/vm/Debugger.h
+++ b/js/src/vm/Debugger.h
@@ -266,27 +266,32 @@ class Debugger : private mozilla::Linked
     JSCList breakpoints;                /* Circular list of all js::Breakpoints in this debugger */
 
     // The set of GC numbers for which one or more of this Debugger's observed
     // debuggees participated in.
     js::HashSet<uint64_t> observedGCs;
 
     struct AllocationSite : public mozilla::LinkedListElement<AllocationSite>
     {
-        AllocationSite(HandleObject frame, int64_t when, const char* className)
+        AllocationSite(HandleObject frame, int64_t when)
             : frame(frame),
               when(when),
-              className(className)
+              className(nullptr),
+              ctorName(nullptr)
         {
             MOZ_ASSERT_IF(frame, UncheckedUnwrap(frame)->is<SavedFrame>());
         };
 
+        static AllocationSite* create(JSContext* cx, HandleObject frame, int64_t when,
+                                      HandleObject obj);
+
         RelocatablePtrObject frame;
         int64_t when;
         const char* className;
+        RelocatablePtrAtom ctorName;
     };
     typedef mozilla::LinkedList<AllocationSite> AllocationSiteList;
 
     bool allowUnobservedAsmJS;
     bool trackingAllocationSites;
     double allocationSamplingProbability;
     AllocationSiteList allocationsLog;
     size_t allocationsLogLength;
--- a/js/src/vm/DebuggerMemory.cpp
+++ b/js/src/vm/DebuggerMemory.cpp
@@ -211,16 +211,22 @@ DebuggerMemory::drainAllocationsLog(JSCo
 
         RootedString className(cx, Atomize(cx, allocSite->className, strlen(allocSite->className)));
         if (!className)
             return false;
         RootedValue classNameValue(cx, StringValue(className));
         if (!DefineProperty(cx, obj, cx->names().class_, classNameValue))
             return false;
 
+        RootedValue ctorName(cx, NullValue());
+        if (allocSite->ctorName)
+            ctorName.setString(allocSite->ctorName);
+        if (!DefineProperty(cx, obj, cx->names().constructor, ctorName))
+            return false;
+
         result->setDenseElement(i, ObjectValue(*obj));
 
         // Pop the front queue entry, and delete it immediately, so that
         // the GC sees the AllocationSite's RelocatablePtr barriers run
         // atomically with the change to the graph (the queue link).
         MOZ_ALWAYS_TRUE(dbg->allocationsLog.popFirst() == allocSite);
         js_delete(allocSite);
     }
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -1314,31 +1314,16 @@ Shape::searchLinear(jsid id)
         if (shape->propidRef() == id)
             return shape;
         shape = shape->parent;
     }
 
     return nullptr;
 }
 
-inline void
-Shape::traceChildren(JSTracer* trc)
-{
-    TraceEdge(trc, &base_, "base");
-    TraceEdge(trc, &propidRef(), "propid");
-    if (parent)
-        TraceEdge(trc, &parent, "parent");
-
-    if (hasGetterObject())
-        TraceManuallyBarrieredEdge(trc, &asAccessorShape().getterObj, "getter");
-
-    if (hasSetterObject())
-        TraceManuallyBarrieredEdge(trc, &asAccessorShape().setterObj, "setter");
-}
-
 /*
  * Keep this function in sync with search. It neither hashifies the start
  * shape nor increments linear search count.
  */
 inline Shape*
 Shape::searchNoHashify(Shape* start, jsid id)
 {
     /*
--- a/js/src/vm/UbiNode.cpp
+++ b/js/src/vm/UbiNode.cpp
@@ -3,16 +3,17 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "js/UbiNode.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/Range.h"
 #include "mozilla/Scoped.h"
 #include "mozilla/UniquePtr.h"
 
 #include "jscntxt.h"
 #include "jsobj.h"
 #include "jsscript.h"
 #include "jsstr.h"
 
@@ -27,16 +28,17 @@
 #include "vm/Shape.h"
 #include "vm/String.h"
 #include "vm/Symbol.h"
 
 #include "jsobjinlines.h"
 #include "vm/Debugger-inl.h"
 
 using mozilla::Some;
+using mozilla::UniquePtr;
 using JS::HandleValue;
 using JS::Value;
 using JS::ZoneSet;
 using JS::ubi::Concrete;
 using JS::ubi::Edge;
 using JS::ubi::EdgeRange;
 using JS::ubi::Node;
 using JS::ubi::SimpleEdge;
@@ -223,16 +225,41 @@ TracerConcreteWithCompartment<Referent>:
 }
 
 const char*
 Concrete<JSObject>::jsObjectClassName() const
 {
     return Concrete::get().getClass()->name;
 }
 
+bool
+Concrete<JSObject>::jsObjectConstructorName(JSContext* cx,
+                                            UniquePtr<char16_t[], JS::FreePolicy>& outName) const
+{
+    JSAtom* name = Concrete::get().maybeConstructorDisplayAtom();
+    if (!name) {
+        outName.reset(nullptr);
+        return true;
+    }
+
+    auto len = JS_GetStringLength(name);
+    auto size = len + 1;
+
+    outName.reset(cx->pod_malloc<char16_t>(size * sizeof(char16_t)));
+    if (!outName)
+        return false;
+
+    mozilla::Range<char16_t> chars(outName.get(), size);
+    if (!JS_CopyStringChars(cx, chars, name))
+        return false;
+
+    outName[len] = '\0';
+    return true;
+}
+
 template<> const char16_t TracerConcrete<JS::Symbol>::concreteTypeName[] =
     MOZ_UTF16("JS::Symbol");
 template<> const char16_t TracerConcrete<JSScript>::concreteTypeName[] =
     MOZ_UTF16("JSScript");
 template<> const char16_t TracerConcrete<js::LazyScript>::concreteTypeName[] =
     MOZ_UTF16("js::LazyScript");
 template<> const char16_t TracerConcrete<js::jit::JitCode>::concreteTypeName[] =
     MOZ_UTF16("js::jit::JitCode");
--- a/js/xpconnect/loader/moz.build
+++ b/js/xpconnect/loader/moz.build
@@ -13,18 +13,16 @@ SOURCES += [
 
 EXTRA_JS_MODULES += [
     'ISO8601DateUtils.jsm',
     'XPCOMUtils.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../src',
     '../wrappers',
     '/dom/base',
 ]
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1456,18 +1456,23 @@ XPCJSRuntime::InterruptCallback(JSContex
         if (!JS_GetPrototype(cx, global, &proto))
             return false;
         if (proto && IsSandboxPrototypeProxy(proto) &&
             (proto = js::CheckedUnwrap(proto, /* stopAtOuter = */ false)))
         {
             win = WindowGlobalOrNull(proto);
         }
     }
-    if (!win)
+
+    if (!win) {
+        NS_WARNING("No active window");
         return true;
+    }
+
+    MOZ_ASSERT(!win->IsDying());
 
     if (win->GetIsPrerendered()) {
         // We cannot display a dialog if the page is being prerendered, so
         // just kill the page.
         mozilla::dom::HandlePrerenderingViolation(win);
         return false;
     }
 
--- a/js/xpconnect/src/moz.build
+++ b/js/xpconnect/src/moz.build
@@ -47,18 +47,16 @@ UNIFIED_SOURCES += [
 
 # XPCComponents.cpp cannot be built in unified mode because it uses plarena.h.
 SOURCES += [
     'XPCComponents.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../loader',
     '../wrappers',
     '/caps',
--- a/js/xpconnect/src/nsScriptError.cpp
+++ b/js/xpconnect/src/nsScriptError.cpp
@@ -198,19 +198,21 @@ nsScriptError::ToString(nsACString& /*UT
     char* temp;
     char* tempMessage = nullptr;
     char* tempSourceName = nullptr;
     char* tempSourceLine = nullptr;
 
     if (!mMessage.IsEmpty())
         tempMessage = ToNewUTF8String(mMessage);
     if (!mSourceName.IsEmpty())
-        tempSourceName = ToNewUTF8String(mSourceName);
+        // Use at most 512 characters from mSourceName.
+        tempSourceName = ToNewUTF8String(StringHead(mSourceName, 512));
     if (!mSourceLine.IsEmpty())
-        tempSourceLine = ToNewUTF8String(mSourceLine);
+        // Use at most 512 characters from mSourceLine.
+        tempSourceLine = ToNewUTF8String(StringHead(mSourceLine, 512));
 
     if (nullptr != tempSourceName && nullptr != tempSourceLine)
         temp = JS_smprintf(format0,
                            severity,
                            tempMessage,
                            tempSourceName,
                            mLineNumber,
                            mColumnNumber,
--- a/js/xpconnect/wrappers/moz.build
+++ b/js/xpconnect/wrappers/moz.build
@@ -25,18 +25,16 @@ SOURCES += [
 # warning C4661 for FilteringWrapper
 if CONFIG['_MSC_VER']:
     CXXFLAGS += [
         '-wd4661', # no suitable definition provided for explicit template instantiation request
     ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../../dom/base',
     '../src',
 ]
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -143,18 +143,16 @@ UNIFIED_SOURCES += [
 # nsRefreshDriver.cpp needs to be built separately because of name clashes in the OS X headers
 SOURCES += [
     'nsPresArena.cpp',
     'nsRefreshDriver.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../forms',
     '../generic',
     '../mathml',
     '../printing',
     '../style',
--- a/layout/build/moz.build
+++ b/layout/build/moz.build
@@ -18,18 +18,16 @@ UNIFIED_SOURCES += [
 
 if CONFIG['MOZ_NFC']:
     LOCAL_INCLUDES += [
         '/dom/nfc'
     ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '../base',
     '../forms',
     '../generic',
     '../inspector',
     '../mathml',
--- a/layout/forms/moz.build
+++ b/layout/forms/moz.build
@@ -37,18 +37,16 @@ UNIFIED_SOURCES += [
     'nsProgressFrame.cpp',
     'nsRangeFrame.cpp',
     'nsSelectsAreaFrame.cpp',
     'nsTextControlFrame.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../editor/libeditor',
     '../../editor/txmgr',
     '../base',
     '../generic',
     '../style',
--- a/layout/generic/moz.build
+++ b/layout/generic/moz.build
@@ -172,18 +172,16 @@ UNIFIED_SOURCES += [
 # nsPluginFrame.cpp needs to be built separately because of name clashes in the OS X headers.
 SOURCES += [
     'nsLineLayout.cpp',
     'nsPluginFrame.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../dom/plugins/base',
     '../base',
     '../forms',
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4877,22 +4877,22 @@ ScrollFrameHelper::SetScrollbarEnabled(n
 
 void
 ScrollFrameHelper::SetCoordAttribute(nsIContent* aContent, nsIAtom* aAtom,
                                          nscoord aSize)
 {
   DebugOnly<nsWeakPtr> weakShell(
     do_GetWeakReference(mOuter->PresContext()->PresShell()));
   // convert to pixels
-  aSize = nsPresContext::AppUnitsToIntCSSPixels(aSize);
+  int32_t pizelSize = nsPresContext::AppUnitsToIntCSSPixels(aSize);
 
   // only set the attribute if it changed.
 
   nsAutoString newValue;
-  newValue.AppendInt(aSize);
+  newValue.AppendInt(pizelSize);
 
   if (aContent->AttrValueIs(kNameSpaceID_None, aAtom, newValue, eCaseMatters))
     return;
 
   nsWeakFrame weakFrame(mOuter);
   nsCOMPtr<nsIContent> kungFuDeathGrip = aContent;
   aContent->SetAttr(kNameSpaceID_None, aAtom, newValue, true);
   MOZ_ASSERT(ShellIsAlive(weakShell), "pres shell was destroyed by scrolling");
--- a/layout/style/Declaration.cpp
+++ b/layout/style/Declaration.cpp
@@ -1166,18 +1166,20 @@ Declaration::AppendPropertyAndValueToStr
   }
   aResult.AppendLiteral("; ");
 }
 
 void
 Declaration::AppendVariableAndValueToString(const nsAString& aName,
                                             nsAString& aResult) const
 {
-  aResult.AppendLiteral("--");
-  aResult.Append(aName);
+  nsAutoString localName;
+  localName.AppendLiteral("--");
+  localName.Append(aName);
+  nsStyleUtil::AppendEscapedCSSIdent(localName, aResult);
   CSSVariableDeclarations::Type type;
   nsString value;
   bool important;
 
   if (mImportantVariables && mImportantVariables->Get(aName, type, value)) {
     important = true;
   } else {
     MOZ_ASSERT(mVariables);
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -173,18 +173,16 @@ SOURCES += [
 
 EXTRA_COMPONENTS += [
     'CSSUnprefixingService.js',
     'CSSUnprefixingService.manifest',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../svg',
--- a/layout/style/test/test_variables.html
+++ b/layout/style/test/test_variables.html
@@ -21,16 +21,19 @@
 <style id="test5">
 </style>
 
 <div id="t5"></div>
 
 <style id="test6">
 </style>
 
+<style id="test7">
+</style>
+
 <script>
 var tests = [
   function() {
     // https://bugzilla.mozilla.org/show_bug.cgi?id=773296#c121
     var test1 = document.getElementById("test1");
     test1.textContent = "p { --a:123!important; }";
     var declaration = test1.sheet.cssRules[0].style;
     declaration.cssText;
@@ -86,16 +89,25 @@ var tests = [
   function() {
     // https://bugzilla.mozilla.org/show_bug.cgi?id=969756
     var test6 = document.getElementById("test6");
     test6.textContent = "p { font: var(--var6) hangul mongolian; font-size-adjust: none; }";
     var declaration = test6.sheet.cssRules[0].style;
     test6.style.color = "white";
     is(declaration.getPropertyValue("-x-system-font"), " var(--var6) hangul mongolian");
   },
+
+  function() {
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=1154356
+    var test7 = document.getElementById("test7");
+    test7.textContent = "p { --weird\\;name: green; }";
+    is(test7.sheet.cssRules[0].style.cssText, "--weird\\;name:  green;");
+    test7.textContent = "p { --0: green; }";
+    is(test7.sheet.cssRules[0].style.cssText, "--0:  green;");
+  },
 ];
 
 function prepareTest() {
   // Load an external style sheet for test 4.
   var e = document.createElement("link");
   e.addEventListener("load", runTest);
   e.setAttribute("rel", "stylesheet");
   e.setAttribute("href", "support/external-variable-url.css");
--- a/layout/tables/moz.build
+++ b/layout/tables/moz.build
@@ -25,18 +25,16 @@ UNIFIED_SOURCES += [
     'nsTablePainter.cpp',
     'nsTableRowFrame.cpp',
     'nsTableRowGroupFrame.cpp',
     'SpanningCellSorter.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../intl/unicharutil/util',
     '../base',
     '../generic',
     '../style',
     '../xul',
--- a/layout/xul/moz.build
+++ b/layout/xul/moz.build
@@ -92,17 +92,15 @@ if CONFIG['MOZ_XUL']:
         'ScrollBoxObject.cpp',
     ]
 
 if CONFIG['MOZ_XUL']:
     DIRS += ['tree', 'grid']
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../base',
     '../generic',
     '../style',
     '/dom/base',
 ]
--- a/layout/xul/nsSliderFrame.cpp
+++ b/layout/xul/nsSliderFrame.cpp
@@ -328,17 +328,16 @@ nsSliderFrame::BuildDisplayListForChildr
     // attach scrolling information to it.
     // We do this here and not in the thumb's nsBoxFrame::BuildDisplayList so
     // that the event region that gets created for the thumb is included in
     // the nsDisplayOwnLayer contents.
 
     uint32_t flags = 0;
     mozilla::layers::FrameMetrics::ViewID scrollTargetId =
       mozilla::layers::FrameMetrics::NULL_SCROLL_ID;
-    float scrollbarThumbRatio = 0.0f;
     aBuilder->GetScrollbarInfo(&scrollTargetId, &flags);
     bool thumbGetsLayer = (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
     nsLayoutUtils::SetScrollbarThumbLayerization(thumb, thumbGetsLayer);
 
     if (thumbGetsLayer) {
       nsDisplayListCollection tempLists;
       nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, tempLists);
 
@@ -350,17 +349,17 @@ nsSliderFrame::BuildDisplayListForChildr
       masterList.AppendToTop(tempLists.Floats());
       masterList.AppendToTop(tempLists.Content());
       masterList.AppendToTop(tempLists.PositionedDescendants());
       masterList.AppendToTop(tempLists.Outlines());
 
       // Wrap the list to make it its own layer.
       aLists.Content()->AppendNewToTop(new (aBuilder)
         nsDisplayOwnLayer(aBuilder, this, &masterList, flags, scrollTargetId,
-                          scrollbarThumbRatio));
+                          GetThumbRatio()));
 
       return;
     }
   }
   
   nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
 }
 
--- a/mach
+++ b/mach
@@ -22,25 +22,24 @@ def ancestors(path):
             break
 
 def load_mach(topsrcdir):
     sys.path[0:0] = [os.path.join(topsrcdir, "build")]
     import mach_bootstrap
     return mach_bootstrap.bootstrap(topsrcdir)
 
 
-def check_and_run_mach(dir_path, args):
+def check_and_get_mach(dir_path):
     # If we find the mach bootstrap module, we are in the srcdir.
     mach_path = os.path.join(dir_path, 'build/mach_bootstrap.py')
     if os.path.isfile(mach_path):
-        mach = load_mach(dir_path)
-        sys.exit(mach.run(args))
+        return load_mach(dir_path)
+    return None
 
-
-def main(args):
+def get_mach():
     # Check whether the current directory is within a mach src or obj dir.
     for dir_path in ancestors(os.getcwd()):
         # If we find a "mozinfo.json" file, we are in the objdir.
         mozinfo_path = os.path.join(dir_path, 'mozinfo.json')
         if os.path.isfile(mozinfo_path):
             import json
             info = json.load(open(mozinfo_path))
             if 'mozconfig' in info and 'MOZCONFIG' not in os.environ:
@@ -51,24 +50,30 @@ def main(args):
                 #
                 # Note: subprocess requires native strings in os.environ on Windows
                 os.environ[b'MOZCONFIG'] = str(info['mozconfig'])
 
             if 'topsrcdir' in info:
                 # Continue searching for mach_bootstrap in the source directory.
                 dir_path = info['topsrcdir']
 
-        check_and_run_mach(dir_path, args)
+        mach = check_and_get_mach(dir_path)
+        if mach:
+            return mach
 
     # If we didn't find a source path by scanning for a mozinfo.json, check
     # whether the directory containing this script is a source directory.
-    check_and_run_mach(os.path.dirname(__file__), args)
+    return check_and_get_mach(os.path.dirname(__file__))
 
-    print('Could not run mach: No mach source directory found.')
-    sys.exit(1)
+def main(args):
+    mach = get_mach()
+    if not mach:
+        print('Could not run mach: No mach source directory found.')
+        sys.exit(1)
+    sys.exit(mach.run(args))
 
 
 if __name__ == '__main__':
     if sys.platform == 'win32':
         # This is a complete hack to work around the fact that Windows
         # multiprocessing needs to import the original module (ie: this
         # file), but only works if it has a .py extension.
         #
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -211,18 +211,16 @@ struct cubeb_stream
   /* Lifetime considerations:
    * - client, render_client, audio_clock and audio_stream_volume are interface
    *   pointer to the IAudioClient.
    * - The lifetime for device_enumerator and notification_client, resampler,
    *   mix_buffer are the same as the cubeb_stream instance. */
 
   /* Main handle on the WASAPI stream. */
   IAudioClient * client;
-  /* Interface pointer to the clock, to estimate latency. */
-  IAudioClock * audio_clock;
   /* Interface pointer to use the event-driven interface. */
   IAudioRenderClient * render_client;
   /* Interface pointer to use the volume facilities. */
   IAudioStreamVolume * audio_stream_volume;
   /* Device enumerator to be able to be notified when the default
    * device change. */
   IMMDeviceEnumerator * device_enumerator;
   /* Device notification client, to be able to be notified when the default
@@ -234,26 +232,18 @@ struct cubeb_stream
   HANDLE shutdown_event;
   /* Set by OnDefaultDeviceChanged when a stream reconfiguration is required.
      The reconfiguration is handled by the render loop thread. */
   HANDLE reconfigure_event;
   /* This is set by WASAPI when we should refill the stream. */
   HANDLE refill_event;
   /* Each cubeb_stream has its own thread. */
   HANDLE thread;
-  /* We synthesize our clock from the callbacks. This in fractional frames, in
-   * the stream samplerate. */
-  double clock;
-  UINT64 prev_position;
-  /* This is the clock value last time we reset the stream. This is in
-   * fractional frames, in the stream samplerate. */
-  double base_clock;
-  /* The latency in frames of the stream */
-  UINT32 latency_frames;
-  UINT64 device_frequency;
+  /* We synthesize our clock from the callbacks. */
+  LONG64 clock;
   owned_critical_section * stream_reset_lock;
   /* Maximum number of frames we can be requested in a callback. */
   uint32_t buffer_frame_count;
   /* Resampler instance. Resampling will only happen if necessary. */
   cubeb_resampler * resampler;
   /* Buffer used to downmix or upmix to the number of channels the mixer has.
    * its size is |frames_to_bytes_before_mix(buffer_frame_count)|. */
   float * mix_buffer;
@@ -348,38 +338,24 @@ public:
   }
 private:
   /* refcount for this instance, necessary to implement MSCOM semantics. */
   LONG ref_count;
   HANDLE reconfigure_event;
 };
 
 namespace {
-void clock_add(cubeb_stream * stm, double value)
+void clock_add(cubeb_stream * stm, LONG64 value)
 {
-  auto_lock lock(stm->stream_reset_lock);
-  stm->clock += value;
+  InterlockedExchangeAdd64(&stm->clock, value);
 }
 
-UINT64 clock_get(cubeb_stream * stm)
-{
-  auto_lock lock(stm->stream_reset_lock);
-  return UINT64(stm->clock);
-}
-
-void latency_set(cubeb_stream * stm, UINT32 value)
+LONG64 clock_get(cubeb_stream * stm)
 {
-  auto_lock lock(stm->stream_reset_lock);
-  stm->latency_frames = value;
-}
-
-UINT32 latency_get(cubeb_stream * stm)
-{
-  auto_lock lock(stm->stream_reset_lock);
-  return stm->latency_frames;
+  return InterlockedExchangeAdd64(&stm->clock, 0);
 }
 
 bool should_upmix(cubeb_stream * stream)
 {
   return stream->mix_params.channels > stream->stream_params.channels;
 }
 
 bool should_downmix(cubeb_stream * stream)
@@ -471,16 +447,18 @@ refill(cubeb_stream * stm, float * data,
   if (should_upmix(stm) || should_downmix(stm)) {
     dest = stm->mix_buffer;
   } else {
     dest = data;
   }
 
   long out_frames = cubeb_resampler_fill(stm->resampler, dest, frames_needed);
 
+  clock_add(stm, roundf(frames_needed * stream_to_mix_samplerate_ratio(stm)));
+
   /* XXX: Handle this error. */
   if (out_frames < 0) {
     XASSERT(false);
   }
 
   /* Go in draining mode if we got fewer frames than requested. */
   if (out_frames < frames_needed) {
     LOG("draining.\n");
@@ -542,30 +520,26 @@ wasapi_stream_render_loop(LPVOID stream)
       timeout_count = 0;
     }
     switch (waitResult) {
     case WAIT_OBJECT_0: { /* shutdown */
       is_playing = false;
       /* We don't check if the drain is actually finished here, we just want to
        * shutdown. */
       if (stm->draining) {
-        LOG("DRAINED");
         stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
       }
-
       continue;
     }
     case WAIT_OBJECT_0 + 1: { /* reconfigure */
       /* Close the stream */
       stm->client->Stop();
       {
         auto_lock lock(stm->stream_reset_lock);
         close_wasapi_stream(stm);
-        stm->base_clock = stm->clock;
-        stm->latency_frames = 0;
         /* Reopen a stream and start it immediately. This will automatically pick the
          * new default device for this role. */
         int r = setup_wasapi_stream(stm);
         if (r != CUBEB_OK) {
           /* Don't destroy the stream here, since we expect the caller to do
              so after the error has propagated via the state callback. */
           is_playing = false;
           hr = -1;
@@ -583,26 +557,16 @@ wasapi_stream_render_loop(LPVOID stream)
         LOG("Failed to get padding\n");
         is_playing = false;
         continue;
       }
       XASSERT(padding <= stm->buffer_frame_count);
 
       long available = stm->buffer_frame_count - padding;
 
-      clock_add(stm, available * stream_to_mix_samplerate_ratio(stm));
-
-      UINT64 position = 0;
-      HRESULT hr = stm->audio_clock->GetPosition(&position, NULL);
-      if (SUCCEEDED(hr)) {
-        double playing_frame = stm->mix_params.rate * (double)position / stm->device_frequency;
-        double last_written_frame = stm->clock - stm->base_clock;
-        latency_set(stm, std::max(last_written_frame - playing_frame, 0.0));
-      }
-
       if (stm->draining) {
         if (padding == 0) {
           stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
           is_playing = false;
         }
         continue;
       }
 
@@ -1085,29 +1049,16 @@ int setup_wasapi_stream(cubeb_stream * s
   }
 
   hr = stm->client->SetEventHandle(stm->refill_event);
   if (FAILED(hr)) {
     LOG("Could set the event handle for the client %x.\n", hr);
     return CUBEB_ERROR;
   }
 
-  hr = stm->client->GetService(__uuidof(IAudioClock),
-                               (void **)&stm->audio_clock);
-  if (FAILED(hr)) {
-    LOG("Could not get IAudioClock: %x.\n", hr);
-    return CUBEB_ERROR;
-  }
-
-  hr = stm->audio_clock->GetFrequency(&stm->device_frequency);
-  if (FAILED(hr)) {
-    LOG("Could not get the device frequency from IAudioClock: %x.\n", hr);
-    return CUBEB_ERROR;
-  }
-
   hr = stm->client->GetService(__uuidof(IAudioRenderClient),
                                (void **)&stm->render_client);
   if (FAILED(hr)) {
     LOG("Could not get the render client %x.\n", hr);
     return CUBEB_ERROR;
   }
 
   hr = stm->client->GetService(__uuidof(IAudioStreamVolume),
@@ -1156,24 +1107,21 @@ wasapi_stream_init(cubeb * context, cube
 
   stm->context = context;
   stm->data_callback = data_callback;
   stm->state_callback = state_callback;
   stm->user_ptr = user_ptr;
   stm->stream_params = stream_params;
   stm->draining = false;
   stm->latency = latency;
-  stm->clock = 0.0;
-  stm->base_clock = 0.0;
-  stm->latency_frames = 0;
+  stm->clock = 0;
 
   /* Null out WASAPI-specific state */
   stm->resampler = NULL;
   stm->client = NULL;
-  stm->audio_clock = NULL;
   stm->render_client = NULL;
   stm->audio_stream_volume = NULL;
   stm->device_enumerator = NULL;
   stm->notification_client = NULL;
 
   stm->stream_reset_lock = new owned_critical_section();
 
   stm->reconfigure_event = CreateEvent(NULL, 0, 0, NULL);
@@ -1221,19 +1169,16 @@ void close_wasapi_stream(cubeb_stream * 
   stm->stream_reset_lock->assert_current_thread_owns();
 
   SafeRelease(stm->client);
   stm->client = NULL;
 
   SafeRelease(stm->render_client);
   stm->render_client = NULL;
 
-  SafeRelease(stm->audio_clock);
-  stm->audio_clock = NULL;
-
   SafeRelease(stm->audio_stream_volume);
   stm->audio_stream_volume = NULL;
 
   if (stm->resampler) {
     cubeb_resampler_destroy(stm->resampler);
     stm->resampler = NULL;
   }
 
@@ -1333,30 +1278,17 @@ int wasapi_stream_stop(cubeb_stream * st
 
   return CUBEB_OK;
 }
 
 int wasapi_stream_get_position(cubeb_stream * stm, uint64_t * position)
 {
   XASSERT(stm && position);
 
-  UINT64 clock = clock_get(stm);
-  UINT32 latency = latency_get(stm);
-
-  *position = clock >= latency ? clock - latency : 0;
-
-  /* This can happen if the clock does not increase, for example, because the
-   * WASAPI endpoint buffer is full for now, and the latency naturally decreases
-   * because more samples have been played by the mixer process.
-   * We return the previous value to keep the clock monotonicaly increasing. */
-  if (*position < stm->prev_position) {
-    *position = stm->prev_position;
-  }
-
-  stm->prev_position = *position;
+  *position = clock_get(stm);
 
   return CUBEB_OK;
 }
 
 int wasapi_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
 {
   XASSERT(stm && latency);
 
--- a/media/libcubeb/src/moz.build
+++ b/media/libcubeb/src/moz.build
@@ -53,18 +53,16 @@ if CONFIG['OS_TARGET'] == 'Android':
     SOURCES['cubeb_opensl.c'].flags += ['-Wno-declaration-after-statement']
     DEFINES['USE_OPENSL'] = True
     if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
         SOURCES += [
             'cubeb_audiotrack.c',
         ]
         DEFINES['USE_AUDIOTRACK'] = True
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     CFLAGS += [
         '-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
--- a/media/libjpeg/moz.build
+++ b/media/libjpeg/moz.build
@@ -145,15 +145,13 @@ elif CONFIG['LIBJPEG_TURBO_X86_ASM']:
     SOURCES += [
         'simd/jsimd_i386.c',
     ]
 else: # No SIMD support?
     SOURCES += [
         'jsimd_none.c',
     ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
--- a/media/libnestegg/src/moz.build
+++ b/media/libnestegg/src/moz.build
@@ -4,14 +4,12 @@
 # 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/.
 
 UNIFIED_SOURCES += [
     'halloc.c',
     'nestegg.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
--- a/media/libogg/moz.build
+++ b/media/libogg/moz.build
@@ -14,14 +14,12 @@ EXPORTS.ogg += [
 ]
 
 UNIFIED_SOURCES += [
     'src/ogg_alloc.c',
     'src/ogg_bitwise.c',
     'src/ogg_framing.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
--- a/media/libopus/moz.build
+++ b/media/libopus/moz.build
@@ -9,18 +9,16 @@ with Files('*'):
 
 EXPORTS.opus += [
     'include/opus.h',
     'include/opus_defines.h',
     'include/opus_multistream.h',
     'include/opus_types.h',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['OPUS_BUILD'] = True
 DEFINES['OPUS_VERSION'] = '"v1.1-mozilla"'
 DEFINES['USE_ALLOCA'] = True
 
 # We only need to export symbols if we're built into libgkmedias
 # instead of libxul.
--- a/media/libpng/moz.build
+++ b/media/libpng/moz.build
@@ -35,14 +35,12 @@ if CONFIG['MOZ_PNG_ARM_NEON']:
     ]
 
     SOURCES += [
         'arm/filter_neon.S'
     ]
 
 Library('mozpng')
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
--- a/media/libsoundtouch/src/moz.build
+++ b/media/libsoundtouch/src/moz.build
@@ -27,17 +27,16 @@ UNIFIED_SOURCES += [
 if CONFIG['INTEL_ARCHITECTURE']:
     if CONFIG['MOZ_SAMPLE_TYPE_FLOAT32']:
         SOURCES += ['sse_optimized.cpp']
         SOURCES['sse_optimized.cpp'].flags += CONFIG['SSE2_FLAGS']
     else:
         SOURCES += ['mmx_optimized.cpp']
         SOURCES['mmx_optimized.cpp'].flags += CONFIG['MMX_FLAGS']
 
-MSVC_ENABLE_PGO = True
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 # Use abort() instead of exception in SoundTouch.
 DEFINES['ST_NO_EXCEPTION_HANDLING'] = 1
 
--- a/media/libspeex_resampler/src/moz.build
+++ b/media/libspeex_resampler/src/moz.build
@@ -10,18 +10,16 @@ EXPORTS.speex += [
     'speex_resampler.h',
 ]
 
 SOURCES += [
     'resample.c',
     'simd_detect.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 # We don't compile the full speex codec, only the resampler.
 DEFINES['OUTSIDE_SPEEX'] = True
 
 # Visibility is handled through VISIBILITY_FLAGS and
 # layout/media/symbols.def.in.
 DEFINES['EXPORT'] = ''
--- a/media/libtheora/moz.build
+++ b/media/libtheora/moz.build
@@ -8,18 +8,16 @@ with Files('*'):
     BUG_COMPONENT = ('Core', 'Video/Audio')
 
 EXPORTS.theora += [
     'include/theora/codec.h',
     'include/theora/theoradec.h',
     'include/theora/theoraenc.h',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 # The encoder is currently not included.
 DEFINES['THEORA_DISABLE_ENCODE'] = True
 
--- a/media/libvorbis/moz.build
+++ b/media/libvorbis/moz.build
@@ -43,18 +43,16 @@ SOURCES += [
 LOCAL_INCLUDES += ['lib']
 
 if CONFIG['OS_ARCH'] == 'AIX':
     DEFINES['alloca'] = '__alloca'
 
 if CONFIG['OS_ARCH'] == 'SunOS':
     DEFINES['HAVE_ALLOCA_H'] = True
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 # Suppress warnings in third-party code.
 if CONFIG['GNU_CC']:
     CFLAGS += ['-Wno-uninitialized']
--- a/media/libvpx/moz.build
+++ b/media/libvpx/moz.build
@@ -68,18 +68,16 @@ if CONFIG['VPX_ARM_ASM']:
 
 # boolhuff_armv5te.asm defines the same functions as boolhuff.c instead of
 # using RTCD, so we have to make sure we only add one of the two.
 if 'vp8/encoder/arm/armv5te/boolhuff_armv5te.asm' not in arm_asm_files:
     SOURCES += [
         'vp8/encoder/boolhuff.c',
     ]
 
-MSVC_ENABLE_PGO = True
-
 if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
     NO_VISIBILITY_FLAGS = True
 
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['HAVE_CONFIG_H'] = 'vpx_config.h'
 
 if CONFIG['OS_TARGET'] == 'Android':
--- a/media/webrtc/moz.build
+++ b/media/webrtc/moz.build
@@ -31,16 +31,26 @@ webrtc_non_unified_sources = [
     'trunk/webrtc/modules/audio_processing/noise_suppression_impl.cc',           # Because of name clash in the Handle typedef
     'trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.mm',       # Because of name clash in the nsAutoreleasePool class
     'trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit_info.mm',  # Because of name clash in the nsAutoreleasePool class
     'trunk/webrtc/modules/video_capture/windows/device_info_ds.cc',              # Because of the MEDIASUBTYPE_HDYC variable
     'trunk/webrtc/modules/video_capture/windows/help_functions_ds.cc',           # Because of initguid.h
     'trunk/webrtc/modules/video_capture/windows/sink_filter_ds.cc',              # Because of the MEDIASUBTYPE_HDYC variable and initguid.h
 ]
 
+IPDL_SOURCES += [
+    'signaling/src/peerconnection/PWebrtcGlobal.ipdl',
+]
+
+EXPORTS.mozilla.media.webrtc += [
+    'signaling/src/peerconnection/WebrtcGlobal.h',
+    'signaling/src/peerconnection/WebrtcGlobalChild.h',
+    'signaling/src/peerconnection/WebrtcGlobalParent.h'
+]
+
 GYP_DIRS += ['trunk']
 
 GYP_DIRS['trunk'].input = 'trunk/peerconnection.gyp'
 GYP_DIRS['trunk'].variables = gyp_vars
 GYP_DIRS['trunk'].sandbox_vars['FINAL_LIBRARY'] = 'webrtc'
 GYP_DIRS['trunk'].non_unified_sources += webrtc_non_unified_sources
 
 if CONFIG['MOZ_WEBRTC_SIGNALING']:
--- a/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp
+++ b/media/webrtc/signaling/src/common/browser_logging/WebRtcLog.cpp
@@ -143,17 +143,16 @@ void ConfigWebRtcLog(uint32_t trace_mask
       webrtc::Trace::SetTraceCallback(&gWebRtcCallback);
     } else {
       webrtc::Trace::SetTraceFile(aLogFile.get(), multi_log);
     }
   }
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
   // Capture the final choices for the trace settings.
   mozilla::Preferences::SetCString("media.webrtc.debug.log_file", aLogFile);
-  mozilla::Preferences::SetUint("media.webrtc.debug.trace_mask", trace_mask);
   mozilla::Preferences::SetCString("media.webrtc.debug.aec_log_dir", aAECLogDir);
 #endif
   return;
 }
 
 void StartWebRtcLog(uint32_t log_level)
 {
   if (gWebRtcTraceLoggingOn && log_level != 0) {
--- a/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcMediaCodecVP8VideoCodec.cpp
@@ -169,19 +169,16 @@ public:
   WebrtcAndroidMediaCodec()
     : mEncoderCallback(nullptr)
     , mDecoderCallback(nullptr)
     , isStarted(false)
     , mEnding(false) {
     CSFLogDebug(logTag,  "%s ", __FUNCTION__);
   }
 
-  virtual ~WebrtcAndroidMediaCodec() {
-  }
-
   nsresult Configure(uint32_t width,
                      uint32_t height,
                      const jobject aSurface,
                      uint32_t flags,
                      const char* mime,
                      bool encoder) {
     CSFLogDebug(logTag,  "%s ", __FUNCTION__);
     nsresult res = NS_OK;
@@ -502,16 +499,20 @@ public:
   void SetDecoderCallback(webrtc::DecodedImageCallback* aCallback) {
     mDecoderCallback = aCallback;
   }
 
   void SetEncoderCallback(webrtc::EncodedImageCallback* aCallback) {
     mEncoderCallback = aCallback;
   }
 
+protected:
+  virtual ~WebrtcAndroidMediaCodec() {
+  }
+
 private:
 class OutputDrain : public MediaCodecOutputDrain
   {
   public:
     OutputDrain(WebrtcAndroidMediaCodec* aMediaCodec)
       : MediaCodecOutputDrain()
       , mMediaCodec(aMediaCodec)
     {}
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/PWebrtcGlobal.ipdl
@@ -0,0 +1,31 @@
+/* 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 protocol PContent;
+
+include "mozilla/media/webrtc/WebrtcGlobal.h";
+
+using struct mozilla::dom::RTCStatsReportInternal from "mozilla/dom/RTCStatsReportBinding.h";
+using WebrtcGlobalLog from "mozilla/media/webrtc/WebrtcGlobal.h";
+
+namespace mozilla {
+namespace dom {
+
+async protocol PWebrtcGlobal {
+  manager PContent;
+
+child: // parent -> child messages
+  GetStatsRequest(int aRequestId, nsString aPcIdFilter);
+  GetLogRequest(int aRequestId, nsCString aPattern);
+  SetAecLogging(bool aEnable);
+  SetDebugMode(int aLevel);
+
+parent: // child -> parent messages
+  GetStatsResult(int aRequestId, RTCStatsReportInternal[] aStats);
+  GetLogResult(int aRequestId, WebrtcGlobalLog aLog);
+  __delete__();
+};
+
+} // end namespace net
+} // end namespace mozilla
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.cpp
@@ -95,16 +95,22 @@ NS_IMPL_ISUPPORTS(PeerConnectionCtxShutd
 }
 
 namespace mozilla {
 
 PeerConnectionCtx* PeerConnectionCtx::gInstance;
 nsIThread* PeerConnectionCtx::gMainThread;
 StaticRefPtr<PeerConnectionCtxShutdown> PeerConnectionCtx::gPeerConnectionCtxShutdown;
 
+const std::map<const std::string, PeerConnectionImpl *>&
+PeerConnectionCtx::mGetPeerConnections()
+{
+  return mPeerConnections;
+}
+
 nsresult PeerConnectionCtx::InitializeGlobal(nsIThread *mainThread,
   nsIEventTarget* stsThread) {
   if (!gMainThread) {
     gMainThread = mainThread;
   } else {
     MOZ_ASSERT(gMainThread == mainThread);
   }
 
@@ -314,16 +320,20 @@ nsresult PeerConnectionCtx::Initialize()
   Telemetry::GetHistogramById(Telemetry::WEBRTC_CALL_COUNT)->Add(0);
 
   mTelemetryTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
   MOZ_ASSERT(mTelemetryTimer);
   nsresult rv = mTelemetryTimer->SetTarget(gMainThread);
   NS_ENSURE_SUCCESS(rv, rv);
   mTelemetryTimer->InitWithFuncCallback(EverySecondTelemetryCallback_m, this, 1000,
                                         nsITimer::TYPE_REPEATING_PRECISE_CAN_SKIP);
+
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    WebrtcGlobalChild::Create();
+  }
 #endif // MOZILLA_INTERNAL_API
 
   return NS_OK;
 }
 
 static void GMPReady_m() {
   if (PeerConnectionCtx::isActive()) {
     PeerConnectionCtx::GetInstance()->onGMPReady();
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionCtx.h
@@ -2,16 +2,20 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef peerconnectionctx_h___h__
 #define peerconnectionctx_h___h__
 
 #include <string>
 
+#if !defined(MOZILLA_EXTERNAL_LINKAGE)
+#include "mozilla/media/webrtc/WebrtcGlobalChild.h"
+#endif
+
 #include "mozilla/Attributes.h"
 #include "StaticPtr.h"
 #include "PeerConnectionImpl.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "nsIRunnable.h"
 
 namespace mozilla {
 class PeerConnectionCtxShutdown;
@@ -51,16 +55,17 @@ class PeerConnectionCtx {
 
 #if !defined(MOZILLA_EXTERNAL_LINKAGE)
   // WebrtcGlobalInformation uses this; we put it here so we don't need to
   // create another shutdown observer class.
   mozilla::dom::Sequence<mozilla::dom::RTCStatsReportInternal>
     mStatsForClosedPeerConnections;
 #endif
 
+  const std::map<const std::string, PeerConnectionImpl *>& mGetPeerConnections();
  private:
   // We could make these available only via accessors but it's too much trouble.
   std::map<const std::string, PeerConnectionImpl *> mPeerConnections;
 
   PeerConnectionCtx() :  mGMPReady(false) {}
   // This is a singleton, so don't copy construct it, etc.
   PeerConnectionCtx(const PeerConnectionCtx& other) = delete;
   void operator=(const PeerConnectionCtx& other) = delete;
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobal.h
@@ -0,0 +1,495 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _WEBRTC_GLOBAL_H_
+#define _WEBRTC_GLOBAL_H_
+
+#include "ipc/IPCMessageUtils.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/dom/RTCStatsReportBinding.h"
+
+typedef mozilla::dom::RTCStatsReportInternal StatsReport;
+typedef nsTArray< nsAutoPtr<StatsReport>> RTCReports;
+typedef mozilla::dom::Sequence<nsString> WebrtcGlobalLog;
+
+namespace IPC {
+
+template<typename T>
+struct ParamTraits<mozilla::dom::Optional<T>>
+{
+  typedef mozilla::dom::Optional<T> paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    if (aParam.WasPassed()) {
+      WriteParam(aMsg, true);
+      WriteParam(aMsg, aParam.Value());
+      return;
+    }
+
+    WriteParam(aMsg, false);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    bool was_passed = false;
+
+    if (!ReadParam(aMsg, aIter, &was_passed)) {
+      return false;
+    }
+
+    aResult->Reset(); //XXX Optional_base seems to reach this point with isSome true.
+
+    if (was_passed) {
+      if (!ReadParam(aMsg, aIter, &(aResult->Construct()))) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+};
+
+template<typename T>
+struct ParamTraits<mozilla::dom::Sequence<T>>
+{
+  typedef mozilla::dom::Sequence<T> paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, static_cast<const FallibleTArray<T>&>(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, dynamic_cast<FallibleTArray<T>*>(aResult));
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCStatsType> :
+  public ContiguousEnumSerializer<
+    mozilla::dom::RTCStatsType,
+    mozilla::dom::RTCStatsType::Inboundrtp,
+    mozilla::dom::RTCStatsType::EndGuard_>
+{};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCStatsIceCandidatePairState> :
+  public ContiguousEnumSerializer<
+    mozilla::dom::RTCStatsIceCandidatePairState,
+    mozilla::dom::RTCStatsIceCandidatePairState::Frozen,
+    mozilla::dom::RTCStatsIceCandidatePairState::EndGuard_>
+{};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCStatsIceCandidateType> :
+  public ContiguousEnumSerializer<
+    mozilla::dom::RTCStatsIceCandidateType,
+    mozilla::dom::RTCStatsIceCandidateType::Host,
+    mozilla::dom::RTCStatsIceCandidateType::EndGuard_>
+{};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCStatsReportInternal>
+{
+  typedef mozilla::dom::RTCStatsReportInternal paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mClosed);
+    WriteParam(aMsg, aParam.mCodecStats);
+    WriteParam(aMsg, aParam.mIceCandidatePairStats);
+    WriteParam(aMsg, aParam.mIceCandidateStats);
+    WriteParam(aMsg, aParam.mIceComponentStats);
+    WriteParam(aMsg, aParam.mInboundRTPStreamStats);
+    WriteParam(aMsg, aParam.mLocalSdp);
+    WriteParam(aMsg, aParam.mMediaStreamStats);
+    WriteParam(aMsg, aParam.mMediaStreamTrackStats);
+    WriteParam(aMsg, aParam.mOutboundRTPStreamStats);
+    WriteParam(aMsg, aParam.mPcid);
+    WriteParam(aMsg, aParam.mRemoteSdp);
+    WriteParam(aMsg, aParam.mTimestamp);
+    WriteParam(aMsg, aParam.mTransportStats);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mClosed)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mCodecStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mIceCandidatePairStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mIceCandidateStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mIceComponentStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mInboundRTPStreamStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mLocalSdp)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMediaStreamStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMediaStreamTrackStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mOutboundRTPStreamStats)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPcid)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mRemoteSdp)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTimestamp)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTransportStats))) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+typedef mozilla::dom::RTCStats RTCStats;
+
+static void WriteRTCStats(Message* aMsg, const RTCStats& aParam)
+{
+  // RTCStats base class
+  WriteParam(aMsg, aParam.mId);
+  WriteParam(aMsg, aParam.mTimestamp);
+  WriteParam(aMsg, aParam.mType);
+}
+
+static bool ReadRTCStats(const Message* aMsg, void** aIter, RTCStats* aResult)
+{
+  // RTCStats base class
+  if (!ReadParam(aMsg, aIter, &(aResult->mId)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mTimestamp)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mType))) {
+    return false;
+  }
+
+  return true;
+}
+
+template<>
+struct ParamTraits<mozilla::dom::RTCCodecStats>
+{
+  typedef mozilla::dom::RTCCodecStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mChannels);
+    WriteParam(aMsg, aParam.mClockRate);
+    WriteParam(aMsg, aParam.mCodec);
+    WriteParam(aMsg, aParam.mParameters);
+    WriteParam(aMsg, aParam.mPayloadType);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mChannels)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mClockRate)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mCodec)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mParameters)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPayloadType)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+ }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCIceCandidatePairStats>
+{
+  typedef mozilla::dom::RTCIceCandidatePairStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mComponentId);
+    WriteParam(aMsg, aParam.mLocalCandidateId);
+    WriteParam(aMsg, aParam.mMozPriority);
+    WriteParam(aMsg, aParam.mNominated);
+    WriteParam(aMsg, aParam.mReadable);
+    WriteParam(aMsg, aParam.mRemoteCandidateId);
+    WriteParam(aMsg, aParam.mSelected);
+    WriteParam(aMsg, aParam.mState);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mComponentId)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mLocalCandidateId)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMozPriority)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mNominated)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mReadable)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mRemoteCandidateId)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mSelected)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mState)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+ }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCIceCandidateStats>
+{
+  typedef mozilla::dom::RTCIceCandidateStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mCandidateId);
+    WriteParam(aMsg, aParam.mCandidateType);
+    WriteParam(aMsg, aParam.mComponentId);
+    WriteParam(aMsg, aParam.mIpAddress);
+    WriteParam(aMsg, aParam.mMozLocalTransport);
+    WriteParam(aMsg, aParam.mPortNumber);
+    WriteParam(aMsg, aParam.mTransport);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mCandidateId)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mCandidateType)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mComponentId)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mIpAddress)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMozLocalTransport)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPortNumber)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTransport)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+ }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCIceComponentStats>
+{
+  typedef mozilla::dom::RTCIceComponentStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mActiveConnection);
+    WriteParam(aMsg, aParam.mBytesReceived);
+    WriteParam(aMsg, aParam.mBytesSent);
+    WriteParam(aMsg, aParam.mComponent);
+    WriteParam(aMsg, aParam.mTransportId);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mActiveConnection)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mComponent)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTransportId)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+static void WriteRTCRTPStreamStats(
+              Message* aMsg,
+              const mozilla::dom::RTCRTPStreamStats& aParam)
+{
+    WriteParam(aMsg, aParam.mBitrateMean);
+    WriteParam(aMsg, aParam.mBitrateStdDev);
+    WriteParam(aMsg, aParam.mCodecId);
+    WriteParam(aMsg, aParam.mFramerateMean);
+    WriteParam(aMsg, aParam.mFramerateStdDev);
+    WriteParam(aMsg, aParam.mIsRemote);
+    WriteParam(aMsg, aParam.mMediaTrackId);
+    WriteParam(aMsg, aParam.mMediaType);
+    WriteParam(aMsg, aParam.mRemoteId);
+    WriteParam(aMsg, aParam.mSsrc);
+    WriteParam(aMsg, aParam.mTransportId);
+}
+
+static bool ReadRTCRTPStreamStats(
+              const Message* aMsg, void** aIter,
+              mozilla::dom::RTCRTPStreamStats* aResult)
+{
+  if (!ReadParam(aMsg, aIter, &(aResult->mBitrateMean)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mBitrateStdDev)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mCodecId)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mFramerateMean)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mFramerateStdDev)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mIsRemote)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mMediaTrackId)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mMediaType)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mRemoteId)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mSsrc)) ||
+      !ReadParam(aMsg, aIter, &(aResult->mTransportId))) {
+    return false;
+  }
+
+  return true;
+}
+
+template<>
+struct ParamTraits<mozilla::dom::RTCInboundRTPStreamStats>
+{
+  typedef mozilla::dom::RTCInboundRTPStreamStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mBytesReceived);
+    WriteParam(aMsg, aParam.mDiscardedPackets);
+    WriteParam(aMsg, aParam.mJitter);
+    WriteParam(aMsg, aParam.mMozAvSyncDelay);
+    WriteParam(aMsg, aParam.mMozJitterBufferDelay);
+    WriteParam(aMsg, aParam.mMozRtt);
+    WriteParam(aMsg, aParam.mPacketsLost);
+    WriteParam(aMsg, aParam.mPacketsReceived);
+    WriteRTCRTPStreamStats(aMsg, aParam);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mDiscardedPackets)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mJitter)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMozAvSyncDelay)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMozJitterBufferDelay)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mMozRtt)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPacketsLost)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPacketsReceived)) ||
+        !ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCOutboundRTPStreamStats>
+{
+  typedef mozilla::dom::RTCOutboundRTPStreamStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mBytesSent);
+    WriteParam(aMsg, aParam.mDroppedFrames);
+    WriteParam(aMsg, aParam.mPacketsSent);
+    WriteParam(aMsg, aParam.mTargetBitrate);
+    WriteRTCRTPStreamStats(aMsg, aParam);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mDroppedFrames)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mPacketsSent)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTargetBitrate)) ||
+        !ReadRTCRTPStreamStats(aMsg, aIter, aResult) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCMediaStreamStats>
+{
+  typedef mozilla::dom::RTCMediaStreamStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mStreamIdentifier);
+    WriteParam(aMsg, aParam.mTrackIds);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mStreamIdentifier)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTrackIds)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCTransportStats>
+{
+  typedef mozilla::dom::RTCTransportStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mBytesReceived);
+    WriteParam(aMsg, aParam.mBytesSent);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mBytesReceived)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mBytesSent)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+
+template<>
+struct ParamTraits<mozilla::dom::RTCMediaStreamTrackStats>
+{
+  typedef mozilla::dom::RTCMediaStreamTrackStats paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mAudioLevel);
+    WriteParam(aMsg, aParam.mEchoReturnLoss);
+    WriteParam(aMsg, aParam.mEchoReturnLossEnhancement);
+    WriteParam(aMsg, aParam.mFrameHeight);
+    WriteParam(aMsg, aParam.mFrameWidth);
+    WriteParam(aMsg, aParam.mFramesCorrupted);
+    WriteParam(aMsg, aParam.mFramesDecoded);
+    WriteParam(aMsg, aParam.mFramesDropped);
+    WriteParam(aMsg, aParam.mFramesPerSecond);
+    WriteParam(aMsg, aParam.mFramesReceived);
+    WriteParam(aMsg, aParam.mFramesSent);
+    WriteParam(aMsg, aParam.mRemoteSource);
+    WriteParam(aMsg, aParam.mSsrcIds);
+    WriteParam(aMsg, aParam.mTrackIdentifier);
+    WriteRTCStats(aMsg, aParam);
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    if (!ReadParam(aMsg, aIter, &(aResult->mAudioLevel)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLoss)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mEchoReturnLossEnhancement)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFrameHeight)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFrameWidth)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesCorrupted)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesDecoded)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesDropped)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesPerSecond)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesReceived)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mFramesSent)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mRemoteSource)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mSsrcIds)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mTrackIdentifier)) ||
+        !ReadRTCStats(aMsg, aIter, aResult)) {
+      return false;
+    }
+
+    return true;
+  }
+};
+} // namespace ipc
+
+#endif  // _WEBRTC_GLOBAL_H_
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalChild.h
@@ -0,0 +1,38 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _WEBRTC_GLOBAL_CHILD_H_
+#define _WEBRTC_GLOBAL_CHILD_H_
+
+#include "mozilla/dom/PWebrtcGlobalChild.h"
+
+namespace mozilla {
+namespace dom {
+
+class WebrtcGlobalChild :
+  public PWebrtcGlobalChild
+{
+  friend class ContentChild;
+
+  bool mShutdown;
+
+  MOZ_IMPLICIT WebrtcGlobalChild();
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+  virtual bool RecvGetStatsRequest(const int& aRequestId,
+                                   const nsString& aPcIdFilter) override;
+  virtual bool RecvGetLogRequest(const int& aReqestId,
+                                 const nsCString& aPattern) override;
+  virtual bool RecvSetAecLogging(const bool& aEnable) override;
+  virtual bool RecvSetDebugMode(const int& aLevel) override;
+
+public:
+  virtual ~WebrtcGlobalChild();
+  static WebrtcGlobalChild* Create();
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif  // _WEBRTC_GLOBAL_CHILD_H_
--- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
@@ -1,273 +1,824 @@
 /* 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 "WebrtcGlobalInformation.h"
+#include "WebrtcGlobalChild.h"
+#include "WebrtcGlobalParent.h"
 
 #include <deque>
 #include <string>
+#include <algorithm>
+#include <vector>
+#include <map>
+#include <queue>
 
 #include "CSFLog.h"
 #include "WebRtcLog.h"
 #include "mozilla/dom/WebrtcGlobalInformationBinding.h"
+#include "WebrtcGlobal.h"
+#include "mozilla/dom/ContentChild.h"
 
 #include "nsAutoPtr.h"
 #include "nsNetCID.h" // NS_SOCKETTRANSPORTSERVICE_CONTRACTID
 #include "nsServiceManagerUtils.h" // do_GetService
 #include "mozilla/ErrorResult.h"
 #include "mozilla/Vector.h"
 #include "nsProxyRelease.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/unused.h"
+#include "mozilla/StaticMutex.h"
+#include "mozilla/RefPtr.h"
 
 #include "rlogringbuffer.h"
 #include "runnable_utils.h"
 #include "PeerConnectionCtx.h"
 #include "PeerConnectionImpl.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 
 static const char* logTag = "WebrtcGlobalInformation";
 
 namespace mozilla {
-
 namespace dom {
 
 typedef Vector<nsAutoPtr<RTCStatsQuery>> RTCStatsQueries;
+typedef nsTArray<RTCStatsReportInternal> Stats;
+
+template<class Request, typename Callback,
+         typename Result, typename QueryParam>
+class RequestManager
+{
+public:
+
+  static Request* Create(Callback& aCallback, QueryParam& aParam)
+  {
+    mozilla::StaticMutexAutoLock lock(sMutex);
+
+    int id = ++sLastRequestId;
+    auto result = sRequests.insert(
+      std::make_pair(id, Request(id, aCallback, aParam)));
+
+    if (!result.second) {
+      return nullptr;
+    }
+
+    return &result.first->second;
+  }
+
+  static void Delete(int aId)
+  {
+    mozilla::StaticMutexAutoLock lock(sMutex);
+    sRequests.erase(aId);
+  }
+
+  static Request* Get(int aId)
+  {
+    mozilla::StaticMutexAutoLock lock(sMutex);
+    auto r = sRequests.find(aId);
+
+    if (r == sRequests.end()) {
+      return nullptr;
+    }
+
+    return &r->second;
+  }
+
+  Result mResult;
+  std::queue<RefPtr<WebrtcGlobalParent>> mContactList;
+  const int mRequestId;
+
+  RefPtr<WebrtcGlobalParent> GetNextParent()
+  {
+    while (!mContactList.empty()) {
+      RefPtr<WebrtcGlobalParent> next = mContactList.front();
+      mContactList.pop();
+      if (next->IsActive()) {
+        return next;
+      }
+    }
+
+    return nullptr;
+  }
+
+  void Complete()
+  {
+    ErrorResult rv;
+    mCallback.get()->Call(mResult, rv);
+
+    if (rv.Failed()) {
+      CSFLogError(logTag, "Error firing stats observer callback");
+    }
+  }
+
+protected:
+  // The mutex is used to protect two related operations involving the sRequest map
+  // and the sLastRequestId. For the map, it prevents more than one thread from
+  // adding or deleting map entries at the same time. For id generation,
+  // it creates an atomic allocation and increment.
+  static mozilla::StaticMutex sMutex;
+  static std::map<int, Request> sRequests;
+  static int sLastRequestId;
+
+  Callback mCallback;
+
+  explicit RequestManager(int aId, Callback& aCallback)
+    : mRequestId(aId)
+    , mCallback(aCallback)
+  {}
+  ~RequestManager() {}
+private:
+
+  RequestManager() = delete;
+  RequestManager& operator=(const RequestManager&) = delete;
+};
+
+template<class Request, typename Callback,
+         typename Result, typename QueryParam>
+mozilla::StaticMutex RequestManager<Request, Callback, Result, QueryParam>::sMutex;
+template<class Request, typename Callback,
+         typename Result, typename QueryParam>
+std::map<int, Request> RequestManager<Request, Callback, Result, QueryParam>::sRequests;
+template<class Request, typename Callback,
+         typename Result, typename QueryParam>
+int RequestManager<Request, Callback, Result, QueryParam>::sLastRequestId;
+
+typedef nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> StatsRequestCallback;
+
+class StatsRequest
+  : public RequestManager<StatsRequest,
+                          StatsRequestCallback,
+                          WebrtcGlobalStatisticsReport,
+                          nsAString>
+{
+public:
+  const nsString mPcIdFilter;
+  explicit StatsRequest(int aId, StatsRequestCallback& aCallback, nsAString& aFilter)
+    : RequestManager(aId, aCallback)
+    , mPcIdFilter(aFilter)
+  {
+    mResult.mReports.Construct();
+  }
+
+private:
+  StatsRequest() = delete;
+  StatsRequest& operator=(const StatsRequest&) = delete;
+};
+
+typedef nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> LogRequestCallback;
+
+class LogRequest
+  : public RequestManager<LogRequest,
+                          LogRequestCallback,
+                          Sequence<nsString>,
+                          const nsACString>
+{
+public:
+  const nsCString mPattern;
+  explicit LogRequest(int aId, LogRequestCallback& aCallback, const nsACString& aPattern)
+    : RequestManager(aId, aCallback)
+    , mPattern(aPattern)
+  {}
+
+private:
+  LogRequest() = delete;
+  LogRequest& operator=(const LogRequest&) = delete;
+};
+
+class WebrtcContentParents
+{
+public:
+  static WebrtcGlobalParent* Alloc();
+  static void Dealloc(WebrtcGlobalParent* aParent);
+  static bool Empty()
+  {
+    return sContentParents.empty();
+  }
+  static const std::vector<RefPtr<WebrtcGlobalParent>>& GetAll()
+  {
+    return sContentParents;
+  }
+private:
+  static std::vector<RefPtr<WebrtcGlobalParent>> sContentParents;
+  WebrtcContentParents() = delete;
+  WebrtcContentParents(const WebrtcContentParents&) = delete;
+  WebrtcContentParents& operator=(const WebrtcContentParents&) = delete;
+};
+
+std::vector<RefPtr<WebrtcGlobalParent>> WebrtcContentParents::sContentParents;
+
+WebrtcGlobalParent* WebrtcContentParents::Alloc()
+{
+  RefPtr<WebrtcGlobalParent> cp = new WebrtcGlobalParent;
+  sContentParents.push_back(cp);
+  return cp.get();
+}
+
+void WebrtcContentParents::Dealloc(WebrtcGlobalParent* aParent)
+{
+  if (aParent) {
+    aParent->mShutdown = true;
+    auto cp = std::find(sContentParents.begin(), sContentParents.end(), aParent);
+    if (cp != sContentParents.end()) {
+      sContentParents.erase(cp);
+    }
+  }
+}
 
 static PeerConnectionCtx* GetPeerConnectionCtx()
 {
   if(PeerConnectionCtx::isActive()) {
     MOZ_ASSERT(PeerConnectionCtx::GetInstance());
     return PeerConnectionCtx::GetInstance();
   }
   return nullptr;
 }
 
-static void OnStatsReport_m(
-  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> aStatsCallback,
-  nsAutoPtr<RTCStatsQueries> aQueryList)
+static void
+OnStatsReport_m(WebrtcGlobalChild* aThisChild,
+                const int aRequestId,
+                nsAutoPtr<RTCStatsQueries> aQueryList)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aQueryList);
 
-  WebrtcGlobalStatisticsReport report;
-  report.mReports.Construct();
+  if (aThisChild) {
+    Stats stats;
 
-  // Reports for the currently active PeerConnections
-  for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) {
-    MOZ_ASSERT(*q);
-    report.mReports.Value().AppendElement(*(*q)->report);
+    // Copy stats generated for the currently active PeerConnections
+    for (auto&& query : *aQueryList) {
+      stats.AppendElement(*(query->report));
+    }
+    // Reports saved for closed/destroyed PeerConnections
+    auto ctx = PeerConnectionCtx::GetInstance();
+    if (ctx) {
+      for (auto&& pc : ctx->mStatsForClosedPeerConnections) {
+        stats.AppendElement(pc);
+      }
+    }
+
+    unused << aThisChild->SendGetStatsResult(aRequestId, stats);
+    return;
   }
 
-  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
-  if (ctx) {
-    // Reports for closed/destroyed PeerConnections
-    report.mReports.Value().AppendElements(ctx->mStatsForClosedPeerConnections);
+  // This is the last stats report to be collected. (Must be the gecko process).
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+
+  StatsRequest* request = StatsRequest::Get(aRequestId);
+
+  if (!request) {
+    CSFLogError(logTag, "Bad RequestId");
+    return;
   }
 
-  ErrorResult rv;
-  aStatsCallback.get()->Call(report, rv);
+  for (auto&& query : *aQueryList) {
+    request->mResult.mReports.Value().AppendElement(*(query->report));
+  }
 
-  if (rv.Failed()) {
-    CSFLogError(logTag, "Error firing stats observer callback");
+  // Reports saved for closed/destroyed PeerConnections
+  auto ctx = PeerConnectionCtx::GetInstance();
+  if (ctx) {
+    for (auto&& pc : ctx->mStatsForClosedPeerConnections) {
+      request->mResult.mReports.Value().AppendElement(pc);
+    }
   }
+
+  request->Complete();
+  StatsRequest::Delete(aRequestId);
 }
 
-static void GetAllStats_s(
-  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> aStatsCallback,
-  nsAutoPtr<RTCStatsQueries> aQueryList)
+static void
+GetAllStats_s(WebrtcGlobalChild* aThisChild,
+              const int aRequestId,
+              nsAutoPtr<RTCStatsQueries> aQueryList)
 {
   MOZ_ASSERT(aQueryList);
+  // The call to PeerConnetionImpl must happen on the from a runnable
+  // dispatched on the STS thread.
 
-  for (auto q = aQueryList->begin(); q != aQueryList->end(); ++q) {
-    MOZ_ASSERT(*q);
-    PeerConnectionImpl::ExecuteStatsQuery_s(*q);
+  // Get stats from active connections.
+  for (auto&& query : *aQueryList) {
+    PeerConnectionImpl::ExecuteStatsQuery_s(query);
   }
 
+  // After the RTCStatsQueries have been filled in, control must return
+  // to the main thread before their eventual destruction.
   NS_DispatchToMainThread(WrapRunnableNM(&OnStatsReport_m,
-                                         aStatsCallback,
+                                         aThisChild,
+                                         aRequestId,
                                          aQueryList),
                           NS_DISPATCH_NORMAL);
 }
 
-static void OnGetLogging_m(
-  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> aLoggingCallback,
-  const std::string& aPattern,
-  nsAutoPtr<std::deque<std::string>> aLogList)
+static void OnGetLogging_m(WebrtcGlobalChild* aThisChild,
+                           const int aRequestId,
+                           nsAutoPtr<std::deque<std::string>> aLogList)
 {
-  ErrorResult rv;
-  if (!aLogList->empty()) {
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (aThisChild) {
+    // Add this log to the collection of logs and call into
+    // the next content process.
     Sequence<nsString> nsLogs;
-    for (auto l = aLogList->begin(); l != aLogList->end(); ++l) {
-      nsLogs.AppendElement(NS_ConvertUTF8toUTF16(l->c_str()));
+
+    if (!aLogList->empty()) {
+      for (auto& line : *aLogList) {
+        nsLogs.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()));
+      }
+      nsLogs.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++"));
     }
-    aLoggingCallback.get()->Call(nsLogs, rv);
+
+    unused << aThisChild->SendGetLogResult(aRequestId, nsLogs);
+    return;
   }
 
-  if (rv.Failed()) {
-    CSFLogError(logTag, "Error firing logging observer callback");
+  // This is the last log to be collected. (Must be the gecko process).
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+
+  LogRequest* request = LogRequest::Get(aRequestId);
+
+  if (!request) {
+    CSFLogError(logTag, "Bad RequestId");
+    return;
   }
+
+  if (!aLogList->empty()) {
+    for (auto& line : *aLogList) {
+      request->mResult.AppendElement(NS_ConvertUTF8toUTF16(line.c_str()));
+    }
+    request->mResult.AppendElement(NS_LITERAL_STRING("+++++++ END ++++++++"));
+  }
+
+  request->Complete();
+  LogRequest::Delete(aRequestId);
 }
 
-static void GetLogging_s(
-  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> aLoggingCallback,
-  const std::string& aPattern)
+static void GetLogging_s(WebrtcGlobalChild* aThisChild,
+                         const int aRequestId,
+                         const std::string& aPattern)
 {
+  // Request log while not on the main thread.
   RLogRingBuffer* logs = RLogRingBuffer::GetInstance();
   nsAutoPtr<std::deque<std::string>> result(new std::deque<std::string>);
   // Might not exist yet.
   if (logs) {
     logs->Filter(aPattern, 0, result);
   }
+  // Return to main thread to complete processing.
   NS_DispatchToMainThread(WrapRunnableNM(&OnGetLogging_m,
-                                         aLoggingCallback,
-                                         aPattern,
+                                         aThisChild,
+                                         aRequestId,
                                          result),
                           NS_DISPATCH_NORMAL);
 }
 
+static nsresult
+BuildStatsQueryList(
+  const std::map<const std::string, PeerConnectionImpl *>& aPeerConnections,
+  const nsAString& aPcIdFilter,
+  RTCStatsQueries* queries)
+{
+  nsresult rv;
+
+  for (auto&& pc : aPeerConnections) {
+    MOZ_ASSERT(pc.second);
+    if (aPcIdFilter.IsEmpty() ||
+        aPcIdFilter.EqualsASCII(pc.second->GetIdAsAscii().c_str())) {
+      if (pc.second->HasMedia()) {
+        queries->append(nsAutoPtr<RTCStatsQuery>(new RTCStatsQuery(true)));
+        rv = pc.second->BuildStatsQuery_m(nullptr, queries->back()); // all tracks
+        if (NS_WARN_IF(NS_FAILED(rv))) {
+          return rv;
+        }
+        MOZ_ASSERT(queries->back()->report);
+      }
+    }
+  }
+
+  return NS_OK;
+}
+
+static nsresult
+RunStatsQuery(
+  const std::map<const std::string, PeerConnectionImpl *>& aPeerConnections,
+  const nsAString& aPcIdFilter,
+  WebrtcGlobalChild* aThisChild,
+  const int aRequestId)
+{
+  auto* queries = new RTCStatsQueries;
+  nsresult rv = BuildStatsQueryList(aPeerConnections, aPcIdFilter, queries);
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIEventTarget> stsThread =
+    do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+
+  if (NS_FAILED(rv)) {
+    return rv;
+  } else if (!stsThread) {
+    return NS_ERROR_FAILURE;
+  }
+
+  rv = RUN_ON_THREAD(stsThread,
+                     WrapRunnableNM(&GetAllStats_s,
+                                    aThisChild,
+                                    aRequestId,
+                                    nsAutoPtr<RTCStatsQueries>(queries)),
+                     NS_DISPATCH_NORMAL);
+  return rv;
+}
 
 void
 WebrtcGlobalInformation::GetAllStats(
   const GlobalObject& aGlobal,
   WebrtcGlobalStatisticsCallback& aStatsCallback,
   const Optional<nsAString>& pcIdFilter,
   ErrorResult& aRv)
 {
   if (!NS_IsMainThread()) {
     aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
     return;
   }
 
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+
+  // CallbackObject does not support threadsafe refcounting, and must be
+  // destroyed on main.
+  StatsRequestCallback callbackHandle(
+    new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(&aStatsCallback));
+
+  nsString filter;
+  if (pcIdFilter.WasPassed()) {
+    filter = pcIdFilter.Value();
+  }
+
+  StatsRequest* request = StatsRequest::Create(callbackHandle, filter);
+
+  if (!request) {
+    aRv.Throw(NS_ERROR_FAILURE);
+    return;
+  }
+
+  if (!WebrtcContentParents::Empty()) {
+    // Pass on the request to any content based PeerConnections.
+    for (auto& cp : WebrtcContentParents::GetAll()) {
+      request->mContactList.push(cp);
+    }
+
+    auto next = request->GetNextParent();
+    if (next) {
+      aRv = next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter) ?
+                NS_OK : NS_ERROR_FAILURE;
+      return;
+    }
+  }
+  // No content resident PeerConnectionCtx instances.
+  // Check this process.
+  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
+  nsresult rv;
+
+  if (ctx) {
+    rv = RunStatsQuery(ctx->mGetPeerConnections(),
+                       filter, nullptr, request->mRequestId);
+
+    if (NS_FAILED(rv)) {
+      StatsRequest::Delete(request->mRequestId);
+    }
+  } else {
+    // Just send back an empty report.
+    rv = NS_OK;
+    request->Complete();
+    StatsRequest::Delete(request->mRequestId);
+  }
+
+  aRv = rv;
+  return;
+}
+
+static nsresult
+RunLogQuery(const nsCString& aPattern,
+            WebrtcGlobalChild* aThisChild,
+            const int aRequestId)
+{
   nsresult rv;
   nsCOMPtr<nsIEventTarget> stsThread =
     do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
 
   if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-    return;
-  }
-
-  if (!stsThread) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
-    return;
+    return rv;
+  } else if (!stsThread) {
+    return NS_ERROR_FAILURE;
   }
 
-  nsAutoPtr<RTCStatsQueries> queries(new RTCStatsQueries);
-
-  // If there is no PeerConnectionCtx, go through the same motions, since
-  // the API consumer doesn't care why there are no PeerConnectionImpl.
-  PeerConnectionCtx *ctx = GetPeerConnectionCtx();
-  if (ctx) {
-    for (auto p = ctx->mPeerConnections.begin();
-         p != ctx->mPeerConnections.end();
-         ++p) {
-      MOZ_ASSERT(p->second);
-
-      if (!pcIdFilter.WasPassed() ||
-          pcIdFilter.Value().EqualsASCII(p->second->GetIdAsAscii().c_str())) {
-        if (p->second->HasMedia()) {
-          queries->append(nsAutoPtr<RTCStatsQuery>(new RTCStatsQuery(true)));
-          rv = p->second->BuildStatsQuery_m(nullptr, queries->back()); // all tracks
-          if (NS_WARN_IF(NS_FAILED(rv))) {
-            aRv.Throw(rv);
-            return;
-          }
-          MOZ_ASSERT(queries->back()->report);
-        }
-      }
-    }
-  }
-
-  // CallbackObject does not support threadsafe refcounting, and must be
-  // destroyed on main.
-  nsMainThreadPtrHandle<WebrtcGlobalStatisticsCallback> callbackHandle(
-    new nsMainThreadPtrHolder<WebrtcGlobalStatisticsCallback>(&aStatsCallback));
-
   rv = RUN_ON_THREAD(stsThread,
-                     WrapRunnableNM(&GetAllStats_s, callbackHandle, queries),
+                     WrapRunnableNM(&GetLogging_s,
+                                    aThisChild,
+                                    aRequestId,
+                                    aPattern.get()),
                      NS_DISPATCH_NORMAL);
-  aRv = rv;
+  return rv;
 }
 
 void
 WebrtcGlobalInformation::GetLogging(
   const GlobalObject& aGlobal,
   const nsAString& aPattern,
   WebrtcGlobalLoggingCallback& aLoggingCallback,
   ErrorResult& aRv)
 {
   if (!NS_IsMainThread()) {
     aRv.Throw(NS_ERROR_NOT_SAME_THREAD);
     return;
   }
 
-  nsresult rv;
-  nsCOMPtr<nsIEventTarget> stsThread =
-    do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+
+  // CallbackObject does not support threadsafe refcounting, and must be
+  // destroyed on main.
+  LogRequestCallback callbackHandle(
+    new nsMainThreadPtrHolder<WebrtcGlobalLoggingCallback>(&aLoggingCallback));
 
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-    return;
-  }
+  nsAutoCString pattern;
+  CopyUTF16toUTF8(aPattern, pattern);
 
-  if (!stsThread) {
-    aRv.Throw(NS_ERROR_UNEXPECTED);
+  LogRequest* request = LogRequest::Create(callbackHandle, pattern);
+
+  if (!request) {
+    aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  std::string pattern(NS_ConvertUTF16toUTF8(aPattern).get());
+  if (!WebrtcContentParents::Empty()) {
+  // Pass on the request to any content based PeerConnections.
+    for (auto& cp : WebrtcContentParents::GetAll()) {
+      request->mContactList.push(cp);
+    }
 
-  // CallbackObject does not support threadsafe refcounting, and must be
-  // destroyed on main.
-  nsMainThreadPtrHandle<WebrtcGlobalLoggingCallback> callbackHandle(
-    new nsMainThreadPtrHolder<WebrtcGlobalLoggingCallback>(&aLoggingCallback));
+    auto next = request->GetNextParent();
+    if (next) {
+      aRv = next->SendGetLogRequest(request->mRequestId, request->mPattern) ?
+                NS_OK : NS_ERROR_FAILURE;
+      return;
+    }
+  }
 
-  rv = RUN_ON_THREAD(stsThread,
-                     WrapRunnableNM(&GetLogging_s, callbackHandle, pattern),
-                     NS_DISPATCH_NORMAL);
+  nsresult rv = RunLogQuery(request->mPattern, nullptr, request->mRequestId);
 
   if (NS_FAILED(rv)) {
-    aLoggingCallback.Release();
+    LogRequest::Delete(request->mRequestId);
   }
 
   aRv = rv;
+  return;
 }
 
 static int32_t sLastSetLevel = 0;
 static bool sLastAECDebug = false;
 
 void
 WebrtcGlobalInformation::SetDebugLevel(const GlobalObject& aGlobal, int32_t aLevel)
 {
   StartWebRtcLog(webrtc::TraceLevel(aLevel));
   sLastSetLevel = aLevel;
+
+  for (auto& cp : WebrtcContentParents::GetAll()){
+    unused << cp->SendSetDebugMode(aLevel);
+  }
 }
 
 int32_t
 WebrtcGlobalInformation::DebugLevel(const GlobalObject& aGlobal)
 {
   return sLastSetLevel;
 }
 
 void
 WebrtcGlobalInformation::SetAecDebug(const GlobalObject& aGlobal, bool aEnable)
 {
   StartWebRtcLog(sLastSetLevel); // to make it read the aec path
   webrtc::Trace::set_aec_debug(aEnable);
   sLastAECDebug = aEnable;
+
+  for (auto& cp : WebrtcContentParents::GetAll()){
+    unused << cp->SendSetAecLogging(aEnable);
+  }
 }
 
 bool
 WebrtcGlobalInformation::AecDebug(const GlobalObject& aGlobal)
 {
   return sLastAECDebug;
 }
 
+bool
+WebrtcGlobalParent::RecvGetStatsResult(const int& aRequestId,
+                                       nsTArray<RTCStatsReportInternal>&& Stats)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  nsresult rv = NS_OK;
+
+  StatsRequest* request = StatsRequest::Get(aRequestId);
+
+  if (!request) {
+    CSFLogError(logTag, "Bad RequestId");
+    return false;
+  }
+
+  for (auto&& s : Stats) {
+    request->mResult.mReports.Value().AppendElement(s);
+  }
+
+  auto next = request->GetNextParent();
+  if (next) {
+    // There are more content instances to query.
+    return next->SendGetStatsRequest(request->mRequestId, request->mPcIdFilter);
+  }
+
+  // Content queries complete, run chrome instance query if applicable
+  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
+
+  if (ctx) {
+    rv = RunStatsQuery(ctx->mGetPeerConnections(),
+                       request->mPcIdFilter, nullptr, aRequestId);
+  } else {
+    // No instance in the process, return the collections as is
+    request->Complete();
+    StatsRequest::Delete(aRequestId);
+  }
+
+  return NS_SUCCEEDED(rv);
+}
+
+bool
+WebrtcGlobalParent::RecvGetLogResult(const int& aRequestId,
+                                     const WebrtcGlobalLog& aLog)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  LogRequest* request = LogRequest::Get(aRequestId);
+
+  if (!request) {
+    CSFLogError(logTag, "Bad RequestId");
+    return false;
+  }
+  request->mResult.AppendElements(aLog);
+
+  auto next = request->GetNextParent();
+  if (next) {
+    // There are more content instances to query.
+    return next->SendGetLogRequest(request->mRequestId, request->mPattern);
+  }
+
+  // Content queries complete, run chrome instance query if applicable
+  nsresult rv = RunLogQuery(request->mPattern, nullptr, aRequestId);
+
+  if (NS_FAILED(rv)) {
+    //Unable to get gecko process log. Return what has been collected.
+    CSFLogError(logTag, "Unable to extract chrome process log");
+    request->Complete();
+    LogRequest::Delete(aRequestId);
+  }
+
+  return true;
+}
+
+WebrtcGlobalParent*
+WebrtcGlobalParent::Alloc()
+{
+  return WebrtcContentParents::Alloc();
+}
+
+bool
+WebrtcGlobalParent::Dealloc(WebrtcGlobalParent * aActor)
+{
+  WebrtcContentParents::Dealloc(aActor);
+  return true;
+}
+
+void
+WebrtcGlobalParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mShutdown = true;
+  return;
+}
+
+bool
+WebrtcGlobalParent::Recv__delete__()
+{
+  return true;
+}
+
+MOZ_IMPLICIT WebrtcGlobalParent::WebrtcGlobalParent()
+  : mShutdown(false)
+{
+  MOZ_COUNT_CTOR(WebrtcGlobalParent);
+}
+
+MOZ_IMPLICIT WebrtcGlobalParent::~WebrtcGlobalParent()
+{
+  MOZ_COUNT_DTOR(WebrtcGlobalParent);
+}
+
+bool
+WebrtcGlobalChild::RecvGetStatsRequest(const int& aRequestId,
+                                       const nsString& aPcIdFilter)
+{
+  if (mShutdown) {
+    return true;
+  }
+
+  PeerConnectionCtx* ctx = GetPeerConnectionCtx();
+
+  if (ctx) {
+    nsresult rv = RunStatsQuery(ctx->mGetPeerConnections(),
+                                aPcIdFilter, this, aRequestId);
+    return NS_SUCCEEDED(rv);
+  }
+
+  nsTArray<RTCStatsReportInternal> empty_stats;
+  SendGetStatsResult(aRequestId, empty_stats);
+
+  return true;
+}
+
+bool
+WebrtcGlobalChild::RecvGetLogRequest(const int& aRequestId,
+                                     const nsCString& aPattern)
+{
+  if (mShutdown) {
+    return true;
+  }
+
+  nsresult rv;
+  nsCOMPtr<nsIEventTarget> stsThread =
+    do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
+
+  if (NS_SUCCEEDED(rv) && stsThread) {
+    rv = RUN_ON_THREAD(stsThread,
+                       WrapRunnableNM(&GetLogging_s, this, aRequestId, aPattern.get()),
+                       NS_DISPATCH_NORMAL);
+
+    if (NS_SUCCEEDED(rv)) {
+      return true;
+    }
+  }
+
+  Sequence<nsString> empty_log;
+  SendGetLogResult(aRequestId, empty_log);
+
+  return true;
+}
+
+bool
+WebrtcGlobalChild::RecvSetAecLogging(const bool& aEnable)
+{
+  if (!mShutdown) {
+    StartWebRtcLog(sLastSetLevel); // to make it read the aec path
+    webrtc::Trace::set_aec_debug(aEnable);
+  }
+  return true;
+}
+
+bool
+WebrtcGlobalChild::RecvSetDebugMode(const int& aLevel)
+{
+  if (!mShutdown) {
+    StartWebRtcLog(webrtc::TraceLevel(aLevel));
+  }
+  return true;
+}
+
+WebrtcGlobalChild*
+WebrtcGlobalChild::Create()
+{
+  WebrtcGlobalChild* child =
+    static_cast<WebrtcGlobalChild*>(
+      ContentChild::GetSingleton()->SendPWebrtcGlobalConstructor());
+  return child;
+}
+
+void
+WebrtcGlobalChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mShutdown = true;
+}
+
+MOZ_IMPLICIT WebrtcGlobalChild::WebrtcGlobalChild()
+  : mShutdown(false)
+{
+  MOZ_COUNT_CTOR(WebrtcGlobalChild);
+}
+
+MOZ_IMPLICIT WebrtcGlobalChild::~WebrtcGlobalChild()
+{
+  MOZ_COUNT_DTOR(WebrtcGlobalChild);
+}
 
 struct StreamResult {
   StreamResult() : candidateTypeBitpattern(0), streamSucceeded(false) {}
   uint8_t candidateTypeBitpattern;
   bool streamSucceeded;
 };
 
 static void StoreLongTermICEStatisticsImpl_m(
@@ -517,12 +1068,10 @@ void WebrtcGlobalInformation::StoreLongT
   NS_ENSURE_SUCCESS_VOID(rv);
 
   RUN_ON_THREAD(aPc.GetSTSThread(),
                 WrapRunnableNM(&GetStatsForLongTermStorage_s,
                                query),
                 NS_DISPATCH_NORMAL);
 }
 
-
 } // namespace dom
 } // namespace mozilla
-
--- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.h
@@ -8,16 +8,17 @@
 #include "nsString.h"
 #include "mozilla/dom/BindingDeclarations.h" // for Optional
 
 namespace mozilla {
 class PeerConnectionImpl;
 class ErrorResult;
 
 namespace dom {
+
 class GlobalObject;
 class WebrtcGlobalStatisticsCallback;
 class WebrtcGlobalLoggingCallback;
 
 class WebrtcGlobalInformation
 {
 public:
   static void GetAllStats(const GlobalObject& aGlobal,
@@ -44,9 +45,8 @@ private:
   WebrtcGlobalInformation& operator=(
     const WebrtcGlobalInformation& aRhs) = delete;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif  // _WEBRTC_GLOBAL_INFORMATION_H_
-
new file mode 100644
--- /dev/null
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalParent.h
@@ -0,0 +1,52 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef _WEBRTC_GLOBAL_PARENT_H_
+#define _WEBRTC_GLOBAL_PARENT_H_
+
+#include "mozilla/dom/PWebrtcGlobalParent.h"
+#include "mozilla/dom/RTCStatsReportBinding.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+namespace dom {
+
+class WebrtcParents;
+
+class WebrtcGlobalParent
+  : public PWebrtcGlobalParent
+  , public RefCounted<WebrtcGlobalParent>
+{
+  friend class ContentParent;
+  friend class WebrtcGlobalInformation;
+  friend class WebrtcContentParents;
+
+  bool mShutdown;
+
+  MOZ_IMPLICIT WebrtcGlobalParent();
+
+  static WebrtcGlobalParent* Alloc();
+  static bool Dealloc(WebrtcGlobalParent* aActor);
+
+  virtual bool RecvGetStatsResult(const int& aRequestId,
+                                  nsTArray<RTCStatsReportInternal>&& aStats) override;
+  virtual bool RecvGetLogResult(const int& aRequestId,
+                                const WebrtcGlobalLog& aLog) override;
+
+  virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+  virtual bool Recv__delete__() override;
+public:
+  virtual ~WebrtcGlobalParent();
+  MOZ_DECLARE_REFCOUNTED_TYPENAME(WebrtcGlobalParent)
+  bool IsActive()
+  {
+    return !mShutdown;
+  }
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif  // _WEBRTC_GLOBAL_PARENT_H_
--- a/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_coding/main/source/jitter_buffer.cc
@@ -655,18 +655,20 @@ VCMFrameBufferEnum VCMJitterBuffer::GetF
   // No match, return empty frame.
   *frame = GetEmptyFrame();
   VCMFrameBufferEnum ret = kNoError;
   if (!*frame) {
     // No free frame! Try to reclaim some...
     LOG(LS_WARNING) << "Unable to get empty frame; Recycling.";
     bool found_key_frame = RecycleFramesUntilKeyFrame();
     *frame = GetEmptyFrame();
-    assert(*frame);
-    if (!found_key_frame) {
+    if (!*frame) {
+      LOG(LS_ERROR) << "GetEmptyFrame returned NULL.";
+      return kGeneralError;
+    } else if (!found_key_frame) {
       ret = kFlushIndicator;
     }
   }
   (*frame)->Reset();
   return ret;
 }
 
 int64_t VCMJitterBuffer::LastPacketTime(const VCMEncodedFrame* frame,
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -249,27 +249,26 @@ public class GeckoAppShell
     static public final int LINK_TYPE_2G = 5;
     static public final int LINK_TYPE_3G = 6;
     static public final int LINK_TYPE_4G = 7;
 
     /* The Android-side API: API methods that Android calls */
 
     // Initialization methods
     public static native void registerJavaUiThread();
-    public static native void nativeInit(ClassLoader clsLoader);
+    public static native void nativeInit(ClassLoader clsLoader, MessageQueue msgQueue);
 
     // helper methods
     public static native void onResume();
     public static void callObserver(String observerKey, String topic, String data) {
         sendEventToGecko(GeckoEvent.createCallObserverEvent(observerKey, topic, data));
     }
     public static void removeObserver(String observerKey) {
         sendEventToGecko(GeckoEvent.createRemoveObserverEvent(observerKey));
     }
-    public static native Message getNextMessageFromQueue(MessageQueue queue);
     public static native void onSurfaceTextureFrameAvailable(Object surfaceTexture, int id);
     public static native void dispatchMemoryPressure();
 
     private static native void reportJavaCrash(String stackTrace);
 
     public static void notifyUriVisited(String uri) {
         sendEventToGecko(GeckoEvent.createVisitedEvent(uri));
     }
@@ -346,17 +345,17 @@ public class GeckoAppShell
                 geckoHandler.sendMessageAtFrontOfQueue(idleMsg);
                 // Keep this IdleHandler
                 return true;
             }
         };
         Looper.myQueue().addIdleHandler(idleHandler);
 
         // Initialize AndroidBridge.
-        nativeInit(GeckoAppShell.class.getClassLoader());
+        nativeInit(GeckoAppShell.class.getClassLoader(), Looper.myQueue());
 
         // First argument is the .apk path
         String combinedArgs = apkPath + " -greomni " + apkPath;
         if (args != null)
             combinedArgs += " " + args;
         if (url != null)
             combinedArgs += " -url " + url;
         if (type != null)
@@ -2427,23 +2426,18 @@ public class GeckoAppShell
     }
 
     @WrapElementForJNI
     public static void unlockScreenOrientation() {
         GeckoScreenOrientation.getInstance().unlock();
     }
 
     @WrapElementForJNI
-    public static boolean pumpMessageLoop() {
-        Handler geckoHandler = ThreadUtils.sGeckoHandler;
-        Message msg = getNextMessageFromQueue(ThreadUtils.sGeckoQueue);
-
-        if (msg == null) {
-            return false;
-        }
+    public static boolean pumpMessageLoop(final Message msg) {
+        final Handler geckoHandler = ThreadUtils.sGeckoHandler;
 
         if (msg.obj == geckoHandler && msg.getTarget() == geckoHandler) {
             // Our "queue is empty" message; see runGecko()
             return false;
         }
 
         if (msg.getTarget() == null) {
             Looper.myLooper().quit();
--- a/mobile/android/base/GeckoThread.java
+++ b/mobile/android/base/GeckoThread.java
@@ -151,17 +151,16 @@ public class GeckoThread extends Thread 
         return (args != null ? args : "") + profileArg + guestArg;
     }
 
     @Override
     public void run() {
         Looper.prepare();
         ThreadUtils.sGeckoThread = this;
         ThreadUtils.sGeckoHandler = new Handler();
-        ThreadUtils.sGeckoQueue = Looper.myQueue();
 
         if (mDebugging) {
             try {
                 Thread.sleep(5 * 1000 /* 5 seconds */);
             } catch (final InterruptedException e) {
             }
         }
 
--- a/mobile/android/base/util/ThreadUtils.java
+++ b/mobile/android/base/util/ThreadUtils.java
@@ -31,17 +31,16 @@ public final class ThreadUtils {
 
     private static volatile Thread sBackgroundThread;
 
     // Referenced directly from GeckoAppShell in highly performance-sensitive code (The extra
     // function call of the getter was harming performance. (Bug 897123))
     // Once Bug 709230 is resolved we should reconsider this as ProGuard should be able to optimise
     // this out at compile time.
     public static Handler sGeckoHandler;
-    public static MessageQueue sGeckoQueue;
     public static volatile Thread sGeckoThread;
 
     // Delayed Runnable that resets the Gecko thread priority.
     private static final Runnable sPriorityResetRunnable = new Runnable() {
         @Override
         public void run() {
             resetGeckoPriority();
         }
--- a/modules/libjar/moz.build
+++ b/modules/libjar/moz.build
@@ -39,13 +39,11 @@ SOURCES += [
     'nsJARChannel.cpp',
     'nsJARFactory.cpp',
     'nsJARInputStream.cpp',
     'nsZipArchive.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
--- a/modules/libjar/zipwriter/moz.build
+++ b/modules/libjar/zipwriter/moz.build
@@ -16,13 +16,11 @@ UNIFIED_SOURCES += [
     'nsDeflateConverter.cpp',
     'nsZipDataStream.cpp',
     'nsZipHeader.cpp',
     'nsZipWriter.cpp',
     'StreamFunctions.cpp',
     'ZipWriterModule.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
--- a/modules/libpref/moz.build
+++ b/modules/libpref/moz.build
@@ -31,18 +31,16 @@ UNIFIED_SOURCES += [
     'prefread.cpp',
 ]
 
 # prefapi.cpp cannot be built in unified mode because it uses plarena.h
 SOURCES += [
     'prefapi.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 DEFINES['OS_ARCH'] = CONFIG['OS_ARCH']
 DEFINES['MOZ_WIDGET_TOOLKIT'] = CONFIG['MOZ_WIDGET_TOOLKIT']
 
 FAIL_ON_WARNINGS = True
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -72,26 +72,26 @@ Java_org_mozilla_gecko_GeckoAppShell_reg
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_registerJavaUiThread", &f_Java_org_mozilla_gecko_GeckoAppShell_registerJavaUiThread);
 #endif
 
 #ifdef JNI_STUBS
 
-typedef void (*Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t)(JNIEnv *, jclass, jobject);
+typedef void (*Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t)(JNIEnv *, jclass, jobject, jobject);
 static Java_org_mozilla_gecko_GeckoAppShell_nativeInit_t f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit;
 extern "C" NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv * arg0, jclass arg1, jobject arg2) {
+Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv * arg0, jclass arg1, jobject arg2, jobject arg3) {
     if (!f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return ;
     }
-     f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit(arg0, arg1, arg2);
+     f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit(arg0, arg1, arg2, arg3);
 }
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_nativeInit", &f_Java_org_mozilla_gecko_GeckoAppShell_nativeInit);
 #endif
 
 #ifdef JNI_STUBS
@@ -110,35 +110,16 @@ Java_org_mozilla_gecko_GeckoAppShell_onR
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_onResume", &f_Java_org_mozilla_gecko_GeckoAppShell_onResume);
 #endif
 
 #ifdef JNI_STUBS
 
-typedef jobject (*Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue_t)(JNIEnv *, jclass, jobject);
-static Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue_t f_Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue;
-extern "C" NS_EXPORT jobject JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv * arg0, jclass arg1, jobject arg2) {
-    if (!f_Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue) {
-        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
-                       "JNI Function called before it was loaded");
-        return nullptr;
-    }
-    return f_Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(arg0, arg1, arg2);
-}
-#endif
-
-#ifdef JNI_BINDINGS
-  xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue", &f_Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue);
-#endif
-
-#ifdef JNI_STUBS
-
 typedef void (*Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable_t)(JNIEnv *, jclass, jobject, jint);
 static Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable_t f_Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable;
 extern "C" NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable(JNIEnv * arg0, jclass arg1, jobject arg2, jint arg3) {
     if (!f_Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return ;
--- a/netwerk/base/moz.build
+++ b/netwerk/base/moz.build
@@ -268,18 +268,16 @@ EXTRA_COMPONENTS += [
 ]
 
 EXTRA_JS_MODULES += [
     'NetUtil.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/netwerk/protocol/http'
 ]
--- a/netwerk/build/moz.build
+++ b/netwerk/build/moz.build
@@ -9,18 +9,16 @@ EXPORTS += [
 ]
 
 SOURCES += [
     'nsNetModule.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
     '/netwerk/cache',
     '/netwerk/dns',
--- a/netwerk/cache/moz.build
+++ b/netwerk/cache/moz.build
@@ -38,15 +38,13 @@ UNIFIED_SOURCES += [
     'nsDiskCacheEntry.cpp',
     'nsDiskCacheMap.cpp',
     'nsDiskCacheStreams.cpp',
     'nsMemoryCacheDevice.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
--- a/netwerk/cache2/moz.build
+++ b/netwerk/cache2/moz.build
@@ -49,11 +49,9 @@ SOURCES += [
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
     '/netwerk/cache',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
--- a/netwerk/cookie/moz.build
+++ b/netwerk/cookie/moz.build
@@ -12,18 +12,16 @@ XPIDL_SOURCES += [
     'nsICookieManager2.idl',
     'nsICookiePermission.idl',
     'nsICookieService.idl',
 ]
 
 XPIDL_MODULE = 'necko_cookie'
 
 if CONFIG['NECKO_COOKIES']:
-    MSVC_ENABLE_PGO = True
-
     EXPORTS.mozilla.net = [
         'CookieServiceChild.h',
         'CookieServiceParent.h',
     ]
     UNIFIED_SOURCES += [
         'CookieServiceChild.cpp',
         'CookieServiceParent.cpp',
         'nsCookie.cpp',
--- a/netwerk/dns/moz.build
+++ b/netwerk/dns/moz.build
@@ -45,18 +45,16 @@ UNIFIED_SOURCES += [
 
 IPDL_SOURCES = [
     'PDNSRequest.ipdl',
     'PDNSRequestParams.ipdlh',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'etld_data.inc',
 ]
 etld_data = GENERATED_FILES['etld_data.inc']
--- a/netwerk/mime/moz.build
+++ b/netwerk/mime/moz.build
@@ -17,11 +17,9 @@ EXPORTS += [
 ]
 
 SOURCES += [
     'nsMIMEHeaderParamImpl.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
--- a/netwerk/protocol/file/moz.build
+++ b/netwerk/protocol/file/moz.build
@@ -17,15 +17,13 @@ XPIDL_MODULE = 'necko_file'
 
 UNIFIED_SOURCES += [
     'nsFileChannel.cpp',
     'nsFileProtocolHandler.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
--- a/netwerk/protocol/ftp/moz.build
+++ b/netwerk/protocol/ftp/moz.build
@@ -29,17 +29,15 @@ UNIFIED_SOURCES += [
 ]
 
 IPDL_SOURCES += [
     'PFTPChannel.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -96,18 +96,16 @@ IPDL_SOURCES += [
 
 EXTRA_JS_MODULES += [
     'UserAgentOverrides.jsm',
     'UserAgentUpdates.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/netwerk/base',
 ]
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -36,16 +36,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsError.h"
 #include "nsPrintfCString.h"
 #include "nsAlgorithm.h"
 #include "nsQueryObject.h"
 #include "GeckoProfiler.h"
 #include "nsIConsoleService.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/DebugOnly.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/VisualEventTracer.h"
 #include "nsISSLSocketControl.h"
 #include "sslt.h"
 #include "nsContentUtils.h"
 #include "nsIClassOfService.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
@@ -78,16 +79,20 @@
 #include "nsIX509Cert.h"
 #include "ScopedNSSTypes.h"
 #include "nsNullPrincipal.h"
 
 namespace mozilla { namespace net {
 
 namespace {
 
+// Monotonically increasing ID for generating unique cache entries per
+// intercepted channel.
+static uint64_t gNumIntercepted = 0;
+
 // True if the local cache should be bypassed when processing a request.
 #define BYPASS_LOCAL_CACHE(loadFlags) \
         (loadFlags & (nsIRequest::LOAD_BYPASS_CACHE | \
                       nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE))
 
 #define RECOVER_FROM_CACHE_FILE_ERROR(result) \
         ((result) == NS_ERROR_FILE_NOT_FOUND || \
          (result) == NS_ERROR_FILE_CORRUPTED || \
@@ -218,16 +223,17 @@ AutoRedirectVetoNotifier::ReportRedirect
 
 nsHttpChannel::nsHttpChannel()
     : HttpAsyncAborter<nsHttpChannel>(this)
     , mLogicalOffset(0)
     , mPostID(0)
     , mRequestTime(0)
     , mOfflineCacheLastModifiedTime(0)
     , mInterceptCache(DO_NOT_INTERCEPT)
+    , mInterceptionID(gNumIntercepted++)
     , mCachedContentIsValid(false)
     , mCachedContentIsPartial(false)
     , mCacheOnlyMetadata(false)
     , mTransactionReplaced(false)
     , mAuthRetryPending(false)
     , mProxyAuthPending(false)
     , mResuming(false)
     , mInitedCacheEntry(false)
@@ -2777,22 +2783,26 @@ nsHttpChannel::OpenCacheEntry(bool isHtt
     // When removed, remove the flags and related code snippets.
     if (mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY)
         cacheEntryOpenFlags |= nsICacheStorage::OPEN_BYPASS_IF_BUSY;
 
     if (mPostID) {
         extension.Append(nsPrintfCString("%d", mPostID));
     }
     if (PossiblyIntercepted()) {
-        extension.Append('u');
+        extension.Append(nsPrintfCString("u%lld", mInterceptionID));
     }
 
     // If this channel should be intercepted, we do not open a cache entry for this channel
     // until the interception process is complete and the consumer decides what to do with it.
     if (mInterceptCache == MAYBE_INTERCEPT) {
+        DebugOnly<bool> exists;
+        MOZ_ASSERT(NS_FAILED(cacheStorage->Exists(openURI, extension, &exists)) || !exists,
+                   "The entry must not exist in the cache before we create it here");
+
         nsCOMPtr<nsICacheEntry> entry;
         rv = cacheStorage->OpenTruncate(openURI, extension, getter_AddRefs(entry));
         NS_ENSURE_SUCCESS(rv, rv);
 
         nsCOMPtr<nsINetworkInterceptController> controller;
         GetCallback(controller);
 
         nsRefPtr<InterceptedChannelChrome> intercepted =
--- a/netwerk/protocol/http/nsHttpChannel.h
+++ b/netwerk/protocol/http/nsHttpChannel.h
@@ -413,16 +413,18 @@ private:
     nsCOMPtr<nsIHttpChannelAuthProvider> mAuthProvider;
 
     // States of channel interception
     enum {
         DO_NOT_INTERCEPT,  // no interception will occur
         MAYBE_INTERCEPT,   // interception in progress, but can be cancelled
         INTERCEPTED,       // a synthesized response has been provided
     } mInterceptCache;
+    // Unique ID of this channel for the interception purposes.
+    const uint64_t mInterceptionID;
 
     bool PossiblyIntercepted() {
         return mInterceptCache != DO_NOT_INTERCEPT;
     }
 
     // If the channel is associated with a cache, and the URI matched
     // a fallback namespace, this will hold the key for the fallback
     // cache entry.
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -377,18 +377,17 @@ nsHttpHandler::Init()
 
 void
 nsHttpHandler::MakeNewRequestTokenBucket()
 {
     if (!mConnMgr)
         return;
 
     nsRefPtr<EventTokenBucket> tokenBucket =
-        new EventTokenBucket(RequestTokenBucketHz(),
-                                           RequestTokenBucketBurst());
+        new EventTokenBucket(RequestTokenBucketHz(), RequestTokenBucketBurst());
     mConnMgr->UpdateRequestTokenBucket(tokenBucket);
 }
 
 nsresult
 nsHttpHandler::InitConnectionMgr()
 {
     nsresult rv;
 
@@ -1447,52 +1446,47 @@ nsHttpHandler::PrefsChanged(nsIPrefBranc
                 mCapabilities &= ~NS_HTTP_ALLOW_PIPELINING;
                 if (mPipelineTestTimer) {
                     mPipelineTestTimer->Cancel();
                     mPipelineTestTimer = nullptr;
                 }
             }
         }
     }
-    if (requestTokenBucketUpdated) {
-        MakeNewRequestTokenBucket();
-    }
 
     if (PREF_CHANGED(HTTP_PREF("pacing.requests.enabled"))) {
-        rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"),
-                                &cVar);
-        if (NS_SUCCEEDED(rv)){
+        rv = prefs->GetBoolPref(HTTP_PREF("pacing.requests.enabled"), &cVar);
+        if (NS_SUCCEEDED(rv)) {
+            mRequestTokenBucketEnabled = cVar;
             requestTokenBucketUpdated = true;
-            mRequestTokenBucketEnabled = cVar;
         }
     }
-
     if (PREF_CHANGED(HTTP_PREF("pacing.requests.min-parallelism"))) {
         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.min-parallelism"), &val);
-        if (NS_SUCCEEDED(rv))
+        if (NS_SUCCEEDED(rv)) {
             mRequestTokenBucketMinParallelism = static_cast<uint16_t>(clamped(val, 1, 1024));
+            requestTokenBucketUpdated = true;
+        }
     }
     if (PREF_CHANGED(HTTP_PREF("pacing.requests.hz"))) {
         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.hz"), &val);
         if (NS_SUCCEEDED(rv)) {
             mRequestTokenBucketHz = static_cast<uint32_t>(clamped(val, 1, 10000));
             requestTokenBucketUpdated = true;
         }
     }
     if (PREF_CHANGED(HTTP_PREF("pacing.requests.burst"))) {
         rv = prefs->GetIntPref(HTTP_PREF("pacing.requests.burst"), &val);
         if (NS_SUCCEEDED(rv)) {
             mRequestTokenBucketBurst = val ? val : 1;
             requestTokenBucketUpdated = true;
         }
     }
     if (requestTokenBucketUpdated) {
-        mRequestTokenBucket =
-            new EventTokenBucket(RequestTokenBucketHz(),
-                                 RequestTokenBucketBurst());
+        MakeNewRequestTokenBucket();
     }
 
     // Keepalive values for initial and idle connections.
     if (PREF_CHANGED(HTTP_PREF("tcp_keepalive.short_lived_connections"))) {
         rv = prefs->GetBoolPref(
             HTTP_PREF("tcp_keepalive.short_lived_connections"), &cVar);
         if (NS_SUCCEEDED(rv) && cVar != mTCPKeepaliveShortLivedEnabled) {
             mTCPKeepaliveShortLivedEnabled = cVar;
--- a/netwerk/protocol/res/moz.build
+++ b/netwerk/protocol/res/moz.build
@@ -11,17 +11,15 @@ XPIDL_SOURCES += [
 XPIDL_MODULE = 'necko_res'
 
 SOURCES += [
     'nsResProtocolHandler.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
--- a/netwerk/protocol/rtsp/moz.build
+++ b/netwerk/protocol/rtsp/moz.build
@@ -39,18 +39,16 @@ SOURCES += [
     'rtsp/ARTPWriter.cpp',
     'rtsp/ARTSPConnection.cpp',
     'rtsp/ASessionDescription.cpp',
     'rtsp/RTSPSource.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 # Suppress some GCC warnings being treated as errors:
 #  - about attributes on forward declarations for types that are already
 #    defined, which complains about an important MOZ_EXPORT for android::AString
 if CONFIG['GNU_CC']:
   CXXFLAGS += ['-Wno-error=attributes']
 
--- a/netwerk/protocol/websocket/moz.build
+++ b/netwerk/protocol/websocket/moz.build
@@ -26,18 +26,16 @@ UNIFIED_SOURCES += [
 ]
 
 IPDL_SOURCES += [
     'PWebSocket.ipdl',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/netwerk/base',
 ]
--- a/netwerk/streamconv/converters/moz.build
+++ b/netwerk/streamconv/converters/moz.build
@@ -23,15 +23,13 @@ if 'ftp' in CONFIG['NECKO_PROTOCOLS']:
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'cocoa':
     UNIFIED_SOURCES += [
         'nsBinHexDecoder.cpp',
     ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/netwerk/base',
 ]
--- a/netwerk/streamconv/moz.build
+++ b/netwerk/streamconv/moz.build
@@ -19,11 +19,9 @@ XPIDL_SOURCES += [
 SOURCES += [
     'nsStreamConverterService.cpp',
 ]
 
 XPIDL_MODULE = 'necko_strconv'
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
--- a/parser/expat/lib/moz.build
+++ b/parser/expat/lib/moz.build
@@ -10,13 +10,11 @@ EXPORTS += [
 ]
 
 SOURCES += [
     'xmlparse.c',
     'xmlrole.c',
     'xmltok.c',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'gkmedias'
 
 DEFINES['HAVE_EXPAT_CONFIG_H'] = True
--- a/parser/html/moz.build
+++ b/parser/html/moz.build
@@ -85,18 +85,16 @@ UNIFIED_SOURCES += [
     'nsHtml5TreeOperation.cpp',
     'nsHtml5TreeOpExecutor.cpp',
     'nsHtml5TreeOpStage.cpp',
     'nsHtml5UTF16Buffer.cpp',
     'nsHtml5ViewSourceUtils.cpp',
     'nsParserUtils.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 # DEFINES['ENABLE_VOID_MENUITEM'] = True
 
 LOCAL_INCLUDES += [
     '/dom/base',
 ]
 
--- a/parser/xml/moz.build
+++ b/parser/xml/moz.build
@@ -28,13 +28,11 @@ EXPORTS += [
 ]
 
 SOURCES += [
     'nsSAXAttributes.cpp',
     'nsSAXLocator.cpp',
     'nsSAXXMLReader.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 FAIL_ON_WARNINGS = True
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -92,17 +92,16 @@ MOZBUILD_VARIABLES = [
     'IS_COMPONENT',
     'JAR_MANIFEST',
     'JAVA_JAR_TARGETS',
     'LD_VERSION_SCRIPT',
     'LIBRARY_NAME',
     'LIBS',
     'MAKE_FRAMEWORK',
     'MODULE',
-    'MSVC_ENABLE_PGO',
     'NO_DIST_INSTALL',
     'NO_JS_MANIFEST',
     'OS_LIBS',
     'PARALLEL_DIRS',
     'PREF_JS_EXPORTS',
     'PROGRAM',
     'PYTHON_UNIT_TESTS',
     'RESOURCE_FILES',
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -23,16 +23,19 @@ from .controller.clobber import Clobbere
 from .mozconfig import (
     MozconfigFindException,
     MozconfigLoadException,
     MozconfigLoader,
 )
 from .virtualenv import VirtualenvManager
 
 
+_config_guess_output = []
+
+
 def ancestors(path):
     """Emit the parent directories of a path."""
     while path:
         yield path
         newpath = os.path.dirname(path)
         if newpath == path:
             break
         path = newpath
@@ -348,26 +351,33 @@ class MozbuildObject(ProcessExecutionMix
         make_extra = mozconfig['make_extra'] or []
         make_extra = dict(m.split('=', 1) for m in make_extra)
 
         config_guess = make_extra.get('CONFIG_GUESS', None)
 
         if config_guess:
             return config_guess
 
+        # config.guess results should be constant for process lifetime. Cache
+        # it.
+        if _config_guess_output:
+            return _config_guess_output[0]
+
         p = os.path.join(topsrcdir, 'build', 'autoconf', 'config.guess')
 
         # This is a little kludgy. We need access to the normalize_command
         # function. However, that's a method of a mach mixin, so we need a
         # class instance. Ideally the function should be accessible as a
         # standalone function.
         o = MozbuildObject(topsrcdir, None, None, None)
         args = o._normalize_command([p], True)
 
-        return subprocess.check_output(args, cwd=topsrcdir).strip()
+        _config_guess_output.append(
+                subprocess.check_output(args, cwd=topsrcdir).strip())
+        return _config_guess_output[0]
 
     def notify(self, msg):
         """Show a desktop notification with the supplied message
 
         On Linux and Mac, this will show a desktop notification with the message,
         but on Windows we can only flash the screen.
         """
         moz_nospam = os.environ.get('MOZ_NOSPAM')
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/compilation/codecomplete.py
@@ -0,0 +1,85 @@
+# 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/.
+
+# This modules provides functionality for dealing with code completion.
+
+import os
+
+from mach.decorators import (
+    CommandArgument,
+    CommandProvider,
+    Command,
+)
+
+from mozbuild.base import MachCommandBase
+
+@CommandProvider
+class Introspection(MachCommandBase):
+    """Instropection commands."""
+
+    @Command('compileflags', category='devenv',
+        description='Display the compilation flags for a given source file')
+    @CommandArgument('what', default=None,
+        help='Source file to display compilation flags for')
+    def compileflags(self, what):
+        from mozbuild.util import resolve_target_to_make
+        import shlex
+
+        top_make = os.path.join(self.topobjdir, 'Makefile')
+        if not os.path.exists(top_make):
+            print('Your tree has not been built yet. Please run '
+                '|mach build| with no arguments.')
+            return 1
+
+        path_arg = self._wrap_path_argument(what)
+
+        make_dir, make_target = resolve_target_to_make(self.topobjdir,
+            path_arg.relpath())
+
+        if make_dir is None and make_target is None:
+            return 1
+
+        build_vars = {}
+
+        def on_line(line):
+            elements = [s.strip() for s in line.split('=', 1)]
+
+            if len(elements) != 2:
+                return
+
+            build_vars[elements[0]] = elements[1]
+
+        try:
+            old_logger = self.log_manager.replace_terminal_handler(None)
+            self._run_make(directory=make_dir, target='showbuild', log=False,
+                    print_directory=False, allow_parallel=False, silent=True,
+                    line_handler=on_line)
+        finally:
+            self.log_manager.replace_terminal_handler(old_logger)
+
+        if what.endswith('.c'):
+            name = 'COMPILE_CFLAGS'
+        else:
+            name = 'COMPILE_CXXFLAGS'
+
+        if name not in build_vars:
+            return
+
+        flags = ['-isystem', '-I', '-include', '-MF']
+        new_args = []
+        path = os.path.join(self.topobjdir, make_dir)
+        for arg in shlex.split(build_vars[name]):
+            if new_args and new_args[-1] in flags:
+                arg = os.path.normpath(os.path.join(path, arg))
+            else:
+                flag = [(f, arg[len(f):]) for f in flags + ['--sysroot=']
+                        if arg.startswith(f)]
+                if flag:
+                    flag, val = flag[0]
+                    if val:
+                        arg = flag + os.path.normpath(os.path.join(path, val))
+            new_args.append(arg)
+
+        print(' '.join(new_args))
+
--- a/python/mozbuild/mozbuild/frontend/context.py
+++ b/python/mozbuild/mozbuild/frontend/context.py
@@ -905,20 +905,16 @@ VARIABLES = {
     'HOST_OS_LIBS': (List, list,
         """List of system libraries for host programs and libraries.
         """, None),
 
     'LOCAL_INCLUDES': (StrictOrderingOnAppendList, list,
         """Additional directories to be searched for include files by the compiler.
         """, None),
 
-    'MSVC_ENABLE_PGO': (bool, bool,
-        """Whether profile-guided optimization is enabled for MSVC in this directory.
-        """, None),
-
     'NO_PGO': (bool, bool,
         """Whether profile-guided optimization is disable in this directory.
         """, None),
 
     'NO_VISIBILITY_FLAGS': (bool, bool,
         """Build sources listed in this file without VISIBILITY_FLAGS.
         """, None),
 
--- a/python/mozbuild/mozbuild/frontend/emitter.py
+++ b/python/mozbuild/mozbuild/frontend/emitter.py
@@ -548,17 +548,16 @@ class TreeMetadataEmitter(LoggingMixin):
             'EXTRA_ASSEMBLER_FLAGS',
             'EXTRA_COMPILE_FLAGS',
             'EXTRA_COMPONENTS',
             'EXTRA_DSO_LDOPTS',
             'EXTRA_PP_COMPONENTS',
             'FAIL_ON_WARNINGS',
             'USE_STATIC_LIBS',
             'IS_GYP_DIR',
-            'MSVC_ENABLE_PGO',
             'NO_DIST_INSTALL',
             'PYTHON_UNIT_TESTS',
             'RCFILE',
             'RESFILE',
             'RCINCLUDE',
             'DEFFILE',
             'WIN32_EXE_LDFLAGS',
             'LD_VERSION_SCRIPT',
--- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build
@@ -1,17 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 EXTRA_COMPONENTS = ['bar.js', 'dummy.manifest', 'foo.js']
 EXTRA_PP_COMPONENTS = ['bar.pp.js', 'foo.pp.js']
 
 FAIL_ON_WARNINGS = True
-MSVC_ENABLE_PGO = True
 NO_VISIBILITY_FLAGS = True
 
 DELAYLOAD_DLLS = ['foo.dll', 'bar.dll']
 
 RCFILE = 'foo.rc'
 RESFILE = 'bar.res'
 RCINCLUDE = 'bar.rc'
 DEFFILE = 'baz.def'
--- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
+++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py
@@ -270,19 +270,16 @@ class TestRecursiveMakeBackend(BackendTe
             ],
             'EXTRA_PP_COMPONENTS': [
                 'EXTRA_PP_COMPONENTS += bar.pp.js',
                 'EXTRA_PP_COMPONENTS += foo.pp.js',
             ],
             'FAIL_ON_WARNINGS': [
                 'FAIL_ON_WARNINGS := 1',
             ],
-            'MSVC_ENABLE_PGO': [
-                'MSVC_ENABLE_PGO := 1',
-            ],
             'VISIBILITY_FLAGS': [
                 'VISIBILITY_FLAGS :=',
             ],
             'RCFILE': [
                 'RCFILE := foo.rc',
             ],
             'RESFILE': [
                 'RESFILE := bar.res',
--- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
+++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build
@@ -1,18 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # Any copyright is dedicated to the Public Domain.
 # http://creativecommons.org/publicdomain/zero/1.0/
 
 EXTRA_COMPONENTS = ['dummy.manifest', 'fans.js', 'tans.js']
 EXTRA_PP_COMPONENTS=['fans.pp.js', 'tans.pp.js']
 
 FAIL_ON_WARNINGS = True
-MSVC_ENABLE_PGO = True
-
 NO_DIST_INSTALL = True
 
 NO_VISIBILITY_FLAGS = True
 
 DELAYLOAD_DLLS = ['foo.dll', 'bar.dll']
 
 RCFILE = 'foo.rc'
 RESFILE = 'bar.res'
--- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py
+++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py
@@ -158,17 +158,16 @@ class TestEmitterBasic(unittest.TestCase
         self.assertEqual(len(objs), 1)
         self.assertIsInstance(objs[0], VariablePassthru)
 
         wanted = {
             'DISABLE_STL_WRAPPING': True,
             'EXTRA_COMPONENTS': ['dummy.manifest', 'fans.js', 'tans.js'],
             'EXTRA_PP_COMPONENTS': ['fans.pp.js', 'tans.pp.js'],
             'FAIL_ON_WARNINGS': True,
-            'MSVC_ENABLE_PGO': True,
             'NO_DIST_INSTALL': True,
             'VISIBILITY_FLAGS': '',
             'RCFILE': 'foo.rc',
             'RESFILE': 'bar.res',
             'RCINCLUDE': 'bar.rc',
             'DEFFILE': 'baz.def',
             'USE_STATIC_LIBS': True,
             'MOZBUILD_CFLAGS': ['-fno-exceptions', '-w'],
--- a/python/mozbuild/mozpack/test/test_unify.py
+++ b/python/mozbuild/mozpack/test/test_unify.py
@@ -58,19 +58,29 @@ class TestUnifiedFinder(TestUnified):
         self.assertEqual(sorted([(f, c.open().read())
                                  for f, c in finder.find('test')]),
                          [('test/bar', 'a\nb\nc\n'),
                           ('test/foo', 'a\nb\nc\n')])
 
 
 class TestUnifiedBuildFinder(TestUnified):
     def test_unified_build_finder(self):
+        finder = UnifiedBuildFinder(FileFinder(self.tmppath('a')),
+                                    FileFinder(self.tmppath('b')))
+
+        # Test chrome.manifest unification
         self.create_both('chrome.manifest', 'a\nb\nc\n')
         self.create_one('a', 'chrome/chrome.manifest', 'a\nb\nc\n')
         self.create_one('b', 'chrome/chrome.manifest', 'b\nc\na\n')
+        self.assertEqual(sorted([(f, c.open().read()) for f, c in
+                                 finder.find('**/chrome.manifest')]),
+                         [('chrome.manifest', 'a\nb\nc\n'),
+                          ('chrome/chrome.manifest', 'a\nb\nc\n')])
+
+        # Test buildconfig.html unification
         self.create_one('a', 'chrome/browser/foo/buildconfig.html',
                         '\n'.join([
                             '<html>',
                             '<body>',
                             '<h1>about:buildconfig</h1>',
                             '<div>foo</div>',
                             '</body>',
                             '</html>',
@@ -79,36 +89,30 @@ class TestUnifiedBuildFinder(TestUnified
                         '\n'.join([
                             '<html>',
                             '<body>',
                             '<h1>about:buildconfig</h1>',
                             '<div>bar</div>',
                             '</body>',
                             '</html>',
                         ]))
-        finder = UnifiedBuildFinder(FileFinder(self.tmppath('a')),
-                                    FileFinder(self.tmppath('b')))
-        self.assertEqual(sorted([(f, c.open().read()) for f, c in
-                                 finder.find('**/chrome.manifest')]),
-                         [('chrome.manifest', 'a\nb\nc\n'),
-                          ('chrome/chrome.manifest', 'a\nb\nc\n')])
-
         self.assertEqual(sorted([(f, c.open().read()) for f, c in
                                  finder.find('**/buildconfig.html')]),
                          [('chrome/browser/foo/buildconfig.html', '\n'.join([
                              '<html>',
                              '<body>',
                              '<h1>about:buildconfig</h1>',
                              '<div>foo</div>',
                              '<hr> </hr>',
                              '<div>bar</div>',
                              '</body>',
                              '</html>',
                          ]))])
 
+        # Test xpi file unification
         xpi = MockDest()
         with JarWriter(fileobj=xpi, compress=True) as jar:
             jar.add('foo', 'foo')
             jar.add('bar', 'bar')
         foo_xpi = xpi.read()
         self.create_both('foo.xpi', foo_xpi)
 
         with JarWriter(fileobj=xpi, compress=True) as jar:
@@ -118,11 +122,78 @@ class TestUnifiedBuildFinder(TestUnified
 
         errors.out = StringIO()
         with self.assertRaises(AccumulatedErrors), errors.accumulate():
             self.assertEqual([(f, c.open().read()) for f, c in
                               finder.find('*.xpi')],
                              [('foo.xpi', foo_xpi)])
         errors.out = sys.stderr
 
+        # Test install.rdf unification
+        x86_64 = 'Darwin_x86_64-gcc3'
+        x86 = 'Darwin_x86-gcc3'
+        target_tag = '<{em}targetPlatform>{platform}</{em}targetPlatform>'
+        target_attr = '{em}targetPlatform="{platform}" '
+
+        rdf_tag = ''.join([
+            '<{RDF}Description {em}bar="bar" {em}qux="qux">',
+              '<{em}foo>foo</{em}foo>',
+              '{targets}',
+              '<{em}baz>baz</{em}baz>',
+            '</{RDF}Description>'
+        ])
+        rdf_attr = ''.join([
+            '<{RDF}Description {em}bar="bar" {attr}{em}qux="qux">',
+              '{targets}',
+              '<{em}foo>foo</{em}foo><{em}baz>baz</{em}baz>',
+            '</{RDF}Description>'
+        ])
+
+        for descr_ns, target_ns in (('RDF:', ''), ('', 'em:'), ('RDF:', 'em:')):
+            # First we need to infuse the above strings with our namespaces and
+            # platform values.
+            ns = { 'RDF': descr_ns, 'em': target_ns }
+            target_tag_x86_64 = target_tag.format(platform=x86_64, **ns)
+            target_tag_x86 = target_tag.format(platform=x86, **ns)
+            target_attr_x86_64 = target_attr.format(platform=x86_64, **ns)
+            target_attr_x86 = target_attr.format(platform=x86, **ns)
+
+            tag_x86_64 = rdf_tag.format(targets=target_tag_x86_64, **ns)
+            tag_x86 = rdf_tag.format(targets=target_tag_x86, **ns)
+            tag_merged = rdf_tag.format(targets=target_tag_x86_64 + target_tag_x86, **ns)
+            tag_empty = rdf_tag.format(targets="", **ns)
+
+            attr_x86_64 = rdf_attr.format(attr=target_attr_x86_64, targets="", **ns)
+            attr_x86 = rdf_attr.format(attr=target_attr_x86, targets="", **ns)
+            attr_merged = rdf_attr.format(attr="", targets=target_tag_x86_64 + target_tag_x86, **ns)
+
+            # This table defines the test cases, columns "a" and "b" being the
+            # contents of the install.rdf of the respective platform and
+            # "result" the exepected merged content after unification.
+            testcases = (
+              #_____a_____  _____b_____  ___result___#
+              (tag_x86_64,  tag_x86,     tag_merged  ),
+              (tag_x86_64,  tag_empty,   tag_empty   ),
+              (tag_empty,   tag_x86,     tag_empty   ),
+              (tag_empty,   tag_empty,   tag_empty   ),
+
+              (attr_x86_64, attr_x86,    attr_merged ),
+              (tag_x86_64,  attr_x86,    tag_merged  ),
+              (attr_x86_64, tag_x86,     attr_merged ),
+
+              (attr_x86_64, tag_empty,   tag_empty   ),
+              (tag_empty,   attr_x86,    tag_empty   )
+            )
+
+            # Now create the files from the above table and compare
+            results = []
+            for emid, (rdf_a, rdf_b, result) in enumerate(testcases):
+                filename = 'ext/id{0}/install.rdf'.format(emid)
+                self.create_one('a', filename, rdf_a)
+                self.create_one('b', filename, rdf_b)
+                results.append((filename, result))
+
+            self.assertEqual(sorted([(f, c.open().read()) for f, c in
+                                     finder.find('**/install.rdf')]), results)
+
 
 if __name__ == '__main__':
     mozunit.main()
--- a/python/mozbuild/mozpack/unify.py
+++ b/python/mozbuild/mozpack/unify.py
@@ -13,19 +13,33 @@ from mozpack.executables import (
     MACHO_SIGNATURES,
 )
 from mozpack.mozjar import JarReader
 from mozpack.errors import errors
 from tempfile import mkstemp
 import mozpack.path as mozpath
 import struct
 import os
+import re
 import subprocess
 from collections import OrderedDict
 
+# Regular expressions for unifying install.rdf
+FIND_TARGET_PLATFORM = re.compile(r"""
+    <(?P<ns>[-._0-9A-Za-z]+:)?targetPlatform>       # The targetPlatform tag, with any namespace
+    (?P<platform>[^<]*)                             # The actual platform value
+    </(?P=ns)?targetPlatform>                       # The closing tag
+    """, re.X)
+FIND_TARGET_PLATFORM_ATTR = re.compile(r"""
+    (?P<tag><(?:[-._0-9A-Za-z]+:)?Description)      # The opening part of the <Description> tag
+    (?P<attrs>[^>]*?)\s+                            # The initial attributes
+    (?P<ns>[-._0-9A-Za-z]+:)?targetPlatform=        # The targetPlatform attribute, with any namespace
+    [\'"](?P<platform>[^\'"]+)[\'"]                 # The actual platform value
+    (?P<otherattrs>[^>]*?>)                         # The remaining attributes and closing angle bracket
+    """, re.X)
 
 def may_unify_binary(file):
     '''
     Return whether the given BaseFile instance is an ExecutableFile that
     may be unified. Only non-fat Mach-O binaries are to be unified.
     '''
     if isinstance(file, ExecutableFile):
         signature = file.open().read(4)
@@ -160,30 +174,51 @@ class UnifiedBuildFinder(UnifiedFinder):
     files by merging their content.
     '''
     def __init__(self, finder1, finder2, **kargs):
         UnifiedFinder.__init__(self, finder1, finder2,
                                sorted=['**/*.manifest'], **kargs)
 
     def unify_file(self, path, file1, file2):
         '''
-        Unify buildconfig.html contents, or defer to UnifiedFinder.unify_file.
+        Unify files taking Mozilla application special cases into account.
+        Otherwise defer to UnifiedFinder.unify_file.
         '''
-        if mozpath.basename(path) == 'buildconfig.html':
+        basename = mozpath.basename(path)
+        if basename == 'buildconfig.html':
             content1 = file1.open().readlines()
             content2 = file2.open().readlines()
             # Copy everything from the first file up to the end of its <body>,
             # insert a <hr> between the two files and copy the second file's
             # content beginning after its leading <h1>.
             return GeneratedFile(''.join(
                 content1[:content1.index('</body>\n')] +
                 ['<hr> </hr>\n'] +
                 content2[content2.index('<h1>about:buildconfig</h1>\n') + 1:]
             ))
-        if path.endswith('.xpi'):
+        elif basename == 'install.rdf':
+            # install.rdf files often have em:targetPlatform (either as
+            # attribute or as tag) that will differ between platforms. The
+            # unified install.rdf should contain both em:targetPlatforms if
+            # they exist, or strip them if only one file has a target platform.
+            content1, content2 = (
+                FIND_TARGET_PLATFORM_ATTR.sub(lambda m: \
+                    m.group('tag') + m.group('attrs') + m.group('otherattrs') +
+                        '<%stargetPlatform>%s</%stargetPlatform>' % \
+                        (m.group('ns') or "", m.group('platform'), m.group('ns') or ""),
+                    f.open().read()
+                ) for f in (file1, file2)
+            )
+
+            platform2 = FIND_TARGET_PLATFORM.search(content2)
+            return GeneratedFile(FIND_TARGET_PLATFORM.sub(
+                lambda m: m.group(0) + platform2.group(0) if platform2 else '',
+                content1
+            ))
+        elif path.endswith('.xpi'):
             finder1 = JarFinder(os.path.join(self._finder1.base, path),
                                 JarReader(fileobj=file1.open()))
             finder2 = JarFinder(os.path.join(self._finder2.base, path),
                                 JarReader(fileobj=file2.open()))
             unifier = UnifiedFinder(finder1, finder2, sorted=self._sorted)
             err = errors.count
             all(unifier.find(''))
             if err == errors.count:
--- a/python/mozversioncontrol/mozversioncontrol/__init__.py
+++ b/python/mozversioncontrol/mozversioncontrol/__init__.py
@@ -11,14 +11,14 @@ import subprocess
 from distutils.version import LooseVersion
 
 def get_hg_version(hg):
     """Obtain the version of the Mercurial client."""
 
     env = os.environ.copy()
     env[b'HGPLAIN'] = b'1'
 
-    info = subprocess.check_output([hg, 'version'], env=env)
+    info = subprocess.check_output([hg, '--version'], env=env)
     match = re.search('version ([^\+\)]+)', info)
     if not match:
         raise Exception('Unable to identify Mercurial version.')
 
     return LooseVersion(match.group(1))
--- a/security/manager/boot/src/moz.build
+++ b/security/manager/boot/src/moz.build
@@ -25,11 +25,9 @@ LOCAL_INCLUDES += [
 ]
 
 GENERATED_INCLUDES += [
     '/dist/public/nss',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -91,40 +91,83 @@ this.Context.fromString = function(s) {
  * browsing context (content) and responses will be provided back as
  * promises.
  *
  * The argument sequence is serialised and passed as an array, unless it
  * consists of a single object type that isn't null, in which case it's
  * passed literally.  The latter specialisation is temporary to achieve
  * backwards compatibility with listener.js.
  *
- * @param {function(): nsIMessageManager} mmFn
+ * @param {function(): (nsIMessageSender|nsIMessageBroadcaster)} mmFn
  *     Function returning the current message manager.
  * @param {function(string, Object, number)} sendAsyncFn
  *     Callback for sending async messages to the current listener.
  * @param {function(): BrowserObj} curBrowserFn
  *     Function that returns the current browser.
  */
 let ListenerProxy = function(mmFn, sendAsyncFn, curBrowserFn) {
+  let sender = new ContentSender(mmFn, sendAsyncFn, curBrowserFn);
+  let handler = {
+    set: (obj, prop, val) => { obj[prop] = val; return true; },
+    get: (obj, prop) => (...args) => obj.send(prop, args),
+  };
+  return new Proxy(sender, handler);
+};
+
+/**
+ * The ContentSender allows one to make synchronous calls to the
+ * message listener of the content frame of the current browsing context.
+ *
+ * Presumptions about the responses from content space are made so we
+ * can provide a nicer API on top of the message listener primitives that
+ * make calls from chrome- to content space seem synchronous by leveraging
+ * promises.
+ *
+ * The promise is guaranteed not to resolve until the execution of the
+ * command in content space is complete.
+ *
+ * @param {function(): (nsIMessageSender|nsIMessageBroadcaster)} mmFn
+ *     Function returning the current message manager.
+ * @param {function(string, Object, number)} sendAsyncFn
+ *     Callback for sending async messages to the current listener.
+ * @param {function(): BrowserObj} curBrowserFn
+ *     Function that returns the current browser.
+ */
+let ContentSender = function(mmFn, sendAsyncFn, curBrowserFn) {
   this.curCmdId = null;
   this.sendAsync = sendAsyncFn;
 
   this.mmFn_ = mmFn;
   this.curBrowserFn_ = curBrowserFn;
 };
 
-Object.defineProperty(ListenerProxy.prototype, "mm", {
+Object.defineProperty(ContentSender.prototype, "mm", {
   get: function() { return this.mmFn_(); }
 });
 
-Object.defineProperty(ListenerProxy.prototype, "curBrowser", {
+Object.defineProperty(ContentSender.prototype, "curBrowser", {
   get: function() { return this.curBrowserFn_(); }
 });
 
-ListenerProxy.prototype.__noSuchMethod__ = function*(name, args) {
+/**
+ * Call registered function in the frame script environment of the
+ * current browsing context's content frame.
+ *
+ * @param {string} name
+ *     Function to call in the listener, e.g. for "Marionette:foo8",
+ *     use "foo".
+ * @param {Array} args
+ *     Argument list to pass the function.  If args has a single entry
+ *     that is an object, we assume it's an old style dispatch, and
+ *     the object will passed literally.
+ *
+ * @return {Promise}
+ *     A promise that resolves to the result of the command.
+ */
+ContentSender.prototype.send = function(name, args) {
   const ok = "Marionette:ok";
   const val = "Marionette:done";
   const err = "Marionette:error";
 
   let proxy = new Promise((resolve, reject) => {
     let removeListeners = (name, fn) => {
       let rmFn = msg => {
         if (this.isOutOfSync(msg.json.command_id)) {
@@ -164,31 +207,30 @@ ListenerProxy.prototype.__noSuchMethod__
       resolve();
     }.bind(this);
 
     // start content process listeners, and install observers for global-
     // and tab modal dialogues
     listeners.add();
     modal.addHandler(handleDialog);
 
-    // convert to array if passed arguments
-    let msg;
-    if (args.length == 1 && typeof args[0] == "object" && args[0] !== null) {
+    // new style dispatches are arrays of arguments, old style dispatches
+    // are key-value objects
+    let msg = args;
+    if (args.length == 1 && typeof args[0] == "object") {
       msg = args[0];
-    } else {
-      msg = Array.prototype.slice.call(args);
     }
 
     this.sendAsync(name, msg, this.curCmdId);
   });
 
   return proxy;
 };
 
-ListenerProxy.prototype.isOutOfSync = function(id) {
+ContentSender.prototype.isOutOfSync = function(id) {
   return this.curCmdId !== id;
 };
 
 /**
  * Implements (parts of) the W3C WebDriver protocol.  GeckoDriver lives
  * in the chrome context and mediates content calls to the listener via
  * ListenerProxy.
  *
@@ -263,17 +305,17 @@ this.GeckoDriver = function(appName, dev
     // Proprietary extensions
     "XULappId" : Services.appinfo.ID,
     "appBuildId" : Services.appinfo.appBuildID,
     "device": device,
     "version": Services.appinfo.version
   };
 
   this.mm = globalMessageManager;
-  this.listener = new ListenerProxy(
+  this.listener = ListenerProxy(
       () => this.mm,
       this.sendAsync.bind(this),
       () => this.curBrowser);
 
   this.dialog = null;
   let handleDialog = (subject, topic) => {
     let winr;
     if (topic == modal.COMMON_DIALOG_LOADED) {
@@ -1276,17 +1318,17 @@ GeckoDriver.prototype.get = function(cmd
   let url = cmd.parameters.url;
 
   switch (this.context) {
     case Context.CONTENT:
       // If a remoteness update interrupts our page load, this will never return
       // We need to re-issue this request to correctly poll for readyState and
       // send errors.
       this.curBrowser.pendingCommands.push(() => {
-        cmd.parameters.command_id = this.listener.curCmdId;
+        cmd.parameters.command_id = cmd.id;
         this.mm.broadcastAsyncMessage(
             "Marionette:pollForReadyState" + this.curBrowser.curFrameId,
             cmd.parameters);
       });
       yield this.listener.get({url: url, pageTimeout: this.pageTimeout});
       break;
 
     case Context.CHROME:
--- a/toolkit/components/places/moz.build
+++ b/toolkit/components/places/moz.build
@@ -9,18 +9,16 @@ if CONFIG['MOZ_PLACES']:
 
 XPIDL_SOURCES += [
     'nsINavHistoryService.idl',
 ]
 
 XPIDL_MODULE = 'places'
 
 if CONFIG['MOZ_PLACES']:
-    MSVC_ENABLE_PGO = True
-
     XPIDL_SOURCES += [
         'mozIAsyncFavicons.idl',
         'mozIAsyncHistory.idl',
         'mozIAsyncLivemarks.idl',
         'mozIColorAnalyzer.idl',
         'mozIPlacesAutoComplete.idl',
         'nsIAnnotationService.idl',
         'nsIBrowserHistory.idl',
--- a/toolkit/components/telemetry/moz.build
+++ b/toolkit/components/telemetry/moz.build
@@ -41,18 +41,16 @@ EXTRA_JS_MODULES += [
 EXTRA_PP_JS_MODULES += [
     'TelemetryController.jsm',
     'TelemetryEnvironment.jsm',
     'TelemetrySession.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 GENERATED_FILES = [
     'TelemetryHistogramData.inc',
 ]
 
--- a/toolkit/components/url-classifier/moz.build
+++ b/toolkit/components/url-classifier/moz.build
@@ -57,18 +57,16 @@ EXTRA_JS_MODULES += [
 EXPORTS += [
     'Entries.h',
     'LookupCache.h',
     'nsUrlClassifierPrefixSet.h',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../build',
     '/ipc/chromium/src',
 ]
 
 CXXFLAGS += CONFIG['SQLITE_CFLAGS']
--- a/toolkit/content/aboutwebrtc/aboutWebrtc.js
+++ b/toolkit/content/aboutwebrtc/aboutWebrtc.js
@@ -288,29 +288,33 @@ let AboutWebRTC = {
     content.appendChild(this.renderConnectionLog());
     return content;
   },
 
   renderPeerConnections: function() {
     let connections = document.createDocumentFragment();
 
     let reports = [...this._reports];
-    reports.sort((a, b) => a.timestamp - b.timestamp);
+    reports.sort((a, b) => b.timestamp - a.timestamp);
     for (let report of reports) {
       let peerConnection = new PeerConnection(report);
       connections.appendChild(peerConnection.render());
     };
 
     return connections;
   },
 
   renderConnectionLog: function() {
     let content = document.createElement("div");
     content.className = "log";
 
+    if (!this._log.length) {
+      return content;
+    }
+
     let elem = document.createElement("h3");
     elem.textContent = getString("log_heading");
     content.appendChild(elem);
 
     let div = document.createElement("div");
     let sectionCtrl = document.createElement("div");
     sectionCtrl.className = "section-ctrl no-print";
     let foldEffect = new FoldEffect(div, {
--- a/toolkit/crashreporter/google-breakpad/src/common/moz.build
+++ b/toolkit/crashreporter/google-breakpad/src/common/moz.build
@@ -73,18 +73,16 @@ if CONFIG['OS_ARCH'] == 'Darwin':
 if CONFIG['OS_TARGET'] == 'Android':
     # We don't support unifying assembly files.
     SOURCES += [
         'android/breakpad_getcontext.S',
     ]
 
 Library('breakpad_common_s')
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
     DEFINES['ELFSIZE'] = 32
 
 if CONFIG['OS_TARGET'] == 'Android':
     DEFINES['NO_STABS_SUPPORT'] = True
 
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -73,18 +73,16 @@ if CONFIG['OS_ARCH'] == 'Darwin':
     ]
 
 EXTRA_JS_MODULES += [
     'CrashReports.jsm',
     'CrashSubmit.jsm',
     'KeyValueParser.jsm',
 ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['OS_TARGET'] == 'Android':
     DEFINES['ANDROID_PACKAGE_NAME'] = '"%s"' % CONFIG['ANDROID_PACKAGE_NAME']
     # NDK5 workarounds
     DEFINES['_STLP_CONST_CONSTRUCTOR_BUG'] = True
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -1,18 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 @template
 def Libxul(name):
-    MSVC_ENABLE_PGO = True
-
     if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
         # This is going to be a framework named "XUL", not an ordinary library named
         # "libxul.dylib"
         GeckoFramework(name, linkage=None)
         SHARED_LIBRARY_NAME = 'XUL'
     else:
         GeckoSharedLibrary(name, linkage=None)
         SHARED_LIBRARY_NAME = 'xul'
@@ -58,18 +56,16 @@ SDK_LIBRARY = True
 FORCE_STATIC_LIB = True
 
 STATIC_LIBRARY_NAME = 'xul_s'
 
 SOURCES += [
     'StaticXULComponentsStart.cpp',
 ]
 
-MSVC_ENABLE_PGO = True
-
 # This, combined with the fact the file is first, makes the start pointer
 # it contains first in Windows PGO builds.
 SOURCES['StaticXULComponentsStart.cpp'].no_pgo = True
 
 # Don't let LTO reorder StaticXULComponentsStart.o.
 if '-flto' in CONFIG['OS_CXXFLAGS']:
     SOURCES['StaticXULComponentsStart.cpp'].flags += ['-fno-lto']
 
--- a/toolkit/locales/en-US/chrome/global/aboutSupport.properties
+++ b/toolkit/locales/en-US/chrome/global/aboutSupport.properties
@@ -32,16 +32,18 @@ pendingReports=All Crash Reports (includ
 # there are no good translations, these are only used in about:support
 
 # LOCALIZATION NOTE: This can be localized with a more generic term, like
 # "Graphics-accelerated Windows". It describes a number of windows, e.g.:
 # "GPU Accelerated Windows: 2/2 (Direct3D 9)"
 # "GPU Accelerated Windows: 0/2"
 acceleratedWindows = GPU Accelerated Windows
 
+supportsHardwareH264 = Supports Hardware H264 Decoding
+
 # LOCALIZATION NOTE (rawDataCopied) Text displayed in a mobile "Toast" to user when the
 # raw data is successfully copied to the clipboard via button press.
 rawDataCopied=Raw data copied to clipboard
 
 # LOCALIZATION NOTE (textCopied) Text displayed in a mobile "Toast" to user when the
 # text is successfully copied to the clipboard via button press.
 textCopied=Text copied to clipboard
 
--- a/toolkit/modules/Troubleshoot.jsm
+++ b/toolkit/modules/Troubleshoot.jsm
@@ -308,16 +308,17 @@ let dataProviders = {
     while (winEnumer.hasMoreElements()) {
       data.numTotalWindows++;
       let winUtils = winEnumer.getNext().
                      QueryInterface(Ci.nsIInterfaceRequestor).
                      getInterface(Ci.nsIDOMWindowUtils);
       try {
         data.windowLayerManagerType = winUtils.layerManagerType;
         data.windowLayerManagerRemote = winUtils.layerManagerRemote;
+        data.supportsHardwareH264 = winUtils.supportsHardwareH264Decoding;
       }
       catch (e) {
         continue;
       }
       if (data.windowLayerManagerType != "Basic")
         data.numAcceleratedWindows++;
     }
 
--- a/toolkit/modules/tests/browser/browser_Troubleshoot.js
+++ b/toolkit/modules/tests/browser/browser_Troubleshoot.js
@@ -194,16 +194,19 @@ const SNAPSHOT_SCHEMA = {
           type: "number",
         },
         windowLayerManagerType: {
           type: "string",
         },
         windowLayerManagerRemote: {
           type: "boolean",
         },
+        supportsHardwareH264: {
+          type: "boolean",
+        },
         numAcceleratedWindowsMessage: {
           type: "array",
         },
         adapterDescription: {
           type: "string",
         },
         adapterVendorID: {
           type: "string",
--- a/toolkit/mozapps/update/updater/updater-common.build
+++ b/toolkit/mozapps/update/updater/updater-common.build
@@ -46,17 +46,17 @@ if CONFIG['OS_ARCH'] == 'WINNT':
         'advapi32',
     ]
 elif CONFIG['OS_ARCH'] == 'Linux' and CONFIG['MOZ_VERIFY_MAR_SIGNATURE']:
     USE_LIBS += [
         'nss',
         'signmar',
         'updatecommon',
     ]
-    OS_LIBS += CONFIG['nspr']
+    OS_LIBS += CONFIG['NSPR_LIBS']
 else:
     USE_LIBS += [
         'updatecommon',
     ]
 
 USE_LIBS += [
     'mar',
 ]
--- a/toolkit/xre/moz.build
+++ b/toolkit/xre/moz.build
@@ -100,18 +100,16 @@ if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
     ]
 
 if CONFIG['MOZ_UPDATER']:
     if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'android':
         UNIFIED_SOURCES += [
             'nsUpdateDriver.cpp',
         ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 if CONFIG['MOZ_GL_DEFAULT_PROVIDER'] == 'GLX':
     DEFINES['USE_GLX_TEST'] = True
 
 for var in ('MOZ_APP_NAME', 'MOZ_APP_BASENAME', 'MOZ_APP_VERSION', 'OS_TARGET',
--- a/toolkit/xre/nsUpdateDriver.cpp
+++ b/toolkit/xre/nsUpdateDriver.cpp
@@ -395,16 +395,46 @@ CopyUpdaterIntoUpdateDir(nsIFile *greDir
   if (NS_FAILED(tmp) || NS_FAILED(rv))
     return false;
 #endif
   rv = updater->AppendNative(NS_LITERAL_CSTRING(kUpdaterBin));
   return NS_SUCCEEDED(rv); 
 }
 
 /**
+ * Appends the specified path to the library path.
+ * This is used so that updater can find libmozsqlite3.so and other shared libs.
+ *
+ * @param pathToAppend A new library path to prepend to LD_LIBRARY_PATH
+ */
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
+#include "prprf.h"
+#define PATH_SEPARATOR ":"
+#define LD_LIBRARY_PATH_ENVVAR_NAME "LD_LIBRARY_PATH"
+static void
+AppendToLibPath(const char *pathToAppend)
+{
+  char *s = nullptr;
+  char *pathValue = getenv(LD_LIBRARY_PATH_ENVVAR_NAME);
+  if (nullptr == pathValue || '\0' == *pathValue) {
+    s = PR_smprintf("%s=%s", LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend);
+  } else {
+    s = PR_smprintf("%s=%s" PATH_SEPARATOR "%s",
+                    LD_LIBRARY_PATH_ENVVAR_NAME, pathToAppend, pathValue);
+  }
+
+  // The memory used by PR_SetEnv is not copied to the environment on all
+  // platform, it can be used by reference directly. So we purposely do not
+  // call PR_smprintf_free on s.  Subsequent calls to PR_SetEnv will free
+  // the old memory first.
+  PR_SetEnv(s);
+}
+#endif
+
+/**
  * Switch an existing application directory to an updated version that has been
  * staged.
  *
  * @param greDir the GRE dir
  * @param updateDir the update dir where the mar file is located
  * @param appDir the app dir
  * @param appArgc the number of args to the application
  * @param appArgv the args to the application, used for restarting if needed
@@ -580,16 +610,19 @@ SwitchToUpdatedApp(nsIFile *greDir, nsIF
   } else {
     argc = 5;
     argv[5] = nullptr;
   }
 
   if (gSafeMode) {
     PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
   }
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
+  AppendToLibPath(installDirPath.get());
+#endif
 
   LOG(("spawning updater process for replacing [%s]\n", updaterPath.get()));
 
 #if defined(USE_EXECV)
 # if defined(MOZ_WIDGET_GONK)
   // In Gonk, we preload libmozglue, which the updater process doesn't need.
   // Since the updater will move and delete libmozglue.so, this can actually
   // stop the /system mount from correctly being remounted as read-only.
@@ -845,16 +878,19 @@ ApplyUpdate(nsIFile *greDir, nsIFile *up
   } else {
     argc = 5;
     argv[5] = nullptr;
   }
 
   if (gSafeMode) {
     PR_SetEnv("MOZ_SAFE_MODE_RESTART=1");
   }
+#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
+  AppendToLibPath(installDirPath.get());
+#endif
 
   if (isOSUpdate) {
     PR_SetEnv("MOZ_OS_UPDATE=1");
   }
 #if defined(MOZ_WIDGET_GONK)
   // We want the updater to be CPU friendly and not subject to being killed by
   // the low memory killer, so we pass in some preferences to allow it to
   // adjust its priority.
--- a/tools/mercurial/hgsetup/wizard.py
+++ b/tools/mercurial/hgsetup/wizard.py
@@ -173,23 +173,31 @@ class MercurialSetupWizard(object):
 
     def run(self, config_paths):
         try:
             os.makedirs(self.ext_dir)
         except OSError as e:
             if e.errno != errno.EEXIST:
                 raise
 
+        # We use subprocess in places, which expects a Win32 executable or
+        # batch script. On some versions of MozillaBuild, we have "hg.exe",
+        # "hg.bat," and "hg" (a Python script). "which" will happily return the
+        # Python script, which will cause subprocess to choke. Explicitly favor
+        # the Windows version over the plain script.
         try:
-            hg = which.which('hg')
-        except which.WhichError as e:
-            print(e)
-            print('Try running |mach bootstrap| to ensure your environment is '
-                'up to date.')
-            return 1
+            hg = which.which('hg.exe')
+        except which.WhichError:
+            try:
+                hg = which.which('hg')
+            except which.WhichError as e:
+                print(e)
+                print('Try running |mach bootstrap| to ensure your environment is '
+                      'up to date.')
+                return 1
 
         try:
             c = MercurialConfig(config_paths)
         except ConfigObjError as e:
             print('Error importing existing Mercurial config!\n')
             for error in e.errors:
                 print(error.message)
 
--- a/uriloader/base/moz.build
+++ b/uriloader/base/moz.build
@@ -25,11 +25,9 @@ EXPORTS += [
 
 UNIFIED_SOURCES += [
     'nsDocLoader.cpp',
     'nsURILoader.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
--- a/view/moz.build
+++ b/view/moz.build
@@ -12,13 +12,11 @@ EXPORTS += [
 # nsViewManager.cpp cannot be built in unified mode because it uses PL_ARENA_CONST_ALIGN_MASK.
 SOURCES += [
     'nsView.cpp',
     'nsViewManager.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -145,31 +145,41 @@ jfieldID AndroidBridge::GetStaticFieldID
              fieldName, fieldType);
         env->ExceptionDescribe();
         MOZ_CRASH();
     }
     return fieldID;
 }
 
 void
-AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader)
+AndroidBridge::ConstructBridge(JNIEnv *jEnv, Object::Param clsLoader, Object::Param msgQueue)
 {
     /* NSS hack -- bionic doesn't handle recursive unloads correctly,
      * because library finalizer functions are called with the dynamic
      * linker lock still held.  This results in a deadlock when trying
      * to call dlclose() while we're already inside dlclose().
      * Conveniently, NSS has an env var that can prevent it from unloading.
      */
     putenv("NSS_DISABLE_UNLOAD=1");
 
     PR_NewThreadPrivateIndex(&sJavaEnvThreadIndex, JavaThreadDetachFunc);
 
     MOZ_ASSERT(!sBridge);
     sBridge = new AndroidBridge;
     sBridge->Init(jEnv, clsLoader); // Success or crash
+
+    auto msgQueueClass = ClassObject::LocalRef::Adopt(
+            jEnv, jEnv->GetObjectClass(msgQueue.Get()));
+    sBridge->mMessageQueue = msgQueue;
+    // mMessageQueueNext must not be null
+    sBridge->mMessageQueueNext = GetMethodID(
+            jEnv, msgQueueClass.Get(), "next", "()Landroid/os/Message;");
+    // mMessageQueueMessages may be null (e.g. due to proguard optimization)
+    sBridge->mMessageQueueMessages = jEnv->GetFieldID(
+            msgQueueClass.Get(), "mMessages", "Landroid/os/Message;");
 }
 
 void
 AndroidBridge::Init(JNIEnv *jEnv, Object::Param clsLoader)
 {
     ALOG_BRIDGE("AndroidBridge::Init");
     jEnv->GetJavaVM(&mJavaVM);
     if (!mJavaVM) {
@@ -1661,16 +1671,42 @@ AndroidBridge::GetProxyForURI(const nsAC
 
     if (!jstrRet)
         return NS_ERROR_FAILURE;
 
     aResult = nsCString(jstrRet);
     return NS_OK;
 }
 
+bool
+AndroidBridge::PumpMessageLoop()
+{
+    JNIEnv* const env = GetJNIEnv();
+
+    if (mMessageQueueMessages) {
+        auto msg = Object::LocalRef::Adopt(env,
+                env->GetObjectField(mMessageQueue.Get(),
+                                    mMessageQueueMessages));
+        // if queue.mMessages is null, queue.next() will block, which we don't
+        // want. It turns out to be an order of magnitude more performant to do
+        // this extra check here and block less vs. one fewer checks here and
+        // more blocking.
+        if (!msg) {
+            return false;
+        }
+    }
+
+    auto msg = Object::LocalRef::Adopt(
+            env, env->CallObjectMethod(mMessageQueue.Get(), mMessageQueueNext));
+    if (!msg) {
+        return false;
+    }
+
+    return GeckoAppShell::PumpMessageLoop(msg);
+}
 
 /* attribute nsIAndroidBrowserApp browserApp; */
 NS_IMETHODIMP nsAndroidBridge::GetBrowserApp(nsIAndroidBrowserApp * *aBrowserApp)
 {
     if (nsAppShell::gAppShell)
         nsAppShell::gAppShell->GetBrowserApp(aBrowserApp);
     return NS_OK;
 }
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -128,17 +128,19 @@ public:
     static void RegisterJavaUiThread() {
         sJavaUiThread = pthread_self();
     }
 
     static bool IsJavaUiThread() {
         return pthread_equal(pthread_self(), sJavaUiThread);
     }
 
-    static void ConstructBridge(JNIEnv *jEnv, jni::Object::Param clsLoader);
+    static void ConstructBridge(JNIEnv *jEnv,
+                                jni::Object::Param clsLoader,
+                                jni::Object::Param msgQueue);
 
     static AndroidBridge *Bridge() {
         return sBridge;
     }
 
     static JavaVM *GetVM() {
         MOZ_ASSERT(sBridge);
         return sBridge->mJavaVM;
@@ -309,16 +311,18 @@ public:
     void ScheduleComposite();
 
     nsresult GetProxyForURI(const nsACString & aSpec,
                             const nsACString & aScheme,
                             const nsACString & aHost,
                             const int32_t      aPort,
                             nsACString & aResult);
 
+    bool PumpMessageLoop();
+
     // Utility methods.
     static jstring NewJavaString(JNIEnv* env, const char16_t* string, uint32_t len);
     static jstring NewJavaString(JNIEnv* env, const nsAString& string);
     static jstring NewJavaString(JNIEnv* env, const char* string);
     static jstring NewJavaString(JNIEnv* env, const nsACString& string);
 
     static jstring NewJavaString(AutoLocalJNIFrame* frame, const char16_t* string, uint32_t len);
     static jstring NewJavaString(AutoLocalJNIFrame* frame, const nsAString& string);
@@ -405,16 +409,20 @@ protected:
     widget::GLController::GlobalRef mGLControllerObj;
 
     // some convinient types to have around
     jclass jStringClass;
 
     jni::Object::GlobalRef mClassLoader;
     jmethodID mClassLoaderLoadClass;
 
+    jni::Object::GlobalRef mMessageQueue;
+    jfieldID mMessageQueueMessages;
+    jmethodID mMessageQueueNext;
+
     // calls we've dlopened from libjnigraphics.so
     int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
     int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);
     int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
 
     void* (*ANativeWindow_fromSurface)(JNIEnv *env, jobject surface);
     void* (*ANativeWindow_fromSurfaceTexture)(JNIEnv *env, jobject surfaceTexture);
     void (*ANativeWindow_release)(void *window);
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -60,19 +60,20 @@ extern "C" {
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_registerJavaUiThread(JNIEnv *jenv, jclass jc)
 {
     AndroidBridge::RegisterJavaUiThread();
 }
 
 NS_EXPORT void JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass, jobject clsLoader)
+Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *jenv, jclass, jobject clsLoader, jobject msgQueue)
 {
-    AndroidBridge::ConstructBridge(jenv, jni::Object::Ref::From(clsLoader));
+    AndroidBridge::ConstructBridge(
+            jenv, jni::Object::Ref::From(clsLoader), jni::Object::Ref::From(msgQueue));
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *jenv, jclass jc, jobject event)
 {
     // poke the appshell
     if (nsAppShell::gAppShell)
         nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeFromJavaObject(jenv, event));
@@ -849,43 +850,16 @@ Java_org_mozilla_gecko_GeckoAppShell_onF
     private:
       jobject mView;
   };
 
   nsCOMPtr<nsIRunnable> runnable = new ExitFullScreenRunnable(jenv->NewGlobalRef(view));
   NS_DispatchToMainThread(runnable);
 }
 
-NS_EXPORT jobject JNICALL
-Java_org_mozilla_gecko_GeckoAppShell_getNextMessageFromQueue(JNIEnv* jenv, jclass, jobject queue)
-{
-    static jclass jMessageQueueCls = nullptr;
-    static jfieldID jMessagesField;
-    static jmethodID jNextMethod;
-    if (!jMessageQueueCls) {
-        jMessageQueueCls = (jclass) jenv->NewGlobalRef(jenv->FindClass("android/os/MessageQueue"));
-        jNextMethod = jenv->GetMethodID(jMessageQueueCls, "next", "()Landroid/os/Message;");
-        jMessagesField = jenv->GetFieldID(jMessageQueueCls, "mMessages", "Landroid/os/Message;");
-    }
-
-    if (!jMessageQueueCls || !jNextMethod)
-        return nullptr;
-
-    if (jMessagesField) {
-        jobject msg = jenv->GetObjectField(queue, jMessagesField);
-        // if queue.mMessages is null, queue.next() will block, which we don't want
-        // It turns out to be an order of magnitude more performant to do this extra check here and
-        // block less vs. one fewer checks here and more blocking.
-        if (!msg) {
-            return nullptr;
-        }
-    }
-    return jenv->CallObjectMethod(queue, jNextMethod);
-}
-
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_onSurfaceTextureFrameAvailable(JNIEnv* jenv, jclass, jobject surfaceTexture, jint id)
 {
   mozilla::gl::AndroidSurfaceTexture* st = mozilla::gl::AndroidSurfaceTexture::Find(id);
   if (!st) {
     __android_log_print(ANDROID_LOG_ERROR, "GeckoJNI", "Failed to find AndroidSurfaceTexture with id %d", id);
     return;
   }
--- a/widget/android/GeneratedJNIWrappers.cpp
+++ b/widget/android/GeneratedJNIWrappers.cpp
@@ -532,19 +532,19 @@ constexpr char GeckoAppShell::PerformHap
 void GeckoAppShell::PerformHapticFeedback(bool a0)
 {
     return mozilla::jni::Method<PerformHapticFeedback_t>::Call(nullptr, nullptr, a0);
 }
 
 constexpr char GeckoAppShell::PumpMessageLoop_t::name[];
 constexpr char GeckoAppShell::PumpMessageLoop_t::signature[];
 
-bool GeckoAppShell::PumpMessageLoop()
+bool GeckoAppShell::PumpMessageLoop(mozilla::jni::Object::Param a0)
 {
-    return mozilla::jni::Method<PumpMessageLoop_t>::Call(nullptr, nullptr);
+    return mozilla::jni::Method<PumpMessageLoop_t>::Call(nullptr, nullptr, a0);
 }
 
 constexpr char GeckoAppShell::RegisterSurfaceTextureFrameListener_t::name[];
 constexpr char GeckoAppShell::RegisterSurfaceTextureFrameListener_t::signature[];
 
 void GeckoAppShell::RegisterSurfaceTextureFrameListener(mozilla::jni::Object::Param a0, int32_t a1)
 {
     return mozilla::jni::Method<RegisterSurfaceTextureFrameListener_t>::Call(nullptr, nullptr, a0, a1);
--- a/widget/android/GeneratedJNIWrappers.h
+++ b/widget/android/GeneratedJNIWrappers.h
@@ -1019,23 +1019,23 @@ public:
 
 public:
     struct PumpMessageLoop_t {
         typedef GeckoAppShell Owner;
         typedef bool ReturnType;
         typedef bool SetterType;
         static constexpr char name[] = "pumpMessageLoop";
         static constexpr char signature[] =
-                "()Z";
+                "(Landroid/os/Message;)Z";
         static const bool isStatic = true;
         static const bool isMultithreaded = false;
         static const mozilla::jni::ExceptionMode exceptionMode = mozilla::jni::ExceptionMode::ABORT;
     };
 
-    static bool PumpMessageLoop();
+    static bool PumpMessageLoop(mozilla::jni::Object::Param);
 
 public:
     struct RegisterSurfaceTextureFrameListener_t {
         typedef GeckoAppShell Owner;
         typedef void ReturnType;
         typedef void SetterType;
         static constexpr char name[] = "registerSurfaceTextureFrameListener";
         static constexpr char signature[] =
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -238,16 +238,26 @@ nsAppShell::ProcessNextNativeEvent(bool 
         js::ProfileEntry::Category::EVENTS);
 
     nsAutoPtr<AndroidGeckoEvent> curEvent;
     {
         MutexAutoLock lock(mCondLock);
 
         curEvent = PopNextEvent();
         if (!curEvent && mayWait) {
+            // This processes messages in the Android Looper. Note that we only
+            // get here if the normal Gecko event loop has been awoken
+            // (bug 750713). Looper messages effectively have the lowest
+            // priority because we only process them before we're about to
+            // wait for new events.
+            if (AndroidBridge::HasEnv() &&
+                    AndroidBridge::Bridge()->PumpMessageLoop()) {
+                return true;
+            }
+
             PROFILER_LABEL("nsAppShell", "ProcessNextNativeEvent::Wait",
                 js::ProfileEntry::Category::EVENTS);
             mozilla::HangMonitor::Suspend();
 
             // hmm, should we really hardcode this 10s?
 #if defined(DEBUG_ANDROID_EVENTS)
             PRTime t0, t1;
             EVLOG("nsAppShell: waiting on mQueueCond");
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -474,16 +474,17 @@ public:
   void WillPaintWindow();
   bool PaintWindow(nsIntRegion aRegion);
 
 #ifdef ACCESSIBILITY
   already_AddRefed<mozilla::a11y::Accessible> GetDocumentAccessible();
 #endif
 
   virtual void CreateCompositor() override;
+  virtual bool IsMultiProcessWindow() override;
   virtual void PrepareWindowEffects() override;
   virtual void CleanupWindowEffects() override;
   virtual bool PreRender(LayerManagerComposite* aManager) override;
   virtual void PostRender(LayerManagerComposite* aManager) override;
   virtual void DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) override;
 
   virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) override;
 
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -1880,16 +1880,26 @@ void
 nsChildView::CreateCompositor()
 {
   nsBaseWidget::CreateCompositor();
   if (mCompositorChild) {
     [(ChildView *)mView setUsingOMTCompositor:true];
   }
 }
 
+bool
+nsChildView::IsMultiProcessWindow()
+{
+  // On OS X the XULWindowWidget object gets the widget's init-data, which
+  // is what has the electrolysis window flag. So here in the child view
+  // we need to get the flag from that window instead.
+  nsCocoaWindow* parent = GetXULWindowWidget();
+  return parent ? parent->IsMultiProcessWindow() : false;
+}
+
 void
 nsChildView::ConfigureAPZCTreeManager()
 {
   nsBaseWidget::ConfigureAPZCTreeManager();
 
   if (gfxPrefs::AsyncPanZoomSeparateEventThread()) {
     if (gNumberOfWidgetsNeedingEventThread == 0) {
       [EventThreadRunner start];
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -209,18 +209,16 @@ if toolkit in ('qt', 'gtk2', 'gtk3', 'wi
         'nsNativeTheme.cpp',
     ]
 
 if not CONFIG['MOZ_B2G']:
     DEFINES['MOZ_CROSS_PROCESS_IME'] = True
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/ipc',
     '/layout/base',
     '/layout/forms',
     '/layout/generic',
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -124,17 +124,16 @@ NS_IMPL_ISUPPORTS(nsBaseWidget, nsIWidge
 nsBaseWidget::nsBaseWidget()
 : mWidgetListener(nullptr)
 , mAttachedWidgetListener(nullptr)
 , mCompositorVsyncDispatcher(nullptr)
 , mCursor(eCursor_standard)
 , mUpdateCursor(true)
 , mBorderStyle(eBorderStyle_none)
 , mUseLayersAcceleration(false)
-, mForceLayersAcceleration(false)
 , mUseAttachedEvents(false)
 , mBounds(0,0,0,0)
 , mOriginalBounds(nullptr)
 , mClipRectCount(0)
 , mSizeMode(nsSizeMode_Normal)
 , mPopupLevel(ePopupLevelTop)
 , mPopupType(ePopupTypeAny)
 {
@@ -290,17 +289,17 @@ void nsBaseWidget::BaseCreate(nsIWidget 
   }
 
   // keep a reference to the device context
   if (nullptr != aInitData) {
     mWindowType = aInitData->mWindowType;
     mBorderStyle = aInitData->mBorderStyle;
     mPopupLevel = aInitData->mPopupLevel;
     mPopupType = aInitData->mPopupHint;
-    mRequireOffMainThreadCompositing = aInitData->mRequireOffMainThreadCompositing;
+    mMultiProcessWindow = aInitData->mMultiProcessWindow;
   }
 
   if (aParent) {
     aParent->AddChild(this);
   }
 }
 
 NS_IMETHODIMP nsBaseWidget::CaptureMouse(bool aCapture)
@@ -821,45 +820,33 @@ nsBaseWidget::AutoLayerManagerSetup::~Au
     mLayerManager->SetDefaultTarget(nullptr);
     mLayerManager->SetDefaultTargetConfiguration(mozilla::layers::BufferMode::BUFFER_NONE, ROTATION_0);
   }
 }
 
 bool
 nsBaseWidget::ComputeShouldAccelerate(bool aDefault)
 {
-#if defined(XP_WIN) || defined(ANDROID) || \
-    defined(MOZ_GL_PROVIDER) || defined(XP_MACOSX) || defined(MOZ_WIDGET_QT)
-  bool accelerateByDefault = true;
-#else
-  bool accelerateByDefault = false;
-#endif
+  // Pref to disable acceleration wins:
+  if (gfxPrefs::LayersAccelerationDisabled()) {
+    return false;
+  }
 
-#ifdef XP_MACOSX
-  // 10.6.2 and lower have a bug involving textures and pixel buffer objects
-  // that caused bug 629016, so we don't allow OpenGL-accelerated layers on
-  // those versions of the OS.
-  // This will still let full-screen video be accelerated on OpenGL, because
-  // that XUL widget opts in to acceleration, but that's probably OK.
-  accelerateByDefault = nsCocoaFeatures::AccelerateByDefault();
-#endif
+  // No acceleration in the safe mode:
+  if (gfxPlatform::InSafeMode()) {
+    return false;
+  }
 
-  // we should use AddBoolPrefVarCache
-  bool disableAcceleration = gfxPrefs::LayersAccelerationDisabled();
-  mForceLayersAcceleration = gfxPrefs::LayersAccelerationForceEnabled();
+  // If the pref forces acceleration, no need to check further:
+  if (gfxPrefs::LayersAccelerationForceEnabled()) {
+    return true;
+  }
 
-  const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
-  accelerateByDefault = accelerateByDefault ||
-                        (acceleratedEnv && (*acceleratedEnv != '0'));
-
-  nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
-  bool safeMode = false;
-  if (xr)
-    xr->GetInSafeMode(&safeMode);
-
+  // Being whitelisted is not enough to accelerate, but not being whitelisted is
+  // enough not to:
   bool whitelisted = false;
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
   if (gfxInfo) {
     // bug 655578: on X11 at least, we must always call GetData (even if we don't need that information)
     // as that's what causes GfxInfo initialization which kills the zombie 'glxtest' process.
     // initially we relied on the fact that GetFeatureStatus calls GetData for us, but bug 681026 showed
     // that assumption to be unsafe.
@@ -868,37 +855,49 @@ nsBaseWidget::ComputeShouldAccelerate(bo
     int32_t status;
     if (NS_SUCCEEDED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_OPENGL_LAYERS, &status))) {
       if (status == nsIGfxInfo::FEATURE_STATUS_OK) {
         whitelisted = true;
       }
     }
   }
 
-  if (disableAcceleration || safeMode)
-    return false;
-
-  if (mForceLayersAcceleration)
-    return true;
-
   if (!whitelisted) {
     static int tell_me_once = 0;
     if (!tell_me_once) {
       NS_WARNING("OpenGL-accelerated layers are not supported on this system");
       tell_me_once = 1;
     }
 #ifdef MOZ_WIDGET_ANDROID
     NS_RUNTIMEABORT("OpenGL-accelerated layers are a hard requirement on this platform. "
                     "Cannot continue without support for them");
 #endif
     return false;
   }
 
-  if (accelerateByDefault)
+#if defined (XP_MACOSX)
+  // 10.6.2 and lower have a bug involving textures and pixel buffer objects
+  // that caused bug 629016, so we don't allow OpenGL-accelerated layers on
+  // those versions of the OS.
+  // This will still let full-screen video be accelerated on OpenGL, because
+  // that XUL widget opts in to acceleration, but that's probably OK.
+  bool accelerateByDefault = nsCocoaFeatures::AccelerateByDefault();
+#elif defined(XP_WIN) || defined(ANDROID) || \
+    defined(MOZ_GL_PROVIDER) || defined(MOZ_WIDGET_QT)
+  bool accelerateByDefault = true;
+#else
+  bool accelerateByDefault = false;
+#endif
+
+  // If the platform is accelerated by default or the environment
+  // variable is set, we accelerate:
+  const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
+  if (accelerateByDefault || (acceleratedEnv && (*acceleratedEnv != '0'))) {
     return true;
+  }
 
   /* use the window acceleration flag */
   return aDefault;
 }
 
 CompositorParent* nsBaseWidget::NewCompositorParent(int aSurfaceWidth,
                                                     int aSurfaceHeight)
 {
@@ -948,16 +947,20 @@ public:
         mTreeManager.get(), &APZCTreeManager::ContentReceivedInputBlock,
         aInputBlockId, aPreventDefault));
   }
 
 private:
   nsRefPtr<APZCTreeManager> mTreeManager;
 };
 
+bool nsBaseWidget::IsMultiProcessWindow()
+{
+  return mMultiProcessWindow;
+}
 
 void nsBaseWidget::ConfigureAPZCTreeManager()
 {
   uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
   mAPZC = CompositorParent::GetAPZCTreeManager(rootLayerTreeId);
   MOZ_ASSERT(mAPZC);
 
   ConfigureAPZControllerThread();
@@ -1140,16 +1143,22 @@ void nsBaseWidget::CreateCompositor(int 
   nsRefPtr<ClientLayerManager> lm = new ClientLayerManager(this);
   mCompositorChild = new CompositorChild(lm);
   mCompositorChild->OpenSameProcess(mCompositorParent);
 
   // Make sure the parent knows it is same process.
   mCompositorParent->SetOtherProcessId(base::GetCurrentProcId());
 
   if (gfxPrefs::AsyncPanZoomEnabled() &&
+#if defined(XP_WIN) || defined(MOZ_WIDGET_COCOA) || defined(MOZ_WIDGET_GTK)
+      // For desktop platforms we only want to use APZ in e10s-enabled windows.
+      // If we ever get input events off the main thread we can consider
+      // relaxing this requirement.
+      IsMultiProcessWindow() &&
+#endif
       (WindowType() == eWindowType_toplevel || WindowType() == eWindowType_child)) {
     ConfigureAPZCTreeManager();
   }
 
   TextureFactoryIdentifier textureFactoryIdentifier;
   PLayerTransactionChild* shadowManager = nullptr;
   nsTArray<LayersBackend> backendHints;
   GetPreferredCompositorBackends(backendHints);
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -149,16 +149,17 @@ public:
                                           LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
                                           bool* aAllowRetaining = nullptr) override;
 
   CompositorVsyncDispatcher* GetCompositorVsyncDispatcher() override;
   void            CreateCompositorVsyncDispatcher();
   virtual CompositorParent* NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight);
   virtual void            CreateCompositor();
   virtual void            CreateCompositor(int aWidth, int aHeight);
+  virtual bool            IsMultiProcessWindow();
   virtual void            PrepareWindowEffects() override {}
   virtual void            CleanupWindowEffects() override {}
   virtual bool            PreRender(LayerManagerComposite* aManager) override { return true; }
   virtual void            PostRender(LayerManagerComposite* aManager) override {}
   virtual void            DrawWindowUnderlay(LayerManagerComposite* aManager, nsIntRect aRect) override {}
   virtual void            DrawWindowOverlay(LayerManagerComposite* aManager, nsIntRect aRect) override {}
   virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() override;
   virtual void            EndRemoteDrawing() override { };
@@ -476,20 +477,17 @@ protected:
   nsRefPtr<APZEventState> mAPZEventState;
   nsRefPtr<SetAllowedTouchBehaviorCallback> mSetAllowedTouchBehaviorCallback;
   nsRefPtr<WidgetShutdownObserver> mShutdownObserver;
   nsRefPtr<TextEventDispatcher> mTextEventDispatcher;
   nsCursor          mCursor;
   bool              mUpdateCursor;
   nsBorderStyle     mBorderStyle;
   bool              mUseLayersAcceleration;
-  bool              mForceLayersAcceleration;
-  // Windows with out-of-process tabs always require OMTC. This flag designates
-  // such windows.
-  bool              mRequireOffMainThreadCompositing;
+  bool              mMultiProcessWindow;
   bool              mUseAttachedEvents;
   nsIntRect         mBounds;
   nsIntRect*        mOriginalBounds;
   // When this pointer is null, the widget is not clipped
   nsAutoArrayPtr<nsIntRect> mClipRects;
   uint32_t          mClipRectCount;
   nsSizeMode        mSizeMode;
   nsPopupLevel      mPopupLevel;
--- a/widget/nsWidgetInitData.h
+++ b/widget/nsWidgetInitData.h
@@ -100,17 +100,17 @@ struct nsWidgetInitData {
       mListenForResizes(false),
       mUnicode(true),
       mRTL(false),
       mNoAutoHide(false),
       mIsDragPopup(false),
       mIsAnimationSuppressed(false),
       mSupportTranslucency(false),
       mMouseTransparent(false),
-      mRequireOffMainThreadCompositing(false)
+      mMultiProcessWindow(false)
   {
   }
 
   nsWindowType  mWindowType;
   nsBorderStyle mBorderStyle;
   nsPopupType   mPopupHint;
   nsPopupLevel  mPopupLevel;
   // when painting exclude area occupied by child windows and sibling windows
@@ -122,14 +122,13 @@ struct nsWidgetInitData {
   bool          mIsDragPopup;  // true for drag feedback panels
   // true if window creation animation is suppressed, e.g. for session restore
   bool          mIsAnimationSuppressed;
   // true if the window should support an alpha channel, if available.
   bool          mSupportTranslucency;
   // true if the window should be transparent to mouse events. Currently this is
   // only valid for eWindowType_popup widgets
   bool          mMouseTransparent;
-  // Windows with out-of-process tabs always require OMTC. This flag designates
-  // such windows.
-  bool          mRequireOffMainThreadCompositing;
+  // This flag designates windows with out-of-process tabs.
+  bool          mMultiProcessWindow;
 };
 
 #endif // nsWidgetInitData_h__
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -80,18 +80,16 @@ if CONFIG['NS_PRINTING']:
 
 if CONFIG['NS_ENABLE_TSF']:
     SOURCES += [
         'nsTextStore.cpp',
     ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/layout/generic',
     '/layout/xul',
     '/toolkit/xre',
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3274,36 +3274,27 @@ struct LayerManagerPrefs {
   bool mForceAcceleration;
   bool mPreferOpenGL;
   bool mPreferD3D9;
 };
 
 static void
 GetLayerManagerPrefs(LayerManagerPrefs* aManagerPrefs)
 {
-  Preferences::GetBool("layers.acceleration.disabled",
-                       &aManagerPrefs->mDisableAcceleration);
-  Preferences::GetBool("layers.acceleration.force-enabled",
-                       &aManagerPrefs->mForceAcceleration);
-  Preferences::GetBool("layers.prefer-opengl",
-                       &aManagerPrefs->mPreferOpenGL);
-  Preferences::GetBool("layers.prefer-d3d9",
-                       &aManagerPrefs->mPreferD3D9);
+  aManagerPrefs->mDisableAcceleration = gfxPrefs::LayersAccelerationDisabled();
+  aManagerPrefs->mForceAcceleration = gfxPrefs::LayersAccelerationForceEnabled();
+  aManagerPrefs->mPreferOpenGL = gfxPrefs::LayersPreferOpenGL();
+  aManagerPrefs->mPreferD3D9 = gfxPrefs::LayersPreferD3D9();
 
   const char *acceleratedEnv = PR_GetEnv("MOZ_ACCELERATED");
   aManagerPrefs->mAccelerateByDefault =
     aManagerPrefs->mAccelerateByDefault ||
     (acceleratedEnv && (*acceleratedEnv != '0'));
-
-  bool safeMode = false;
-  nsCOMPtr<nsIXULRuntime> xr = do_GetService("@mozilla.org/xre/runtime;1");
-  if (xr)
-    xr->GetInSafeMode(&safeMode);
   aManagerPrefs->mDisableAcceleration =
-    aManagerPrefs->mDisableAcceleration || safeMode;
+    aManagerPrefs->mDisableAcceleration || gfxPlatform::InSafeMode();
 }
 
 LayerManager*
 nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
                           LayersBackend aBackendHint,
                           LayerManagerPersistence aPersistence,
                           bool* aAllowRetaining)
 {
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -59,16 +59,17 @@
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/DebuggerOnGCRunnable.h"
 #include "mozilla/dom/DOMJSClass.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "jsprf.h"
+#include "js/Debug.h"
 #include "nsCycleCollectionNoteRootCallback.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsCycleCollector.h"
 #include "nsDOMJSUtils.h"
 #include "nsJSUtils.h"
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
@@ -498,16 +499,18 @@ CycleCollectedJSRuntime::CycleCollectedJ
   JS_SetDestroyZoneCallback(mJSRuntime, XPCStringConvert::FreeZoneCache);
   JS_SetSweepZoneCallback(mJSRuntime, XPCStringConvert::ClearZoneCache);
 
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
   SetDOMCallbacks(mJSRuntime, &DOMcallbacks);
 
+  JS::dbg::SetDebuggerMallocSizeOf(mJSRuntime, moz_malloc_size_of);
+
   nsCycleCollector_registerJSRuntime(this);
 }
 
 CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
 {
   MOZ_ASSERT(mJSRuntime);
   MOZ_ASSERT(!mDeferredFinalizerTable.Count());
 
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -146,18 +146,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
     SOURCES += [
         'nsMacUtilsImpl.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
         'nsCrashOnException.cpp',
     ]
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../build',
     '/xpcom/ds',
 ]
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -1255,21 +1255,23 @@ nsMemoryReporterManager::nsMemoryReporte
 nsMemoryReporterManager::~nsMemoryReporterManager()
 {
   delete mStrongReporters;
   delete mWeakReporters;
   NS_ASSERTION(!mSavedStrongReporters, "failed to restore strong reporters");
   NS_ASSERTION(!mSavedWeakReporters, "failed to restore weak reporters");
 }
 
-//#define DEBUG_CHILD_PROCESS_MEMORY_REPORTING 1
+#ifdef MOZ_WIDGET_GONK
+#define DEBUG_CHILD_PROCESS_MEMORY_REPORTING 1
+#endif
 
 #ifdef DEBUG_CHILD_PROCESS_MEMORY_REPORTING
 #define MEMORY_REPORTING_LOG(format, ...) \
-  fprintf(stderr, "++++ MEMORY REPORTING: " format, ##__VA_ARGS__);
+  printf_stderr("++++ MEMORY REPORTING: " format, ##__VA_ARGS__);
 #else
 #define MEMORY_REPORTING_LOG(...)
 #endif
 
 void
 nsMemoryReporterManager::IncrementNumChildProcesses()
 {
   if (!NS_IsMainThread()) {
--- a/xpcom/build/moz.build
+++ b/xpcom/build/moz.build
@@ -65,18 +65,16 @@ if CONFIG['OS_ARCH'] != 'WINNT':
 # use plarena.h.
 SOURCES += [
     'FileLocation.cpp',
     'Omnijar.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
-MSVC_ENABLE_PGO = True
-
 include('/ipc/chromium/chromium-config.mozbuild')
<