Merge m-c to fx-team. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 06 May 2015 16:29:44 -0400
changeset 274023 feefdfa526a80bc51010582ca8eae5263735a657
parent 274022 84a6852a3733e3a3e91582e97d5dd0e5c8dc5424 (current diff)
parent 273989 5593ac626826e11ea1a5f2e29970ec89db12982e (diff)
child 274024 eac6ac60b5e648bd0bb52a8a085f73491bf66faa
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
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 m-c to fx-team. a=merge CLOSED TREE
b2g/branding/official/android-resources.mn
b2g/branding/unofficial/android-resources.mn
--- a/.ycm_extra_conf.py
+++ b/.ycm_extra_conf.py
@@ -16,12 +16,19 @@ if not os.path.exists(path):
 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)
 
+    flag_list = shlex.split(out.getvalue())
+
+    # This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
+    # Removing this flag is a workaround until ycmd starts to handle this flag properly.
+    # https://github.com/Valloric/YouCompleteMe/issues/1490
+    final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
+
     return {
-        'flags': shlex.split(out.getvalue()),
+        'flags': final_flags,
         'do_cache': True
     }
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -490,17 +490,17 @@ STDMETHODIMP
 ia2Accessible::get_uniqueID(long* aUniqueID)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aUniqueID)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
-  *aUniqueID = - reinterpret_cast<intptr_t>(acc->UniqueID());
+  *aUniqueID = AccessibleWrap::GetChildIDFor(acc);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_windowHandle(HWND* aWindowHandle)
 {
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -51,26 +51,58 @@ const uint32_t USE_ROLE_STRING = 0;
  */
 
 //#define DEBUG_LEAKS
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
 #endif
 
+#ifdef _WIN64
+IDSet AccessibleWrap::sIDGen;
+
+static const uint32_t kNoID = 0;
+#endif
+
 static const int32_t kIEnumVariantDisconnected = -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
+AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
+  Accessible(aContent, aDoc)
+#ifdef _WIN64
+  , mID(kNoID)
+#endif
+{
+}
+
+AccessibleWrap::~AccessibleWrap()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    sIDGen.ReleaseID(mID);
+#endif
+}
 
 ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
 
 NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
 
+void
+AccessibleWrap::Shutdown()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    static_cast<DocAccessibleWrap*>(mDoc)->RemoveID(mID);
+#endif
+
+  Accessible::Shutdown();
+}
+
 //-----------------------------------------------------
 // IUnknown interface methods - see iunknown.h for documentation
 //-----------------------------------------------------
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
@@ -1249,20 +1281,33 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 
 int32_t
 AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
 
-  // Yes, this means we're only compatibible with 32 bit
-  // MSAA is only available for 32 bit windows, so it's okay
-  // XXX: bug 606080
-  return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
+#ifdef _WIN64
+  if (!aAccessible || !aAccessible->Document())
+    return 0;
+
+  uint32_t* id = & static_cast<AccessibleWrap*>(aAccessible)->mID;
+  if (*id != kNoID)
+    return *id;
+
+  *id = sIDGen.GetID();
+  DocAccessibleWrap* doc =
+    static_cast<DocAccessibleWrap*>(aAccessible->Document());
+  doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
+
+  return *id;
+#else
+  return - reinterpret_cast<intptr_t>(aAccessible);
+#endif
 }
 
 HWND
 AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
 {
   if (aAccessible) {
     DocAccessible* document = aAccessible->Document();
     if(!document)
@@ -1302,16 +1347,35 @@ AccessibleWrap::NativeAccessible(Accessi
     return nullptr;
   }
 
   IAccessible* msaaAccessible = nullptr;
   aAccessible->GetNativeInterface(reinterpret_cast<void**>(&msaaAccessible));
   return static_cast<IDispatch*>(msaaAccessible);
 }
 
+#ifdef _WIN64
+static Accessible*
+GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
+{
+  Accessible* child = static_cast<DocAccessibleWrap*>(aDoc)->GetAccessibleByID(aID);
+  if (child)
+    return child;
+
+  uint32_t childDocCount = aDoc->ChildDocumentCount();
+  for (uint32_t i = 0; i < childDocCount; i++) {
+    child = GetAccessibleInSubtree(aDoc->GetChildDocumentAt(i), aID);
+    if (child)
+      return child;
+  }
+
+    return nullptr;
+  }
+#endif
+
 Accessible*
 AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
 {
   if (aVarChild.vt != VT_I4)
     return nullptr;
 
   // if its us real easy - this seems to always be the case
   if (aVarChild.lVal == CHILDID_SELF)
@@ -1337,17 +1401,21 @@ AccessibleWrap::GetXPAccessibleFor(const
   // Otherwise we treat lVal as index in parent.
 
   if (aVarChild.lVal < 0) {
     // Convert child ID to unique ID.
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
 
     DocAccessible* document = Document();
     Accessible* child =
+#ifdef _WIN64
+    GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
+#else
       document->GetAccessibleByUniqueIDInSubtree(uniqueID);
+#endif
 
     // If it is a document then just return an accessible.
     if (IsDoc())
       return child;
 
     // Otherwise check whether the accessible is a child (this path works for
     // ARIA documents and popups).
     Accessible* parent = child;
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -10,16 +10,17 @@
 #include "nsCOMPtr.h"
 #include "Accessible.h"
 #include "Accessible2.h"
 #include "ia2Accessible.h"
 #include "ia2AccessibleComponent.h"
 #include "ia2AccessibleHyperlink.h"
 #include "ia2AccessibleValue.h"
 #include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/a11y/IDSet.h"
 
 #ifdef __GNUC__
 // Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
 // about virtual functions being hidden by each other. This is done by
 // design, so silence the warning.
 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
 #endif
 
@@ -28,18 +29,17 @@ namespace a11y {
 
 class AccessibleWrap : public Accessible,
                        public ia2Accessible,
                        public ia2AccessibleComponent,
                        public ia2AccessibleHyperlink,
                        public ia2AccessibleValue
 {
 public: // construction, destruction
-  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
-    Accessible(aContent, aDoc) { }
+  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   public: // IUnknown methods - see iunknown.h for documentation
     STDMETHODIMP QueryInterface(REFIID, void**);
 
   // Return the registered OLE class ID of this object's CfDataObj.
@@ -147,16 +147,17 @@ public: // construction, destruction
                                            LCID lcid, WORD wFlags,
                                            DISPPARAMS *pDispParams,
                                            VARIANT *pVarResult,
                                            EXCEPINFO *pExcepInfo,
                                            UINT *puArgErr);
 
   // Accessible
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
+  virtual void Shutdown() override;
 
   // Helper methods
   static int32_t GetChildIDFor(Accessible* aAccessible);
   static HWND GetHWNDFor(Accessible* aAccessible);
 
   /**
    * System caret support: update the Windows caret position. 
    * The system caret works more universally than the MSAA caret
@@ -171,25 +172,32 @@ public: // construction, destruction
    */
   Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
 
   virtual void GetNativeInterface(void **aOutAccessible) override;
 
   static IDispatch* NativeAccessible(Accessible* aAccessible);
 
 protected:
-  virtual ~AccessibleWrap() { }
+  virtual ~AccessibleWrap();
+
+#ifdef _WIN64
+  uint32_t mID;
+#endif
 
   /**
    * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.
    */
   static ITypeInfo* GetTI(LCID lcid);
 
   static ITypeInfo* gTypeInfo;
 
+#ifdef _WIN64
+  static IDSet sIDGen;
+#endif
 
   enum navRelations {
     NAVRELATION_CONTROLLED_BY = 0x1000,
     NAVRELATION_CONTROLLER_FOR = 0x1001,
     NAVRELATION_LABEL_FOR = 0x1002,
     NAVRELATION_LABELLED_BY = 0x1003,
     NAVRELATION_MEMBER_OF = 0x1004,
     NAVRELATION_NODE_CHILD_OF = 0x1005,
--- a/accessible/windows/msaa/DocAccessibleWrap.h
+++ b/accessible/windows/msaa/DocAccessibleWrap.h
@@ -29,20 +29,38 @@ public:
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
   // Accessible
   virtual void Shutdown();
 
   // DocAccessible
   virtual void* GetNativeWindow() const;
 
+  /**
+   * Manage the mapping from id to Accessible.
+   */
+#ifdef _WIN64
+  void AddID(uint32_t aID, AccessibleWrap* aAcc)
+    { mIDToAccessibleMap.Put(aID, aAcc); }
+  void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
+  AccessibleWrap* GetAccessibleByID(uint32_t aID) const
+    { return mIDToAccessibleMap.Get(aID); }
+#endif
+
 protected:
   // DocAccessible
   virtual void DoInitialUpdate();
 
 protected:
   void* mHWND;
+
+  /*
+   * This provides a mapping from 32 bit id to accessible objects.
+   */
+#ifdef _WIN64
+  nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
+#endif
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/IDSet.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * A class to generate unique IDs in the range [ - 2^31, 0 )
+ */
+
+#ifndef MOZILLA_A11Y_IDSet_h_
+#define MOZILLA_A11Y_IDSet_h_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/SplayTree.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * On windows an accessible's id must be a negative 32 bit integer.  It is
+ * important to support recycling arbitrary IDs because accessibles can be
+ * created and destroyed at any time in the life of a page.  IDSet provides 2
+ * operations: generate an ID in the range [ - 2^31, 0 ), and release an ID so
+ * it can be allocated again.  Allocated ID are tracked by a sparse bitmap
+ * implemented with a splay tree.  Nodes in the tree are keyed by the upper N
+ * bits of the bitwise negation of the ID, and the node contains a bitmap
+ * tracking the allocation of 2^(32 - N) IDs.
+ */
+class IDSet
+{
+public:
+  MOZ_CONSTEXPR IDSet() : mBitSet(), mIdx(0) {}
+
+  /**
+   * Return a new unique id.
+   */
+  uint32_t GetID()
+  {
+    uint32_t idx = mIdx;
+    while (true) {
+      BitSetElt* elt = mBitSet.findOrInsert(BitSetElt(idx));
+      if (elt->mBitvec[0] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[0]);
+
+        elt->mBitvec[0] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + i);
+      }
+
+      if (elt->mBitvec[1] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[1]);
+
+        elt->mBitvec[1] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + bitsPerWord + i);
+      }
+
+      idx++;
+      if (idx > sMaxIdx) {
+        idx = 0;
+      }
+
+      if (idx == mIdx) {
+        MOZ_CRASH("used up all the available ids");
+      }
+    }
+  }
+
+  /**
+   * Free a no longer required id so it may be allocated again.
+   */
+  void ReleaseID(uint32_t aID)
+  {
+    aID = ~aID;
+    MOZ_ASSERT(aID < static_cast<uint32_t>(INT32_MAX));
+
+    uint32_t idx = aID / bitsPerElt;
+    mIdx = idx;
+    BitSetElt* elt = mBitSet.find(BitSetElt(idx));
+    MOZ_ASSERT(elt);
+
+    uint32_t vecIdx = (aID % bitsPerElt) / bitsPerWord;
+    elt->mBitvec[vecIdx] &= ~(1ull << (aID % bitsPerWord));
+    if (elt->mBitvec[0] == 0 && elt->mBitvec[1] == 0) {
+      delete mBitSet.remove(*elt);
+    }
+  }
+
+private:
+  static const unsigned int wordsPerElt = 2;
+  static const unsigned int bitsPerWord = 64;
+  static const unsigned int bitsPerElt = wordsPerElt * bitsPerWord;
+  static const uint32_t sMaxIdx = INT32_MAX / bitsPerElt;
+
+  struct BitSetElt : mozilla::SplayTreeNode<BitSetElt>
+  {
+    explicit BitSetElt(uint32_t aIdx) :
+      mIdx(aIdx)
+    { mBitvec[0] = mBitvec[1] = 0; }
+
+    uint64_t mBitvec[wordsPerElt];
+    uint32_t mIdx;
+
+    static int compare(const BitSetElt& a, const BitSetElt& b)
+    {
+      if (a.mIdx == b.mIdx) {
+        return 0;
+      }
+
+      if (a.mIdx < b.mIdx) {
+        return -1;
+      }
+      return 1;
+    }
+  };
+
+  SplayTree<BitSetElt, BitSetElt> mBitSet;
+  uint32_t mIdx;
+};
+
+}
+}
+
+#endif
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -7,16 +7,17 @@
 EXPORTS += [
     'IUnknownImpl.h',
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'Compatibility.h',
     'HyperTextAccessibleWrap.h',
+    'IDSet.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
deleted file mode 100644
--- a/b2g/branding/official/android-resources.mn
+++ /dev/null
@@ -1,1 +0,0 @@
-b2g/branding/official/content/splash.png
deleted file mode 100644
--- a/b2g/branding/unofficial/android-resources.mn
+++ /dev/null
@@ -1,1 +0,0 @@
-b2g/branding/unofficial/content/splash.png
--- 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="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- 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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- 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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- 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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- 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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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": "eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785", 
+        "git_revision": "426fe6450ab8da92bb473fef12ccb39c6c920dd0", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "78e99873114b371f245690c3b0b80834a649f2f2", 
+    "revision": "b48088c5abd6ad5a64b9b870e52d6de14b3f2bc3", 
     "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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <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="eb3f82f3b947f1ed52fa4e9246bed0f0b3e49785"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="426fe6450ab8da92bb473fef12ccb39c6c920dd0"/>
   <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="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -293,21 +293,17 @@ BluetoothA2dpManager::ResetA2dp()
 void
 BluetoothA2dpManager::ResetAvrcp()
 {
   mAvrcpConnected = false;
   mDuration = 0;
   mMediaNumber = 0;
   mTotalMediaCount = 0;
   mPosition = 0;
-#ifdef MOZ_B2G_BT_API_V2
-  mPlayStatus = ControlPlayStatus::PLAYSTATUS_UNKNOWN;
-#else
   mPlayStatus = ControlPlayStatus::PLAYSTATUS_STOPPED;
-#endif
 }
 
 /*
  * Static functions
  */
 
 static BluetoothA2dpManager::SinkState
 StatusStringToSinkState(const nsAString& aStatus)
@@ -928,28 +924,24 @@ BluetoothA2dpManager::UpdateRegisterNoti
       mPlayPosChangedNotifyType = AVRCP_NTF_INTERIM;
       if (mSinkState == BluetoothA2dpManager::SinkState::SINK_PLAYING) {
         param.mSongPos = mPosition;
       } else {
         param.mSongPos = 0xFFFFFFFF;
       }
       mPlaybackInterval = aParam;
       break;
-#ifdef MOZ_B2G_BT_API_V2
-      // Missing in bluetooth2
-#else
     case AVRCP_EVENT_APP_SETTINGS_CHANGED:
       mAppSettingsChangedNotifyType = AVRCP_NTF_INTERIM;
       param.mNumAttr = 2;
       param.mIds[0] = AVRCP_PLAYER_ATTRIBUTE_REPEAT;
       param.mValues[0] = AVRCP_PLAYER_VAL_OFF_REPEAT;
       param.mIds[1] = AVRCP_PLAYER_ATTRIBUTE_SHUFFLE;
       param.mValues[1] = AVRCP_PLAYER_VAL_OFF_SHUFFLE;
       break;
-#endif
     default:
       break;
   }
 
   sBtAvrcpInterface->RegisterNotificationRsp(aEvent, AVRCP_NTF_INTERIM,
                                              param, nullptr);
 }
 
--- a/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothDaemonInterface.cpp
@@ -1507,16 +1507,22 @@ nsresult
 BluetoothDaemonProtocol::Send(BluetoothDaemonPDU* aPDU, void* aUserData)
 {
   MOZ_ASSERT(mConnection);
   MOZ_ASSERT(aPDU);
 
   aPDU->SetConsumer(this);
   aPDU->SetUserData(aUserData);
   aPDU->UpdateHeader();
+
+  if (mConnection->GetConnectionStatus() == SOCKET_DISCONNECTED) {
+    BT_LOGR("Connection to Bluetooth daemon is closed.");
+    return NS_ERROR_FAILURE;
+  }
+
   mConnection->SendSocketData(aPDU); // Forward PDU to command channel
 
   return NS_OK;
 }
 
 void
 BluetoothDaemonProtocol::HandleSetupSvc(
   const BluetoothDaemonPDUHeader& aHeader, BluetoothDaemonPDU& aPDU,
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.cpp
@@ -84,25 +84,21 @@ public:
 
 NS_IMETHODIMP
 BluetoothOppManager::Observe(nsISupports* aSubject,
                              const char* aTopic,
                              const char16_t* aData)
 {
   MOZ_ASSERT(sBluetoothOppManager);
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
   // if state of any volume was changed
   if (!strcmp(aTopic, NS_VOLUME_STATE_CHANGED)) {
     HandleVolumeStateChanged(aSubject);
     return NS_OK;
   }
-#endif
 
   if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
     HandleShutdown();
     return NS_OK;
   }
 
   MOZ_ASSERT(false, "BluetoothOppManager got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
@@ -221,43 +217,35 @@ BluetoothOppManager::BluetoothOppManager
 BluetoothOppManager::~BluetoothOppManager()
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE_VOID(obs);
   if (NS_FAILED(obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID))) {
     BT_WARNING("Failed to remove shutdown observer!");
   }
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
   if (NS_FAILED(obs->RemoveObserver(this, NS_VOLUME_STATE_CHANGED))) {
     BT_WARNING("Failed to remove volume observer!");
   }
-#endif
 }
 
 bool
 BluetoothOppManager::Init()
 {
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, false);
   if (NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
     BT_WARNING("Failed to add shutdown observer!");
     return false;
   }
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
   if (NS_FAILED(obs->AddObserver(this, NS_VOLUME_STATE_CHANGED, false))) {
     BT_WARNING("Failed to add ns volume observer!");
     return false;
   }
-#endif
 
   /**
    * We don't start listening here as BluetoothServiceBluedroid calls Listen()
    * immediately when BT stops.
    *
    * If we start listening here, the listening fails when device boots up since
    * Listen() is called again and restarts server socket. The restart causes
    * absence of read events when device boots up.
@@ -316,19 +304,16 @@ void
 BluetoothOppManager::HandleShutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   sInShutdown = true;
   Disconnect(nullptr);
   sBluetoothOppManager = nullptr;
 }
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
 void
 BluetoothOppManager::HandleVolumeStateChanged(nsISupports* aSubject)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // We will disconnect OPP connection no matter which volume becomes non
   // STATE_MOUNTED, since user may select files scattered in multiple volumes
   // in a single transfer, (e.g., user selects 2 files to transfer, one is in
@@ -352,17 +337,16 @@ BluetoothOppManager::HandleVolumeStateCh
     // Disconnect any connected OPP connection since volume state becomes
     // non STATE_MOUNTED. Then |OnSocketDisconnect| would also be called to
     // handle remaining files during send(|DiscardBlobsToSend|) or
     // receive(|DeleteReceivedFile|).
     BT_LOGR("Volume state is not STATE_MOUNTED. Abort any ongoing OPP connection.");
     Disconnect(nullptr);
   }
 }
-#endif
 
 bool
 BluetoothOppManager::Listen()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mSocket) {
     BT_WARNING("mSocket exists. Failed to listen.");
--- a/dom/bluetooth/bluedroid/BluetoothOppManager.h
+++ b/dom/bluetooth/bluedroid/BluetoothOppManager.h
@@ -72,21 +72,17 @@ public:
 protected:
   virtual ~BluetoothOppManager();
 
 private:
   BluetoothOppManager();
   bool Init();
   void HandleShutdown();
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
   void HandleVolumeStateChanged(nsISupports* aSubject);
-#endif
 
   void StartFileTransfer();
   void StartSendingNextFile();
   void FileTransferComplete();
   void UpdateProgress();
   void ReceivingFileConfirmation();
   bool CreateFile();
   bool WriteToFile(const uint8_t* aData, int aDataLength);
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -203,37 +203,16 @@ BluetoothHfpManager::ResetCallArray()
   Call call;
   mCurrentCallArray.AppendElement(call);
 
   if (mPhoneType == PhoneType::CDMA) {
     mCdmaSecondCall.Reset();
   }
 }
 
-#ifdef MOZ_B2G_BT_API_V2
-void
-BluetoothHfpManager::Reset()
-{
-  mReceiveVgsFlag = false;
-  mDialingRequestProcessed = true;
-
-  mConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
-  mPrevConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
-  mAudioState = HFP_AUDIO_STATE_DISCONNECTED;
-
-  // Phone & Device CIND
-  ResetCallArray();
-  mBattChg = 5;
-  mService = HFP_NETWORK_STATE_NOT_AVAILABLE;
-  mRoam = HFP_SERVICE_TYPE_HOME;
-  mSignal = 0;
-
-  mController = nullptr;
-}
-#else
 void
 BluetoothHfpManager::Cleanup()
 {
   mReceiveVgsFlag = false;
   mDialingRequestProcessed = true;
 
   mConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
   mPrevConnectionState = HFP_CONNECTION_STATE_DISCONNECTED;
@@ -250,27 +229,22 @@ BluetoothHfpManager::Reset()
 {
   mFirstCKPD = false;
   // Phone & Device CIND
   ResetCallArray();
   // Clear Sco state
   mAudioState = HFP_AUDIO_STATE_DISCONNECTED;
   Cleanup();
 }
-#endif
 
 bool
 BluetoothHfpManager::Init()
 {
-#ifdef MOZ_B2G_BT_API_V2
   // The function must run at b2g process since it would access SettingsService.
   MOZ_ASSERT(IsMainProcess());
-#else
-  // Missing on bluetooth1
-#endif
 
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, false);
 
   if (NS_FAILED(obs->AddObserver(this, MOZSETTINGS_CHANGED_ID, false)) ||
       NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
@@ -619,21 +593,17 @@ BluetoothHfpManager::NotifyConnectionSta
         // Bug 979160: This implies the outgoing connection failure.
         // When the outgoing hfp connection fails, state changes to disconnected
         // state. Since bluedroid would not report connecting state, but only
         // report connected/disconnected.
         OnConnect(NS_LITERAL_STRING(ERR_CONNECTION_FAILED));
       } else {
         OnDisconnect(EmptyString());
       }
-#ifdef MOZ_B2G_BT_API_V2
-      Reset();
-#else
       Cleanup();
-#endif
     }
   }
 }
 
 void
 BluetoothHfpManager::NotifyDialer(const nsAString& aCommand)
 {
   NS_NAMED_LITERAL_STRING(type, "bluetooth-dialer-command");
@@ -714,34 +684,24 @@ BluetoothHfpManager::HandleVoiceConnecti
   bool roaming;
   voiceInfo->GetRoaming(&roaming);
   mRoam = (roaming) ? HFP_SERVICE_TYPE_ROAMING : HFP_SERVICE_TYPE_HOME;
 
   // Service
   nsString regState;
   voiceInfo->GetState(regState);
 
-#ifdef MOZ_B2G_BT_API_V2
   BluetoothHandsfreeNetworkState service =
     (regState.EqualsLiteral("registered")) ? HFP_NETWORK_STATE_AVAILABLE :
                                              HFP_NETWORK_STATE_NOT_AVAILABLE;
   if (service != mService) {
     // Notify BluetoothRilListener of service change
     mListener->ServiceChanged(aClientId, service);
   }
   mService = service;
-#else
-  int service = (regState.EqualsLiteral("registered")) ? 1 : 0;
-  if (service != mService) {
-    // Notify BluetoothRilListener of service change
-    mListener->ServiceChanged(aClientId, service);
-  }
-  mService = service ? HFP_NETWORK_STATE_AVAILABLE :
-                       HFP_NETWORK_STATE_NOT_AVAILABLE;
-#endif
 
   // Signal
   JS::Rooted<JS::Value> value(nsContentUtils::RootingCxForThread());
   voiceInfo->GetRelSignalStrength(&value);
   NS_ENSURE_TRUE_VOID(value.isNumber());
   mSignal = (int)ceil(value.toNumber() / 20.0);
 
   UpdateDeviceCIND();
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.h
@@ -167,21 +167,17 @@ private:
   friend class GetVolumeTask;
   friend class CloseScoTask;
   friend class RespondToBLDNTask;
   friend class MainThreadTask;
 
   BluetoothHfpManager();
   bool Init();
 
-#ifdef MOZ_B2G_BT_API_V2
-  // Removed in bluetooth2
-#else
   void Cleanup();
-#endif
 
   void HandleShutdown();
   void HandleVolumeChanged(nsISupports* aSubject);
   void Notify(const hal::BatteryInformation& aBatteryInfo);
 
   void NotifyConnectionStateChanged(const nsAString& aType);
   void NotifyDialer(const nsAString& aCommand);
 
--- a/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp
+++ b/dom/bluetooth/bluetooth2/BluetoothGattCharacteristic.cpp
@@ -295,18 +295,18 @@ BluetoothGattCharacteristic::WriteValue(
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsRefPtr<Promise> promise = Promise::Create(global, aRv);
   NS_ENSURE_TRUE(!aRv.Failed(), nullptr);
 
   BT_ENSURE_TRUE_REJECT(mProperties &
-                          (GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE ||
-                           GATT_CHAR_PROP_BIT_WRITE ||
+                          (GATT_CHAR_PROP_BIT_WRITE_NO_RESPONSE |
+                           GATT_CHAR_PROP_BIT_WRITE |
                            GATT_CHAR_PROP_BIT_SIGNED_WRITE),
                         promise,
                         NS_ERROR_NOT_AVAILABLE);
 
   aValue.ComputeLengthAndData();
 
   nsTArray<uint8_t> value;
   value.AppendElements(aValue.Data(), aValue.Length());
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp
@@ -437,22 +437,18 @@ BluetoothHfpManager::Reset()
   mIsHsp = false;
   mReceiveVgsFlag = false;
   mController = nullptr;
 }
 
 bool
 BluetoothHfpManager::Init()
 {
-#ifdef MOZ_B2G_BT_API_V2
   // The function must run at b2g process since it would access SettingsService.
   MOZ_ASSERT(IsMainProcess());
-#else
-// Missing in bluetooth1
-#endif
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   NS_ENSURE_TRUE(obs, false);
 
   if (NS_FAILED(obs->AddObserver(this, MOZSETTINGS_CHANGED_ID, false)) ||
       NS_FAILED(obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false))) {
     BT_WARNING("Failed to add observers!");
@@ -592,21 +588,18 @@ void
 BluetoothHfpManager::HandleVolumeChanged(nsISupports* aSubject)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // The string that we're interested in will be a JSON string that looks like:
   //  {"key":"volumeup", "value":10}
   //  {"key":"volumedown", "value":2}
 
-#ifdef MOZ_B2G_BT_API_V2
   RootedDictionary<dom::SettingChangeNotification> setting(nsContentUtils::RootingCx());
-#else
-  RootedDictionary<SettingChangeNotification> setting(nsContentUtils::RootingCx());
-#endif
+
   if (!WrappedJSToDictionary(aSubject, setting)) {
     return;
   }
   if (!setting.mKey.EqualsASCII(AUDIO_VOLUME_BT_SCO_ID)) {
     return;
   }
   if (!setting.mValue.isNumber()) {
     return;
@@ -1110,30 +1103,17 @@ BluetoothHfpManager::ReceiveSocketData(B
           return;
         }
       } else {
         // Ignore requests to activate/deactivate mandatory indicators
       }
     }
 #endif // MOZ_B2G_RIL
   } else {
-#ifdef MOZ_B2G_BT_API_V2
-    nsCString warningMsg;
-    warningMsg.Append(NS_LITERAL_CSTRING("Unsupported AT command: "));
-    warningMsg.Append(msg);
-    warningMsg.Append(NS_LITERAL_CSTRING(", reply with ERROR"));
-    BT_WARNING(warningMsg.get());
-#else
-    nsCString warningMsg;
-    warningMsg.AppendLiteral("Unsupported AT command: ");
-    warningMsg.Append(msg);
-    warningMsg.AppendLiteral(", reply with ERROR");
-    BT_WARNING(warningMsg.get());
-#endif
-
+    BT_WARNING("Unsupported AT command: %s, reply with ERROR", msg.get());
     SendLine("ERROR");
     return;
   }
 
 respond_with_ok:
   // We always respond to remote device with "OK" in general cases.
   SendLine("OK");
 }
@@ -1695,21 +1675,17 @@ BluetoothHfpManager::HandleCallStateChan
         UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
       }
 
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
           GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
         // we postpone the timing of dropping SCO.
-#ifdef MOZ_B2G_BT_API_V2
         if (!(aError.Equals(NS_LITERAL_STRING("BusyError")))) {
-#else
-        if (!(aError.EqualsLiteral("BusyError"))) {
-#endif
           DisconnectSco();
         } else {
           // Close Sco later since Dialer is still playing busy tone via HF.
           MessageLoop::current()->PostDelayedTask(FROM_HERE,
                                                   new CloseScoTask(),
                                                   sBusyToneInterval);
         }
 
--- a/dom/broadcastchannel/BroadcastChannel.cpp
+++ b/dom/broadcastchannel/BroadcastChannel.cpp
@@ -11,20 +11,17 @@
 #include "mozilla/dom/StructuredCloneUtils.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/Preferences.h"
 #include "WorkerPrivate.h"
 #include "WorkerRunnable.h"
 
-#include "nsIAppsService.h"
 #include "nsIDocument.h"
-#include "nsIScriptSecurityManager.h"
-#include "nsServiceManagerUtils.h"
 #include "nsISupportsPrimitives.h"
 
 #ifdef XP_WIN
 #undef PostMessage
 #endif
 
 namespace mozilla {
 
@@ -52,46 +49,16 @@ private:
 
 namespace {
 
 void
 GetOrigin(nsIPrincipal* aPrincipal, nsAString& aOrigin, ErrorResult& aRv)
 {
   MOZ_ASSERT(aPrincipal);
 
-  bool unknownAppId;
-  aRv = aPrincipal->GetUnknownAppId(&unknownAppId);
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
-  }
-
-  if (!unknownAppId) {
-    uint32_t appId;
-    aRv = aPrincipal->GetAppId(&appId);
-    if (NS_WARN_IF(aRv.Failed())) {
-      return;
-    }
-
-    if (appId != nsIScriptSecurityManager::NO_APP_ID) {
-      // If we are in "app code", use manifest URL as unique origin since
-      // multiple apps can share the same origin but not same broadcast
-      // messages.
-      nsresult rv;
-      nsCOMPtr<nsIAppsService> appsService =
-        do_GetService("@mozilla.org/AppsService;1", &rv);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        aRv.Throw(rv);
-        return;
-      }
-
-      appsService->GetManifestURLByLocalId(appId, aOrigin);
-      return;
-    }
-  }
-
   nsAutoString tmp;
   aRv = nsContentUtils::GetUTFOrigin(aPrincipal, tmp);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   // 'null' means an unknown origin (it can be chrome code or it can be some
   // about: page).
--- a/dom/broadcastchannel/BroadcastChannelParent.cpp
+++ b/dom/broadcastchannel/BroadcastChannelParent.cpp
@@ -5,51 +5,63 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "BroadcastChannelParent.h"
 #include "BroadcastChannelService.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/ipc/BlobParent.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/unused.h"
+#include "nsIScriptSecurityManager.h"
 
 namespace mozilla {
 
 using namespace ipc;
 
 namespace dom {
 
 BroadcastChannelParent::BroadcastChannelParent(
+                                            const PrincipalInfo& aPrincipalInfo,
                                             const nsAString& aOrigin,
                                             const nsAString& aChannel,
                                             bool aPrivateBrowsing)
   : mService(BroadcastChannelService::GetOrCreate())
   , mOrigin(aOrigin)
   , mChannel(aChannel)
+  , mAppId(nsIScriptSecurityManager::UNKNOWN_APP_ID)
+  , mIsInBrowserElement(false)
   , mPrivateBrowsing(aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
   mService->RegisterActor(this);
+
+  if (aPrincipalInfo.type() ==PrincipalInfo::TContentPrincipalInfo) {
+    const ContentPrincipalInfo& info =
+      aPrincipalInfo.get_ContentPrincipalInfo();
+    mAppId = info.appId();
+    mIsInBrowserElement = info.isInBrowserElement();
+  }
 }
 
 BroadcastChannelParent::~BroadcastChannelParent()
 {
   AssertIsOnBackgroundThread();
 }
 
 bool
 BroadcastChannelParent::RecvPostMessage(const ClonedMessageData& aData)
 {
   AssertIsOnBackgroundThread();
 
   if (NS_WARN_IF(!mService)) {
     return false;
   }
 
-  mService->PostMessage(this, aData, mOrigin, mChannel, mPrivateBrowsing);
+  mService->PostMessage(this, aData, mOrigin, mAppId, mIsInBrowserElement,
+                        mChannel, mPrivateBrowsing);
   return true;
 }
 
 bool
 BroadcastChannelParent::RecvClose()
 {
   AssertIsOnBackgroundThread();
 
@@ -75,22 +87,26 @@ BroadcastChannelParent::ActorDestroy(Act
     // released too.
     mService->UnregisterActor(this);
   }
 }
 
 void
 BroadcastChannelParent::CheckAndDeliver(const ClonedMessageData& aData,
                                         const nsString& aOrigin,
+                                        uint64_t aAppId,
+                                        bool aInBrowserElement,
                                         const nsString& aChannel,
                                         bool aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
 
   if (aOrigin == mOrigin &&
+      aAppId == mAppId &&
+      aInBrowserElement == mIsInBrowserElement &&
       aChannel == mChannel &&
       aPrivateBrowsing == mPrivateBrowsing) {
     // We need to duplicate data only if we have blobs or if the manager of
     // them is different than the manager of this parent actor.
     if (aData.blobsParent().IsEmpty() ||
         static_cast<BlobParent*>(aData.blobsParent()[0])->GetBackgroundManager() == Manager()) {
       unused << SendNotify(aData);
       return;
--- a/dom/broadcastchannel/BroadcastChannelParent.h
+++ b/dom/broadcastchannel/BroadcastChannelParent.h
@@ -8,47 +8,55 @@
 #define mozilla_dom_BroadcastChannelParent_h
 
 #include "mozilla/dom/PBroadcastChannelParent.h"
 
 namespace mozilla {
 
 namespace ipc {
 class BackgroundParentImpl;
+class PrincipalInfo;
 }
 
 namespace dom {
 
 class BroadcastChannelService;
 
 class BroadcastChannelParent final : public PBroadcastChannelParent
 {
   friend class mozilla::ipc::BackgroundParentImpl;
 
+  typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
+
 public:
   void CheckAndDeliver(const ClonedMessageData& aData,
                        const nsString& aOrigin,
+                       const uint64_t aAppId,
+                       const bool aIsInBrowserElement,
                        const nsString& aChannel,
                        bool aPrivateBrowsing);
 
 private:
-  BroadcastChannelParent(const nsAString& aOrigin,
+  BroadcastChannelParent(const PrincipalInfo& aPrincipalInfo,
+                         const nsAString& aOrigin,
                          const nsAString& aChannel,
                          bool aPrivateBrowsing);
   ~BroadcastChannelParent();
 
   virtual bool
   RecvPostMessage(const ClonedMessageData& aData) override;
 
   virtual bool RecvClose() override;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   nsRefPtr<BroadcastChannelService> mService;
   nsString mOrigin;
   nsString mChannel;
+  uint64_t mAppId;
+  bool mIsInBrowserElement;
   bool mPrivateBrowsing;
 };
 
 } // dom namespace
 } // mozilla namespace
 
 #endif // mozilla_dom_BroadcastChannelParent_h
--- a/dom/broadcastchannel/BroadcastChannelService.cpp
+++ b/dom/broadcastchannel/BroadcastChannelService.cpp
@@ -79,22 +79,26 @@ BroadcastChannelService::UnregisterActor
 
 namespace {
 
 struct MOZ_STACK_CLASS PostMessageData final
 {
   PostMessageData(BroadcastChannelParent* aParent,
                   const ClonedMessageData& aData,
                   const nsAString& aOrigin,
+                  uint64_t aAppId,
+                  bool aIsInBrowserElement,
                   const nsAString& aChannel,
                   bool aPrivateBrowsing)
     : mParent(aParent)
     , mData(aData)
     , mOrigin(aOrigin)
     , mChannel(aChannel)
+    , mAppId(aAppId)
+    , mIsInBrowserElement(aIsInBrowserElement)
     , mPrivateBrowsing(aPrivateBrowsing)
   {
     MOZ_ASSERT(aParent);
     MOZ_COUNT_CTOR(PostMessageData);
 
     // We need to keep the array alive for the life-time of this
     // PostMessageData.
     if (!aData.blobsParent().IsEmpty()) {
@@ -114,47 +118,53 @@ struct MOZ_STACK_CLASS PostMessageData f
     MOZ_COUNT_DTOR(PostMessageData);
   }
 
   BroadcastChannelParent* mParent;
   const ClonedMessageData& mData;
   nsTArray<nsRefPtr<FileImpl>> mFiles;
   const nsString mOrigin;
   const nsString mChannel;
+  uint64_t mAppId;
+  bool mIsInBrowserElement;
   bool mPrivateBrowsing;
 };
 
 PLDHashOperator
 PostMessageEnumerator(nsPtrHashKey<BroadcastChannelParent>* aKey, void* aPtr)
 {
   AssertIsOnBackgroundThread();
 
   auto* data = static_cast<PostMessageData*>(aPtr);
   BroadcastChannelParent* parent = aKey->GetKey();
   MOZ_ASSERT(parent);
 
   if (parent != data->mParent) {
-    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mChannel,
+    parent->CheckAndDeliver(data->mData, data->mOrigin, data->mAppId,
+                            data->mIsInBrowserElement, data->mChannel,
                             data->mPrivateBrowsing);
   }
 
   return PL_DHASH_NEXT;
 }
 
 } // anonymous namespace
 
 void
 BroadcastChannelService::PostMessage(BroadcastChannelParent* aParent,
                                      const ClonedMessageData& aData,
                                      const nsAString& aOrigin,
+                                     uint64_t aAppId,
+                                     bool aIsInBrowserElement,
                                      const nsAString& aChannel,
                                      bool aPrivateBrowsing)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aParent);
   MOZ_ASSERT(mAgents.Contains(aParent));
 
-  PostMessageData data(aParent, aData, aOrigin, aChannel, aPrivateBrowsing);
+  PostMessageData data(aParent, aData, aOrigin, aAppId, aIsInBrowserElement,
+                       aChannel, aPrivateBrowsing);
   mAgents.EnumerateEntries(PostMessageEnumerator, &data);
 }
 
 } // dom namespace
 } // mozilla namespace
--- a/dom/broadcastchannel/BroadcastChannelService.h
+++ b/dom/broadcastchannel/BroadcastChannelService.h
@@ -29,16 +29,18 @@ public:
   static already_AddRefed<BroadcastChannelService> GetOrCreate();
 
   void RegisterActor(BroadcastChannelParent* aParent);
   void UnregisterActor(BroadcastChannelParent* aParent);
 
   void PostMessage(BroadcastChannelParent* aParent,
                    const ClonedMessageData& aData,
                    const nsAString& aOrigin,
+                   uint64_t aAppId,
+                   bool aIsInBrowserElement,
                    const nsAString& aChannel,
                    bool aPrivateBrowsing);
 
 private:
   BroadcastChannelService();
   ~BroadcastChannelService();
 
   nsTHashtable<nsPtrHashKey<BroadcastChannelParent>> mAgents;
--- a/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html
+++ b/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.html
@@ -14,30 +14,30 @@
 
 var frame_src = 'http://example.com/tests/dom/browser-element/mochitest/file_browserElement_XFrameOptionsAllowFrom.sjs';
 
 var iframe1 = document.createElement('iframe');
 iframe1.height = '300px';
 var iframe2 = document.createElement('iframe');
 iframe2.height = '300px';
 document.body.appendChild(iframe1);
-document.body.appendChild(iframe2);
 
 iframe1.addEventListener('load', function iframe1Load() {
   iframe1.removeEventListener('load', iframe1Load);
   // This causes our embedder to take a screenshot (and blocks until the
   // screenshot is completed).
   var iframe2Loaded = false;
   iframe2.addEventListener('load', function iframe2Load() {
     iframe2.removeEventListener('load', iframe2Load);
     iframe2Loaded = true;
     alert('finish');
   });
 
-  setTimeout(function() { iframe2.src = frame_src; }, 1000);
+  document.body.appendChild(iframe2);
+  iframe2.src = frame_src;
 });
 
 
 iframe1.src = frame_src + '?iframe1';
 </script>
 
 </body>
 </html>
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -35,16 +35,18 @@
 #include "nsIDOMEvent.h"
 #include "nsIEventTarget.h"
 #include "nsPIDOMWindow.h"
 #include "nsThreadUtils.h"
 #include "nsTraceRefcnt.h"
 #include "PermissionRequestBase.h"
 #include "ProfilerHelpers.h"
 #include "ReportInternalError.h"
+#include "WorkerPrivate.h"
+#include "WorkerRunnable.h"
 
 #ifdef DEBUG
 #include "IndexedDatabaseManager.h"
 #endif
 
 #define GC_ON_IPC_MESSAGES 0
 
 #if defined(DEBUG) || GC_ON_IPC_MESSAGES
@@ -52,17 +54,23 @@
 #include "js/GCAPI.h"
 #include "nsJSEnvironment.h"
 
 #define BUILD_GC_ON_IPC_MESSAGES
 
 #endif // DEBUG || GC_ON_IPC_MESSAGES
 
 namespace mozilla {
+
+using ipc::PrincipalInfo;
+
 namespace dom {
+
+using namespace workers;
+
 namespace indexedDB {
 
 /*******************************************************************************
  * ThreadLocal
  ******************************************************************************/
 
 ThreadLocal::ThreadLocal(const nsID& aBackgroundChildLoggingId)
   : mLoggingInfo(aBackgroundChildLoggingId, 1, -1, 1)
@@ -772,16 +780,245 @@ DispatchSuccessEvent(ResultHelper* aResu
 
   if (transaction &&
       transaction->IsOpen() &&
       internalEvent->mFlags.mExceptionHasBeenRisen) {
     transaction->Abort(NS_ERROR_DOM_INDEXEDDB_ABORT_ERR);
   }
 }
 
+class WorkerPermissionChallenge;
+
+// This class calles WorkerPermissionChallenge::OperationCompleted() in the
+// worker thread.
+class WorkerPermissionOperationCompleted final : public WorkerRunnable
+{
+  nsRefPtr<WorkerPermissionChallenge> mChallenge;
+
+public:
+  WorkerPermissionOperationCompleted(WorkerPrivate* aWorkerPrivate,
+                                     WorkerPermissionChallenge* aChallenge)
+    : WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
+    , mChallenge(aChallenge)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  virtual bool
+  WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override;
+};
+
+// This class used to do prompting in the main thread and main process.
+class WorkerPermissionRequest final : public PermissionRequestBase
+{
+  nsRefPtr<WorkerPermissionChallenge> mChallenge;
+
+public:
+  WorkerPermissionRequest(Element* aElement,
+                          nsIPrincipal* aPrincipal,
+                          WorkerPermissionChallenge* aChallenge)
+    : PermissionRequestBase(aElement, aPrincipal)
+    , mChallenge(aChallenge)
+  {
+    MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(aChallenge);
+  }
+
+private:
+  ~WorkerPermissionRequest()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  virtual void
+  OnPromptComplete(PermissionValue aPermissionValue) override;
+};
+
+// This class is used in the main thread of all child processes.
+class WorkerPermissionRequestChildProcessActor final
+  : public PIndexedDBPermissionRequestChild
+{
+  nsRefPtr<WorkerPermissionChallenge> mChallenge;
+
+public:
+  explicit WorkerPermissionRequestChildProcessActor(
+                                          WorkerPermissionChallenge* aChallenge)
+    : mChallenge(aChallenge)
+  {
+    MOZ_ASSERT(XRE_GetProcessType() != GeckoProcessType_Default);
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(aChallenge);
+  }
+
+protected:
+  ~WorkerPermissionRequestChildProcessActor()
+  {}
+
+  virtual bool
+  Recv__delete__(const uint32_t& aPermission) override;
+};
+
+class WorkerPermissionChallenge final : public nsRunnable
+                                      , public WorkerFeature
+{
+public:
+  WorkerPermissionChallenge(WorkerPrivate* aWorkerPrivate,
+                            BackgroundFactoryRequestChild* aActor,
+                            IDBFactory* aFactory,
+                            const PrincipalInfo& aPrincipalInfo)
+    : mWorkerPrivate(aWorkerPrivate)
+    , mActor(aActor)
+    , mFactory(aFactory)
+    , mPrincipalInfo(aPrincipalInfo)
+  {
+    MOZ_ASSERT(mWorkerPrivate);
+    MOZ_ASSERT(aActor);
+    MOZ_ASSERT(aFactory);
+    mWorkerPrivate->AssertIsOnWorkerThread();
+  }
+
+  NS_IMETHOD
+  Run() override
+  {
+    bool completed = RunInternal();
+    if (completed) {
+      OperationCompleted();
+    }
+
+    return NS_OK;
+  }
+
+  virtual bool
+  Notify(JSContext* aCx, workers::Status aStatus) override
+  {
+    // We don't care about the notification. We just want to keep the
+    // mWorkerPrivate alive.
+    return true;
+  }
+
+  void
+  OperationCompleted()
+  {
+    if (NS_IsMainThread()) {
+      nsRefPtr<WorkerPermissionOperationCompleted> runnable =
+        new WorkerPermissionOperationCompleted(mWorkerPrivate, this);
+
+      if (!runnable->Dispatch(nullptr)) {
+        NS_WARNING("Failed to dispatch a runnable to the worker thread.");
+        return;
+      }
+
+      return;
+    }
+
+    MOZ_ASSERT(mActor);
+    mActor->AssertIsOnOwningThread();
+
+    MaybeCollectGarbageOnIPCMessage();
+
+    nsRefPtr<IDBFactory> factory;
+    mFactory.swap(factory);
+
+    mActor->SendPermissionRetry();
+    mActor = nullptr;
+
+    mWorkerPrivate->AssertIsOnWorkerThread();
+    JSContext* cx = mWorkerPrivate->GetJSContext();
+    mWorkerPrivate->RemoveFeature(cx, this);
+  }
+
+private:
+  bool
+  RunInternal()
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    // Walk up to our containing page
+    WorkerPrivate* wp = mWorkerPrivate;
+    while (wp->GetParent()) {
+      wp = wp->GetParent();
+    }
+
+    nsPIDOMWindow* window = wp->GetWindow();
+    if (!window) {
+      return true;
+    }
+
+    nsresult rv;
+    nsCOMPtr<nsIPrincipal> principal =
+      mozilla::ipc::PrincipalInfoToPrincipal(mPrincipalInfo, &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return true;
+    }
+
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+      nsCOMPtr<Element> ownerElement =
+        do_QueryInterface(window->GetChromeEventHandler());
+      if (NS_WARN_IF(!ownerElement)) {
+        return true;
+      }
+
+      nsRefPtr<WorkerPermissionRequest> helper =
+        new WorkerPermissionRequest(ownerElement, principal, this);
+
+      PermissionRequestBase::PermissionValue permission;
+      if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {
+        return true;
+      }
+
+      MOZ_ASSERT(permission == PermissionRequestBase::kPermissionAllowed ||
+                 permission == PermissionRequestBase::kPermissionDenied ||
+                 permission == PermissionRequestBase::kPermissionPrompt);
+
+      return permission != PermissionRequestBase::kPermissionPrompt;
+    }
+
+    TabChild* tabChild = TabChild::GetFrom(window);
+    MOZ_ASSERT(tabChild);
+
+    IPC::Principal ipcPrincipal(principal);
+
+    auto* actor = new WorkerPermissionRequestChildProcessActor(this);
+    tabChild->SendPIndexedDBPermissionRequestConstructor(actor, ipcPrincipal);
+    return false;
+  }
+
+private:
+  WorkerPrivate* mWorkerPrivate;
+  BackgroundFactoryRequestChild* mActor;
+  nsRefPtr<IDBFactory> mFactory;
+  PrincipalInfo mPrincipalInfo;
+};
+
+void
+WorkerPermissionRequest::OnPromptComplete(PermissionValue aPermissionValue)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mChallenge->OperationCompleted();
+}
+
+bool
+WorkerPermissionOperationCompleted::WorkerRun(JSContext* aCx,
+                                              WorkerPrivate* aWorkerPrivate)
+{
+  aWorkerPrivate->AssertIsOnWorkerThread();
+  mChallenge->OperationCompleted();
+  return true;
+}
+
+bool
+WorkerPermissionRequestChildProcessActor::Recv__delete__(
+                                              const uint32_t& /* aPermission */)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mChallenge->OperationCompleted();
+  return true;
+}
+
 } // anonymous namespace
 
 /*******************************************************************************
  * Local class implementations
  ******************************************************************************/
 
 void
 PermissionRequestMainProcessHelper::OnPromptComplete(
@@ -1119,17 +1356,33 @@ bool
 BackgroundFactoryRequestChild::RecvPermissionChallenge(
                                             const PrincipalInfo& aPrincipalInfo)
 {
   AssertIsOnOwningThread();
 
   MaybeCollectGarbageOnIPCMessage();
 
   if (!NS_IsMainThread()) {
-    MOZ_CRASH("Implement me for workers!");
+    WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
+    MOZ_ASSERT(workerPrivate);
+    workerPrivate->AssertIsOnWorkerThread();
+
+    nsRefPtr<WorkerPermissionChallenge> challenge =
+      new WorkerPermissionChallenge(workerPrivate, this, mFactory,
+                                    aPrincipalInfo);
+
+    JSContext* cx = workerPrivate->GetJSContext();
+    MOZ_ASSERT(cx);
+
+    if (!workerPrivate->AddFeature(cx, challenge)) {
+      return false;
+    }
+
+    MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(challenge)));
+    return true;
   }
 
   nsresult rv;
   nsCOMPtr<nsIPrincipal> principal =
     mozilla::ipc::PrincipalInfoToPrincipal(aPrincipalInfo, &rv);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return false;
   }
--- a/dom/indexedDB/test/browser.ini
+++ b/dom/indexedDB/test/browser.ini
@@ -1,16 +1,21 @@
 [DEFAULT]
 skip-if = (buildapp != "browser") || e10s
 support-files =
   head.js
   browser_forgetThisSiteAdd.html
   browser_forgetThisSiteGet.html
   browserHelpers.js
   browser_permissionsPrompt.html
+  browser_permissionsSharedWorker.html
+  browser_permissionsSharedWorker.js
+  browser_permissionsWorker.html
+  browser_permissionsWorker.js
   bug839193.js
   bug839193.xul
 
 [browser_forgetThisSite.js]
 [browser_permissionsPromptAllow.js]
 [browser_permissionsPromptDeny.js]
+[browser_permissionsPromptWorker.js]
 [browser_perwindow_privateBrowsing.js]
 [browser_bug839193.js]
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/browser_permissionsPromptWorker.js
@@ -0,0 +1,91 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const testWorkerURL = "http://mochi.test:8888/browser/" +
+  "dom/indexedDB/test/browser_permissionsWorker.html";
+const testSharedWorkerURL = "http://mochi.test:8888/browser/" +
+  "dom/indexedDB/test/browser_permissionsSharedWorker.html";
+const notificationID = "indexedDB-permissions-prompt";
+
+function test()
+{
+  waitForExplicitFinish();
+  executeSoon(test1);
+}
+
+function test1()
+{
+  // We want a prompt.
+  removePermission(testWorkerURL, "indexedDB");
+
+  info("creating tab");
+  gBrowser.selectedTab = gBrowser.addTab();
+
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    setFinishedCallback(function(isIDBDatabase, exception) {
+      ok(isIDBDatabase, "First database creation was successful");
+      ok(!exception, "No exception");
+      is(getPermission(testWorkerURL, "indexedDB"),
+         Components.interfaces.nsIPermissionManager.ALLOW_ACTION,
+         "Correct permission set");
+      gBrowser.removeCurrentTab();
+      executeSoon(test2);
+    });
+
+    registerPopupEventHandler("popupshowing", function () {
+      ok(true, "prompt showing");
+    });
+    registerPopupEventHandler("popupshown", function () {
+      ok(true, "prompt shown");
+      triggerMainCommand(this);
+    });
+    registerPopupEventHandler("popuphidden", function () {
+      ok(true, "prompt hidden");
+    });
+
+  }, true);
+
+  info("loading test page: " + testWorkerURL);
+  content.location = testWorkerURL;
+}
+
+function test2()
+{
+  // We want a prompt.
+  removePermission(testSharedWorkerURL, "indexedDB");
+
+  info("creating tab");
+  gBrowser.selectedTab = gBrowser.addTab();
+
+  gBrowser.selectedBrowser.addEventListener("load", function () {
+    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+
+    setFinishedCallback(function(isIDBDatabase, exception) {
+      ok(!isIDBDatabase, "First database creation was successful");
+      ok(exception, "No exception");
+      is(getPermission(testSharedWorkerURL, "indexedDB"),
+         Components.interfaces.nsIPermissionManager.UNKNOWN_ACTION,
+         "Correct permission set");
+      gBrowser.removeCurrentTab();
+      executeSoon(finish);
+    });
+
+    registerPopupEventHandler("popupshowing", function () {
+      ok(false, "prompt showing");
+    });
+    registerPopupEventHandler("popupshown", function () {
+      ok(false, "prompt shown");
+    });
+    registerPopupEventHandler("popuphidden", function () {
+      ok(false, "prompt hidden");
+    });
+
+  }, true);
+
+  info("loading test page: " + testSharedWorkerURL);
+  content.location = testSharedWorkerURL;
+}
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/browser_permissionsSharedWorker.html
@@ -0,0 +1,34 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+  <head>
+    <title>Indexed Database Test</title>
+
+    <script type="text/javascript;version=1.7">
+    let testIsIDBDatabase;
+    let testException;
+
+    function runTest() {
+      let w = new SharedWorker('browser_permissionsSharedWorker.js');
+      w.port.onmessage = function(e) {
+        if (e.data.status == 'success') {
+          testIsIDBDatabase = e.data.isIDBDatabase;
+        } else {
+          testException = e.data.error;
+        }
+
+        setTimeout(testFinishedCallback, 0, testIsIDBDatabase, testException);
+      }
+
+      const name = window.location.pathname + "_sharedWorker";
+      w.port.postMessage(name);
+    }
+    </script>
+
+  </head>
+
+  <body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/browser_permissionsSharedWorker.js
@@ -0,0 +1,14 @@
+onconnect = function(e) {
+  e.ports[0].onmessage = function(e) {
+    var request = indexedDB.open(e.data, { version: 1,
+                                           storage: "persistent" });
+    request.onsuccess = function(event) {
+      e.target.postMessage({ status: 'success',
+                             isIDBDatabase: (event.target.result instanceof IDBDatabase) });
+    }
+
+    request.onerror = function(event) {
+      e.target.postMessage({ status: 'error', error: event.target.error.name });
+    }
+  }
+}
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/browser_permissionsWorker.html
@@ -0,0 +1,34 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+  <head>
+    <title>Indexed Database Test</title>
+
+    <script type="text/javascript;version=1.7">
+    let testIsIDBDatabase;
+    let testException;
+
+    function runTest() {
+      let w = new Worker('browser_permissionsWorker.js');
+      w.onmessage = function(e) {
+        if (e.data.status == 'success') {
+          testIsIDBDatabase = e.data.isIDBDatabase;
+        } else {
+          testException = e.data.error;
+        }
+
+        setTimeout(testFinishedCallback, 0, testIsIDBDatabase, testException);
+      }
+
+      const name = window.location.pathname;
+      w.postMessage(name);
+    }
+    </script>
+
+  </head>
+
+  <body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/browser_permissionsWorker.js
@@ -0,0 +1,12 @@
+onmessage = function(e) {
+  var request = indexedDB.open(e.data, { version: 1,
+                                         storage: "persistent" });
+  request.onsuccess = function(event) {
+    postMessage({ status: 'success',
+                  isIDBDatabase: (event.target.result instanceof IDBDatabase) });
+  }
+
+  request.onerror = function(event) {
+    postMessage({ status: 'error', error: event.target.error.name });
+  }
+}
--- a/dom/plugins/ipc/TaskFactory.h
+++ b/dom/plugins/ipc/TaskFactory.h
@@ -2,16 +2,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_plugins_TaskFactory_h
 #define mozilla_plugins_TaskFactory_h
 
 #include <base/task.h>
 
+#include "mozilla/Move.h"
+
 /*
  * This is based on the ScopedRunnableMethodFactory from ipc/chromium/src/base/task.h
  * Chromium's factories assert if tasks are created and run on different threads,
  * which is something we need to do in PluginModuleParent (hang UI vs. main thread).
  * TaskFactory just provides cancellable tasks that don't assert this.
  * This version also allows both ScopedMethod and regular Tasks to be generated
  * by the same Factory object.
  */
@@ -22,35 +24,40 @@ namespace plugins {
 template<class T>
 class TaskFactory : public RevocableStore
 {
 private:
   template<class TaskType>
   class TaskWrapper : public TaskType
   {
   public:
-    explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
+    template<typename... Args>
+    explicit TaskWrapper(RevocableStore* store, Args&&... args)
+      : TaskType(mozilla::Forward<Args>(args)...)
+      , revocable_(store)
+    {
+    }
 
     virtual void Run() {
       if (!revocable_.revoked())
         TaskType::Run();
     }
 
   private:
     Revocable revocable_;
   };
 
 public:
   explicit TaskFactory(T* object) : object_(object) { }
 
-  template <class TaskParamType>
-  inline TaskParamType* NewTask()
+  template <typename TaskParamType, typename... Args>
+  inline TaskParamType* NewTask(Args&&... args)
   {
     typedef TaskWrapper<TaskParamType> TaskWrapper;
-    TaskWrapper* task = new TaskWrapper(this);
+    TaskWrapper* task = new TaskWrapper(this, mozilla::Forward<Args>(args)...);
     return task;
   }
 
   template <class Method>
   inline Task* NewRunnableMethod(Method method) {
     typedef TaskWrapper<RunnableMethod<Method, Tuple0> > TaskWrapper;
 
     TaskWrapper* task = new TaskWrapper(this);
--- a/dom/system/gonk/AutoMounter.cpp
+++ b/dom/system/gonk/AutoMounter.cpp
@@ -840,36 +840,36 @@ AutoMounter::UpdateState()
 
       // if ums/rndis is not available and mtp is disable,
       // restore the usb function as PERSIST_SYS_USB_CONFIG.
       SetUsbFunction(USB_FUNC_DEFAULT);
       SetState(STATE_IDLE);
       break;
 
     case STATE_UMS_CONFIGURING:
+      if (mtpEnabled) {
+        // MTP was enabled. Start reconfiguring.
+        SetState(STATE_MTP_CONFIGURING);
+        SetUsbFunction(USB_FUNC_MTP);
+        break;
+      }
+      if (rndisConfigured) {
+        SetState(STATE_RNDIS_CONFIGURED);
+        break;
+      }
       // While configuring, the USB configuration state will change from
       // CONFIGURED -> CONNECTED -> DISCONNECTED -> CONNECTED -> CONFIGURED
       // so we don't check for cable unplugged here. However, having said
       // that, we'll often sit in this state while the cable is unplugged,
       // since we might not get any events until the cable gets plugged back
       // in. This is why we need to check for mtpEnabled once we get the
       // configured event.
       if (umsConfigured) {
-        if (mtpEnabled) {
-          // MTP was enabled. Start reconfiguring.
-          SetState(STATE_MTP_CONFIGURING);
-          SetUsbFunction(USB_FUNC_MTP);
-          break;
-        }
         SetState(STATE_UMS_CONFIGURED);
       }
-      if (rndisConfigured) {
-        SetState(STATE_RNDIS_CONFIGURED);
-        break;
-      }
       break;
 
     case STATE_UMS_CONFIGURED:
       if (usbCablePluggedIn) {
         if (mtpEnabled) {
           // MTP was enabled. Start reconfiguring.
           SetState(STATE_MTP_CONFIGURING);
           SetUsbFunction(USB_FUNC_MTP);
@@ -1114,16 +1114,17 @@ AutoMounter::UpdateState()
 }
 
 /***************************************************************************/
 
 void AutoMounter::GetStatus(bool& umsAvail, bool& umsConfigured, bool& umsEnabled,
                             bool& mtpAvail, bool& mtpConfigured, bool& mtpEnabled,
                             bool& rndisConfigured)
 {
+  umsAvail = false;
   umsConfigured = false;
   umsEnabled = false;
   mtpAvail = false;
   mtpConfigured = false;
   mtpEnabled = false;
   rndisConfigured = false;
 
   if (access(ICS_SYS_USB_FUNCTIONS, F_OK) != 0) {
--- a/dom/system/gonk/TetheringService.js
+++ b/dom/system/gonk/TetheringService.js
@@ -34,18 +34,16 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyGetter(this, "gRil", function() {
   try {
     return Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
   } catch (e) {}
 
   return null;
 });
 
-const TOPIC_INTERFACE_REGISTERED     = "network-interface-registered";
-const TOPIC_INTERFACE_UNREGISTERED   = "network-interface-unregistered";
 const TOPIC_MOZSETTINGS_CHANGED      = "mozsettings-changed";
 const TOPIC_CONNECTION_STATE_CHANGED = "network-connection-state-changed";
 const TOPIC_PREF_CHANGED             = "nsPref:changed";
 const TOPIC_XPCOM_SHUTDOWN           = "xpcom-shutdown";
 const PREF_NETWORK_DEBUG_ENABLED     = "network.debugging.enabled";
 
 const POSSIBLE_USB_INTERFACE_NAME = "rndis0,usb0";
 const DEFAULT_USB_INTERFACE_NAME  = "rndis0";
@@ -121,18 +119,16 @@ function updateDebug() {
   }
 }
 updateDebug();
 
 function TetheringService() {
   Services.obs.addObserver(this, TOPIC_XPCOM_SHUTDOWN, false);
   Services.obs.addObserver(this, TOPIC_MOZSETTINGS_CHANGED, false);
   Services.obs.addObserver(this, TOPIC_CONNECTION_STATE_CHANGED, false);
-  Services.obs.addObserver(this, TOPIC_INTERFACE_REGISTERED, false);
-  Services.obs.addObserver(this, TOPIC_INTERFACE_UNREGISTERED, false);
   Services.prefs.addObserver(PREF_NETWORK_DEBUG_ENABLED, this, false);
 
   this._dataDefaultServiceId = 0;
 
   // Possible usb tethering interfaces for different gonk platform.
   this.possibleInterface = POSSIBLE_USB_INTERFACE_NAME.split(",");
 
   // Default values for internal and external interfaces.
@@ -252,38 +248,20 @@ TetheringService.prototype = {
         this.handle(aSubject.key, aSubject.value);
         break;
       case TOPIC_CONNECTION_STATE_CHANGED:
         network = aSubject.QueryInterface(Ci.nsINetworkInterface);
         debug("Network " + network.type + "/" + network.name +
               " changed state to " + network.state);
         this.onConnectionChanged(network);
         break;
-      case TOPIC_INTERFACE_REGISTERED:
-        network = aSubject.QueryInterface(Ci.nsINetworkInterface);
-        if (network &&
-            network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
-          debug("Force setting " + SETTINGS_DUN_REQUIRED + " to true.");
-          this.tetheringSettings[SETTINGS_DUN_REQUIRED] = true;
-        }
-        break;
-      case TOPIC_INTERFACE_UNREGISTERED:
-        network = aSubject.QueryInterface(Ci.nsINetworkInterface);
-        if (network &&
-            network.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN) {
-          this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
-          libcutils.property_get("ro.tethering.dun_required") === "1";
-        }
-        break;
       case TOPIC_XPCOM_SHUTDOWN:
         Services.obs.removeObserver(this, TOPIC_XPCOM_SHUTDOWN);
         Services.obs.removeObserver(this, TOPIC_MOZSETTINGS_CHANGED);
         Services.obs.removeObserver(this, TOPIC_CONNECTION_STATE_CHANGED);
-        Services.obs.removeObserver(this, TOPIC_INTERFACE_REGISTERED);
-        Services.obs.removeObserver(this, TOPIC_INTERFACE_UNREGISTERED);
         Services.prefs.removeObserver(PREF_NETWORK_DEBUG_ENABLED, this);
 
         this.dunConnectTimer.cancel();
         this.dunRetryTimer.cancel();
         break;
     }
   },
 
@@ -638,16 +616,20 @@ TetheringService.prototype = {
       // the request params and redo |setWifiTethering| on
       // usb tethering task complete.
       debug('USB tethering request is being processed. Queue this wifi tethering request.');
       this._pendingWifiTetheringRequestArgs = Array.prototype.slice.call(arguments);
       debug('Pending args: ' + JSON.stringify(this._pendingWifiTetheringRequestArgs));
       return;
     }
 
+    // Re-check again, test cases set this property later.
+    this.tetheringSettings[SETTINGS_DUN_REQUIRED] =
+      libcutils.property_get("ro.tethering.dun_required") === "1";
+
     if (!aEnable) {
       this.enableWifiTethering(false, aConfig, aCallback);
       return;
     }
 
     this._tetheringInterface[TETHERING_TYPE_WIFI].internalInterface = aNetwork.name;
 
     if (this.tetheringSettings[SETTINGS_DUN_REQUIRED]) {
--- a/dom/tethering/tests/marionette/head.js
+++ b/dom/tethering/tests/marionette/head.js
@@ -214,16 +214,24 @@ let gTestSuite = (function() {
   /**
    * Convenient MozSettings setter for SETTINGS_KEY_DATA_APN_SETTINGS.
    */
   function setDataApnSettings(aApnSettings, aAllowError) {
     return setSettings1(SETTINGS_KEY_DATA_APN_SETTINGS, aApnSettings, aAllowError);
   }
 
   /**
+   * Set 'ro.tethering.dun_required' system property to 1. Note that this is a
+   * 'ro' property, it can only be set once.
+   */
+  function setTetheringDunRequired() {
+    return runEmulatorShellSafe(['setprop', 'ro.tethering.dun_required', '1']);
+  }
+
+  /**
    * Wrap DOMRequest onsuccess/onerror events to Promise resolve/reject.
    *
    * Fulfill params: A DOMEvent.
    * Reject params: A DOMEvent.
    *
    * @param aRequest
    *        A DOMRequest instance.
    *
@@ -699,16 +707,17 @@ let gTestSuite = (function() {
 
   //---------------------------------------------------
   // Public test suite functions
   //---------------------------------------------------
   suite.ensureWifiEnabled = ensureWifiEnabled;
   suite.setWifiTetheringEnabled = setWifiTetheringEnabled;
   suite.getDataApnSettings = getDataApnSettings;
   suite.setDataApnSettings = setDataApnSettings;
+  suite.setTetheringDunRequired = setTetheringDunRequired;
 
 
   /**
    * The common test routine for wifi tethering.
    *
    * Set 'ril.data.enabled' to true
    * before testing and restore it afterward. It will also verify 'ril.data.enabled'
    * and 'tethering.wifi.enabled' to be false in the beginning. Note that this routine
--- a/dom/tethering/tests/marionette/manifest.ini
+++ b/dom/tethering/tests/marionette/manifest.ini
@@ -1,7 +1,9 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_wifi_tethering_enabled.js]
+; The following test must be the last tethering test ran, as it sets the
+; 'ro.tethering.dun_required' property.
 [test_wifi_tethering_dun.js]
--- a/dom/tethering/tests/marionette/test_wifi_tethering_dun.js
+++ b/dom/tethering/tests/marionette/test_wifi_tethering_dun.js
@@ -17,16 +17,17 @@ gTestSuite.startTest(function() {
                              "apn": "epc1.tmobile.com",
                              "mmsc": "http://mms.msg.eng.t-mobile.com/mms/wapenc",
                              "types": ["default","supl","mms"] },
                            { "carrier": "T-Mobile US",
                              "apn": "epc2.tmobile.com",
                              "types": ["dun"] } ]];
       return gTestSuite.setDataApnSettings(apnSettings);
     })
+    .then(() => gTestSuite.setTetheringDunRequired())
     .then(() => gTestSuite.startTetheringTest(function() {
       return gTestSuite.ensureWifiEnabled(false)
         .then(() => gTestSuite.setWifiTetheringEnabled(true, true))
         .then(() => gTestSuite.setWifiTetheringEnabled(false, true));
     }))
     // Restore apn settings.
     .then(() => {
       if (origApnSettings) {
--- a/dom/workers/test/serviceworkers/fetch/context/index.html
+++ b/dom/workers/test/serviceworkers/fetch/context/index.html
@@ -321,20 +321,16 @@
           iframe.parentNode.removeChild(iframe);
           resolve();
         }
       }, false);
     });
   }
 
   function testCache() {
-    if (isAndroid) {
-      // FIXME: Re-enable this test on Android once bug 1148818 gets fixed.
-      return Promise.resolve();
-    }
     return new Promise(function(resolve, reject) {
       // Issue an XHR that will be intercepted by the SW in order to start off
       // the test with a RequestContext value that is not the default ("fetch").
       // This needs to run inside a fetch event handler because synthesized
       // RequestContext objects can only have the "fetch" context, and we'd
       // prefer to test the more general case of some other RequestContext value.
       var xhr = new XMLHttpRequest();
       xhr.open("get", "cache", true);
--- a/gfx/layers/GrallocImages.cpp
+++ b/gfx/layers/GrallocImages.cpp
@@ -293,16 +293,17 @@ ConvertOmxYUVFormatToRGB565(android::sp<
     return BAD_VALUE;
   }
 
   GraphicBufferAutoUnlock unlock(aBuffer);
 
   uint32_t format = aBuffer->getPixelFormat();
   uint32_t width = aSurface->GetSize().width;
   uint32_t height = aSurface->GetSize().height;
+  uint32_t stride = aBuffer->getStride();
 
   if (format == GrallocImage::HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO) {
     // The Adreno hardware decoder aligns image dimensions to a multiple of 32,
     // so we have to account for that here
     uint32_t alignedWidth = ALIGN(width, 32);
     uint32_t alignedHeight = ALIGN(height, 32);
     uint32_t uvOffset = ALIGN(alignedHeight * alignedWidth, 4096);
     uint32_t uvStride = 2 * ALIGN(width / 2, 32);
@@ -311,21 +312,21 @@ ConvertOmxYUVFormatToRGB565(android::sp<
                             buffer + uvOffset,
                             uvStride,
                             aMappedSurface->mData,
                             width, height);
     return OK;
   }
 
   if (format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
-    uint32_t uvOffset = height * width;
-    ConvertYVU420SPToRGB565(buffer, width,
+    uint32_t uvOffset = height * stride;
+    ConvertYVU420SPToRGB565(buffer, stride,
                             buffer + uvOffset + 1,
                             buffer + uvOffset,
-                            width,
+                            stride,
                             aMappedSurface->mData,
                             width, height);
     return OK;
   }
 
   if (format == HAL_PIXEL_FORMAT_YV12) {
     // Depend on platforms, it is possible for HW decoder to output YV12 format.
     // It means the mData won't be configured during the SetData API because the
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -257,17 +257,18 @@ BackgroundParentImpl::AllocPBroadcastCha
                                             const PrincipalInfo& aPrincipalInfo,
                                             const nsString& aOrigin,
                                             const nsString& aChannel,
                                             const bool& aPrivateBrowsing)
 {
   AssertIsInMainProcess();
   AssertIsOnBackgroundThread();
 
-  return new BroadcastChannelParent(aOrigin, aChannel, aPrivateBrowsing);
+  return new BroadcastChannelParent(aPrincipalInfo, aOrigin, aChannel,
+                                    aPrivateBrowsing);
 }
 
 namespace {
 
 class CheckPrincipalRunnable final : public nsRunnable
 {
 public:
   CheckPrincipalRunnable(already_AddRefed<ContentParent> aParent,
@@ -310,57 +311,16 @@ public:
 
     bool isNullPrincipal;
     nsresult rv = principal->GetIsNullPrincipal(&isNullPrincipal);
     if (NS_WARN_IF(NS_FAILED(rv)) || isNullPrincipal) {
       mContentParent->KillHard("BroadcastChannel killed: no null principal.");
       return NS_OK;
     }
 
-    bool unknownAppId;
-    rv = principal->GetUnknownAppId(&unknownAppId);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      mContentParent->KillHard("BroadcastChannel killed: failed to get the app status.");
-      return NS_OK;
-    }
-
-    if (!unknownAppId) {
-      uint32_t appId;
-      rv = principal->GetAppId(&appId);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        mContentParent->KillHard("BroadcastChannel killed: failed to get the app id.");
-        return NS_OK;
-      }
-
-      // If the broadcastChannel is used by an app, the origin is the manifest URL.
-      if (appId != nsIScriptSecurityManager::NO_APP_ID) {
-        nsresult rv;
-        nsCOMPtr<nsIAppsService> appsService =
-          do_GetService("@mozilla.org/AppsService;1", &rv);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          mContentParent->KillHard("BroadcastChannel killed: appService getter failed.");
-          return NS_OK;
-        }
-
-        nsAutoString origin;
-        rv = appsService->GetManifestURLByLocalId(appId, origin);
-        if (NS_WARN_IF(NS_FAILED(rv))) {
-          mContentParent->KillHard("BroadcastChannel killed: failed to retrieve the manifestURL.");
-          return NS_OK;
-        }
-
-        if (!origin.Equals(mOrigin)) {
-          mContentParent->KillHard("BroadcastChannel killed: origins do not match.");
-          return NS_OK;
-        }
-
-        return NS_OK;
-      }
-    }
-
     nsCOMPtr<nsIURI> uri;
     rv = NS_NewURI(getter_AddRefs(uri), mOrigin);
     if (NS_FAILED(rv) || !uri) {
       mContentParent->KillHard("BroadcastChannel killed: invalid origin URI.");
       return NS_OK;
     }
 
     rv = principal->CheckMayLoad(uri, false, false);
--- a/js/public/TrackedOptimizationInfo.h
+++ b/js/public/TrackedOptimizationInfo.h
@@ -26,16 +26,17 @@ namespace JS {
     _(GetProp_Innerize)                                 \
     _(GetProp_InlineCache)                              \
                                                         \
     _(SetProp_CommonSetter)                             \
     _(SetProp_TypedObject)                              \
     _(SetProp_DefiniteSlot)                             \
     _(SetProp_Unboxed)                                  \
     _(SetProp_InlineAccess)                             \
+    _(SetProp_InlineCache)                              \
                                                         \
     _(GetElem_TypedObject)                              \
     _(GetElem_Dense)                                    \
     _(GetElem_TypedStatic)                              \
     _(GetElem_TypedArray)                               \
     _(GetElem_String)                                   \
     _(GetElem_Arguments)                                \
     _(GetElem_ArgumentsInlined)                         \
--- a/js/src/asmjs/AsmJSLink.cpp
+++ b/js/src/asmjs/AsmJSLink.cpp
@@ -794,17 +794,17 @@ CallAsmJS(JSContext* cx, unsigned argc, 
 static JSFunction*
 NewExportedFunction(JSContext* cx, const AsmJSModule::ExportedFunction& func,
                     HandleObject moduleObj, unsigned exportIndex)
 {
     RootedPropertyName name(cx, func.name());
     unsigned numArgs = func.isChangeHeap() ? 1 : func.numArgs();
     JSFunction* fun =
         NewNativeConstructor(cx, CallAsmJS, numArgs, name,
-                             JSFunction::ExtendedFinalizeKind, GenericObject,
+                             gc::AllocKind::FUNCTION_EXTENDED, GenericObject,
                              JSFunction::ASMJS_CTOR);
     if (!fun)
         return nullptr;
 
     fun->setExtendedSlot(ASM_MODULE_SLOT, ObjectValue(*moduleObj));
     fun->setExtendedSlot(ASM_EXPORT_INDEX_SLOT, Int32Value(exportIndex));
     return fun;
 }
@@ -827,17 +827,17 @@ HandleDynamicLinkFailure(JSContext* cx, 
 
     uint32_t begin = module.srcBodyStart();  // starts right after 'use asm'
     uint32_t end = module.srcEndBeforeCurly();
     Rooted<JSFlatString*> src(cx, module.scriptSource()->substringDontDeflate(cx, begin, end));
     if (!src)
         return false;
 
     RootedFunction fun(cx, NewScriptedFunction(cx, 0, JSFunction::INTERPRETED,
-                                               name, JSFunction::FinalizeKind,
+                                               name, gc::AllocKind::FUNCTION,
                                                TenuredObject));
     if (!fun)
         return false;
 
     AutoNameVector formals(cx);
     if (!formals.reserve(3))
         return false;
 
@@ -1090,17 +1090,17 @@ JSFunction*
 js::NewAsmJSModuleFunction(ExclusiveContext* cx, JSFunction* origFun, HandleObject moduleObj)
 {
     RootedPropertyName name(cx, origFun->name());
 
     JSFunction::Flags flags = origFun->isLambda() ? JSFunction::ASMJS_LAMBDA_CTOR
                                                   : JSFunction::ASMJS_CTOR;
     JSFunction* moduleFun =
         NewNativeConstructor(cx, LinkAsmJS, origFun->nargs(), name,
-                             JSFunction::ExtendedFinalizeKind, TenuredObject,
+                             gc::AllocKind::FUNCTION_EXTENDED, TenuredObject,
                              flags);
     if (!moduleFun)
         return nullptr;
 
     moduleFun->setExtendedSlot(MODULE_FUN_SLOT, ObjectValue(*moduleObj));
     return moduleFun;
 }
 
--- a/js/src/asmjs/AsmJSValidate.cpp
+++ b/js/src/asmjs/AsmJSValidate.cpp
@@ -5979,29 +5979,29 @@ CheckSimdOperationCall(FunctionCompiler&
 
       case AsmJSSimdOperation_swizzle:
         return CheckSimdSwizzle(f, call, opType, def, type);
       case AsmJSSimdOperation_shuffle:
         return CheckSimdShuffle(f, call, opType, def, type);
 
       case AsmJSSimdOperation_load:
         return CheckSimdLoad(f, call, opType, 4, def, type);
-      case AsmJSSimdOperation_loadX:
+      case AsmJSSimdOperation_load1:
         return CheckSimdLoad(f, call, opType, 1, def, type);
-      case AsmJSSimdOperation_loadXY:
+      case AsmJSSimdOperation_load2:
         return CheckSimdLoad(f, call, opType, 2, def, type);
-      case AsmJSSimdOperation_loadXYZ:
+      case AsmJSSimdOperation_load3:
         return CheckSimdLoad(f, call, opType, 3, def, type);
       case AsmJSSimdOperation_store:
         return CheckSimdStore(f, call, opType, 4, def, type);
-      case AsmJSSimdOperation_storeX:
+      case AsmJSSimdOperation_store1:
         return CheckSimdStore(f, call, opType, 1, def, type);
-      case AsmJSSimdOperation_storeXY:
+      case AsmJSSimdOperation_store2:
         return CheckSimdStore(f, call, opType, 2, def, type);
-      case AsmJSSimdOperation_storeXYZ:
+      case AsmJSSimdOperation_store3:
         return CheckSimdStore(f, call, opType, 3, def, type);
 
       case AsmJSSimdOperation_bitselect:
         return CheckSimdSelect(f, call, opType, /*isElementWise */ false, def, type);
       case AsmJSSimdOperation_select:
         return CheckSimdSelect(f, call, opType, /*isElementWise */ true, def, type);
 
       case AsmJSSimdOperation_splat: {
@@ -7580,17 +7580,17 @@ ParseFunction(ModuleCompiler& m, ParseNo
 
     ParseNode* fn = m.parser().handler.newFunctionDefinition();
     if (!fn)
         return false;
 
     // This flows into FunctionBox, so must be tenured.
     RootedFunction fun(m.cx(),
                        NewScriptedFunction(m.cx(), 0, JSFunction::INTERPRETED,
-                                           name, JSFunction::FinalizeKind,
+                                           name, gc::AllocKind::FUNCTION,
                                            TenuredObject));
     if (!fun)
         return false;
 
     AsmJSParseContext* outerpc = m.parser().pc;
 
     Directives directives(outerpc);
     FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, outerpc, directives, NotGenerator);
--- a/js/src/builtin/Object.cpp
+++ b/js/src/builtin/Object.cpp
@@ -1091,17 +1091,17 @@ static JSObject*
 CreateObjectConstructor(JSContext* cx, JSProtoKey key)
 {
     Rooted<GlobalObject*> self(cx, cx->global());
     if (!GlobalObject::ensureConstructor(cx, self, JSProto_Function))
         return nullptr;
 
     /* Create the Object function now that we have a [[Prototype]] for it. */
     return NewNativeConstructor(cx, obj_construct, 1, HandlePropertyName(cx->names().Object),
-                                JSFunction::FinalizeKind, SingletonObject);
+                                gc::AllocKind::FUNCTION, SingletonObject);
 }
 
 static JSObject*
 CreateObjectPrototype(JSContext* cx, JSProtoKey key)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     MOZ_ASSERT(cx->global()->isNative());
 
--- a/js/src/builtin/SIMD.cpp
+++ b/js/src/builtin/SIMD.cpp
@@ -73,18 +73,23 @@ ErrorBadArgs(JSContext* cx)
 static inline bool
 ErrorWrongTypeArg(JSContext* cx, size_t argIndex, Handle<TypeDescr*> typeDescr)
 {
     MOZ_ASSERT(argIndex < 10);
     char charArgIndex[2];
     JS_snprintf(charArgIndex, sizeof charArgIndex, "%d", argIndex);
 
     HeapSlot& typeNameSlot = typeDescr->getReservedSlotRef(JS_DESCR_SLOT_STRING_REPR);
+    char* typeNameStr = JS_EncodeString(cx, typeNameSlot.toString());
+    if (!typeNameStr)
+        return false;
+
     JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR,
-                         JS_EncodeString(cx, typeNameSlot.toString()), charArgIndex);
+                         typeNameStr, charArgIndex);
+    JS_free(cx, typeNameStr);
     return false;
 }
 
 template<typename V>
 bool
 js::ToSimdConstant(JSContext* cx, HandleValue v, jit::SimdConstant* out)
 {
     typedef typename V::Elem Elem;
--- a/js/src/builtin/SIMD.h
+++ b/js/src/builtin/SIMD.h
@@ -38,31 +38,31 @@
   V(add, (BinaryFunc<Float32x4, Add, Float32x4>), 2)                                  \
   V(and, (CoercedBinaryFunc<Float32x4, Int32x4, And, Float32x4>), 2)                  \
   V(div, (BinaryFunc<Float32x4, Div, Float32x4>), 2)                                  \
   V(equal, (CompareFunc<Float32x4, Equal>), 2)                                        \
   V(greaterThan, (CompareFunc<Float32x4, GreaterThan>), 2)                            \
   V(greaterThanOrEqual, (CompareFunc<Float32x4, GreaterThanOrEqual>), 2)              \
   V(lessThan, (CompareFunc<Float32x4, LessThan>), 2)                                  \
   V(lessThanOrEqual, (CompareFunc<Float32x4, LessThanOrEqual>), 2)                    \
-  V(load,    (Load<Float32x4, 4>), 2)                                                 \
-  V(loadXYZ, (Load<Float32x4, 3>), 2)                                                 \
-  V(loadXY,  (Load<Float32x4, 2>), 2)                                                 \
-  V(loadX,   (Load<Float32x4, 1>), 2)                                                 \
+  V(load,  (Load<Float32x4, 4>), 2)                                                   \
+  V(load3, (Load<Float32x4, 3>), 2)                                                   \
+  V(load2, (Load<Float32x4, 2>), 2)                                                   \
+  V(load1, (Load<Float32x4, 1>), 2)                                                   \
   V(max, (BinaryFunc<Float32x4, Maximum, Float32x4>), 2)                              \
   V(maxNum, (BinaryFunc<Float32x4, MaxNum, Float32x4>), 2)                            \
   V(min, (BinaryFunc<Float32x4, Minimum, Float32x4>), 2)                              \
   V(minNum, (BinaryFunc<Float32x4, MinNum, Float32x4>), 2)                            \
   V(mul, (BinaryFunc<Float32x4, Mul, Float32x4>), 2)                                  \
   V(notEqual, (CompareFunc<Float32x4, NotEqual>), 2)                                  \
   V(or, (CoercedBinaryFunc<Float32x4, Int32x4, Or, Float32x4>), 2)                    \
-  V(store,    (Store<Float32x4, 4>), 3)                                               \
-  V(storeXYZ, (Store<Float32x4, 3>), 3)                                               \
-  V(storeXY,  (Store<Float32x4, 2>), 3)                                               \
-  V(storeX,   (Store<Float32x4, 1>), 3)                                               \
+  V(store,  (Store<Float32x4, 4>), 3)                                                 \
+  V(store3, (Store<Float32x4, 3>), 3)                                                 \
+  V(store2, (Store<Float32x4, 2>), 3)                                                 \
+  V(store1, (Store<Float32x4, 1>), 3)                                                 \
   V(sub, (BinaryFunc<Float32x4, Sub, Float32x4>), 2)                                  \
   V(withX, (FuncWith<Float32x4, WithX>), 2)                                           \
   V(withY, (FuncWith<Float32x4, WithY>), 2)                                           \
   V(withZ, (FuncWith<Float32x4, WithZ>), 2)                                           \
   V(withW, (FuncWith<Float32x4, WithW>), 2)                                           \
   V(xor, (CoercedBinaryFunc<Float32x4, Int32x4, Xor, Float32x4>), 2)
 
 #define FLOAT32X4_TERNARY_FUNCTION_LIST(V)                                            \
@@ -96,26 +96,26 @@
 #define FLOAT64X2_BINARY_FUNCTION_LIST(V)                                             \
   V(add, (BinaryFunc<Float64x2, Add, Float64x2>), 2)                                  \
   V(div, (BinaryFunc<Float64x2, Div, Float64x2>), 2)                                  \
   V(equal, (CompareFunc<Float64x2, Equal>), 2)                                        \
   V(greaterThan, (CompareFunc<Float64x2, GreaterThan>), 2)                            \
   V(greaterThanOrEqual, (CompareFunc<Float64x2, GreaterThanOrEqual>), 2)              \
   V(lessThan, (CompareFunc<Float64x2, LessThan>), 2)                                  \
   V(lessThanOrEqual, (CompareFunc<Float64x2, LessThanOrEqual>), 2)                    \
-  V(load,    (Load<Float64x2, 2>), 2)                                                 \
-  V(loadX,   (Load<Float64x2, 1>), 2)                                                 \
+  V(load,  (Load<Float64x2, 2>), 2)                                                   \
+  V(load1, (Load<Float64x2, 1>), 2)                                                   \
   V(max, (BinaryFunc<Float64x2, Maximum, Float64x2>), 2)                              \
   V(maxNum, (BinaryFunc<Float64x2, MaxNum, Float64x2>), 2)                            \
   V(min, (BinaryFunc<Float64x2, Minimum, Float64x2>), 2)                              \
   V(minNum, (BinaryFunc<Float64x2, MinNum, Float64x2>), 2)                            \
   V(mul, (BinaryFunc<Float64x2, Mul, Float64x2>), 2)                                  \
   V(notEqual, (CompareFunc<Float64x2, NotEqual>), 2)                                  \
-  V(store,    (Store<Float64x2, 2>), 3)                                               \
-  V(storeX,   (Store<Float64x2, 1>), 3)                                               \
+  V(store,  (Store<Float64x2, 2>), 3)                                                 \
+  V(store1, (Store<Float64x2, 1>), 3)                                                 \
   V(sub, (BinaryFunc<Float64x2, Sub, Float64x2>), 2)                                  \
   V(withX, (FuncWith<Float64x2, WithX>), 2)                                           \
   V(withY, (FuncWith<Float64x2, WithY>), 2)
 
 #define FLOAT64X2_TERNARY_FUNCTION_LIST(V)                                            \
   V(bitselect, BitSelect<Float64x2>, 3)                                               \
   V(clamp, Clamp<Float64x2>, 3)                                                       \
   V(select, Select<Float64x2>, 3)
@@ -143,31 +143,31 @@
 #define INT32X4_BINARY_FUNCTION_LIST(V)                                               \
   V(add, (BinaryFunc<Int32x4, Add, Int32x4>), 2)                                      \
   V(and, (BinaryFunc<Int32x4, And, Int32x4>), 2)                                      \
   V(equal, (CompareFunc<Int32x4, Equal>), 2)                                          \
   V(greaterThan, (CompareFunc<Int32x4, GreaterThan>), 2)                              \
   V(greaterThanOrEqual, (CompareFunc<Int32x4, GreaterThanOrEqual>), 2)                \
   V(lessThan, (CompareFunc<Int32x4, LessThan>), 2)                                    \
   V(lessThanOrEqual, (CompareFunc<Int32x4, LessThanOrEqual>), 2)                      \
-  V(load,    (Load<Int32x4, 4>), 2)                                                   \
-  V(loadXYZ, (Load<Int32x4, 3>), 2)                                                   \
-  V(loadXY,  (Load<Int32x4, 2>), 2)                                                   \
-  V(loadX,   (Load<Int32x4, 1>), 2)                                                   \
+  V(load,  (Load<Int32x4, 4>), 2)                                                     \
+  V(load3, (Load<Int32x4, 3>), 2)                                                     \
+  V(load2, (Load<Int32x4, 2>), 2)                                                     \
+  V(load1, (Load<Int32x4, 1>), 2)                                                     \
   V(mul, (BinaryFunc<Int32x4, Mul, Int32x4>), 2)                                      \
   V(notEqual, (CompareFunc<Int32x4, NotEqual>), 2)                                    \
   V(or, (BinaryFunc<Int32x4, Or, Int32x4>), 2)                                        \
   V(sub, (BinaryFunc<Int32x4, Sub, Int32x4>), 2)                                      \
   V(shiftLeftByScalar, (Int32x4BinaryScalar<ShiftLeft>), 2)                           \
   V(shiftRightArithmeticByScalar, (Int32x4BinaryScalar<ShiftRightArithmetic>), 2)     \
   V(shiftRightLogicalByScalar, (Int32x4BinaryScalar<ShiftRightLogical>), 2)           \
-  V(store,    (Store<Int32x4, 4>), 3)                                                 \
-  V(storeXYZ, (Store<Int32x4, 3>), 3)                                                 \
-  V(storeXY,  (Store<Int32x4, 2>), 3)                                                 \
-  V(storeX,   (Store<Int32x4, 1>), 3)                                                 \
+  V(store,  (Store<Int32x4, 4>), 3)                                                   \
+  V(store3, (Store<Int32x4, 3>), 3)                                                   \
+  V(store2, (Store<Int32x4, 2>), 3)                                                   \
+  V(store1, (Store<Int32x4, 1>), 3)                                                   \
   V(withX, (FuncWith<Int32x4, WithX>), 2)                                             \
   V(withY, (FuncWith<Int32x4, WithY>), 2)                                             \
   V(withZ, (FuncWith<Int32x4, WithZ>), 2)                                             \
   V(withW, (FuncWith<Int32x4, WithW>), 2)                                             \
   V(xor, (BinaryFunc<Int32x4, Xor, Int32x4>), 2)
 
 #define INT32X4_TERNARY_FUNCTION_LIST(V)                                              \
   V(bitselect, BitSelect<Int32x4>, 3)                                                 \
@@ -239,23 +239,23 @@
     _(bitselect)                     \
     _(select)                        \
     _(splat)                         \
     _(not)                           \
     _(neg)                           \
     _(swizzle)                       \
     _(shuffle)                       \
     _(load)                          \
-    _(loadX)                         \
-    _(loadXY)                        \
-    _(loadXYZ)                       \
+    _(load1)                         \
+    _(load2)                         \
+    _(load3)                         \
     _(store)                         \
-    _(storeX)                        \
-    _(storeXY)                       \
-    _(storeXYZ)                      \
+    _(store1)                        \
+    _(store2)                        \
+    _(store3)                        \
     _(check)
 #define ION_ONLY_INT32X4_SIMD_OP(_)  \
     _(bool)
 #define FOREACH_COMMONX4_SIMD_OP(_)  \
     ION_COMMONX4_SIMD_OP(_)          \
     COMP_COMMONX4_TO_INT32X4_SIMD_OP(_)
 #define FORALL_SIMD_OP(_)            \
     FOREACH_INT32X4_SIMD_OP(_)       \
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -1223,20 +1223,20 @@ Parser<ParseHandler>::newFunction(Handle
         break;
       case Method:
         flags = JSFunction::INTERPRETED_METHOD;
         break;
       default:
         flags = JSFunction::INTERPRETED;
         break;
     }
-    
-    gc::AllocKind allocKind = JSFunction::FinalizeKind;
+
+    gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
     if (kind == Arrow || kind == Method)
-        allocKind = JSFunction::ExtendedFinalizeKind;
+        allocKind = gc::AllocKind::FUNCTION_EXTENDED;
     fun = NewFunctionWithProto(context, nullptr, 0, flags, NullPtr(), atom, proto,
                                allocKind, TenuredObject);
     if (!fun)
         return nullptr;
     if (options().selfHostingMode)
         fun->setIsSelfHostedBuiltin();
     return fun;
 }
--- a/js/src/gc/Heap.h
+++ b/js/src/gc/Heap.h
@@ -74,17 +74,20 @@ enum InitialHeap {
     TenuredHeap
 };
 
 /* The GC allocation kinds. */
 // FIXME: uint8_t would make more sense for the underlying type, but causes
 // miscompilations in GCC (fixed in 4.8.5 and 4.9.3). See also bug 1143966.
 enum class AllocKind {
     FIRST,
-    OBJECT0 = FIRST,
+    OBJECT_FIRST = FIRST,
+    FUNCTION = FIRST,
+    FUNCTION_EXTENDED,
+    OBJECT0,
     OBJECT0_BACKGROUND,
     OBJECT2,
     OBJECT2_BACKGROUND,
     OBJECT4,
     OBJECT4_BACKGROUND,
     OBJECT8,
     OBJECT8_BACKGROUND,
     OBJECT12,
@@ -105,23 +108,23 @@ enum class AllocKind {
     SYMBOL,
     JITCODE,
     LIMIT,
     LAST = LIMIT - 1
 };
 
 static_assert(int(AllocKind::FIRST) == 0, "Various places depend on AllocKind starting at 0, "
                                           "please audit them carefully!");
-static_assert(int(AllocKind::OBJECT0) == 0, "Various places depend on AllocKind::OBJECT0 being 0, "
-                                            "please audit them carefully!");
+static_assert(int(AllocKind::OBJECT_FIRST) == 0, "Various places depend on AllocKind::OBJECT_FIRST "
+                                                 "being 0, please audit them carefully!");
 
 inline bool
 IsObjectAllocKind(AllocKind kind)
 {
-    return kind >= AllocKind::OBJECT0 && kind <= AllocKind::OBJECT_LAST;
+    return kind >= AllocKind::OBJECT_FIRST && kind <= AllocKind::OBJECT_LAST;
 }
 
 inline bool
 IsValidAllocKind(AllocKind kind)
 {
     return kind >= AllocKind::FIRST && kind <= AllocKind::LAST;
 }
 
@@ -135,20 +138,20 @@ inline bool IsAllocKind(AllocKind kind)
 inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT))
 AllAllocKinds()
 {
     return mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT);
 }
 
 // Returns a sequence for use in a range-based for loop,
 // to iterate over all object alloc kinds.
-inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT0, AllocKind::OBJECT_LIMIT))
+inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT_FIRST, AllocKind::OBJECT_LIMIT))
 ObjectAllocKinds()
 {
-    return mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT0, AllocKind::OBJECT_LIMIT);
+    return mozilla::MakeEnumeratedRange<int>(AllocKind::OBJECT_FIRST, AllocKind::OBJECT_LIMIT);
 }
 
 // Returns a sequence for use in a range-based for loop,
 // to iterate over alloc kinds from |first| to |limit|, exclusive.
 inline decltype(mozilla::MakeEnumeratedRange<int>(AllocKind::FIRST, AllocKind::LIMIT))
 SomeAllocKinds(AllocKind first = AllocKind::FIRST, AllocKind limit = AllocKind::LIMIT)
 {
     MOZ_ASSERT(IsAllocKind(first), "|first| is not a valid AllocKind!");
@@ -165,16 +168,18 @@ template<typename ValueType> using AllAl
 // with each index corresponding to a particular object alloc kind.
 template<typename ValueType> using ObjectAllocKindArray =
     mozilla::EnumeratedArray<AllocKind, AllocKind::OBJECT_LIMIT, ValueType>;
 
 static inline JSGCTraceKind
 MapAllocToTraceKind(AllocKind kind)
 {
     static const JSGCTraceKind map[] = {
+        JSTRACE_OBJECT,       /* AllocKind::FUNCTION */
+        JSTRACE_OBJECT,       /* AllocKind::FUNCTION_EXTENDED */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT0 */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT0_BACKGROUND */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT2 */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT2_BACKGROUND */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT4 */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT4_BACKGROUND */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT8 */
         JSTRACE_OBJECT,       /* AllocKind::OBJECT8_BACKGROUND */
@@ -1019,36 +1024,40 @@ struct Chunk
 
     bool hasAvailableArenas() const {
         return info.numArenasFree != 0;
     }
 
     ArenaHeader* allocateArena(JSRuntime* rt, JS::Zone* zone, AllocKind kind,
                                const AutoLockGC& lock);
 
-    enum ArenaDecommitState { IsCommitted = false, IsDecommitted = true };
-    void releaseArena(JSRuntime* rt, ArenaHeader* aheader, const AutoLockGC& lock,
-                      ArenaDecommitState state = IsCommitted);
+    void releaseArena(JSRuntime* rt, ArenaHeader* aheader, const AutoLockGC& lock);
     void recycleArena(ArenaHeader* aheader, SortedArenaList& dest, AllocKind thingKind,
                       size_t thingsPerArena);
 
-    static Chunk* allocate(JSRuntime* rt);
+    bool decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock);
+    void decommitAllArenasWithoutUnlocking(const AutoLockGC& lock);
 
-    void decommitAllArenas(JSRuntime* rt);
+    static Chunk* allocate(JSRuntime* rt);
 
   private:
     inline void init(JSRuntime* rt);
 
+    void decommitAllArenas(JSRuntime* rt);
+
     /* Search for a decommitted arena to allocate. */
     unsigned findDecommittedArenaOffset();
     ArenaHeader* fetchNextDecommittedArena();
 
     void addArenaToFreeList(JSRuntime* rt, ArenaHeader* aheader);
     void addArenaToDecommittedList(JSRuntime* rt, const ArenaHeader* aheader);
 
+    void updateChunkListAfterAlloc(JSRuntime* rt, const AutoLockGC& lock);
+    void updateChunkListAfterFree(JSRuntime* rt, const AutoLockGC& lock);
+
   public:
     /* Unlink and return the freeArenasHead. */
     inline ArenaHeader* fetchNextFreeArena(JSRuntime* rt);
 };
 
 static_assert(sizeof(Chunk) == ChunkSize,
               "Ensure the hardcoded chunk size definition actually matches the struct.");
 static_assert(js::gc::ChunkMarkBitmapOffset == offsetof(Chunk, bitmap),
--- a/js/src/jit-test/tests/SIMD/load.js
+++ b/js/src/jit-test/tests/SIMD/load.js
@@ -28,75 +28,75 @@ function f() {
         assertEqX4(SIMD.float32x4.load(f32, 16 - 4),               [13,14,15,16]);
         assertEqX4(SIMD.float32x4.load(i32, 16 - 4),               [13,14,15,16]);
         assertEqX4(SIMD.float32x4.load(i16, (16 << 1) - (4 << 1)), [13,14,15,16]);
         assertEqX4(SIMD.float32x4.load(u16, (16 << 1) - (4 << 1)), [13,14,15,16]);
         assertEqX4(SIMD.float32x4.load(i8,  (16 << 2) - (4 << 2)), [13,14,15,16]);
         assertEqX4(SIMD.float32x4.load(u8,  (16 << 2) - (4 << 2)), [13,14,15,16]);
     }
 
-    function testLoadX() {
-        assertEqX4(SIMD.float32x4.loadX(f64, 0),      [1,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(f32, 1),      [2,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i32, 2),      [3,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i16, 3 << 1), [4,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(u16, 4 << 1), [5,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i8 , 5 << 2), [6,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(u8 , 6 << 2), [7,0,0,0]);
+    function testLoad1() {
+        assertEqX4(SIMD.float32x4.load1(f64, 0),      [1,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(f32, 1),      [2,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i32, 2),      [3,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i16, 3 << 1), [4,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(u16, 4 << 1), [5,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i8 , 5 << 2), [6,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(u8 , 6 << 2), [7,0,0,0]);
 
-        assertEqX4(SIMD.float32x4.loadX(f64, (16 >> 1) - (4 >> 1)), [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(f32, 16 - 4),               [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i32, 16 - 4),               [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i16, (16 << 1) - (4 << 1)), [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(u16, (16 << 1) - (4 << 1)), [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(i8,  (16 << 2) - (4 << 2)), [13,0,0,0]);
-        assertEqX4(SIMD.float32x4.loadX(u8,  (16 << 2) - (4 << 2)), [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(f64, (16 >> 1) - (4 >> 1)), [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(f32, 16 - 4),               [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i32, 16 - 4),               [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i16, (16 << 1) - (4 << 1)), [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(u16, (16 << 1) - (4 << 1)), [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(i8,  (16 << 2) - (4 << 2)), [13,0,0,0]);
+        assertEqX4(SIMD.float32x4.load1(u8,  (16 << 2) - (4 << 2)), [13,0,0,0]);
     }
 
-    function testLoadXY() {
-        assertEqX4(SIMD.float32x4.loadXY(f64, 0),      [1,2,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(f32, 1),      [2,3,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i32, 2),      [3,4,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i16, 3 << 1), [4,5,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(u16, 4 << 1), [5,6,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i8 , 5 << 2), [6,7,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(u8 , 6 << 2), [7,8,0,0]);
+    function testLoad2() {
+        assertEqX4(SIMD.float32x4.load2(f64, 0),      [1,2,0,0]);
+        assertEqX4(SIMD.float32x4.load2(f32, 1),      [2,3,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i32, 2),      [3,4,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i16, 3 << 1), [4,5,0,0]);
+        assertEqX4(SIMD.float32x4.load2(u16, 4 << 1), [5,6,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i8 , 5 << 2), [6,7,0,0]);
+        assertEqX4(SIMD.float32x4.load2(u8 , 6 << 2), [7,8,0,0]);
 
-        assertEqX4(SIMD.float32x4.loadXY(f64, (16 >> 1) - (4 >> 1)), [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(f32, 16 - 4),               [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i32, 16 - 4),               [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i16, (16 << 1) - (4 << 1)), [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(u16, (16 << 1) - (4 << 1)), [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(i8,  (16 << 2) - (4 << 2)), [13,14,0,0]);
-        assertEqX4(SIMD.float32x4.loadXY(u8,  (16 << 2) - (4 << 2)), [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(f64, (16 >> 1) - (4 >> 1)), [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(f32, 16 - 4),               [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i32, 16 - 4),               [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i16, (16 << 1) - (4 << 1)), [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(u16, (16 << 1) - (4 << 1)), [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(i8,  (16 << 2) - (4 << 2)), [13,14,0,0]);
+        assertEqX4(SIMD.float32x4.load2(u8,  (16 << 2) - (4 << 2)), [13,14,0,0]);
     }
 
-    function testLoadXYZ() {
-        assertEqX4(SIMD.float32x4.loadXYZ(f64, 0),      [1,2,3,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(f32, 1),      [2,3,4,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i32, 2),      [3,4,5,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i16, 3 << 1), [4,5,6,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(u16, 4 << 1), [5,6,7,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i8 , 5 << 2), [6,7,8,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(u8 , 6 << 2), [7,8,9,0]);
+    function testLoad3() {
+        assertEqX4(SIMD.float32x4.load3(f64, 0),      [1,2,3,0]);
+        assertEqX4(SIMD.float32x4.load3(f32, 1),      [2,3,4,0]);
+        assertEqX4(SIMD.float32x4.load3(i32, 2),      [3,4,5,0]);
+        assertEqX4(SIMD.float32x4.load3(i16, 3 << 1), [4,5,6,0]);
+        assertEqX4(SIMD.float32x4.load3(u16, 4 << 1), [5,6,7,0]);
+        assertEqX4(SIMD.float32x4.load3(i8 , 5 << 2), [6,7,8,0]);
+        assertEqX4(SIMD.float32x4.load3(u8 , 6 << 2), [7,8,9,0]);
 
-        assertEqX4(SIMD.float32x4.loadXYZ(f64, (16 >> 1) - (4 >> 1)), [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(f32, 16 - 4),               [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i32, 16 - 4),               [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i16, (16 << 1) - (4 << 1)), [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(u16, (16 << 1) - (4 << 1)), [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(i8,  (16 << 2) - (4 << 2)), [13,14,15,0]);
-        assertEqX4(SIMD.float32x4.loadXYZ(u8,  (16 << 2) - (4 << 2)), [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(f64, (16 >> 1) - (4 >> 1)), [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(f32, 16 - 4),               [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(i32, 16 - 4),               [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(i16, (16 << 1) - (4 << 1)), [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(u16, (16 << 1) - (4 << 1)), [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(i8,  (16 << 2) - (4 << 2)), [13,14,15,0]);
+        assertEqX4(SIMD.float32x4.load3(u8,  (16 << 2) - (4 << 2)), [13,14,15,0]);
     }
 
     for (var i = 0; i < 150; i++) {
         testLoad();
-        testLoadX();
-        testLoadXY();
-        testLoadXYZ();
+        testLoad1();
+        testLoad2();
+        testLoad3();
     }
 }
 
 f();
 
 function testBailout(uglyDuckling) {
     var f32 = new Float32Array(16);
     for (var i = 0; i < 16; i++)
--- a/js/src/jit-test/tests/SIMD/store.js
+++ b/js/src/jit-test/tests/SIMD/store.js
@@ -43,78 +43,78 @@ function f() {
         SIMD.float32x4.store(u16, 0, f4);
         check(4);
         SIMD.float32x4.store(i8, 0, f4);
         check(4);
         SIMD.float32x4.store(u8, 0, f4);
         check(4);
     }
 
-    function testStoreX() {
-        SIMD.float32x4.storeX(f64, 0, f4);
+    function testStore1() {
+        SIMD.float32x4.store1(f64, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(f32, 0, f4);
+        SIMD.float32x4.store1(f32, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(i32, 0, f4);
+        SIMD.float32x4.store1(i32, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(u32, 0, f4);
+        SIMD.float32x4.store1(u32, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(i16, 0, f4);
+        SIMD.float32x4.store1(i16, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(u16, 0, f4);
+        SIMD.float32x4.store1(u16, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(i8, 0, f4);
+        SIMD.float32x4.store1(i8, 0, f4);
         check(1);
-        SIMD.float32x4.storeX(u8, 0, f4);
+        SIMD.float32x4.store1(u8, 0, f4);
         check(1);
     }
 
-    function testStoreXY() {
-        SIMD.float32x4.storeXY(f64, 0, f4);
+    function testStore2() {
+        SIMD.float32x4.store2(f64, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(f32, 0, f4);
+        SIMD.float32x4.store2(f32, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(i32, 0, f4);
+        SIMD.float32x4.store2(i32, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(u32, 0, f4);
+        SIMD.float32x4.store2(u32, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(i16, 0, f4);
+        SIMD.float32x4.store2(i16, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(u16, 0, f4);
+        SIMD.float32x4.store2(u16, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(i8, 0, f4);
+        SIMD.float32x4.store2(i8, 0, f4);
         check(2);
-        SIMD.float32x4.storeXY(u8, 0, f4);
+        SIMD.float32x4.store2(u8, 0, f4);
         check(2);
     }
 
-    function testStoreXYZ() {
-        SIMD.float32x4.storeXYZ(f64, 0, f4);
+    function testStore3() {
+        SIMD.float32x4.store3(f64, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(f32, 0, f4);
+        SIMD.float32x4.store3(f32, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(i32, 0, f4);
+        SIMD.float32x4.store3(i32, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(u32, 0, f4);
+        SIMD.float32x4.store3(u32, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(i16, 0, f4);
+        SIMD.float32x4.store3(i16, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(u16, 0, f4);
+        SIMD.float32x4.store3(u16, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(i8, 0, f4);
+        SIMD.float32x4.store3(i8, 0, f4);
         check(3);
-        SIMD.float32x4.storeXYZ(u8, 0, f4);
+        SIMD.float32x4.store3(u8, 0, f4);
         check(3);
     }
 
     for (var i = 0; i < 150; i++) {
         testStore();
-        testStoreX();
-        testStoreXY();
-        testStoreXYZ();
+        testStore1();
+        testStore2();
+        testStore3();
     }
 }
 
 f();
 
 function testBailout(uglyDuckling) {
     var f32 = new Float32Array(16);
     for (var i = 0; i < 16; i++)
@@ -136,9 +136,8 @@ function testBailout(uglyDuckling) {
         assertEq(i < 149 || caught, true);
     }
 }
 
 print('Testing range checks...');
 testBailout(-1);
 testBailout(-15);
 testBailout(12 * 4 + 1);
-
--- a/js/src/jit-test/tests/asm.js/testSIMD-load-store.js
+++ b/js/src/jit-test/tests/asm.js/testSIMD-load-store.js
@@ -275,55 +275,55 @@ for (var i = 0; i < SIZE; i++)
 
 //      Variable indexes
 function MakeCodeFor(typeName) {
     return `
     "use asm";
     var type = glob.SIMD.${typeName};
     var c = type.check;
 
-    var lx = type.loadX;
-    var lxy = type.loadXY;
-    var lxyz = type.loadXYZ;
+    var l1 = type.load1;
+    var l2 = type.load2;
+    var l3 = type.load3;
 
-    var sx = type.storeX;
-    var sxy = type.storeXY;
-    var sxyz = type.storeXYZ;
+    var s1 = type.store1;
+    var s2 = type.store2;
+    var s3 = type.store3;
 
     var u8 = new glob.Uint8Array(heap);
 
-    function loadX(i) { i=i|0; return lx(u8, i); }
-    function loadXY(i) { i=i|0; return lxy(u8, i); }
-    function loadXYZ(i) { i=i|0; return lxyz(u8, i); }
+    function load1(i) { i=i|0; return l1(u8, i); }
+    function load2(i) { i=i|0; return l2(u8, i); }
+    function load3(i) { i=i|0; return l3(u8, i); }
 
-    function loadCstX() { return lx(u8, 41 << 2); }
-    function loadCstXY() { return lxy(u8, 41 << 2); }
-    function loadCstXYZ() { return lxyz(u8, 41 << 2); }
+    function loadCst1() { return l1(u8, 41 << 2); }
+    function loadCst2() { return l2(u8, 41 << 2); }
+    function loadCst3() { return l3(u8, 41 << 2); }
 
-    function storeX(i, x) { i=i|0; x=c(x); return sx(u8, i, x); }
-    function storeXY(i, x) { i=i|0; x=c(x); return sxy(u8, i, x); }
-    function storeXYZ(i, x) { i=i|0; x=c(x); return sxyz(u8, i, x); }
+    function store1(i, x) { i=i|0; x=c(x); return s1(u8, i, x); }
+    function store2(i, x) { i=i|0; x=c(x); return s2(u8, i, x); }
+    function store3(i, x) { i=i|0; x=c(x); return s3(u8, i, x); }
 
-    function storeCstX(x) { x=c(x); return sx(u8, 41 << 2, x); }
-    function storeCstXY(x) { x=c(x); return sxy(u8, 41 << 2, x); }
-    function storeCstXYZ(x) { x=c(x); return sxyz(u8, 41 << 2, x); }
+    function storeCst1(x) { x=c(x); return s1(u8, 41 << 2, x); }
+    function storeCst2(x) { x=c(x); return s2(u8, 41 << 2, x); }
+    function storeCst3(x) { x=c(x); return s3(u8, 41 << 2, x); }
 
     return {
-        loadX: loadX,
-        loadXY: loadXY,
-        loadXYZ: loadXYZ,
-        loadCstX: loadCstX,
-        loadCstXY: loadCstXY,
-        loadCstXYZ: loadCstXYZ,
-        storeX: storeX,
-        storeXY: storeXY,
-        storeXYZ: storeXYZ,
-        storeCstX: storeCstX,
-        storeCstXY: storeCstXY,
-        storeCstXYZ: storeCstXYZ,
+        load1: load1,
+        load2: load2,
+        load3: load3,
+        loadCst1: loadCst1,
+        loadCst2: loadCst2,
+        loadCst3: loadCst3,
+        store1: store1,
+        store2: store2,
+        store3: store3,
+        storeCst1: storeCst1,
+        storeCst2: storeCst2,
+        storeCst3: storeCst3,
     }
 `;
 }
 
 var SIZE = 0x10000;
 
 function TestPartialLoads(m, typedArray, x, y, z, w) {
     // Fill array with predictable values
@@ -331,90 +331,90 @@ function TestPartialLoads(m, typedArray,
         typedArray[i] =     x(i);
         typedArray[i + 1] = y(i);
         typedArray[i + 2] = z(i);
         typedArray[i + 3] = w(i);
     }
 
     // Test correct loads
     var i = 0, j = 0; // i in elems, j in bytes
-    assertEqX4(m.loadX(j),   [x(i), 0, 0, 0]);
-    assertEqX4(m.loadXY(j),  [x(i), y(i), 0, 0]);
-    assertEqX4(m.loadXYZ(j), [x(i), y(i), z(i), 0]);
+    assertEqX4(m.load1(j), [x(i), 0, 0, 0]);
+    assertEqX4(m.load2(j), [x(i), y(i), 0, 0]);
+    assertEqX4(m.load3(j), [x(i), y(i), z(i), 0]);
 
     j += 4;
-    assertEqX4(m.loadX(j),   [y(i), 0, 0, 0]);
-    assertEqX4(m.loadXY(j),  [y(i), z(i), 0, 0]);
-    assertEqX4(m.loadXYZ(j), [y(i), z(i), w(i), 0]);
+    assertEqX4(m.load1(j), [y(i), 0, 0, 0]);
+    assertEqX4(m.load2(j), [y(i), z(i), 0, 0]);
+    assertEqX4(m.load3(j), [y(i), z(i), w(i), 0]);
 
     j += 4;
-    assertEqX4(m.loadX(j),   [z(i), 0, 0, 0]);
-    assertEqX4(m.loadXY(j),  [z(i), w(i), 0, 0]);
-    assertEqX4(m.loadXYZ(j), [z(i), w(i), x(i+4), 0]);
+    assertEqX4(m.load1(j), [z(i), 0, 0, 0]);
+    assertEqX4(m.load2(j), [z(i), w(i), 0, 0]);
+    assertEqX4(m.load3(j), [z(i), w(i), x(i+4), 0]);
 
     j += 4;
-    assertEqX4(m.loadX(j),   [w(i), 0, 0, 0]);
-    assertEqX4(m.loadXY(j),  [w(i), x(i+4), 0, 0]);
-    assertEqX4(m.loadXYZ(j), [w(i), x(i+4), y(i+4), 0]);
+    assertEqX4(m.load1(j), [w(i), 0, 0, 0]);
+    assertEqX4(m.load2(j), [w(i), x(i+4), 0, 0]);
+    assertEqX4(m.load3(j), [w(i), x(i+4), y(i+4), 0]);
 
     j += 4;
     i += 4;
-    assertEqX4(m.loadX(j),   [x(i), 0, 0, 0]);
-    assertEqX4(m.loadXY(j),  [x(i), y(i), 0, 0]);
-    assertEqX4(m.loadXYZ(j), [x(i), y(i), z(i), 0]);
+    assertEqX4(m.load1(j), [x(i), 0, 0, 0]);
+    assertEqX4(m.load2(j), [x(i), y(i), 0, 0]);
+    assertEqX4(m.load3(j), [x(i), y(i), z(i), 0]);
 
     // Test loads with constant indexes (41)
-    assertEqX4(m.loadCstX(),   [y(40), 0, 0, 0]);
-    assertEqX4(m.loadCstXY(),  [y(40), z(40), 0, 0]);
-    assertEqX4(m.loadCstXYZ(), [y(40), z(40), w(40), 0]);
+    assertEqX4(m.loadCst1(), [y(40), 0, 0, 0]);
+    assertEqX4(m.loadCst2(), [y(40), z(40), 0, 0]);
+    assertEqX4(m.loadCst3(), [y(40), z(40), w(40), 0]);
 
     // Test limit and OOB accesses
-    assertEqX4(m.loadX((SIZE - 1) << 2), [w(SIZE - 4), 0, 0, 0]);
-    assertThrowsInstanceOf(() => m.loadX(((SIZE - 1) << 2) + 1), RangeError);
+    assertEqX4(m.load1((SIZE - 1) << 2), [w(SIZE - 4), 0, 0, 0]);
+    assertThrowsInstanceOf(() => m.load1(((SIZE - 1) << 2) + 1), RangeError);
 
-    assertEqX4(m.loadXY((SIZE - 2) << 2), [z(SIZE - 4), w(SIZE - 4), 0, 0]);
-    assertThrowsInstanceOf(() => m.loadXY(((SIZE - 2) << 2) + 1), RangeError);
+    assertEqX4(m.load2((SIZE - 2) << 2), [z(SIZE - 4), w(SIZE - 4), 0, 0]);
+    assertThrowsInstanceOf(() => m.load2(((SIZE - 2) << 2) + 1), RangeError);
 
-    assertEqX4(m.loadXYZ((SIZE - 3) << 2), [y(SIZE - 4), z(SIZE - 4), w(SIZE - 4), 0]);
-    assertThrowsInstanceOf(() => m.loadXYZ(((SIZE - 3) << 2) + 1), RangeError);
+    assertEqX4(m.load3((SIZE - 3) << 2), [y(SIZE - 4), z(SIZE - 4), w(SIZE - 4), 0]);
+    assertThrowsInstanceOf(() => m.load3(((SIZE - 3) << 2) + 1), RangeError);
 }
 
 // Partial stores
 function TestPartialStores(m, typedArray, typeName, x, y, z, w) {
     var val = SIMD[typeName](x, y, z, w);
 
     function Reset() {
         for (var i = 0; i < SIZE; i++)
             typedArray[i] = i + 1;
     }
     function CheckNotModified(low, high) {
         for (var i = low; i < high; i++)
             assertEq(typedArray[i], i + 1);
     }
 
-    function TestStoreX(i) {
-        m.storeX(i, val);
+    function TestStore1(i) {
+        m.store1(i, val);
         CheckNotModified(0, i >> 2);
         assertEq(typedArray[i >> 2], x);
         CheckNotModified((i >> 2) + 1, SIZE);
         typedArray[i >> 2] = (i >> 2) + 1;
     }
 
-    function TestStoreXY(i) {
-        m.storeXY(i, val);
+    function TestStore2(i) {
+        m.store2(i, val);
         CheckNotModified(0, i >> 2);
         assertEq(typedArray[i >> 2], x);
         assertEq(typedArray[(i >> 2) + 1], y);
         CheckNotModified((i >> 2) + 2, SIZE);
         typedArray[i >> 2] = (i >> 2) + 1;
         typedArray[(i >> 2) + 1] = (i >> 2) + 2;
     }
 
-    function TestStoreXYZ(i) {
-        m.storeXYZ(i, val);
+    function TestStore3(i) {
+        m.store3(i, val);
         CheckNotModified(0, i >> 2);
         assertEq(typedArray[i >> 2], x);
         assertEq(typedArray[(i >> 2) + 1], y);
         assertEq(typedArray[(i >> 2) + 2], z);
         CheckNotModified((i >> 2) + 3, SIZE);
         typedArray[i >> 2] = (i >> 2) + 1;
         typedArray[(i >> 2) + 1] = (i >> 2) + 2;
         typedArray[(i >> 2) + 2] = (i >> 2) + 3;
@@ -422,66 +422,66 @@ function TestPartialStores(m, typedArray
 
     function TestOOBStore(f) {
         assertThrowsInstanceOf(f, RangeError);
         CheckNotModified(0, SIZE);
     }
 
     Reset();
 
-    TestStoreX(0);
-    TestStoreX(1 << 2);
-    TestStoreX(2 << 2);
-    TestStoreX(3 << 2);
-    TestStoreX(1337 << 2);
+    TestStore1(0);
+    TestStore1(1 << 2);
+    TestStore1(2 << 2);
+    TestStore1(3 << 2);
+    TestStore1(1337 << 2);
 
     var i = (SIZE - 1) << 2;
-    TestStoreX(i);
-    TestOOBStore(() => m.storeX(i + 1, val));
-    TestOOBStore(() => m.storeX(-1, val));
+    TestStore1(i);
+    TestOOBStore(() => m.store1(i + 1, val));
+    TestOOBStore(() => m.store1(-1, val));
 
-    TestStoreXY(0);
-    TestStoreXY(1 << 2);
-    TestStoreXY(2 << 2);
-    TestStoreXY(3 << 2);
-    TestStoreXY(1337 << 2);
+    TestStore2(0);
+    TestStore2(1 << 2);
+    TestStore2(2 << 2);
+    TestStore2(3 << 2);
+    TestStore2(1337 << 2);
 
     var i = (SIZE - 2) << 2;
-    TestStoreXY(i);
-    TestOOBStore(() => m.storeXY(i + 1, val));
-    TestOOBStore(() => m.storeXY(-1, val));
+    TestStore2(i);
+    TestOOBStore(() => m.store2(i + 1, val));
+    TestOOBStore(() => m.store2(-1, val));
 
-    TestStoreXYZ(0);
-    TestStoreXYZ(1 << 2);
-    TestStoreXYZ(2 << 2);
-    TestStoreXYZ(3 << 2);
-    TestStoreXYZ(1337 << 2);
+    TestStore3(0);
+    TestStore3(1 << 2);
+    TestStore3(2 << 2);
+    TestStore3(3 << 2);
+    TestStore3(1337 << 2);
 
     var i = (SIZE - 3) << 2;
-    TestStoreXYZ(i);
-    TestOOBStore(() => m.storeXYZ(i + 1, val));
-    TestOOBStore(() => m.storeXYZ(-1, val));
-    TestOOBStore(() => m.storeXYZ(-9, val));
+    TestStore3(i);
+    TestOOBStore(() => m.store3(i + 1, val));
+    TestOOBStore(() => m.store3(-1, val));
+    TestOOBStore(() => m.store3(-9, val));
 
     // Constant indexes (41)
-    m.storeCstX(val);
+    m.storeCst1(val);
     CheckNotModified(0, 41);
     assertEq(typedArray[41], x);
     CheckNotModified(42, SIZE);
     typedArray[41] = 42;
 
-    m.storeCstXY(val);
+    m.storeCst2(val);
     CheckNotModified(0, 41);
     assertEq(typedArray[41], x);
     assertEq(typedArray[42], y);
     CheckNotModified(43, SIZE);
     typedArray[41] = 42;
     typedArray[42] = 43;
 
-    m.storeCstXYZ(val);
+    m.storeCst3(val);
     CheckNotModified(0, 41);
     assertEq(typedArray[41], x);
     assertEq(typedArray[42], y);
     assertEq(typedArray[43], z);
     CheckNotModified(44, SIZE);
     typedArray[41] = 42;
     typedArray[42] = 43;
     typedArray[43] = 44;
--- a/js/src/jit-test/tests/asm.js/testZOOB.js
+++ b/js/src/jit-test/tests/asm.js/testZOOB.js
@@ -99,117 +99,117 @@ function testSimdX4(ctor, shift, scale, 
     var arr = new ctor(ab);
 
     var c = asmCompile('glob', 'imp', 'b',
                        USE_ASM +
                        'var arr=new glob.' + ctor.name + '(b); ' +
                        'var SIMD_' + simdName + ' = glob.SIMD.' + simdName + '; ' +
                        'var SIMD_' + simdName + '_check = SIMD_' + simdName + '.check; ' +
                        'var SIMD_' + simdName + '_load = SIMD_' + simdName + '.load; ' +
-                       'var SIMD_' + simdName + '_loadXYZ = SIMD_' + simdName + '.loadXYZ; ' +
-                       'var SIMD_' + simdName + '_loadXY = SIMD_' + simdName + '.loadXY; ' +
-                       'var SIMD_' + simdName + '_loadX = SIMD_' + simdName + '.loadX; ' +
+                       'var SIMD_' + simdName + '_load3 = SIMD_' + simdName + '.load3; ' +
+                       'var SIMD_' + simdName + '_load2 = SIMD_' + simdName + '.load2; ' +
+                       'var SIMD_' + simdName + '_load1 = SIMD_' + simdName + '.load1; ' +
                        'var SIMD_' + simdName + '_store = SIMD_' + simdName + '.store; ' +
-                       'var SIMD_' + simdName + '_storeXYZ = SIMD_' + simdName + '.storeXYZ; ' +
-                       'var SIMD_' + simdName + '_storeXY = SIMD_' + simdName + '.storeXY; ' +
-                       'var SIMD_' + simdName + '_storeX = SIMD_' + simdName + '.storeX; ' +
+                       'var SIMD_' + simdName + '_store3 = SIMD_' + simdName + '.store3; ' +
+                       'var SIMD_' + simdName + '_store2 = SIMD_' + simdName + '.store2; ' +
+                       'var SIMD_' + simdName + '_store1 = SIMD_' + simdName + '.store1; ' +
                        'function load(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
-                       'function loadXYZ(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_loadXYZ(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
-                       'function loadXY(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_loadXY(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
-                       'function loadX(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_loadX(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+                       'function load3(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load3(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+                       'function load2(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
+                       'function load1(i) {i=i|0; return SIMD_' + simdName + '_check(SIMD_' + simdName + '_load1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ')) } ' +
                        'function store(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
-                       'function storeXYZ(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_storeXYZ(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
-                       'function storeXY(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_storeXY(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
-                       'function storeX(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_storeX(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
-                       'return { load: load, loadXYZ: loadXYZ, loadXY: loadXY, loadX: loadX, store: store, storeXYZ: storeXYZ, storeXY : storeXY, storeX : storeX }');
+                       'function store3(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store3(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+                       'function store2(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store2(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+                       'function store1(i,j) {i=i|0;j=SIMD_' + simdName + '_check(j); SIMD_' + simdName + '_store1(arr, ((i<<' + scale + ')+' + disp + ')>>' + shift + ', j) } ' +
+                       'return { load: load, load3: load3, load2: load2, load1: load1, store: store, store3: store3, store2 : store2, store1 : store1 }');
     var f = asmLink(c, this, null, ab);
 
     for (var i of indices) {
         var index = ((i<<scale)+disp)>>shift;
 
-        var v, vXYZ, vXY, vX;
-        var t = false, tXYZ = false, tXY = false, tX = false;
+        var v, v3, v2, v1;
+        var t = false, t3 = false, t2 = false, t1 = false;
         try { v = simdCtor.load(arr, index); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
             t = true;
         }
-        try { vXYZ = simdCtor.loadXYZ(arr, index); }
+        try { v3 = simdCtor.load3(arr, index); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            tXYZ = true;
+            t3 = true;
         }
-        try { vXY = simdCtor.loadXY(arr, index); }
+        try { v2 = simdCtor.load2(arr, index); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            tXY = true;
+            t2 = true;
         }
-        try { vX = simdCtor.loadX(arr, index); }
+        try { v1 = simdCtor.load1(arr, index); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            tX = true;
+            t1 = true;
         }
 
         // Loads
-        var l, lXYZ, lXY, lX;
-        var r = false, rXYZ = false, rXY = false, rX = false;
+        var l, l3, l2, l1;
+        var r = false, r3 = false, r2 = false, r1 = false;
         try { l = f.load(i); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
             r = true;
         }
-        try { lXYZ = f.loadXYZ(i); }
+        try { l3 = f.load3(i); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            rXYZ = true;
+            r3 = true;
         }
-        try { lXY = f.loadXY(i); }
+        try { l2 = f.load2(i); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            rXY = true;
+            r2 = true;
         }
-        try { lX = f.loadX(i); }
+        try { l1 = f.load1(i); }
         catch (e) {
             assertEq(e instanceof RangeError, true);
-            rX = true;
+            r1 = true;
         }
         assertEq(t, r);
-        assertEq(tXYZ, rXYZ);
-        assertEq(tXY, rXY);
-        assertEq(tX, rX);
+        assertEq(t3, r3);
+        assertEq(t2, r2);
+        assertEq(t1, r1);
         if (!t) assertEqX4(v, l);
-        if (!tXYZ) assertEqX4(vXYZ, lXYZ);
-        if (!tXY) assertEqX4(vXY, lXY);
-        if (!tX) assertEqX4(vX, lX);
+        if (!t3) assertEqX4(v3, l3);
+        if (!t2) assertEqX4(v2, l2);
+        if (!t1) assertEqX4(v1, l1);
 
         // Stores
         if (!t) {
             simdCtor.store(arr, index, simdCtor.not(v));
             f.store(i, v);
             assertEqX4(simdCtor.load(arr, index), v);
         } else
             assertThrowsInstanceOf(() => f.store(i, simdCtor()), RangeError);
-        if (!tXYZ) {
-            simdCtor.storeXYZ(arr, index, simdCtor.not(vXYZ));
-            f.storeXYZ(i, vXYZ);
-            assertEqX4(simdCtor.loadXYZ(arr, index), vXYZ);
+        if (!t3) {
+            simdCtor.store3(arr, index, simdCtor.not(v3));
+            f.store3(i, v3);
+            assertEqX4(simdCtor.load3(arr, index), v3);
         } else
-            assertThrowsInstanceOf(() => f.storeXYZ(i, simdCtor()), RangeError);
-        if (!tXY) {
-            simdCtor.storeXY(arr, index, simdCtor.not(vXY));
-            f.storeXY(i, vXY);
-            assertEqX4(simdCtor.loadXY(arr, index), vXY);
+            assertThrowsInstanceOf(() => f.store3(i, simdCtor()), RangeError);
+        if (!t2) {
+            simdCtor.store2(arr, index, simdCtor.not(v2));
+            f.store2(i, v2);
+            assertEqX4(simdCtor.load2(arr, index), v2);
         } else
-            assertThrowsInstanceOf(() => f.storeXY(i, simdCtor()), RangeError);
-        if (!tX) {
-            simdCtor.storeX(arr, index, simdCtor.not(vX));
-            f.storeX(i, vX);
-            assertEqX4(simdCtor.loadX(arr, index), vX);
+            assertThrowsInstanceOf(() => f.store2(i, simdCtor()), RangeError);
+        if (!t1) {
+            simdCtor.store1(arr, index, simdCtor.not(v1));
+            f.store1(i, v1);
+            assertEqX4(simdCtor.load1(arr, index), v1);
         } else
-            assertThrowsInstanceOf(() => f.storeX(i, simdCtor()), RangeError);
+            assertThrowsInstanceOf(() => f.store1(i, simdCtor()), RangeError);
     }
 }
 
 function testFloat32x4(ctor, shift, scale, disp) {
     testSimdX4(ctor, shift, scale, disp, 'float32x4', SIMD.float32x4);
 }
 function testInt32x4(ctor, shift, scale, disp) {
     testSimdX4(ctor, shift, scale, disp, 'int32x4', SIMD.int32x4);
--- a/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js
+++ b/js/src/jit-test/tests/heap-analysis/byteSize-of-object.js
@@ -74,10 +74,10 @@ assertEq(tByteSize([1, 2, 3, 4]),       
 assertEq(tByteSize([1, 2, 3, 4, 5]),                    s(80,  96));
 assertEq(tByteSize([1, 2, 3, 4, 5, 6]),                 s(80,  96));
 assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7]),              s(112, 128));
 assertEq(tByteSize([1, 2, 3, 4, 5, 6, 7, 8]),           s(112, 128));
 
 // Various forms of functions.
 assertEq(tByteSize(function () {}),                     s(32,  64));
 assertEq(tByteSize(function () {}.bind()),              s(96,  128));
-assertEq(tByteSize(() => 1),                            s(48,  96));
+assertEq(tByteSize(() => 1),                            s(48,  80));
 assertEq(tByteSize(Math.sin),                           s(32,  64));
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -11194,16 +11194,17 @@ IonBuilder::jsop_setprop(PropertyName* n
         return emitted;
 
     // Try to emit a monomorphic/polymorphic store based on baseline caches.
     trackOptimizationAttempt(TrackedStrategy::SetProp_InlineAccess);
     if (!setPropTryInlineAccess(&emitted, obj, name, value, barrier, objTypes) || emitted)
         return emitted;
 
     // Emit a polymorphic cache.
+    trackOptimizationAttempt(TrackedStrategy::SetProp_InlineCache);
     return setPropTryCache(&emitted, obj, name, value, barrier, objTypes);
 }
 
 bool
 IonBuilder::setPropTryCommonSetter(bool* emitted, MDefinition* obj,
                                    PropertyName* name, MDefinition* value)
 {
     MOZ_ASSERT(*emitted == false);
@@ -11711,16 +11712,17 @@ IonBuilder::setPropTryCache(bool* emitte
         ins->setNeedsBarrier();
 
     current->add(ins);
     current->push(value);
 
     if (!resumeAfter(ins))
         return false;
 
+    trackOptimizationSuccess();
     *emitted = true;
     return true;
 }
 
 bool
 IonBuilder::jsop_delprop(PropertyName* name)
 {
     MDefinition* obj = current->pop();
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -378,47 +378,47 @@ IonBuilder::inlineNativeCall(CallInfo& c
         return inlineSimdShuffle(callInfo, native, SimdTypeDescr::Float32x4, 1, 4);
     if (native == js::simd_int32x4_shuffle)
         return inlineSimdShuffle(callInfo, native, SimdTypeDescr::Int32x4, 2, 4);
     if (native == js::simd_float32x4_shuffle)
         return inlineSimdShuffle(callInfo, native, SimdTypeDescr::Float32x4, 2, 4);
 
     if (native == js::simd_int32x4_load)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Int32x4, 4);
-    if (native == js::simd_int32x4_loadX)
+    if (native == js::simd_int32x4_load1)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Int32x4, 1);
-    if (native == js::simd_int32x4_loadXY)
+    if (native == js::simd_int32x4_load2)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Int32x4, 2);
-    if (native == js::simd_int32x4_loadXYZ)
+    if (native == js::simd_int32x4_load3)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Int32x4, 3);
 
     if (native == js::simd_float32x4_load)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Float32x4, 4);
-    if (native == js::simd_float32x4_loadX)
+    if (native == js::simd_float32x4_load1)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Float32x4, 1);
-    if (native == js::simd_float32x4_loadXY)
+    if (native == js::simd_float32x4_load2)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Float32x4, 2);
-    if (native == js::simd_float32x4_loadXYZ)
+    if (native == js::simd_float32x4_load3)
         return inlineSimdLoad(callInfo, native, SimdTypeDescr::Float32x4, 3);
 
     if (native == js::simd_int32x4_store)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Int32x4, 4);
-    if (native == js::simd_int32x4_storeX)
+    if (native == js::simd_int32x4_store1)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Int32x4, 1);
-    if (native == js::simd_int32x4_storeXY)
+    if (native == js::simd_int32x4_store2)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Int32x4, 2);
-    if (native == js::simd_int32x4_storeXYZ)
+    if (native == js::simd_int32x4_store3)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Int32x4, 3);
     if (native == js::simd_float32x4_store)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Float32x4, 4);
-    if (native == js::simd_float32x4_storeX)
+    if (native == js::simd_float32x4_store1)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Float32x4, 1);
-    if (native == js::simd_float32x4_storeXY)
+    if (native == js::simd_float32x4_store2)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Float32x4, 2);
-    if (native == js::simd_float32x4_storeXYZ)
+    if (native == js::simd_float32x4_store3)
         return inlineSimdStore(callInfo, native, SimdTypeDescr::Float32x4, 3);
 
     if (native == js::simd_int32x4_bool)
         return inlineSimdBool(callInfo, native, SimdTypeDescr::Int32x4);
 
     // Reaching here means we tried to inline a native for which there is no
     // Ion specialization.
     trackOptimizationOutcome(TrackedOutcome::CantInlineNativeNoSpecialization);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -3477,17 +3477,17 @@ JS_DefineFunctions(JSContext* cx, Handle
             JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass());
             MOZ_ASSERT(obj == &obj->global().getPrototype(key).toObject());
             RootedObject ctor(cx, &obj->global().getConstructor(key).toObject());
 
             flags &= ~JSFUN_GENERIC_NATIVE;
             JSFunction* fun = DefineFunction(cx, ctor, id,
                                              GenericNativeMethodDispatcher,
                                              fs->nargs + 1, flags,
-                                             JSFunction::ExtendedFinalizeKind);
+                                             gc::AllocKind::FUNCTION_EXTENDED);
             if (!fun)
                 return false;
 
             /*
              * As jsapi.h notes, fs must point to storage that lives as long
              * as fun->object lives.
              */
             fun->setExtendedSlot(0, PrivateValue(const_cast<JSFunctionSpec*>(fs)));
@@ -4036,17 +4036,17 @@ CompileFunction(JSContext* cx, const Rea
     AutoNameVector formals(cx);
     for (unsigned i = 0; i < nargs; i++) {
         RootedAtom argAtom(cx, Atomize(cx, argnames[i], strlen(argnames[i])));
         if (!argAtom || !formals.append(argAtom->asPropertyName()))
             return false;
     }
 
     fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED, funAtom,
-                                JSFunction::FinalizeKind, TenuredObject,
+                                gc::AllocKind::FUNCTION, TenuredObject,
                                 enclosingDynamicScope));
     if (!fun)
         return false;
 
     // Make sure to handle cases when we have a polluted scopechain.
     CompileOptions options(cx, optionsArg);
     if (!enclosingDynamicScope->is<GlobalObject>())
         options.setHasPollutedScope(true);
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -3257,17 +3257,17 @@ const Class ArrayObject::class_ = {
     nullptr, /* mayResolve */
     nullptr, /* convert */
     nullptr, /* finalize */
     nullptr, /* call */
     nullptr, /* hasInstance */
     nullptr, /* construct */
     nullptr, /* trace */
     {
-        GenericCreateConstructor<ArrayConstructor, 1, JSFunction::FinalizeKind>,
+        GenericCreateConstructor<ArrayConstructor, 1, gc::AllocKind::FUNCTION>,
         CreateArrayPrototype,
         array_static_methods,
         nullptr,
         array_methods
     }
 };
 
 /*
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -760,30 +760,28 @@ CreateLazyScriptsForCompartment(JSContex
     // script. The last condition is so that we don't compile lazy scripts
     // whose enclosing scripts failed to compile, indicating that the lazy
     // script did not escape the script.
     //
     // Note that while we ideally iterate over LazyScripts, LazyScripts do not
     // currently stand in 1-1 relation with JSScripts; JSFunctions with the
     // same LazyScript may create different JSScripts due to relazification of
     // clones. See bug 1105306.
-    for (gc::ZoneCellIter i(cx->zone(), JSFunction::FinalizeKind); !i.done(); i.next()) {
-        JSObject* obj = i.get<JSObject>();
+    for (gc::ZoneCellIter i(cx->zone(), AllocKind::FUNCTION); !i.done(); i.next()) {
+        JSFunction* fun = &i.get<JSObject>()->as<JSFunction>();
 
         // Sweeping is incremental; take care to not delazify functions that
         // are about to be finalized. GC things referenced by objects that are
         // about to be finalized (e.g., in slots) may already be freed.
-        if (gc::IsAboutToBeFinalizedUnbarriered(&obj) ||
-            obj->compartment() != cx->compartment() ||
-            !obj->is<JSFunction>())
+        if (gc::IsAboutToBeFinalizedUnbarriered(&fun) ||
+            fun->compartment() != cx->compartment())
         {
             continue;
         }
 
-        JSFunction* fun = &obj->as<JSFunction>();
         if (fun->isInterpretedLazy()) {
             LazyScript* lazy = fun->lazyScriptOrNull();
             if (lazy && lazy->sourceObject() && !lazy->maybeScript() &&
                 !lazy->hasUncompiledEnclosingScript())
             {
                 if (!lazyFunctions.append(fun))
                     return false;
             }
--- a/js/src/jsdate.cpp
+++ b/js/src/jsdate.cpp
@@ -3158,17 +3158,17 @@ const Class DateObject::class_ = {
     nullptr, /* mayResolve */
     date_convert,
     nullptr, /* finalize */
     nullptr, /* call */
     nullptr, /* hasInstance */
     nullptr, /* construct */
     nullptr, /* trace */
     {
-        GenericCreateConstructor<DateConstructor, 7, JSFunction::FinalizeKind>,
+        GenericCreateConstructor<DateConstructor, 7, gc::AllocKind::FUNCTION>,
         GenericCreatePrototype,
         date_static_methods,
         nullptr,
         date_methods,
         nullptr,
         FinishDateClassInit
     }
 };
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -485,17 +485,17 @@ ErrorObject::createProto(JSContext* cx, 
 
     return errorProto;
 }
 
 /* static */ JSObject*
 ErrorObject::createConstructor(JSContext* cx, JSProtoKey key)
 {
     RootedObject ctor(cx);
-    ctor = GenericCreateConstructor<Error, 1, JSFunction::ExtendedFinalizeKind>(cx, key);
+    ctor = GenericCreateConstructor<Error, 1, gc::AllocKind::FUNCTION_EXTENDED>(cx, key);
     if (!ctor)
         return nullptr;
 
     ctor->as<JSFunction>().setExtendedSlot(0, Int32Value(ExnTypeFromProtoKey(key)));
     return ctor;
 }
 
 JS_FRIEND_API(JSFlatString*)
--- a/js/src/jsfriendapi.cpp
+++ b/js/src/jsfriendapi.cpp
@@ -419,17 +419,17 @@ js::DefineFunctionWithReserved(JSContext
     RootedObject obj(cx, objArg);
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     JSAtom* atom = Atomize(cx, name, strlen(name));
     if (!atom)
         return nullptr;
     Rooted<jsid> id(cx, AtomToId(atom));
-    return DefineFunction(cx, obj, id, call, nargs, attrs, JSFunction::ExtendedFinalizeKind);
+    return DefineFunction(cx, obj, id, call, nargs, attrs, gc::AllocKind::FUNCTION_EXTENDED);
 }
 
 JS_FRIEND_API(JSFunction*)
 js::NewFunctionWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
                             const char* name)
 {
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
 
@@ -438,32 +438,32 @@ js::NewFunctionWithReserved(JSContext* c
     RootedAtom atom(cx);
     if (name) {
         atom = Atomize(cx, name, strlen(name));
         if (!atom)
             return nullptr;
     }
 
     return (flags & JSFUN_CONSTRUCTOR) ?
-        NewNativeConstructor(cx, native, nargs, atom, JSFunction::ExtendedFinalizeKind) :
-        NewNativeFunction(cx, native, nargs, atom, JSFunction::ExtendedFinalizeKind);
+        NewNativeConstructor(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED) :
+        NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
 }
 
 JS_FRIEND_API(JSFunction*)
 js::NewFunctionByIdWithReserved(JSContext* cx, JSNative native, unsigned nargs, unsigned flags,
                                 jsid id)
 {
     MOZ_ASSERT(JSID_IS_STRING(id));
     MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
     CHECK_REQUEST(cx);
 
     RootedAtom atom(cx, JSID_TO_ATOM(id));
     return (flags & JSFUN_CONSTRUCTOR) ?
-        NewNativeConstructor(cx, native, nargs, atom, JSFunction::ExtendedFinalizeKind) :
-        NewNativeFunction(cx, native, nargs, atom, JSFunction::ExtendedFinalizeKind);
+        NewNativeConstructor(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED) :
+        NewNativeFunction(cx, native, nargs, atom, gc::AllocKind::FUNCTION_EXTENDED);
 }
 
 JS_FRIEND_API(const Value&)
 js::GetFunctionNativeReserved(JSObject* fun, size_t which)
 {
     MOZ_ASSERT(fun->as<JSFunction>().isNative());
     return fun->as<JSFunction>().getExtendedSlot(which);
 }
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -591,19 +591,19 @@ js::XDRInterpretedFunction(XDRState<mode
     if (mode == XDR_DECODE) {
         RootedObject proto(cx);
         if (firstword & IsStarGenerator) {
             proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
             if (!proto)
                 return false;
         }
 
-        gc::AllocKind allocKind = JSFunction::FinalizeKind;
+        gc::AllocKind allocKind = gc::AllocKind::FUNCTION;
         if (uint16_t(flagsword) & JSFunction::EXTENDED)
-            allocKind = JSFunction::ExtendedFinalizeKind;
+            allocKind = gc::AllocKind::FUNCTION_EXTENDED;
         fun = NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
                                    /* enclosingDynamicScope = */ NullPtr(), NullPtr(), proto,
                                    allocKind, TenuredObject);
         if (!fun)
             return false;
         script = nullptr;
     }
 
@@ -649,19 +649,17 @@ js::CloneFunctionAndScript(JSContext* cx
     /* NB: Keep this in sync with XDRInterpretedFunction. */
     RootedObject cloneProto(cx);
     if (srcFun->isStarGenerator()) {
         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
 
-    gc::AllocKind allocKind = JSFunction::FinalizeKind;
-    if (srcFun->isExtended())
-        allocKind = JSFunction::ExtendedFinalizeKind;
+    gc::AllocKind allocKind = srcFun->getAllocKind();
     RootedFunction clone(cx, NewFunctionWithProto(cx, nullptr, 0,
                                                   JSFunction::INTERPRETED, NullPtr(), NullPtr(),
                                                   cloneProto, allocKind, TenuredObject));
     if (!clone)
         return nullptr;
 
     JSScript::AutoDelazify srcScript(cx, srcFun);
     if (!srcScript)
@@ -779,17 +777,17 @@ static JSObject*
 CreateFunctionConstructor(JSContext* cx, JSProtoKey key)
 {
     Rooted<GlobalObject*> global(cx, cx->global());
     RootedObject functionProto(cx, &global->getPrototype(JSProto_Function).toObject());
 
     RootedObject functionCtor(cx,
       NewFunctionWithProto(cx, Function, 1, JSFunction::NATIVE_CTOR,
                            NullPtr(), HandlePropertyName(cx->names().Function),
-                           functionProto, JSFunction::FinalizeKind, SingletonObject));
+                           functionProto, AllocKind::FUNCTION, SingletonObject));
     if (!functionCtor)
         return nullptr;
 
     return functionCtor;
 
 }
 
 static JSObject*
@@ -799,17 +797,17 @@ CreateFunctionPrototype(JSContext* cx, J
 
     RootedObject objectProto(cx, &self->getPrototype(JSProto_Object).toObject());
     /*
      * Bizarrely, |Function.prototype| must be an interpreted function, so
      * give it the guts to be one.
      */
     JSObject* functionProto_ =
         NewFunctionWithProto(cx, nullptr, 0, JSFunction::INTERPRETED,
-                             self, NullPtr(), objectProto, JSFunction::FinalizeKind,
+                             self, NullPtr(), objectProto, AllocKind::FUNCTION,
                              SingletonObject);
     if (!functionProto_)
         return nullptr;
 
     RootedFunction functionProto(cx, &functionProto_->as<JSFunction>());
     functionProto->setIsFunctionPrototype();
 
     const char* rawSource = "() {\n}";
@@ -867,17 +865,17 @@ CreateFunctionPrototype(JSContext* cx, J
     // |Function.prototype| right now.)
     //
     // Note that we can't use NewFunction here, even though we want the normal
     // Function.prototype for our proto, because we're still in the middle of
     // creating that as far as the world is concerned, so things will get all
     // confused.
     RootedFunction throwTypeError(cx,
       NewFunctionWithProto(cx, ThrowTypeError, 0, JSFunction::NATIVE_FUN,
-                           NullPtr(), NullPtr(), functionProto, JSFunction::FinalizeKind,
+                           NullPtr(), NullPtr(), functionProto, AllocKind::FUNCTION,
                            SingletonObject));
     if (!throwTypeError || !PreventExtensions(cx, throwTypeError))
         return nullptr;
 
     self->setThrowTypeError(throwTypeError);
 
     return functionProto;
 }
@@ -1949,17 +1947,17 @@ FunctionConstructor(JSContext* cx, unsig
     if (isStarGenerator) {
         proto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, global);
         if (!proto)
             return false;
     }
     RootedFunction fun(cx, NewFunctionWithProto(cx, nullptr, 0,
                                                 JSFunction::INTERPRETED_LAMBDA, global,
                                                 anonymousAtom, proto,
-                                                JSFunction::FinalizeKind, TenuredObject));
+                                                AllocKind::FUNCTION, TenuredObject));
     if (!fun)
         return false;
 
     if (!JSFunction::setTypeForScriptedFunction(cx, fun))
         return false;
 
     if (hasRest)
         fun->setHasRest();
@@ -1998,56 +1996,54 @@ js::Generator(JSContext* cx, unsigned ar
 bool
 JSFunction::isBuiltinFunctionConstructor()
 {
     return maybeNative() == Function || maybeNative() == Generator;
 }
 
 JSFunction*
 js::NewNativeFunction(ExclusiveContext* cx, Native native, unsigned nargs, HandleAtom atom,
-                      gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
+                      gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
                       NewObjectKind newKind /* = GenericObject */)
 {
     return NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_FUN,
                                 NullPtr(), atom, NullPtr(), allocKind, newKind);
 }
 
 JSFunction*
 js::NewNativeConstructor(ExclusiveContext* cx, Native native, unsigned nargs, HandleAtom atom,
-                         gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
+                         gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
                          NewObjectKind newKind /* = GenericObject */,
                          JSFunction::Flags flags /* = JSFunction::NATIVE_CTOR */)
 {
     MOZ_ASSERT(flags & JSFunction::NATIVE_CTOR);
     return NewFunctionWithProto(cx, native, nargs, flags, NullPtr(), atom,
                                 NullPtr(), allocKind, newKind);
 }
 
 JSFunction*
 js::NewScriptedFunction(ExclusiveContext* cx, unsigned nargs,
                         JSFunction::Flags flags, HandleAtom atom,
-                        gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
+                        gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
                         NewObjectKind newKind /* = GenericObject */,
                         HandleObject enclosingDynamicScope /* = NullPtr() */)
 {
     return NewFunctionWithProto(cx, nullptr, nargs, flags,
                                 enclosingDynamicScope ? enclosingDynamicScope : cx->global(),
                                 atom, NullPtr(), allocKind, newKind);
 }
 
 JSFunction*
 js::NewFunctionWithProto(ExclusiveContext* cx, Native native,
                          unsigned nargs, JSFunction::Flags flags, HandleObject enclosingDynamicScope,
                          HandleAtom atom, HandleObject proto,
-                         gc::AllocKind allocKind /* = JSFunction::FinalizeKind */,
+                         gc::AllocKind allocKind /* = AllocKind::FUNCTION */,
                          NewObjectKind newKind /* = GenericObject */)
 {
-    MOZ_ASSERT(allocKind == JSFunction::FinalizeKind || allocKind == JSFunction::ExtendedFinalizeKind);
-    MOZ_ASSERT(sizeof(JSFunction) <= gc::Arena::thingSize(JSFunction::FinalizeKind));
-    MOZ_ASSERT(sizeof(FunctionExtended) <= gc::Arena::thingSize(JSFunction::ExtendedFinalizeKind));
+    MOZ_ASSERT(allocKind == AllocKind::FUNCTION || allocKind == AllocKind::FUNCTION_EXTENDED);
     MOZ_ASSERT_IF(native, !enclosingDynamicScope);
 
     RootedObject funobj(cx);
     // Don't mark asm.js module functions as singleton since they are
     // cloned (via CloneFunctionObjectIfNotSingleton) which assumes that
     // isSingleton implies isInterpreted.
     if (native && !IsAsmJSModuleNative(native))
         newKind = SingletonObject;
@@ -2064,17 +2060,17 @@ js::NewFunctionWithProto(ExclusiveContex
 #endif
     funobj = NewObjectWithClassProto(cx, &JSFunction::class_, proto, allocKind,
                                      newKind);
     if (!funobj)
         return nullptr;
 
     RootedFunction fun(cx, &funobj->as<JSFunction>());
 
-    if (allocKind == JSFunction::ExtendedFinalizeKind)
+    if (allocKind == AllocKind::FUNCTION_EXTENDED)
         flags = JSFunction::Flags(flags | JSFunction::EXTENDED);
 
     /* Initialize all function members. */
     fun->setArgCount(uint16_t(nargs));
     fun->setFlags(flags);
     if (fun->isInterpreted()) {
         MOZ_ASSERT(!native);
         if (fun->isInterpretedLazy())
@@ -2082,17 +2078,17 @@ js::NewFunctionWithProto(ExclusiveContex
         else
             fun->initScript(nullptr);
         fun->initEnvironment(enclosingDynamicScope);
     } else {
         MOZ_ASSERT(fun->isNative());
         MOZ_ASSERT(native);
         fun->initNative(native, nullptr);
     }
-    if (allocKind == JSFunction::ExtendedFinalizeKind)
+    if (allocKind == AllocKind::FUNCTION_EXTENDED)
         fun->initializeExtended();
     fun->initAtom(atom);
 
     return fun;
 }
 
 bool
 js::CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
@@ -2164,17 +2160,17 @@ js::CloneFunctionObject(JSContext* cx, H
                                                  allocKind, newKind);
     if (!cloneobj)
         return nullptr;
     RootedFunction clone(cx, &cloneobj->as<JSFunction>());
 
     MOZ_ASSERT(useSameScript || !fun->isInterpretedLazy());
 
     uint16_t flags = fun->flags() & ~JSFunction::EXTENDED;
-    if (allocKind == JSFunction::ExtendedFinalizeKind)
+    if (allocKind == AllocKind::FUNCTION_EXTENDED)
         flags |= JSFunction::EXTENDED;
 
     clone->setArgCount(fun->nargs());
     clone->setFlags(flags);
     if (fun->hasScript()) {
         clone->initScript(fun->nonLazyScript());
         clone->initEnvironment(parent);
     } else if (fun->isInterpretedLazy()) {
@@ -2183,17 +2179,17 @@ js::CloneFunctionObject(JSContext* cx, H
         LazyScript* lazy = fun->lazyScriptOrNull();
         clone->initLazyScript(lazy);
         clone->initEnvironment(parent);
     } else {
         clone->initNative(fun->native(), fun->jitInfo());
     }
     clone->initAtom(fun->displayAtom());
 
-    if (allocKind == JSFunction::ExtendedFinalizeKind) {
+    if (allocKind == AllocKind::FUNCTION_EXTENDED) {
         if (fun->isExtended() && fun->compartment() == cx->compartment()) {
             for (unsigned i = 0; i < FunctionExtended::NUM_EXTENDED_SLOTS; i++)
                 clone->initExtendedSlot(i, fun->getExtendedSlot(i));
         } else {
             clone->initializeExtended();
         }
     }
 
@@ -2251,17 +2247,17 @@ js::IdToFunctionName(JSContext* cx, Hand
     }
 
     RootedValue idv(cx, IdToValue(id));
     return ToAtom<CanGC>(cx, idv);
 }
 
 JSFunction*
 js::DefineFunction(JSContext* cx, HandleObject obj, HandleId id, Native native,
-                   unsigned nargs, unsigned flags, AllocKind allocKind /* = FinalizeKind */,
+                   unsigned nargs, unsigned flags, AllocKind allocKind /* = AllocKind::FUNCTION */,
                    NewObjectKind newKind /* = GenericObject */)
 {
     GetterOp gop;
     SetterOp sop;
     if (flags & JSFUN_STUB_GSOPS) {
         /*
          * JSFUN_STUB_GSOPS is a request flag only, not stored in fun->flags or
          * the defined property's attributes. This allows us to encode another,
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -449,24 +449,16 @@ class JSFunction : public js::NativeObje
                       "for offsetOfNativeOrScript() have any sense");
         static_assert(offsetof(U, n.native) == offsetof(U, nativeOrScript),
                       "U::nativeOrScript must be at the same offset as "
                       "native");
 
         return offsetof(JSFunction, u.nativeOrScript);
     }
 
-#if JS_BITS_PER_WORD == 32
-    static const js::gc::AllocKind FinalizeKind = js::gc::AllocKind::OBJECT2_BACKGROUND;
-    static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::AllocKind::OBJECT4_BACKGROUND;
-#else
-    static const js::gc::AllocKind FinalizeKind = js::gc::AllocKind::OBJECT4_BACKGROUND;
-    static const js::gc::AllocKind ExtendedFinalizeKind = js::gc::AllocKind::OBJECT8_BACKGROUND;
-#endif
-
     inline void trace(JSTracer* trc);
 
     /* Bound function accessors. */
 
     inline bool initBoundFunction(JSContext* cx, js::HandleObject target, js::HandleValue thisArg,
                                   const js::Value* args, unsigned argslen);
 
     JSObject* getBoundFunctionTarget() const;
@@ -480,18 +472,20 @@ class JSFunction : public js::NativeObje
         return *(js::HeapPtrScript*)&u.i.s.script_;
     }
 
     inline js::FunctionExtended* toExtended();
     inline const js::FunctionExtended* toExtended() const;
 
   public:
     inline bool isExtended() const {
-        MOZ_ASSERT_IF(isTenured(), !!(flags() & EXTENDED) == (asTenured().getAllocKind() == ExtendedFinalizeKind));
-        return !!(flags() & EXTENDED);
+        bool extended = !!(flags() & EXTENDED);
+        MOZ_ASSERT_IF(isTenured(),
+                      extended == (asTenured().getAllocKind() == js::gc::AllocKind::FUNCTION_EXTENDED));
+        return extended;
     }
 
     /*
      * Accessors for data stored in extended functions. Use setExtendedSlot if
      * the function has already been initialized. Otherwise use
      * initExtendedSlot.
      */
     inline void initializeExtended();
@@ -500,23 +494,23 @@ class JSFunction : public js::NativeObje
     inline const js::Value& getExtendedSlot(size_t which) const;
 
     /* Constructs a new type for the function if necessary. */
     static bool setTypeForScriptedFunction(js::ExclusiveContext* cx, js::HandleFunction fun,
                                            bool singleton = false);
 
     /* GC support. */
     js::gc::AllocKind getAllocKind() const {
-        static_assert(FinalizeKind != ExtendedFinalizeKind,
+        static_assert(js::gc::AllocKind::FUNCTION != js::gc::AllocKind::FUNCTION_EXTENDED,
                       "extended/non-extended AllocKinds have to be different "
                       "for getAllocKind() to have a reason to exist");
 
-        js::gc::AllocKind kind = FinalizeKind;
+        js::gc::AllocKind kind = js::gc::AllocKind::FUNCTION;
         if (isExtended())
-            kind = ExtendedFinalizeKind;
+            kind = js::gc::AllocKind::FUNCTION_EXTENDED;
         MOZ_ASSERT_IF(isTenured(), kind == asTenured().getAllocKind());
         return kind;
     }
 };
 
 static_assert(sizeof(JSFunction) == sizeof(js::shadow::Function),
               "shadow interface must match actual interface");
 
@@ -529,52 +523,52 @@ extern bool
 Function(JSContext* cx, unsigned argc, Value* vp);
 
 extern bool
 Generator(JSContext* cx, unsigned argc, Value* vp);
 
 // Allocate a new function backed by a JSNative.
 extern JSFunction*
 NewNativeFunction(ExclusiveContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
-                  gc::AllocKind allocKind = JSFunction::FinalizeKind,
+                  gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                   NewObjectKind newKind = GenericObject);
 
 // Allocate a new constructor backed by a JSNative.
 extern JSFunction*
 NewNativeConstructor(ExclusiveContext* cx, JSNative native, unsigned nargs, HandleAtom atom,
-                     gc::AllocKind allocKind = JSFunction::FinalizeKind,
+                     gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                      NewObjectKind newKind = GenericObject,
                      JSFunction::Flags flags = JSFunction::NATIVE_CTOR);
 
 // Allocate a new scripted function.  If enclosingDynamicScope is null, the
 // global will be used.  In all cases the parent of the resulting object will be
 // the global.
 extern JSFunction*
 NewScriptedFunction(ExclusiveContext* cx, unsigned nargs, JSFunction::Flags flags,
-                    HandleAtom atom, gc::AllocKind allocKind = JSFunction::FinalizeKind,
+                    HandleAtom atom, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                     NewObjectKind newKind = GenericObject,
                     HandleObject enclosingDynamicScope = NullPtr());
 
 // If proto is nullptr, Function.prototype is used instead.  If
 // enclosingDynamicScope is null, the function will have a null environment()
 // (yes, null, not the global).  In all cases, the global will be used as the
 // parent.
 extern JSFunction*
 NewFunctionWithProto(ExclusiveContext* cx, JSNative native, unsigned nargs,
                      JSFunction::Flags flags, HandleObject enclosingDynamicScope, HandleAtom atom,
-                     HandleObject proto, gc::AllocKind allocKind = JSFunction::FinalizeKind,
+                     HandleObject proto, gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                      NewObjectKind newKind = GenericObject);
 
 extern JSAtom*
 IdToFunctionName(JSContext* cx, HandleId id);
 
 extern JSFunction*
 DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,
                unsigned nargs, unsigned flags,
-               gc::AllocKind allocKind = JSFunction::FinalizeKind,
+               gc::AllocKind allocKind = gc::AllocKind::FUNCTION,
                NewObjectKind newKind = GenericObject);
 
 bool
 FunctionHasResolveHook(const JSAtomState& atomState, jsid id);
 
 extern bool
 fun_toString(JSContext* cx, unsigned argc, Value* vp);
 
@@ -612,17 +606,17 @@ class FunctionExtended : public JSFuncti
 };
 
 extern bool
 CloneFunctionObjectUseSameScript(JSCompartment* compartment, HandleFunction fun,
                                  HandleObject newParent);
 
 extern JSFunction*
 CloneFunctionObject(JSContext* cx, HandleFunction fun, HandleObject parent,
-                    gc::AllocKind kind = JSFunction::FinalizeKind,
+                    gc::AllocKind kind = gc::AllocKind::FUNCTION,
                     NewObjectKind newKindArg = GenericObject,
                     HandleObject proto = NullPtr());
 
 extern bool
 FindBody(JSContext* cx, HandleFunction fun, HandleLinearString src, size_t* bodyStart,
          size_t* bodyEnd);
 
 } // namespace js
--- a/js/src/jsfuninlines.h
+++ b/js/src/jsfuninlines.h
@@ -75,18 +75,18 @@ CloneFunctionObjectIfNotSingleton(JSCont
             return nullptr;
         MOZ_ASSERT(!proto || succeeded);
         fun->setEnvironment(parent);
         return fun;
     }
 
     // These intermediate variables are needed to avoid link errors on some
     // platforms.  Sigh.
-    gc::AllocKind finalizeKind = JSFunction::FinalizeKind;
-    gc::AllocKind extendedFinalizeKind = JSFunction::ExtendedFinalizeKind;
+    gc::AllocKind finalizeKind = gc::AllocKind::FUNCTION;
+    gc::AllocKind extendedFinalizeKind = gc::AllocKind::FUNCTION_EXTENDED;
     gc::AllocKind kind = fun->isExtended()
                          ? extendedFinalizeKind
                          : finalizeKind;
     return CloneFunctionObject(cx, fun, parent, kind, newKind, proto);
 }
 
 } /* namespace js */
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -265,16 +265,18 @@ static_assert(JS_ARRAY_LENGTH(slotsToThi
 // Assert that SortedArenaList::MinThingSize is <= the real minimum thing size.
 #define CHECK_MIN_THING_SIZE_INNER(x_)                                         \
     static_assert(x_ >= SortedArenaList::MinThingSize,                         \
     #x_ " is less than SortedArenaList::MinThingSize!");
 #define CHECK_MIN_THING_SIZE(...) { __VA_ARGS__ }; /* Define the array. */     \
     MOZ_FOR_EACH(CHECK_MIN_THING_SIZE_INNER, (), (__VA_ARGS__ UINT32_MAX))
 
 const uint32_t Arena::ThingSizes[] = CHECK_MIN_THING_SIZE(
+    sizeof(JSFunction),         /* AllocKind::FUNCTION            */
+    sizeof(FunctionExtended),   /* AllocKind::FUNCTION_EXTENDED   */
     sizeof(JSObject_Slots0),    /* AllocKind::OBJECT0             */
     sizeof(JSObject_Slots0),    /* AllocKind::OBJECT0_BACKGROUND  */
     sizeof(JSObject_Slots2),    /* AllocKind::OBJECT2             */
     sizeof(JSObject_Slots2),    /* AllocKind::OBJECT2_BACKGROUND  */
     sizeof(JSObject_Slots4),    /* AllocKind::OBJECT4             */
     sizeof(JSObject_Slots4),    /* AllocKind::OBJECT4_BACKGROUND  */
     sizeof(JSObject_Slots8),    /* AllocKind::OBJECT8             */
     sizeof(JSObject_Slots8),    /* AllocKind::OBJECT8_BACKGROUND  */
@@ -296,16 +298,18 @@ const uint32_t Arena::ThingSizes[] = CHE
 );
 
 #undef CHECK_MIN_THING_SIZE_INNER
 #undef CHECK_MIN_THING_SIZE
 
 #define OFFSET(type) uint32_t(sizeof(ArenaHeader) + (ArenaSize - sizeof(ArenaHeader)) % sizeof(type))
 
 const uint32_t Arena::FirstThingOffsets[] = {
+    OFFSET(JSFunction),         /* AllocKind::FUNCTION            */
+    OFFSET(FunctionExtended),   /* AllocKind::FUNCTION_EXTENDED   */
     OFFSET(JSObject_Slots0),    /* AllocKind::OBJECT0             */
     OFFSET(JSObject_Slots0),    /* AllocKind::OBJECT0_BACKGROUND  */
     OFFSET(JSObject_Slots2),    /* AllocKind::OBJECT2             */
     OFFSET(JSObject_Slots2),    /* AllocKind::OBJECT2_BACKGROUND  */
     OFFSET(JSObject_Slots4),    /* AllocKind::OBJECT4             */
     OFFSET(JSObject_Slots4),    /* AllocKind::OBJECT4_BACKGROUND  */
     OFFSET(JSObject_Slots8),    /* AllocKind::OBJECT8             */
     OFFSET(JSObject_Slots8),    /* AllocKind::OBJECT8_BACKGROUND  */
@@ -360,16 +364,18 @@ static const FinalizePhase IncrementalFi
     PHASE(IncrementalPhaseJitCode, gcstats::PHASE_SWEEP_JITCODE)
 };
 
 /*
  * Finalization order for things swept in the background.
  */
 
 static const AllocKind BackgroundPhaseObjects[] = {
+    AllocKind::FUNCTION,
+    AllocKind::FUNCTION_EXTENDED,
     AllocKind::OBJECT0_BACKGROUND,
     AllocKind::OBJECT2_BACKGROUND,
     AllocKind::OBJECT4_BACKGROUND,
     AllocKind::OBJECT8_BACKGROUND,
     AllocKind::OBJECT12_BACKGROUND,
     AllocKind::OBJECT16_BACKGROUND
 };
 
@@ -583,16 +589,18 @@ static bool
 FinalizeArenas(FreeOp* fop,
                ArenaHeader** src,
                SortedArenaList& dest,
                AllocKind thingKind,
                SliceBudget& budget,
                ArenaLists::KeepArenasEnum keepArenas)
 {
     switch (thingKind) {
+      case AllocKind::FUNCTION:
+      case AllocKind::FUNCTION_EXTENDED:
       case AllocKind::OBJECT0:
       case AllocKind::OBJECT0_BACKGROUND:
       case AllocKind::OBJECT2:
       case AllocKind::OBJECT2_BACKGROUND:
       case AllocKind::OBJECT4:
       case AllocKind::OBJECT4_BACKGROUND:
       case AllocKind::OBJECT8:
       case AllocKind::OBJECT8_BACKGROUND:
@@ -887,20 +895,17 @@ Chunk::fetchNextFreeArena(JSRuntime* rt)
 
 ArenaHeader*
 Chunk::allocateArena(JSRuntime* rt, Zone* zone, AllocKind thingKind, const AutoLockGC& lock)
 {
     ArenaHeader* aheader = info.numArenasFreeCommitted > 0
                            ? fetchNextFreeArena(rt)
                            : fetchNextDecommittedArena();
     aheader->init(zone, thingKind);
-    if (MOZ_UNLIKELY(!hasAvailableArenas())) {
-        rt->gc.availableChunks(lock).remove(this);
-        rt->gc.fullChunks(lock).push(this);
-    }
+    updateChunkListAfterAlloc(rt, lock);
     return aheader;
 }
 
 inline void
 GCRuntime::updateOnArenaFree(const ChunkInfo& info)
 {
     ++numArenasFreeCommitted;
 }
@@ -927,29 +932,74 @@ void
 Chunk::recycleArena(ArenaHeader* aheader, SortedArenaList& dest, AllocKind thingKind,
                     size_t thingsPerArena)
 {
     aheader->getArena()->setAsFullyUnused(thingKind);
     dest.insertAt(aheader, thingsPerArena);
 }
 
 void
-Chunk::releaseArena(JSRuntime* rt, ArenaHeader* aheader, const AutoLockGC& lock,
-                    ArenaDecommitState state /* = IsCommitted */)
+Chunk::releaseArena(JSRuntime* rt, ArenaHeader* aheader, const AutoLockGC& lock)
 {
     MOZ_ASSERT(aheader->allocated());
     MOZ_ASSERT(!aheader->hasDelayedMarking);
 
-    if (state == IsCommitted) {
-        aheader->setAsNotAllocated();
+    aheader->setAsNotAllocated();
+    addArenaToFreeList(rt, aheader);
+    updateChunkListAfterFree(rt, lock);
+}
+
+bool
+Chunk::decommitOneFreeArena(JSRuntime* rt, AutoLockGC& lock)
+{
+    MOZ_ASSERT(info.numArenasFreeCommitted > 0);
+    ArenaHeader* aheader = fetchNextFreeArena(rt);
+    updateChunkListAfterAlloc(rt, lock);
+
+    bool ok;
+    {
+        AutoUnlockGC unlock(lock);
+        ok = MarkPagesUnused(aheader->getArena(), ArenaSize);
+    }
+
+    if (ok)
+        addArenaToDecommittedList(rt, aheader);
+    else
         addArenaToFreeList(rt, aheader);
-    } else {
-        addArenaToDecommittedList(rt, aheader);
-    }
-
+    updateChunkListAfterFree(rt, lock);
+
+    return ok;
+}
+
+void
+Chunk::decommitAllArenasWithoutUnlocking(const AutoLockGC& lock)
+{
+    for (size_t i = 0; i < ArenasPerChunk; ++i) {
+        if (decommittedArenas.get(i) || arenas[i].aheader.allocated())
+            continue;
+
+        if (MarkPagesUnused(&arenas[i], ArenaSize)) {
+            info.numArenasFreeCommitted--;
+            decommittedArenas.set(i);
+        }
+    }
+}
+
+void
+Chunk::updateChunkListAfterAlloc(JSRuntime* rt, const AutoLockGC& lock)
+{
+    if (MOZ_UNLIKELY(!hasAvailableArenas())) {
+        rt->gc.availableChunks(lock).remove(this);
+        rt->gc.fullChunks(lock).push(this);
+    }
+}
+
+void
+Chunk::updateChunkListAfterFree(JSRuntime* rt, const AutoLockGC& lock)
+{
     if (info.numArenasFree == 1) {
         rt->gc.fullChunks(lock).remove(this);
         rt->gc.availableChunks(lock).push(this);
     } else if (!unused()) {
         MOZ_ASSERT(!rt->gc.fullChunks(lock).contains(this));
         MOZ_ASSERT(rt->gc.availableChunks(lock).contains(this));
         MOZ_ASSERT(!rt->gc.emptyChunks(lock).contains(this));
     } else {
@@ -2239,16 +2289,18 @@ UpdateCellPointersTyped(MovingTracer* tr
  */
 static void
 UpdateCellPointers(MovingTracer* trc, ArenaHeader* arena)
 {
     AllocKind kind = arena->getAllocKind();
     JSGCTraceKind traceKind = MapAllocToTraceKind(kind);
 
     switch (kind) {
+      case AllocKind::FUNCTION:
+      case AllocKind::FUNCTION_EXTENDED:
       case AllocKind::OBJECT0:
       case AllocKind::OBJECT0_BACKGROUND:
       case AllocKind::OBJECT2:
       case AllocKind::OBJECT2_BACKGROUND:
       case AllocKind::OBJECT4:
       case AllocKind::OBJECT4_BACKGROUND:
       case AllocKind::OBJECT8:
       case AllocKind::OBJECT8_BACKGROUND:
@@ -3144,27 +3196,18 @@ GCRuntime::maybePeriodicFullGC()
 }
 
 // Do all possible decommit immediately from the current thread without
 // releasing the GC lock or allocating any memory.
 void
 GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC& lock)
 {
     MOZ_ASSERT(emptyChunks(lock).count() == 0);
-    for (ChunkPool::Iter chunk(availableChunks(lock)); !chunk.done(); chunk.next()) {
-        for (size_t i = 0; i < ArenasPerChunk; ++i) {
-            if (chunk->decommittedArenas.get(i) || chunk->arenas[i].aheader.allocated())
-                continue;
-
-            if (MarkPagesUnused(&chunk->arenas[i], ArenaSize)) {
-                chunk->info.numArenasFreeCommitted--;
-                chunk->decommittedArenas.set(i);
-            }
-        }
-    }
+    for (ChunkPool::Iter chunk(availableChunks(lock)); !chunk.done(); chunk.next())
+        chunk->decommitAllArenasWithoutUnlocking(lock);
     MOZ_ASSERT(availableChunks(lock).verify());
 }
 
 void
 GCRuntime::decommitArenas(AutoLockGC& lock)
 {
     // Verify that all entries in the empty chunks pool are decommitted.
     for (ChunkPool::Iter chunk(emptyChunks(lock)); !chunk.done(); chunk.next())
@@ -3187,23 +3230,17 @@ GCRuntime::decommitArenas(AutoLockGC& lo
     // head and don't want to thrash with the mutator.
     for (size_t i = toDecommit.length(); i > 1; --i) {
         Chunk* chunk = toDecommit[i - 1];
         MOZ_ASSERT(chunk);
 
         // The arena list is not doubly-linked, so we have to work in the free
         // list order and not in the natural order.
         while (chunk->info.numArenasFreeCommitted) {
-            ArenaHeader* aheader = chunk->allocateArena(rt, nullptr, AllocKind::OBJECT0, lock);
-            bool ok;
-            {
-                AutoUnlockGC unlock(lock);
-                ok = MarkPagesUnused(aheader->getArena(), ArenaSize);
-            }
-            chunk->releaseArena(rt, aheader, lock, Chunk::ArenaDecommitState(ok));
+            bool ok = chunk->decommitOneFreeArena(rt, lock);
 
             // FIXME Bug 1095620: add cancellation support when this becomes
             // a ParallelTask.
             if (/* cancel_ || */ !ok)
                 return;
         }
     }
     MOZ_ASSERT(availableChunks(lock).verify());
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -91,16 +91,18 @@ template <typename T> struct Participate
 FOR_EACH_GC_LAYOUT(EXPAND_PARTICIPATES_IN_CC)
 #undef EXPAND_PARTICIPATES_IN_CC
 
 static inline bool
 IsNurseryAllocable(AllocKind kind)
 {
     MOZ_ASSERT(IsValidAllocKind(kind));
     static const bool map[] = {
+        true,      /* AllocKind::FUNCTION */
+        true,      /* AllocKind::FUNCTION_EXTENDED */
         false,     /* AllocKind::OBJECT0 */
         true,      /* AllocKind::OBJECT0_BACKGROUND */
         false,     /* AllocKind::OBJECT2 */
         true,      /* AllocKind::OBJECT2_BACKGROUND */
         false,     /* AllocKind::OBJECT4 */
         true,      /* AllocKind::OBJECT4_BACKGROUND */
         false,     /* AllocKind::OBJECT8 */
         true,      /* AllocKind::OBJECT8_BACKGROUND */
@@ -124,16 +126,18 @@ IsNurseryAllocable(AllocKind kind)
     return map[size_t(kind)];
 }
 
 static inline bool
 IsBackgroundFinalized(AllocKind kind)
 {
     MOZ_ASSERT(IsValidAllocKind(kind));
     static const bool map[] = {
+        true,      /* AllocKind::FUNCTION */
+        true,      /* AllocKind::FUNCTION_EXTENDED */
         false,     /* AllocKind::OBJECT0 */
         true,      /* AllocKind::OBJECT0_BACKGROUND */
         false,     /* AllocKind::OBJECT2 */
         true,      /* AllocKind::OBJECT2_BACKGROUND */
         false,     /* AllocKind::OBJECT4 */
         true,      /* AllocKind::OBJECT4_BACKGROUND */
         false,     /* AllocKind::OBJECT8 */
         true,      /* AllocKind::OBJECT8_BACKGROUND */
@@ -282,19 +286,21 @@ GetBackgroundAllocKind(AllocKind kind)
 }
 
 /* Get the number of fixed slots and initial capacity associated with a kind. */
 static inline size_t
 GetGCKindSlots(AllocKind thingKind)
 {
     /* Using a switch in hopes that thingKind will usually be a compile-time constant. */
     switch (thingKind) {
+      case AllocKind::FUNCTION:
       case AllocKind::OBJECT0:
       case AllocKind::OBJECT0_BACKGROUND:
         return 0;
+      case AllocKind::FUNCTION_EXTENDED:
       case AllocKind::OBJECT2:
       case AllocKind::OBJECT2_BACKGROUND:
         return 2;
       case AllocKind::OBJECT4:
       case AllocKind::OBJECT4_BACKGROUND:
         return 4;
       case AllocKind::OBJECT8:
       case AllocKind::OBJECT8_BACKGROUND:
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -14,17 +14,17 @@
 
 namespace js {
 namespace gc {
 
 static inline AllocKind
 GetGCObjectKind(const Class* clasp)
 {
     if (clasp == FunctionClassPtr)
-        return JSFunction::FinalizeKind;
+        return AllocKind::FUNCTION;
     uint32_t nslots = JSCLASS_RESERVED_SLOTS(clasp);
     if (clasp->flags & JSCLASS_HAS_PRIVATE)
         nslots++;
     return GetGCObjectKind(nslots);
 }
 
 inline JSGCTraceKind
 GetGCThingTraceKind(const void* thing)
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1080,17 +1080,17 @@ NewObjectGCKind(const js::Class* clasp)
 static inline JSObject*
 NewObject(ExclusiveContext* cx, HandleObjectGroup group, gc::AllocKind kind,
           NewObjectKind newKind)
 {
     const Class* clasp = group->clasp();
 
     MOZ_ASSERT(clasp != &ArrayObject::class_);
     MOZ_ASSERT_IF(clasp == &JSFunction::class_,
-                  kind == JSFunction::FinalizeKind || kind == JSFunction::ExtendedFinalizeKind);
+                  kind == AllocKind::FUNCTION || kind == AllocKind::FUNCTION_EXTENDED);
 
     // For objects which can have fixed data following the object, only use
     // enough fixed slots to cover the number of reserved slots in the object,
     // regardless of the allocation kind specified.
     size_t nfixed = ClassCanHaveFixedData(clasp)
                     ? GetGCKindSlots(gc::GetGCObjectKind(clasp), clasp)
                     : GetGCKindSlots(kind, clasp);
 
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -818,13 +818,13 @@ Unbox(JSContext* cx, HandleObject obj, M
 }
 
 extern NativeObject*
 InitClass(JSContext* cx, HandleObject obj, HandleObject parent_proto,
           const Class* clasp, JSNative constructor, unsigned nargs,
           const JSPropertySpec* ps, const JSFunctionSpec* fs,
           const JSPropertySpec* static_ps, const JSFunctionSpec* static_fs,
           NativeObject** ctorp = nullptr,
-          gc::AllocKind ctorKind = JSFunction::FinalizeKind);
+          gc::AllocKind ctorKind = gc::AllocKind::FUNCTION);
 
 } /* namespace js */
 
 #endif /* jsobjinlines_h */
--- a/js/src/tests/ecma_7/SIMD/load.js
+++ b/js/src/tests/ecma_7/SIMD/load.js
@@ -46,43 +46,43 @@ function MakeComparator(kind, arr, share
     // these bytes as a typed array equivalent to the typed SIMD vector.
     var slice = function(start, numElemToRead) {
         // Read enough bytes
         var startBytes = start * bpe;
         var endBytes = startBytes + numElemToRead * sizeOfLaneElem;
         var asArray = Array.prototype.slice.call(uint8, startBytes, endBytes);
 
         // If length is less than SIZE_BYTES bytes, fill with 0.
-        // This is needed for loadX, loadXY, loadXYZ which do only partial
+        // This is needed for load1, load2, load3 which do only partial
         // reads.
         for (var i = asArray.length; i < SIZE_BYTES; i++) asArray[i] = 0;
         assertEq(asArray.length, SIZE_BYTES);
 
         return new typedArrayCtor(new Uint8Array(asArray).buffer);
     }
 
     var assertFunc = (lanes == 2) ? assertEqX2 : assertEqX4;
     var type = SIMD[kind];
     return {
-        loadX: function(index) {
-            var v = type.loadX(arr, index);
+        load1: function(index) {
+            var v = type.load1(arr, index);
             assertFunc(v, slice(index, 1));
         },
 
-        loadXY: function(index) {
+        load2: function(index) {
             if (lanes < 4)
                 return;
-            var v = type.loadXY(arr, index);
+            var v = type.load2(arr, index);
             assertFunc(v, slice(index, 2));
         },
 
-       loadXYZ: function(index) {
+       load3: function(index) {
            if (lanes < 4)
                return;
-           var v = type.loadXYZ(arr, index);
+           var v = type.load3(arr, index);
            assertFunc(v, slice(index, 3));
         },
 
         load: function(index) {
            var v = type.load(arr, index);
            assertFunc(v, slice(index, 4));
         }
     }
@@ -109,50 +109,50 @@ function testLoad(kind, TA) {
         assertThrowsInstanceOf(() => SIMD[kind].load(ta), TypeError);
         assertThrowsInstanceOf(() => SIMD[kind].load("hello", 0), TypeError);
         assertThrowsInstanceOf(() => SIMD[kind].load(ta, -1), RangeError);
 
         // Valid and invalid reads
         var C = MakeComparator(kind, ta);
         var bpe = ta.BYTES_PER_ELEMENT;
 
-        var lastValidArgLoadX   = (SIZE_BYTES - (lanes == 4 ? 4 : 8))  / bpe | 0;
-        var lastValidArgLoadXY  = (SIZE_BYTES - 8)  / bpe | 0;
-        var lastValidArgLoadXYZ = (SIZE_BYTES - 12) / bpe | 0;
+        var lastValidArgLoad1   = (SIZE_BYTES - (lanes == 4 ? 4 : 8))  / bpe | 0;
+        var lastValidArgLoad2   = (SIZE_BYTES - 8)  / bpe | 0;
+        var lastValidArgLoad3   = (SIZE_BYTES - 12) / bpe | 0;
         var lastValidArgLoad    = (SIZE_BYTES - 16) / bpe | 0;
 
         C.load(0);
         C.load(1);
         C.load(2);
         C.load(3);
         C.load(lastValidArgLoad);
         assertThrowsInstanceOf(() => SIMD[kind].load(ta, lastValidArgLoad + 1), RangeError);
 
-        C.loadX(0);
-        C.loadX(1);
-        C.loadX(2);
-        C.loadX(3);
-        C.loadX(lastValidArgLoadX);
-        assertThrowsInstanceOf(() => SIMD[kind].loadX(ta, lastValidArgLoadX + 1), RangeError);
+        C.load1(0);
+        C.load1(1);
+        C.load1(2);
+        C.load1(3);
+        C.load1(lastValidArgLoad1);
+        assertThrowsInstanceOf(() => SIMD[kind].load1(ta, lastValidArgLoad1 + 1), RangeError);
 
-        C.loadXY(0);
-        C.loadXY(1);
-        C.loadXY(2);
-        C.loadXY(3);
-        C.loadXY(lastValidArgLoadXY);
+        C.load2(0);
+        C.load2(1);
+        C.load2(2);
+        C.load2(3);
+        C.load2(lastValidArgLoad2);
 
-        C.loadXYZ(0);
-        C.loadXYZ(1);
-        C.loadXYZ(2);
-        C.loadXYZ(3);
-        C.loadXYZ(lastValidArgLoadXYZ);
+        C.load3(0);
+        C.load3(1);
+        C.load3(2);
+        C.load3(3);
+        C.load3(lastValidArgLoad3);
 
         if (lanes >= 4) {
-            assertThrowsInstanceOf(() => SIMD[kind].loadXY(ta, lastValidArgLoadXY + 1), RangeError);
-            assertThrowsInstanceOf(() => SIMD[kind].loadXYZ(ta, lastValidArgLoadXYZ + 1), RangeError);
+            assertThrowsInstanceOf(() => SIMD[kind].load2(ta, lastValidArgLoad2 + 1), RangeError);
+            assertThrowsInstanceOf(() => SIMD[kind].load3(ta, lastValidArgLoad3 + 1), RangeError);
         }
     }
 
     if (lanes == 4) {
         // Test ToInt32 behavior
         var v = SIMD[kind].load(TA, 12.5);
         assertEqX4(v, [12, 13, 14, 15]);
 
@@ -186,24 +186,24 @@ function testSharedArrayBufferCompat() {
                     new SharedInt32Array(TA.buffer),
                     new SharedFloat32Array(TA.buffer),
                     new SharedFloat64Array(TA.buffer)
                    ])
     {
         for (var kind of ['int32x4', 'float32x4', 'float64x2']) {
             var comp = MakeComparator(kind, ta);
             comp.load(0);
-            comp.loadX(0);
-            comp.loadXY(0);
-            comp.loadXYZ(0);
+            comp.load1(0);
+            comp.load2(0);
+            comp.load3(0);
 
             comp.load(3);
-            comp.loadX(3);
-            comp.loadXY(3);
-            comp.loadXYZ(3);
+            comp.load1(3);
+            comp.load2(3);
+            comp.load3(3);
         }
 
         assertThrowsInstanceOf(() => SIMD.int32x4.load(ta, 1024), RangeError);
         assertThrowsInstanceOf(() => SIMD.float32x4.load(ta, 1024), RangeError);
         assertThrowsInstanceOf(() => SIMD.float64x2.load(ta, 1024), RangeError);
     }
 }
 
--- a/js/src/tests/ecma_7/SIMD/store.js
+++ b/js/src/tests/ecma_7/SIMD/store.js
@@ -23,30 +23,30 @@ function assertChanged(ta, from, expecte
     for (; i < from + expected.length; i++)
         assertEq(ta[i], expected[i - from]);
     for (; i < ta.length; i++)
         assertEq(ta[i], POISON + i);
 }
 
 function testStore(ta, kind, i, v) {
     reset(ta);
-    SIMD[kind].storeX(ta, i, v);
+    SIMD[kind].store1(ta, i, v);
     assertChanged(ta, i, [v.x]);
 
     reset(ta);
     SIMD[kind].store(ta, i, v);
     assertChanged(ta, i, simdToArray(v));
 
     if (simdLength(v) > 2) {
         reset(ta);
-        SIMD[kind].storeXY(ta, i, v);
+        SIMD[kind].store2(ta, i, v);
         assertChanged(ta, i, [v.x, v.y]);
 
         reset(ta);
-        SIMD[kind].storeXYZ(ta, i, v);
+        SIMD[kind].store3(ta, i, v);
         assertChanged(ta, i, [v.x, v.y, v.z]);
     }
 }
 
 function testStoreInt32x4() {
     var I32 = new Int32Array(16);
 
     var v = SIMD.int32x4(0, 1, Math.pow(2,31) - 1, -Math.pow(2, 31));
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5996,17 +5996,17 @@ DebuggerFrame_getArguments(JSContext* cx
         {
             return false;
         }
 
         Rooted<jsid> id(cx);
         for (unsigned i = 0; i < fargc; i++) {
             RootedFunction getobj(cx);
             getobj = NewNativeFunction(cx, DebuggerArguments_getArg, 0, js::NullPtr(),
-                                       JSFunction::ExtendedFinalizeKind);
+                                       gc::AllocKind::FUNCTION_EXTENDED);
             if (!getobj)
                 return false;
             id = INT_TO_JSID(i);
             if (!getobj ||
                 !NativeDefineProperty(cx, argsobj, id, UndefinedHandleValue,
                                       JS_DATA_TO_FUNC_PTR(GetterOp, getobj.get()), nullptr,
                                       JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_GETTER))
             {
--- a/js/src/vm/GlobalObject.cpp
+++ b/js/src/vm/GlobalObject.cpp
@@ -602,17 +602,17 @@ GlobalObject::getSelfHostedFunction(JSCo
     RootedId shId(cx, AtomToId(selfHostedName));
     RootedObject holder(cx, cx->global()->intrinsicsHolder());
 
     if (cx->global()->maybeGetIntrinsicValue(shId, funVal.address()))
         return true;
 
     JSFunction* fun =
         NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY,
-                            name, JSFunction::ExtendedFinalizeKind, SingletonObject);
+                            name, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
     if (!fun)
         return false;
     fun->setIsSelfHostedBuiltin();
     fun->setExtendedSlot(0, StringValue(selfHostedName));
     funVal.setObject(*fun);
 
     return cx->global()->addIntrinsicValue(cx, shId, funVal);
 }
--- a/js/src/vm/GlobalObject.h
+++ b/js/src/vm/GlobalObject.h
@@ -294,17 +294,17 @@ class GlobalObject : public NativeObject
          JS::OnNewGlobalHookOption hookOption, const JS::CompartmentOptions& options);
 
     /*
      * Create a constructor function with the specified name and length using
      * ctor, a method which creates objects with the given class.
      */
     JSFunction*
     createConstructor(JSContext* cx, JSNative ctor, JSAtom* name, unsigned length,
-                      gc::AllocKind kind = JSFunction::FinalizeKind);
+                      gc::AllocKind kind = gc::AllocKind::FUNCTION);
 
     /*
      * Create an object to serve as [[Prototype]] for instances of the given
      * class, using |Object.prototype| as its [[Prototype]].  Users creating
      * prototype objects with particular internal structure (e.g. reserved
      * slots guaranteed to contain values of particular types) must immediately
      * complete the minimal initialization to make the returned object safe to
      * touch.
--- a/js/src/vm/RegExpObject.cpp
+++ b/js/src/vm/RegExpObject.cpp
@@ -274,17 +274,17 @@ const Class RegExpObject::class_ = {
     nullptr, /* finalize */
     nullptr, /* call */
     nullptr, /* hasInstance */
     nullptr, /* construct */
     RegExpObject::trace,
 
     // ClassSpec
     {
-        GenericCreateConstructor<js::regexp_construct, 2, JSFunction::FinalizeKind>,
+        GenericCreateConstructor<js::regexp_construct, 2, gc::AllocKind::FUNCTION>,
         CreateRegExpPrototype,
         nullptr,
         js::regexp_static_props,
         js::regexp_methods,
         js::regexp_properties
     }
 };
 
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -191,17 +191,17 @@ SavedFrame::finishSavedFrameInit(JSConte
     SavedFrame::finalize,       // finalize
     nullptr,                    // call
     nullptr,                    // hasInstance
     nullptr,                    // construct
     nullptr,                    // trace
 
     // ClassSpec
     {
-        GenericCreateConstructor<SavedFrame::construct, 0, JSFunction::FinalizeKind>,
+        GenericCreateConstructor<SavedFrame::construct, 0, gc::AllocKind::FUNCTION>,
         GenericCreatePrototype,
         SavedFrame::staticFunctions,
         nullptr,
         SavedFrame::protoFunctions,
         SavedFrame::protoAccessors,
         SavedFrame::finishSavedFrameInit,
         ClassSpec::DontDefineConstructor
     }
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -1776,17 +1776,17 @@ CloneObject(JSContext* cx, HandleNativeO
 
     RootedObject clone(cx);
     if (selfHostedObject->is<JSFunction>()) {
         RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>());
         bool hasName = selfHostedFunction->atom() != nullptr;
         // Arrow functions use the first extended slot for their lexical |this| value.
         MOZ_ASSERT(!selfHostedFunction->isArrow());
         js::gc::AllocKind kind = hasName
-                                 ? JSFunction::ExtendedFinalizeKind
+                                 ? gc::AllocKind::FUNCTION_EXTENDED
                                  : selfHostedFunction->getAllocKind();
         clone = CloneFunctionObject(cx, selfHostedFunction, cx->global(), kind, TenuredObject);
         // To be able to re-lazify the cloned function, its name in the
         // self-hosting compartment has to be stored on the clone.
         if (clone && hasName)
             clone->as<JSFunction>().setExtendedSlot(0, StringValue(selfHostedFunction->atom()));
     } else if (selfHostedObject->is<RegExpObject>()) {
         RegExpObject& reobj = selfHostedObject->as<RegExpObject>();
--- a/js/src/vm/SharedTypedArrayObject.cpp
+++ b/js/src/vm/SharedTypedArrayObject.cpp
@@ -685,17 +685,17 @@ IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPP
 IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPPERS(Int32, int32_t, int32_t)
 IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPPERS(Uint32, uint32_t, uint32_t)
 IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float32, float, float)
 IMPL_SHARED_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
 
 #define SHARED_TYPED_ARRAY_CLASS_SPEC(_typedArray)                             \
 {                                                                              \
     GenericCreateConstructor<Shared##_typedArray##Object::class_constructor, 3, \
-                             JSFunction::FinalizeKind>,                        \
+                             gc::AllocKind::FUNCTION>,                         \
     Shared##_typedArray##Object::CreatePrototype,                              \
     nullptr,                                                                   \
     nullptr,                                                                   \
     Shared##_typedArray##Object::jsfuncs,                                      \
     Shared##_typedArray##Object::jsprops,                                      \
     Shared##_typedArray##Object::FinishClassInit                               \
 }
 
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -625,23 +625,16 @@ js::ConcatStrings<CanGC>(ExclusiveContex
 
 template JSString*
 js::ConcatStrings<NoGC>(ExclusiveContext* cx, JSString* left, JSString* right);
 
 template <typename CharT>
 JSFlatString*
 JSDependentString::undependInternal(ExclusiveContext* cx)
 {
-    /*
-     * We destroy the base() pointer in undepend, so we need a pre-barrier. We
-     * don't need a post-barrier because there aren't any outgoing pointers
-     * afterwards.
-     */
-    JSString::writeBarrierPre(base());
-
     size_t n = length();
     CharT* s = cx->pod_malloc<CharT>(n + 1);
     if (!s)
         return nullptr;
 
     AutoCheckCannotGC nogc;
     PodCopy(s, nonInlineChars<CharT>(nogc), n);
     s[n] = '\0';
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -230,17 +230,17 @@ class TypedArrayObjectTemplate : public 
         Handle<GlobalObject*> global = cx->global();
         RootedFunction ctorProto(cx, GlobalObject::getOrCreateTypedArrayConstructor(cx, global));
         if (!ctorProto)
             return nullptr;
 
         return NewFunctionWithProto(cx, class_constructor, 3,
                                     JSFunction::NATIVE_CTOR, NullPtr(),
                                     ClassName(key, cx),
-                                    ctorProto, JSFunction::FinalizeKind,
+                                    ctorProto, gc::AllocKind::FUNCTION,
                                     SingletonObject);
     }
 
     static bool
     finishClassInit(JSContext* cx, HandleObject ctor, HandleObject proto)
     {
         RootedValue bytesValue(cx, Int32Value(BYTES_PER_ELEMENT));
         if (!DefineProperty(cx, ctor, cx->names().BYTES_PER_ELEMENT, bytesValue,
@@ -842,17 +842,17 @@ TypedArrayObject::sharedTypedArrayProtot
     nullptr,                /* mayResolve */
     nullptr,                /* convert */
     nullptr,                /* finalize */
     nullptr,                /* call */
     nullptr,                /* hasInstance */
     nullptr,                /* construct */
     nullptr,                /* trace */
     {
-        GenericCreateConstructor<TypedArrayConstructor, 3, JSFunction::FinalizeKind>,
+        GenericCreateConstructor<TypedArrayConstructor, 3, gc::AllocKind::FUNCTION>,
         GenericCreatePrototype,
         TypedArrayObject::staticFunctions,
         nullptr,
         TypedArrayObject::protoFunctions,
         TypedArrayObject::protoAccessors,
         FinishTypedArrayInit,
         ClassSpec::DontDefineConstructor
     }
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -4480,17 +4480,19 @@ ChooseScaleAndSetTransform(FrameLayerBui
   gfxSize scale;
   // XXX Should we do something for 3D transforms?
   if (canDraw2D) {
     // If the container's transform is animated off main thread, fix a suitable scale size
     // for animation
     if (aContainerFrame->GetContent() &&
         nsLayoutUtils::HasAnimationsForCompositor(
           aContainerFrame->GetContent(), eCSSProperty_transform)) {
-      scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(aContainerFrame->GetContent());
+      scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
+                aContainerFrame->GetContent(), aVisibleRect.Size(),
+                aContainerFrame->PresContext()->GetVisibleArea().Size());
     } else {
       // Scale factors are normalized to a power of 2 to reduce the number of resolution changes
       scale = RoundToFloatPrecision(ThebesMatrix(transform2d).ScaleFactors(true));
       // For frames with a changing transform that's not just a translation,
       // round scale factors up to nearest power-of-2 boundary so that we don't
       // keep having to redraw the content as it scales up and down. Rounding up to nearest
       // power-of-2 boundary ensures we never scale up, only down --- avoiding
       // jaggies. It also ensures we never scale down by more than a factor of 2,
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -476,28 +476,26 @@ GetScaleForValue(const StyleAnimationVal
   if (!canDraw2D) {
     return gfxSize();
   }
 
   return transform2d.ScaleFactors(true);
 }
 
 static float
-GetSuitableScale(float aMaxScale, float aMinScale)
-{
-  // If the minimum scale >= 1.0f, use it; if the maximum <= 1.0f, use it;
-  // otherwise use 1.0f.
-  if (aMinScale >= 1.0f) {
-    return aMinScale;
-  }
-  else if (aMaxScale <= 1.0f) {
-    return aMaxScale;
-  }
-
-  return 1.0f;
+GetSuitableScale(float aMaxScale, float aMinScale,
+                 nscoord aVisibleDimension, nscoord aDisplayDimension)
+{
+  float displayVisibleRatio = float(aDisplayDimension) /
+                              float(aVisibleDimension);
+  // We want to rasterize based on the largest scale used during the
+  // transform animation, unless that would make us rasterize something
+  // larger than the screen.  But we never want to go smaller than the
+  // minimum scale over the animation.
+  return std::max(std::min(aMaxScale, displayVisibleRatio), aMinScale);
 }
 
 static void
 GetMinAndMaxScaleForAnimationProperty(nsIContent* aContent,
                                       AnimationCollection* aAnimations,
                                       gfxSize& aMaxScale,
                                       gfxSize& aMinScale)
 {
@@ -526,17 +524,19 @@ GetMinAndMaxScaleForAnimationProperty(ns
           aMinScale.height = std::min<float>(aMinScale.height, to.height);
         }
       }
     }
   }
 }
 
 gfxSize
-nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent)
+nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent,
+                                                const nsSize& aVisibleSize,
+                                                const nsSize& aDisplaySize)
 {
   gfxSize maxScale(std::numeric_limits<gfxFloat>::min(),
                    std::numeric_limits<gfxFloat>::min());
   gfxSize minScale(std::numeric_limits<gfxFloat>::max(),
                    std::numeric_limits<gfxFloat>::max());
 
   AnimationCollection* animations =
     nsAnimationManager::GetAnimationsForCompositor(aContent,
@@ -551,21 +551,23 @@ nsLayoutUtils::ComputeSuitableScaleForAn
                                                     eCSSProperty_transform);
   if (animations) {
     GetMinAndMaxScaleForAnimationProperty(aContent, animations,
                                           maxScale, minScale);
   }
 
   if (maxScale.width == std::numeric_limits<gfxFloat>::min()) {
     // We didn't encounter a transform
-    maxScale = minScale = gfxSize(1.0, 1.0);
-  }
-
-  return gfxSize(GetSuitableScale(maxScale.width, minScale.width),
-                 GetSuitableScale(maxScale.height, minScale.height));
+    return gfxSize(1.0, 1.0);
+  }
+
+  return gfxSize(GetSuitableScale(maxScale.width, minScale.width,
+                                  aVisibleSize.width, aDisplaySize.width),
+                 GetSuitableScale(maxScale.height, minScale.height,
+                                  aVisibleSize.height, aDisplaySize.height));
 }
 
 bool
 nsLayoutUtils::AreAsyncAnimationsEnabled()
 {
   static bool sAreAsyncAnimationsEnabled;
   static bool sAsyncPrefCached = false;
 
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -2142,23 +2142,28 @@ public:
 
   /**
    * Checks if we should warn about animations that can't be async
    */
   static bool IsAnimationLoggingEnabled();
 
   /**
    * Find a suitable scale for an element (aContent) over the course of any
-   * animations and transitions on the element.
+   * animations and transitions of the CSS transform property on the
+   * element that run on the compositor thread.
    * It will check the maximum and minimum scale during the animations and
    * transitions and return a suitable value for performance and quality.
-   * Will return scale(1,1) if there is no animated scaling.
-   * Always return positive value.
+   * Will return scale(1,1) if there are no such animations.
+   * Always returns a positive value.
+   * @param aVisibleSize is the size of the area we want to paint
+   * @param aDisplaySize is the size of the display area of the pres context
    */
-  static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent);
+  static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent,
+                                                  const nsSize& aVisibleSize,
+                                                  const nsSize& aDisplaySize);
 
   /**
    * Checks if we should forcibly use nearest pixel filtering for the
    * background.
    */
   static bool UseBackgroundNearestFiltering();
 
   /**
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -95,47 +95,37 @@ using namespace mozilla::layers;
 
 // static icon information
 nsImageFrame::IconLoad* nsImageFrame::gIconLoad = nullptr;
 
 // cached IO service for loading icons
 nsIIOService* nsImageFrame::sIOService;
 
 // test if the width and height are fixed, looking at the style data
-static bool HaveFixedSize(const nsStylePosition* aStylePosition)
+// This is used by nsImageFrame::ShouldCreateImageFrameFor and should
+// not be used for layout decisions.
+static bool HaveSpecifiedSize(const nsStylePosition* aStylePosition)
 {
   // check the width and height values in the reflow state's style struct
   // - if width and height are specified as either coord or percentage, then
   //   the size of the image frame is constrained
   return aStylePosition->mWidth.IsCoordPercentCalcUnit() &&
          aStylePosition->mHeight.IsCoordPercentCalcUnit();
 }
 
-// use the data in the reflow state to decide if the image has a constrained size
-// (i.e. width and height that are based on the containing block size and not the image size)
-// so we can avoid animated GIF related reflows
+// Decide whether we can optimize away reflows that result from the
+// image's intrinsic size changing.
 inline bool HaveFixedSize(const nsHTMLReflowState& aReflowState)
 {
   NS_ASSERTION(aReflowState.mStylePosition, "crappy reflowState - null stylePosition");
-  // when an image has percent css style height or width, but ComputedHeight()
-  // or ComputedWidth() of reflow state is  NS_UNCONSTRAINEDSIZE
-  // it needs to return false to cause an incremental reflow later
-  // if an image is inside table like bug 156731 simple testcase III,
-  // during pass 1 reflow, ComputedWidth() is NS_UNCONSTRAINEDSIZE
-  // in pass 2 reflow, ComputedWidth() is 0, it also needs to return false
-  // see bug 156731
-  const nsStyleCoord &height = aReflowState.mStylePosition->mHeight;
-  const nsStyleCoord &width = aReflowState.mStylePosition->mWidth;
-  return ((height.HasPercent() &&
-           NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight()) ||
-          (width.HasPercent() &&
-           (NS_UNCONSTRAINEDSIZE == aReflowState.ComputedWidth() ||
-            0 == aReflowState.ComputedWidth())))
-          ? false
-          : HaveFixedSize(aReflowState.mStylePosition);
+  // Don't try to make this optimization when an image has percentages
+  // in its 'width' or 'height'.  The percentages might be treated like
+  // auto (especially for intrinsic width calculations and for heights).
+  return aReflowState.mStylePosition->mHeight.ConvertsToLength() &&
+         aReflowState.mStylePosition->mWidth.ConvertsToLength();
 }
 
 nsIFrame*
 NS_NewImageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsImageFrame(aContext);
 }
 
@@ -446,17 +436,17 @@ nsImageFrame::SourceRectToDest(const nsI
 
 /* static */
 bool
 nsImageFrame::ShouldCreateImageFrameFor(Element* aElement,
                                         nsStyleContext* aStyleContext)
 {
   EventStates state = aElement->State();
   if (IMAGE_OK(state,
-               HaveFixedSize(aStyleContext->StylePosition()))) {
+               HaveSpecifiedSize(aStyleContext->StylePosition()))) {
     // Image is fine; do the image frame thing
     return true;
   }
 
   // Check if we want to use a placeholder box with an icon or just
   // let the presShell make us into inline text.  Decide as follows:
   //
   //  - if our special "force icons" style is set, show an icon
@@ -484,18 +474,18 @@ nsImageFrame::ShouldCreateImageFrameFor(
     // text).
     useSizedBox = true;
   }
   else if (aStyleContext->PresContext()->CompatibilityMode() !=
            eCompatibility_NavQuirks) {
     useSizedBox = false;
   }
   else {
-    // check whether we have fixed size
-    useSizedBox = HaveFixedSize(aStyleContext->StylePosition());
+    // check whether we have specified size
+    useSizedBox = HaveSpecifiedSize(aStyleContext->StylePosition());
   }
 
   return useSizedBox;
 }
 
 nsresult
 nsImageFrame::Notify(imgIRequest* aRequest,
                      int32_t aType,
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..85d980424c5791bfefe08d3b89b163070f26bc80
GIT binary patch
literal 219
zc%17D@N?(olHy`uVBq!ia0vp^DL`z*!2~2#!(YAxQk(@Ik;M!Q+`=Ht$S`Y;1W=H@
z#M9T6{XQ!zhb-HPd5=4RLXst}5hc#~xw)x%B@E6*sfi`2DGKG8B^e6tp1uL$jeO!j
zMWLQ9jv*QM-d<qjWnkbryx^Dl-{=_(LLvdO#;luCPEJzgCY{>Mex<H-8jorJ6rcqR
Mp00i_>zopr0J4-n_5c6?
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..d09f03b25f5d955ffa5bcbf8955637a5e1dc90af
GIT binary patch
literal 220
zc%17D@N?(olHy`uVBq!ia0vp^MnIgx!2~3|yT0%MDb50q$YKTtZeb8+WSBKa0w~B{
z;_2(kexH?<L&h-EqWm~eNV3E=qQp5rH#aq}gu%HeHL)Z$MWH;iBtya7(>EZzkxv|`
zD9qEvF(l*O+jES(3=AC13-;G%tbM4avf$*Cd0Clcg1_0iCCgG6b&gH$1KPmg>FVdQ
I&MBb@020_kN&o-=
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..bdb91e34c89484610a5a057065a9e5768e675f78
GIT binary patch
literal 191
zc%17D@N?(olHy`uVBq!ia0vp^Mj*_=1SBWM%0B~AoCO|{#S9GG!XV7ZFl&wkP>{XE
z)7O>#J}WDSjMUMVzILFHWQl7;iF1B#Zfaf$gL6@8Vo7R>LV0FMhJw4NZ$Nk>pEyvF
zrKgKyNW|f{=NNez7&w?0?61#QyHHwX!O17{vNCalzgfBmMU5E6pTw2|4Po$f^>bP0
Hl+XkK<LNeO
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-resize-percent-height.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<script>
+function run() {
+  var img = document.getElementsByTagName("img")[0];
+  img.offsetWidth; // flush layout
+  img.onload = imgload;
+  img.src = "blue-50x50.png";
+}
+function imgload() {
+  document.documentElement.classList.remove("reftest-wait");
+}
+</script>
+<body onload="run()">
+<div><img src="blue-50x100.png" style="width: 50px; height: 100%"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-resize-percent-width.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<script>
+function run() {
+  var img = document.getElementsByTagName("img")[0];
+  img.offsetWidth; // flush layout
+  img.onload = imgload;
+  img.src = "blue-50x50.png";
+}
+function imgload() {
+  document.documentElement.classList.remove("reftest-wait");
+}
+</script>
+<body onload="run()">
+<div style="width: -moz-max-content"><img src="blue-100x50.png" style="width: 100%; height: 50px"></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/image/image-resize-ref.html
@@ -0,0 +1,3 @@
+<!DOCTYPE HTML>
+<body>
+<div><img src="blue-50x50.png"></div>
--- a/layout/reftests/image/reftest.list
+++ b/layout/reftests/image/reftest.list
@@ -118,8 +118,11 @@ pref(dom.image.srcset.enabled,true) == i
 pref(dom.image.srcset.enabled,true) == image-srcset-default-src-1x.html image-srcset-default-src-1x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-orientation-2x.html image-srcset-orientation-2x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-orientation-1x.html image-srcset-orientation-1x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-svg-3x.html image-srcset-svg-3x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-svg-2x.html image-srcset-svg-2x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-svg-1x.html image-srcset-svg-1x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-svg-default-2x.html image-srcset-svg-default-2x-ref.html
 pref(dom.image.srcset.enabled,true) == image-srcset-svg-default-1x.html image-srcset-svg-default-1x-ref.html
+
+== image-resize-percent-height.html image-resize-ref.html
+== image-resize-percent-width.html image-resize-ref.html
--- a/mfbt/SplayTree.h
+++ b/mfbt/SplayTree.h
@@ -8,16 +8,17 @@
  * A sorted tree with optimal access times, where recently-accessed elements
  * are faster to access again.
  */
 
 #ifndef mozilla_SplayTree_h
 #define mozilla_SplayTree_h
 
 #include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
 
 namespace mozilla {
 
 template<class T, class C>
 class SplayTree;
 
 template<typename T>
 class SplayTreeNode
@@ -50,17 +51,17 @@ private:
  * method must be free from side effects.
  */
 template<typename T, class Comparator>
 class SplayTree
 {
   T* mRoot;
 
 public:
-  SplayTree()
+  MOZ_CONSTEXPR SplayTree()
     : mRoot(nullptr)
   {}
 
   bool empty() const
   {
     return !mRoot;
   }
 
@@ -81,25 +82,22 @@ public:
 
     if (!mRoot) {
       mRoot = aValue;
       return true;
     }
     T* last = lookup(*aValue);
     int cmp = Comparator::compare(*aValue, *last);
 
-    T** parentPointer = (cmp < 0) ? &last->mLeft : &last->mRight;
-    MOZ_ASSERT(!*parentPointer);
-    *parentPointer = aValue;
-    aValue->mParent = last;
-
-    splay(aValue);
+    finishInsertion(last, cmp, aValue);
     return true;
   }
 
+  T* findOrInsert(const T& aValue);
+
   T* remove(const T& aValue)
   {
     T* last = lookup(aValue);
     MOZ_ASSERT(last, "This tree must contain the element being removed.");
     MOZ_ASSERT(Comparator::compare(aValue, *last) == 0);
 
     // Splay the tree so that the item to remove is the root.
     splay(last);
@@ -191,16 +189,29 @@ private:
         node = node->mLeft;
       } else {
         node = node->mRight;
       }
     } while (node);
     return parent;
   }
 
+  T* finishInsertion(T* aLast, int32_t aCmp, T* aNew)
+  {
+    MOZ_ASSERT(aCmp, "Nodes shouldn't be equal!");
+
+    T** parentPointer = (aCmp < 0) ? &aLast->mLeft : &aLast->mRight;
+    MOZ_ASSERT(!*parentPointer);
+    *parentPointer = aNew;
+    aNew->mParent = aLast;
+
+    splay(aNew);
+    return aNew;
+  }
+
   /**
    * Rotate the tree until |node| is at the root of the tree. Performing
    * the rotations in this fashion preserves the amortized balancing of
    * the tree.
    */
   void splay(T* aNode)
   {
     MOZ_ASSERT(aNode);
@@ -290,11 +301,29 @@ private:
     }
     return aNode;
   }
 
   SplayTree(const SplayTree&) = delete;
   void operator=(const SplayTree&) = delete;
 };
 
+template<typename T, class Comparator>
+T*
+SplayTree<T, Comparator>::findOrInsert(const T& aValue)
+{
+  if (!mRoot) {
+    mRoot = new T(aValue);
+    return mRoot;
+  }
+
+  T* last = lookup(aValue);
+  int cmp = Comparator::compare(aValue, *last);
+  if (!cmp) {
+    return last;
+  }
+
+  return finishInsertion(last, cmp, new T(aValue));
+}
+
 }  /* namespace mozilla */
 
 #endif /* mozilla_SplayTree_h */
--- a/mfbt/tests/TestSplayTree.cpp
+++ b/mfbt/tests/TestSplayTree.cpp
@@ -100,37 +100,81 @@ struct SplayInt : SplayTreeNode<SplayInt
       return 1;
     }
     return 0;
   }
 
   int mValue;
 };
 
+struct SplayNoCopy : SplayTreeNode<SplayNoCopy>
+{
+  SplayNoCopy(const SplayNoCopy&) = delete;
+  SplayNoCopy(SplayNoCopy&&) = delete;
+
+  static int compare(const SplayNoCopy&, const SplayNoCopy&) { return 0; }
+};
+
+static SplayTree<SplayNoCopy, SplayNoCopy> testNoCopy;
+
 int
 main()
 {
   SplayTree<SplayInt, SplayInt> tree;
 
   MOZ_RELEASE_ASSERT(tree.empty());
 
   MOZ_RELEASE_ASSERT(!tree.find(SplayInt(0)));
 
   static const int N = mozilla::ArrayLength(gValues);
 
   // Insert the values, and check each one is findable just after insertion.
   for (int i = 0; i < N; i++) {
     tree.insert(new SplayInt(gValues[i]));
-    MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
+    SplayInt* inserted = tree.find(SplayInt(gValues[i]));
+    MOZ_RELEASE_ASSERT(inserted);
+    MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])) == inserted);
     tree.checkCoherency();
   }
 
   // Check they're all findable after all insertions.
   for (int i = 0; i < N; i++) {
     MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
+    MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])));
+    tree.checkCoherency();
+  }
+
+  // Check that non-inserted values cannot be found.
+  MOZ_RELEASE_ASSERT(!tree.find(SplayInt(-1)));
+  MOZ_RELEASE_ASSERT(!tree.find(SplayInt(N)));
+  MOZ_RELEASE_ASSERT(!tree.find(SplayInt(0x7fffffff)));
+
+  // Remove the values, and check each one is not findable just after removal.
+  for (int i = 0; i < N; i++) {
+    SplayInt* removed = tree.remove(SplayInt(gValues[i]));
+    MOZ_RELEASE_ASSERT(removed->mValue == gValues[i]);
+    MOZ_RELEASE_ASSERT(!tree.find(*removed));
+    delete removed;
+    tree.checkCoherency();
+  }
+
+  MOZ_RELEASE_ASSERT(tree.empty());
+
+  // Insert the values, and check each one is findable just after insertion.
+  for (int i = 0; i < N; i++) {
+    SplayInt* inserted = tree.findOrInsert(SplayInt(gValues[i]));
+    MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])) == inserted);
+    MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])) == inserted);
+    tree.checkCoherency();
+  }
+
+  // Check they're all findable after all insertions.
+  for (int i = 0; i < N; i++) {
+    MOZ_RELEASE_ASSERT(tree.find(SplayInt(gValues[i])));
+    MOZ_RELEASE_ASSERT(tree.findOrInsert(SplayInt(gValues[i])));
     tree.checkCoherency();
   }
 
   // Check that non-inserted values cannot be found.
   MOZ_RELEASE_ASSERT(!tree.find(SplayInt(-1)));
   MOZ_RELEASE_ASSERT(!tree.find(SplayInt(N)));
   MOZ_RELEASE_ASSERT(!tree.find(SplayInt(0x7fffffff)));
 
--- a/netwerk/dns/effective_tld_names.dat
+++ b/netwerk/dns/effective_tld_names.dat
@@ -821,16 +821,17 @@ edu.es
 et
 com.et
 gov.et
 org.et
 edu.et
 biz.et
 name.et
 info.et
+net.et
 
 // eu : http://en.wikipedia.org/wiki/.eu
 eu
 
 // fi : http://en.wikipedia.org/wiki/.fi
 fi
 // aland.fi : http://en.wikipedia.org/wiki/.ax
 // This domain is being phased out in favor of .ax. As there are still many
@@ -3571,16 +3572,17 @@ org.lk
 edu.lk
 ngo.lk
 soc.lk
 web.lk
 ltd.lk
 assn.lk
 grp.lk
 hotel.lk
+ac.lk
 
 // lr : http://psg.com/dns/lr/lr.txt
 // Submitted by registry <randy@psg.com> 2008-06-17
 lr
 com.lr
 edu.lr
 gov.lr
 org.lr
@@ -6659,189 +6661,220 @@ net.ws
 org.ws
 gov.ws
 edu.ws
 
 // yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
 yt
 
 // IDN ccTLDs
-// Please sort by ISO 3166 ccTLD, then punicode string
-// when submitting patches and follow this format:
-// <Punicode> ("<english word>" <language>) : <ISO 3166 ccTLD>
-// [optional sponsoring org]
-// <URL>
-
-// xn--mgbaam7a8h ("Emerat" Arabic) : AE
+// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then
+// U-label, and follow this format:
+// // A-Label ("<Latin renderings>", <language name>[, variant info]) : <ISO 3166 ccTLD>
+// // [sponsoring org]
+// U-Label
+
+// xn--mgbaam7a8h ("Emerat", Arabic) : AE
 // http://nic.ae/english/arabicdomain/rules.jsp
 امارات
 
-// xn--54b7fta0cc ("Bangla" Bangla) : BD
+// xn--y9a3aq ("hye", Armenian) : AM
+// ISOC AM (operated by .am Registry)
+հայ
+
+// xn--54b7fta0cc ("Bangla", Bangla) : BD
 বাংলা
 
-// xn--fiqs8s ("China" Chinese-Han-Simplified <.Zhongguo>) : CN
+// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY
+// Operated by .by registry
+бел
+
+// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN
 // CNNIC
 // http://cnnic.cn/html/Dir/2005/10/11/3218.htm
 中国
 
-// xn--fiqz9s ("China" Chinese-Han-Traditional <.Zhongguo>) : CN
+// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN
 // CNNIC
 // http://cnnic.cn/html/Dir/2005/10/11/3218.htm
 中國
 
-// xn--lgbbat1ad8j ("Algeria / Al Jazair" Arabic) : DZ
+// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ
 الجزائر
 
-// xn--wgbh1c ("Egypt" Arabic .masr) : EG
+// xn--wgbh1c ("Egypt/Masr", Arabic) : EG
 // http://www.dotmasr.eg/
 مصر
 
-// xn--node ("ge" Georgian (Mkhedruli)) : GE
+// xn--node ("ge", Georgian Mkhedruli) : GE
 გე
 
-// xn--j6w193g ("Hong Kong" Chinese-Han) : HK
+// xn--qxam ("el", Greek) : GR
+// Hellenic Ministry of Infrastructure, Transport, and Networks
+ελ
+
+// xn--j6w193g ("Hong Kong", Chinese) : HK
 // https://www2.hkirc.hk/register/rules.jsp
 香港
 
-// xn--h2brj9c ("Bharat" Devanagari) : IN
+// xn--h2brj9c ("Bharat", Devanagari) : IN
 // India
 भारत
 
-// xn--mgbbh1a71e ("Bharat" Arabic) : IN
+// xn--mgbbh1a71e ("Bharat", Arabic) : IN
 // India
 بھارت
 
-// xn--fpcrj9c3d ("Bharat" Telugu) : IN
+// xn--fpcrj9c3d ("Bharat", Telugu) : IN
 // India
 భారత్
 
-// xn--gecrj9c ("Bharat" Gujarati) : IN
+// xn--gecrj9c ("Bharat", Gujarati) : IN
 // India
 ભારત
 
-// xn--s9brj9c ("Bharat" Gurmukhi) : IN
+// xn--s9brj9c ("Bharat", Gurmukhi) : IN
 // India
 ਭਾਰਤ
 
-// xn--45brj9c ("Bharat" Bengali) : IN
+// xn--45brj9c ("Bharat", Bengali) : IN
 // India
 ভারত
 
-// xn--xkc2dl3a5ee0h ("India" Tamil) : IN
+// xn--xkc2dl3a5ee0h ("India", Tamil) : IN
 // India
 இந்தியா
 
-// xn--mgba3a4f16a ("Iran" Persian) : IR
+// xn--mgba3a4f16a ("Iran", Persian) : IR
 ایران
 
-// xn--mgba3a4fra ("Iran" Arabic) : IR
+// xn--mgba3a4fra ("Iran", Arabic) : IR
 ايران
 
-// xn--mgbayh7gpa ("al-Ordon" Arabic) : JO
+// xn--mgbtx2b ("Iraq", Arabic) : IQ
+// Communications and Media Commission
+عراق
+
+// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO
 // National Information Technology Center (NITC)
 // Royal Scientific Society, Al-Jubeiha
 الاردن
 
-// xn--3e0b707e ("Republic of Korea" Hangul) : KR
+// xn--3e0b707e ("Republic of Korea", Hangul) : KR
 한국
 
-// xn--80ao21a ("Kaz" Kazakh) : KZ
+// xn--80ao21a ("Kaz", Kazakh) : KZ
 қаз
 
-// xn--fzc2c9e2c ("Lanka" Sinhalese-Sinhala) : LK
+// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK
 // http://nic.lk
 ලංකා
 
-// xn--xkc2al3hye2a ("Ilangai" Tamil) : LK
+// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK
 // http://nic.lk
 இலங்கை
 
-// xn--mgbc0a9azcg ("Morocco / al-Maghrib" Arabic) : MA
+// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA
 المغرب
 
-// xn--l1acc ("mon" Mongolian) : MN
+// xn--d1alf ("mkd", Macedonian) : MK
+// MARnet
+мкд
+
+// xn--l1acc ("mon", Mongolian) : MN
 мон
 
-// xn--mgbx4cd0ab ("Malaysia" Malay) : MY
+// xn--mix891f ("Macao", Chinese, Traditional) : MO
+// MONIC / HNET Asia (Registry Operator for .mo)
+澳門
+
+// xn--mix082f ("Macao", Chinese, Simplified) : MO
+澳门
+
+// xn--mgbx4cd0ab ("Malaysia", Malay) : MY
 مليسيا
 
-// xn--mgb9awbf ("Oman" Arabic) : OM
+// xn--mgb9awbf ("Oman", Arabic) : OM
 عمان
 
-// xn--ygbi2ammx ("Falasteen" Arabic) : PS
+// xn--ygbi2ammx ("Falasteen", Arabic) : PS
 // The Palestinian National Internet Naming Authority (PNINA)
 // http://www.pnina.ps
 فلسطين
 
-// xn--90a3ac ("srb" Cyrillic) : RS
+// xn--90a3ac ("srb", Cyrillic) : RS
 // http://www.rnids.rs/en/the-.срб-domain
 срб
 пр.срб
 орг.срб
 обр.срб
 од.срб
 упр.срб
 ак.срб
 
-// xn--p1ai ("rf" Russian-Cyrillic) : RU
+// xn--p1ai ("rf", Russian-Cyrillic) : RU
 // http://www.cctld.ru/en/docs/rulesrf.php
 рф
 
-// xn--wgbl6a ("Qatar" Arabic) : QA
+// xn--wgbl6a ("Qatar", Arabic) : QA
 // http://www.ict.gov.qa/
 قطر
 
-// xn--mgberp4a5d4ar ("AlSaudiah" Arabic) : SA
+// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA
 // http://www.nic.net.sa/
 السعودية
 
-// xn--mgberp4a5d4a87g ("AlSaudiah" Arabic) variant : SA
+// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant)  : SA
 السعودیة
 
-// xn--mgbqly7c0a67fbc ("AlSaudiah" Arabic) variant : SA
+// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA
 السعودیۃ
 
-// xn--mgbqly7cvafr ("AlSaudiah" Arabic) variant : SA
+// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA
 السعوديه
 
-// xn--ogbpf8fl ("Syria" Arabic) : SY
+// xn--mgbpl2fh ("sudan", Arabic) : SD
+// Operated by .sd registry
+سودان
+
+// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG
+新加坡
+
+// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG
+சிங்கப்பூர்
+
+// xn--ogbpf8fl ("Syria", Arabic) : SY
 سورية
 
-// xn--mgbtf8fl ("Syria" Arabic) variant : SY
+// xn--mgbtf8fl ("Syria", Arabic, variant) : SY
 سوريا
 
-// xn--yfro4i67o Singapore ("Singapore" Chinese-Han) : SG
-新加坡
-
-// xn--clchc0ea0b2g2a9gcd ("Singapore" Tamil) : SG
-சிங்கப்பூர்
-
-// xn--o3cw4h ("Thai" Thai) : TH
+// xn--o3cw4h ("Thai", Thai) : TH
 // http://www.thnic.co.th
 ไทย
 
-// xn--pgbs0dh ("Tunis") : TN
+// xn--pgbs0dh ("Tunisia", Arabic) : TN
 // http://nic.tn
 تونس
 
-// xn--kpry57d ("Taiwan" Chinese-Han-Traditional) : TW
+// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW
 // http://www.twnic.net/english/dn/dn_07a.htm
 台灣
 
-// xn--kprw13d ("Taiwan" Chinese-Han-Simplified) : TW
+// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW
 // http://www.twnic.net/english/dn/dn_07a.htm
 台湾
 
-// xn--nnx388a ("Taiwan") variant : TW
+// xn--nnx388a ("Taiwan", Chinese, variant) : TW
 臺灣
 
-// xn--j1amh ("ukr" Cyrillic) : UA
+// xn--j1amh ("ukr", Cyrillic) : UA
 укр
 
-// xn--mgb2ddes ("AlYemen" Arabic) : YE
+// xn--mgb2ddes ("AlYemen", Arabic) : YE
 اليمن
 
 // xxx : http://icmregistry.com
 xxx
 
 // ye : http://www.y.net.ye/services/domain_name.htm
 *.ye
 
@@ -6850,17 +6883,17 @@ xxx
 
 // zm : http://en.wikipedia.org/wiki/.zm
 *.zm
 
 // zw : http://en.wikipedia.org/wiki/.zw
 *.zw
 
 
-// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2015-04-07T06:02:08Z
+// List of new gTLDs imported from https://newgtlds.icann.org/newgtlds.csv on 2015-05-06T09:31:08Z
 
 // aaa : 2015-02-26 American Automobile Association, Inc.
 aaa
 
 // abb : 2014-10-24 ABB Ltd
 abb
 
 // abbott : 2014-07-24 Abbott Laboratories, Inc.
@@ -6903,28 +6936,34 @@ aeg
 afl
 
 // africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
 africa
 
 // africamagic : 2015-03-05 Electronic Media Network (Pty) Ltd
 africamagic
 
+// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+agakhan
+
 // agency : 2013-11-14 Steel Falls, LLC
 agency
 
 // aig : 2014-12-18 American International Group, Inc.
 aig
 
 // airforce : 2014-03-06 United TLD Holdco Ltd.
 airforce
 
 // airtel : 2014-10-24 Bharti Airtel Limited
 airtel
 
+// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
+akdn
+
 // alibaba : 2015-01-15 Alibaba Group Holding Limited
 alibaba
 
 // alipay : 2015-01-15 Alibaba Group Holding Limited
 alipay
 
 // allfinanz : 2014-07-03 Allfinanz Deutsche Vermögensberatung Aktiengesellschaft
 allfinanz
@@ -6987,16 +7026,19 @@ autos
 avianca
 
 // axa : 2013-12-19 AXA SA
 axa
 
 // azure : 2014-12-18 Microsoft Corporation
 azure
 
+// baby : 2015-04-09 Johnson & Johnson Services, Inc.
+baby
+
 // baidu : 2015-01-08 Baidu, Inc.
 baidu
 
 // band : 2014-06-12
 band
 
 // bank : 2014-09-25 fTLD Registry Services LLC
 bank
@@ -7218,34 +7260,43 @@ casino
 catering
 
 // cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
 cba
 
 // cbn : 2014-08-22 The Christian Broadcasting Network, Inc.
 cbn
 
+// ceb : 2015-04-09 The Corporate Executive Board Company
+ceb
+
 // center : 2013-11-07 Tin Mill, LLC
 center
 
 // ceo : 2013-11-07 CEOTLD Pty Ltd
 ceo
 
-// cern : 2014-06-05 European Organization for Nuclear Research (\
+// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
 cern
 
 // cfa : 2014-08-28 CFA Institute
 cfa
 
 // cfd : 2014-12-11 IG Group Holdings PLC
 cfd
 
+// chanel : 2015-04-09 Chanel International B.V.
+chanel
+
 // channel : 2014-05-08 Charleston Road Registry Inc.
 channel
 
+// chase : 2015-04-30 JPMorgan Chase & Co.
+chase
+
 // chat : 2014-12-04 Sand Fields, LLC
 chat
 
 // cheap : 2013-11-14 Sand Cover, LLC
 cheap
 
 // chloe : 2014-10-16 Richemont DNS Inc.
 chloe
@@ -7287,16 +7338,19 @@ cleaning
 click
 
 // clinic : 2014-03-20 Goose Park, LLC
 clinic
 
 // clothing : 2013-08-27 Steel Lake, LLC
 clothing
 
+// cloud : 2015-04-16 ARUBA S.p.A.
+cloud
+
 // club : 2013-11-08 .CLUB DOMAINS, LLC
 club
 
 // coach : 2014-10-09 Koko Island, LLC
 coach
 
 // codes : 2013-10-31 Puff Willow, LLC
 codes
@@ -7713,17 +7767,17 @@ gallery
 gallup
 
 // garden : 2014-06-26 Top Level Domain Holdings Limited
 garden
 
 // gbiz : 2014-07-17 Charleston Road Registry Inc.
 gbiz
 
-// gdn : 2014-07-31 Joint Stock Company \
+// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems"
 gdn
 
 // gea : 2014-12-04 GEA Group Aktiengesellschaft
 gea
 
 // gent : 2014-01-23 COMBELL GROUP NV/SA
 gent
 
@@ -7983,16 +8037,19 @@ iwc
 jaguar
 
 // java : 2014-06-19 Oracle Corporation
 java
 
 // jcb : 2014-11-20 JCB Co., Ltd.
 jcb
 
+// jcp : 2015-04-23 JCP Media, Inc.
+jcp
+
 // jetzt : 2014-01-09 New TLD Company AB
 jetzt
 
 // jewelry : 2015-03-05 Wild Bloom, LLC
 jewelry
 
 // jio : 2015-04-02 Affinity Names, Inc.
 jio
@@ -8010,28 +8067,40 @@ jmp
 joburg
 
 // jot : 2014-12-18 Amazon EU S.à r.l.
 jot
 
 // joy : 2014-12-18 Amazon EU S.à r.l.
 joy
 
+// jpmorgan : 2015-04-30 JPMorgan Chase & Co.
+jpmorgan
+
 // jprs : 2014-09-18 Japan Registry Services Co., Ltd.
 jprs
 
 // juegos : 2014-03-20 Uniregistry, Corp.
 juegos
 
 // kaufen : 2013-11-07 United TLD Holdco Ltd.
 kaufen
 
 // kddi : 2014-09-12 KDDI CORPORATION
 kddi
 
+// kerryhotels : 2015-04-30 Kerry Trading Co. Limited
+kerryhotels
+
+// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited
+kerrylogistics
+
+// kerryproperties : 2015-04-09 Kerry Trading Co. Limited
+kerryproperties
+
 // kfh : 2014-12-04 Kuwait Finance House
 kfh
 
 // kim : 2013-09-23 Afilias Limited
 kim
 
 // kinder : 2014-11-07 Ferrero Trading Lux S.A.
 kinder
@@ -8043,25 +8112,31 @@ kitchen
 kiwi
 
 // koeln : 2014-01-09 NetCologne Gesellschaft für Telekommunikation mbH
 koeln
 
 // komatsu : 2015-01-08 Komatsu Ltd.
 komatsu
 
+// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft)
+kpmg
+
 // kpn : 2015-01-08 Koninklijke KPN N.V.
 kpn
 
 // krd : 2013-12-05 KRG Department of Information Technology
 krd
 
 // kred : 2013-12-19 KredTLD Pty Ltd
 kred
 
+// kuokgroup : 2015-04-09 Kerry Trading Co. Limited
+kuokgroup
+
 // kyknet : 2015-03-05 Electronic Media Network (Pty) Ltd
 kyknet
 
 // kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen
 kyoto
 
 // lacaixa : 2014-01-09 CAIXA D'ESTALVIS I PENSIONS DE BARCELONA
 lacaixa
@@ -8085,28 +8160,31 @@ lat
 latrobe
 
 // law : 2015-01-22 Minds + Machines Group Limited
 law
 
 // lawyer : 2014-03-20
 lawyer
 
-// lds : 2014-03-20 IRI Domain Management, LLC (\
+// lds : 2014-03-20 IRI Domain Management, LLC ("Applicant")
 lds
 
 // lease : 2014-03-06 Victor Trail, LLC
 lease
 
 // leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
 leclerc
 
 // legal : 2014-10-16 Blue Falls, LLC
 legal
 
+// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION
+lexus
+
 // lgbt : 2014-05-08 Afilias Limited
 lgbt
 
 // liaison : 2014-10-02 Liaison Technologies, Incorporated
 liaison
 
 // lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
 lidl
@@ -8247,16 +8325,19 @@ meo
 miami
 
 // microsoft : 2014-12-18 Microsoft Corporation
 microsoft
 
 // mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
 mini
 
+// mls : 2015-04-23 The Canadian Real Estate Association
+mls
+
 // mma : 2014-11-07 MMA IARD
 mma
 
 // mnet : 2015-03-05 Electronic Media Network (Pty) Ltd
 mnet
 
 // mobily : 2014-12-18 GreenTech Consultancy Company W.L.L.
 mobily
@@ -8265,26 +8346,29 @@ mobily
 moda
 
 // moe : 2013-11-13 Interlink Co., Ltd.
 moe
 
 // moi : 2014-12-18 Amazon EU S.à r.l.
 moi
 
+// mom : 2015-04-16 Uniregistry, Corp.
+mom
+
 // monash : 2013-09-30 Monash University
 monash
 
 // money : 2014-10-16 Outer McCook, LLC
 money
 
 // montblanc : 2014-06-23 Richemont DNS Inc.
 montblanc
 
-// mormon : 2013-12-05 IRI Domain Management, LLC (\
+// mormon : 2013-12-05 IRI Domain Management, LLC ("Applicant")
 mormon
 
 // mortgage : 2014-03-20
 mortgage
 
 // moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
 moscow
 
@@ -8388,16 +8472,19 @@ nrw
 ntt
 
 // nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications
 nyc
 
 // obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
 obi
 
+// observer : 2015-04-30 Guardian News and Media Limited
+observer
+
 // office : 2015-03-12 Microsoft Corporation
 office
 
 // okinawa : 2013-12-05 BusinessRalliart Inc.
 okinawa
 
 // omega : 2015-01-08 The Swatch Group Ltd
 omega
@@ -8550,16 +8637,19 @@ prof
 promo
 
 // properties : 2013-12-05 Big Pass, LLC
 properties
 
 // property : 2014-05-22 Uniregistry, Corp.
 property
 
+// protection : 2015-04-23 Symantec Corporation
+protection
+
 // pub : 2013-12-12 United TLD Holdco Ltd.
 pub
 
 // qpon : 2013-11-14 dotCOOL, Inc.
 qpon
 
 // quebec : 2013-12-19 PointQuébec Inc
 quebec
@@ -8727,17 +8817,17 @@ saxo
 sbi
 
 // sbs : 2014-11-07 SPECIAL BROADCASTING SERVICE CORPORATION
 sbs
 
 // sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
 sca
 
-// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited (\
+// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB")
 scb
 
 // schmidt : 2014-04-03 SALM S.A.S.
 schmidt
 
 // scholarships : 2014-04-24 Scholarships.com, LLC
 scholarships
 
@@ -8778,16 +8868,19 @@ sew
 sex
 
 // sexy : 2013-09-11 Uniregistry, Corp.
 sexy
 
 // sharp : 2014-05-01 Sharp Corporation
 sharp
 
+// shaw : 2015-04-23 Shaw Cablesystems G.P.
+shaw
+
 // shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
 shia
 
 // shiksha : 2013-11-14 Afilias Limited
 shiksha
 
 // shoes : 2013-10-02 Binky Galley, LLC
 shoes
@@ -8805,16 +8898,19 @@ shriram
 sina
 
 // singles : 2013-08-27 Fern Madison, LLC
 singles
 
 // site : 2015-01-15 DotSite Inc.
 site
 
+// ski : 2015-04-09 STARTING DOT LIMITED
+ski
+
 // skin : 2015-01-15 L'Oréal
 skin
 
 // sky : 2014-06-19 Sky IP International Ltd, a company incorporated in England and Wales, operating via its registered Swiss branch
 sky
 
 // skype : 2014-12-18 Microsoft Corporation
 skype
@@ -8886,16 +8982,19 @@ stc
 stcgroup
 
 // stockholm : 2014-12-18 Stockholms kommun
 stockholm
 
 // storage : 2014-12-22 Self Storage Company LLC
 storage
 
+// store : 2015-04-09 DotStore Inc.
+store
+
 // studio : 2015-02-11 Spring Goodbye, LLC
 studio
 
 // study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
 study
 
 // style : 2014-12-04 Binky Moon, LLC
 style
@@ -8940,23 +9039,26 @@ symantec
 systems
 
 // tab : 2014-12-04 Tabcorp Holdings Limited
 tab
 
 // taipei : 2014-07-10 Taipei City Government
 taipei
 
+// talk : 2015-04-09 Amazon EU S.à r.l.
+talk
+
 // taobao : 2015-01-15 Alibaba Group Holding Limited
 taobao
 
 // tatamotors : 2015-03-12 Tata Motors Ltd
 tatamotors
 
-// tatar : 2014-04-24 Limited Liability Company \
+// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
 tatar
 
 // tattoo : 2013-08-30 Uniregistry, Corp.
 tattoo
 
 // tax : 2014-03-20 Storm Orchard, LLC
 tax
 
@@ -8988,16 +9090,19 @@ temasek
 tennis
 
 // thd : 2015-04-02 Homer TLC, Inc.
 thd
 
 // theater : 2015-03-19 Blue Tigers, LLC
 theater
 
+// theguardian : 2015-04-30 Guardian News and Media Limited
+theguardian
+
 // tickets : 2015-02-05 Accent Media Limited
 tickets
 
 // tienda : 2013-11-14 Victor Manor, LLC
 tienda
 
 // tiffany : 2015-01-30 Tiffany and Company
 tiffany
@@ -9033,16 +9138,19 @@ toray
 toshiba
 
 // tours : 2015-01-22 Sugar Station, LLC
 tours
 
 // town : 2014-03-06 Koko Moon, LLC
 town
 
+// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION
+toyota
+
 // toys : 2014-03-06 Pioneer Orchard, LLC
 toys
 
 // trade : 2014-01-23 Elite Registry Limited
 trade
 
 // trading : 2014-12-11 IG Group Holdings PLC
 trading
@@ -9345,16 +9453,19 @@ xin
 ポイント
 
 // xn--efvy88h : 2014-08-22 Xinhua News Agency Guangdong Branch 新华通讯社广东分社
 新闻
 
 // xn--estv75g : 2015-02-19 Industrial and Commercial Bank of China Limited
 工行
 
+// xn--fct429k : 2015-04-09 Amazon EU S.à r.l.
+家電
+
 // xn--fhbei : 2015-01-15 VeriSign Sarl
 كوم
 
 // xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED
 中文网
 
 // xn--fiq64b : 2013-10-14 CITIC Group Corporation
 中信
@@ -9474,16 +9585,19 @@ vermögensberater
 vermögensberatung
 
 // xn--vhquv : 2013-08-27 Dash McCook, LLC
 企业
 
 // xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd.
 信息
 
+// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited
+嘉里大酒店
+
 // xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
 广东
 
 // xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
 政务
 
 // xyz : 2013-12-05 XYZ.COM LLC
 xyz
@@ -9504,16 +9618,19 @@ yandex
 yodobashi
 
 // yoga : 2014-05-29 Top Level Domain Holdings Limited
 yoga
 
 // yokohama : 2013-12-12 GMO Registry, Inc.
 yokohama
 
+// you : 2015-04-09 Amazon EU S.à r.l.
+you
+
 // youtube : 2014-05-01 Charleston Road Registry Inc.
 youtube
 
 // yun : 2015-01-08 QIHOO 360 TECHNOLOGY CO. LTD.
 yun
 
 // zara : 2014-11-07 Industria de Diseño Textil, S.A. (INDITEX, S.A.)
 zara
--- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
+++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp
@@ -93,19 +93,17 @@ SandboxBroker::SetSecurityLevelForConten
   } else if (aSandboxLevel == 1) {
     jobLevel = sandbox::JOB_NONE;
     accessTokenLevel = sandbox::USER_NON_ADMIN;
     initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
     delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
   } else {
     jobLevel = sandbox::JOB_NONE;
     accessTokenLevel = sandbox::USER_NON_ADMIN;
-    // INTEGRITY_LEVEL_LAST effectively means don't change from the integrity
-    // level of the broker process.
-    initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LAST;
+    initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
     delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
   }
 
   sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel,
                                                     0 /* ui_exceptions */);
   bool ret = (sandbox::SBOX_ALL_OK == result);
 
   result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
--- a/testing/web-platform/meta/websockets/interfaces/CloseEvent/historical.html.ini
+++ b/testing/web-platform/meta/websockets/interfaces/CloseEvent/historical.html.ini
@@ -1,8 +1,10 @@
 [historical.html]
   type: testharness
   [createEvent("CloseEvent")]
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1161950
     expected: FAIL
 
   [initCloseEvent]
+    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1161950
     expected: FAIL
 
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -3491,25 +3491,20 @@ Checker.prototype = {
     url = url.replace(/%DISTRIBUTION_VERSION%/g,
                       getDistributionPrefValue(PREF_APP_DISTRIBUTION_VERSION));
     url = url.replace(/%CUSTOM%/g, getPref("getCharPref", PREF_APP_UPDATE_CUSTOM, ""));
     url = url.replace(/\+/g, "%2B");
 
     if (AppConstants.platform == "gonk") {
       let sysLibs = {};
       Cu.import("resource://gre/modules/systemlibs.js", sysLibs);
-      let productDevice = sysLibs.libcutils.property_get("ro.product.device");
-      let buildType = sysLibs.libcutils.property_get("ro.build.type");
       url = url.replace(/%PRODUCT_MODEL%/g,
                         sysLibs.libcutils.property_get("ro.product.model"));
-      if (buildType == "user") {
-        url = url.replace(/%PRODUCT_DEVICE%/g, productDevice);
-      } else {
-        url = url.replace(/%PRODUCT_DEVICE%/g, productDevice + "-" + buildType);
-      }
+      url = url.replace(/%PRODUCT_DEVICE%/g,
+                        sysLibs.libcutils.property_get("ro.product.device"));
       url = url.replace(/%B2G_VERSION%/g,
                         getPref("getCharPref", PREF_APP_B2G_VERSION, null));
     }
 
     if (force) {
       url += (url.indexOf("?") != -1 ? "&" : "?") + "force=1";
     }
 
--- a/toolkit/xre/nsXREDirProvider.cpp
+++ b/toolkit/xre/nsXREDirProvider.cpp
@@ -108,22 +108,25 @@ nsXREDirProvider::Initialize(nsIFile *aX
   mGREBinDir->SetNativeLeafName(NS_LITERAL_CSTRING("MacOS"));
 #endif
 
   if (!mProfileDir) {
     nsCOMPtr<nsIDirectoryServiceProvider> app(do_QueryInterface(mAppProvider));
     if (app) {
       bool per = false;
       app->GetFile(NS_APP_USER_PROFILE_50_DIR, &per, getter_AddRefs(mProfileDir));
-      NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!"); 
-      NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!"); 
+      NS_ASSERTION(per, "NS_APP_USER_PROFILE_50_DIR must be persistent!");
+      NS_ASSERTION(mProfileDir, "NS_APP_USER_PROFILE_50_DIR not defined! This shouldn't happen!");
     }
   }
 
+#ifdef MOZ_B2G
   LoadAppBundleDirs();
+#endif
+
   return NS_OK;
 }
 
 nsresult
 nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir)
 {
   NS_ASSERTION(aDir && aLocalDir, "We don't support no-profile apps yet!");
 
@@ -636,16 +639,17 @@ nsXREDirProvider::LoadExtensionBundleDir
     RegisterExtensionInterpositions(parser);
     LoadExtensionDirectories(parser, "ExtensionDirs", mExtensionDirectories,
                              NS_EXTENSION_LOCATION);
     LoadExtensionDirectories(parser, "ThemeDirs", mThemeDirectories,
                              NS_SKIN_LOCATION);
   }
 }
 
+#ifdef MOZ_B2G
 void
 nsXREDirProvider::LoadAppBundleDirs()
 {
   nsCOMPtr<nsIFile> dir;
   bool persistent = false;
   nsresult rv = GetFile(XRE_APP_DISTRIBUTION_DIR, &persistent, getter_AddRefs(dir));
   if (NS_FAILED(rv))
     return;
@@ -662,19 +666,20 @@ nsXREDirProvider::LoadAppBundleDirs()
     return;
 
   nsCOMPtr<nsIFile> subdir;
   while (NS_SUCCEEDED(files->GetNextFile(getter_AddRefs(subdir))) && subdir) {
     mAppBundleDirectories.AppendObject(subdir);
 
     nsCOMPtr<nsIFile> manifest =
       CloneAndAppend(subdir, "chrome.manifest");
-    XRE_AddManifestLocation(NS_EXTENSION_LOCATION, manifest);
+    XRE_AddManifestLocation(NS_APP_LOCATION, manifest);
   }
 }
+#endif
 
 static const char *const kAppendPrefDir[] = { "defaults", "preferences", nullptr };
 
 #ifdef DEBUG_bsmedberg
 static void
 DumpFileArray(const char *key,
               nsCOMArray<nsIFile> dirs)
 {
--- a/toolkit/xre/nsXREDirProvider.h
+++ b/toolkit/xre/nsXREDirProvider.h
@@ -122,18 +122,20 @@ protected:
 
   // Internal helper that splits a path into components using the '/' and '\\'
   // delimiters.
   static inline nsresult AppendProfileString(nsIFile* aFile, const char* aPath);
 
   // Calculate and register extension and theme bundle directories.
   void LoadExtensionBundleDirectories();
 
+#ifdef MOZ_B2G
   // Calculate and register app-bundled extension directories.
   void LoadAppBundleDirs();
+#endif
 
   void Append(nsIFile* aDirectory);
 
   nsCOMPtr<nsIDirectoryServiceProvider> mAppProvider;
   // On OSX, mGREDir points to .app/Contents/Resources
   nsCOMPtr<nsIFile>      mGREDir;
   // On OSX, mGREBinDir points to .app/Contents/MacOS
   nsCOMPtr<nsIFile>      mGREBinDir;
--- a/widget/gonk/libdisplay/GonkDisplayJB.cpp
+++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp
@@ -162,19 +162,18 @@ GonkDisplayJB::~GonkDisplayJB()
     if (mFBDevice)
         framebuffer_close(mFBDevice);
     free(mList);
 }
 
 ANativeWindow*
 GonkDisplayJB::GetNativeWindow()
 {
-    if (!mBootAnimBuffer.get()) {
-        StopBootAnimation();
-    }
+    StopBootAnim();
+
     return mSTClient.get();
 }
 
 void
 GonkDisplayJB::SetEnabled(bool enabled)
 {
     if (enabled) {
         autosuspend_disable();
@@ -230,20 +229,17 @@ void*
 GonkDisplayJB::GetDispSurface()
 {
     return mDispSurface.get();
 }
 
 bool
 GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur)
 {
-    if (mBootAnimBuffer.get()) {
-        StopBootAnimation();
-        mBootAnimBuffer = nullptr;
-    }
+    StopBootAnim();
 
     // Should be called when composition rendering is complete for a frame.
     // Only HWC v1.0 needs this call.
     // HWC > v1.0 case, do not call compositionComplete().
     // mFBDevice is present only when HWC is v1.0.
     if (mFBDevice && mFBDevice->compositionComplete) {
         mFBDevice->compositionComplete(mFBDevice);
     }
@@ -332,35 +328,42 @@ GonkDisplayJB::QueueBuffer(ANativeWindow
         error = mSTClient->queueBuffer(mSTClient.get(), buf, mFence);
     }
     return error == 0 && success;
 }
 
 void
 GonkDisplayJB::UpdateDispSurface(EGLDisplay dpy, EGLSurface sur)
 {
-    if (mBootAnimBuffer.get()) {
-        StopBootAnimation();
-        mBootAnimBuffer = nullptr;
-    }
+    StopBootAnim();
+
     eglSwapBuffers(dpy, sur);
 }
 
 void
 GonkDisplayJB::SetDispReleaseFd(int fd)
 {
     mDispSurface->setReleaseFenceFd(fd);
 }
 
 int
 GonkDisplayJB::GetPrevDispAcquireFd()
 {
     return mDispSurface->GetPrevDispAcquireFd();
 }
 
+void
+GonkDisplayJB::StopBootAnim()
+{
+    if (mBootAnimBuffer.get()) {
+        mBootAnimBuffer = nullptr;
+    }
+    StopBootAnimation();
+}
+
 __attribute__ ((visibility ("default")))
 GonkDisplay*
 GetGonkDisplay()
 {
     if (!sGonkDisplay)
         sGonkDisplay = new GonkDisplayJB();
     return sGonkDisplay;
 }
--- a/widget/gonk/libdisplay/GonkDisplayJB.h
+++ b/widget/gonk/libdisplay/GonkDisplayJB.h
@@ -50,16 +50,18 @@ public:
 
     virtual void SetDispReleaseFd(int fd);
 
     virtual int GetPrevDispAcquireFd();
 
     bool Post(buffer_handle_t buf, int fence);
 
 private:
+    void StopBootAnim();
+
     hw_module_t const*        mModule;
     hw_module_t const*        mFBModule;
     hwc_composer_device_1_t*  mHwc;
     framebuffer_device_t*     mFBDevice;
     power_module_t*           mPowerModule;
     android::sp<android::DisplaySurface> mDispSurface;
     android::sp<ANativeWindow> mSTClient;
     android::sp<android::IGraphicBufferAlloc> mAlloc;
--- a/widget/gonk/nsScreenManagerGonk.h
+++ b/widget/gonk/nsScreenManagerGonk.h
@@ -74,16 +74,17 @@ public:
     static already_AddRefed<nsScreenManagerGonk> GetInstance();
     static already_AddRefed<nsScreenGonk> GetPrimaryScreen();
 
     void Initialize();
     void DisplayEnabled(bool aEnabled);
 
 protected:
     ~nsScreenManagerGonk();
+    void VsyncControl(bool aEnabled);
 
     bool mInitialized;
     nsCOMPtr<nsIScreen> mOneScreen;
     nsRefPtr<nsRunnable> mScreenOnEvent;
     nsRefPtr<nsRunnable> mScreenOffEvent;
 };
 
 #endif /* nsScreenManagerGonk_h___ */
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -51,16 +51,17 @@
 #include "mozilla/layers/APZCTreeManager.h"
 #include "mozilla/layers/APZThreadUtils.h"
 #include "mozilla/layers/CompositorParent.h"
 #include "mozilla/layers/InputAPZContext.h"
 #include "mozilla/MouseEvents.h"
 #include "mozilla/TouchEvents.h"
 #include "nsThreadUtils.h"
 #include "HwcComposer2D.h"
+#include "VsyncSource.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
 #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
 
 #define IS_TOPLEVEL() (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
 
 using namespace mozilla;
@@ -1111,17 +1112,20 @@ nsScreenManagerGonk::Initialize()
 
     nsAppShell::NotifyScreenInitialized();
     mInitialized = true;
 }
 
 void
 nsScreenManagerGonk::DisplayEnabled(bool aEnabled)
 {
-    HwcComposer2D::GetInstance()->EnableVsync(aEnabled);
+    if (gfxPrefs::HardwareVsyncEnabled()) {
+        VsyncControl(aEnabled);
+    }
+
     NS_DispatchToMainThread(aEnabled ? mScreenOnEvent : mScreenOffEvent);
 }
 
 NS_IMETHODIMP
 nsScreenManagerGonk::GetPrimaryScreen(nsIScreen **outScreen)
 {
     NS_IF_ADDREF(*outScreen = mOneScreen.get());
     return NS_OK;
@@ -1158,8 +1162,30 @@ nsScreenManagerGonk::GetNumberOfScreens(
 }
 
 NS_IMETHODIMP
 nsScreenManagerGonk::GetSystemDefaultScale(float *aDefaultScale)
 {
     *aDefaultScale = 1.0f;
     return NS_OK;
 }
+
+void
+nsScreenManagerGonk::VsyncControl(bool aEnabled)
+{
+    MOZ_ASSERT(gfxPrefs::HardwareVsyncEnabled());
+
+    if (!NS_IsMainThread()) {
+        NS_DispatchToMainThread(
+            NS_NewRunnableMethodWithArgs<bool>(this,
+                                               &nsScreenManagerGonk::VsyncControl,
+                                               aEnabled));
+        return;
+    }
+
+    MOZ_ASSERT(NS_IsMainThread());
+    VsyncSource::Display &display = gfxPlatform::GetPlatform()->GetHardwareVsync()->GetGlobalDisplay();
+    if (aEnabled) {
+        display.EnableVsync();
+    } else {
+        display.DisableVsync();
+    }
+}