Merge m-c to b2g-inbound
authorWes Kocher <wkocher@mozilla.com>
Thu, 27 Feb 2014 17:47:32 -0800
changeset 171577 8a80d7a4e4db0f67bca8587a8d78bdc4dbbfc220
parent 171576 3894715d275f4efd6902a990dded16874a5a2bbf (current diff)
parent 171469 58eca03214a6afaa92714ad0eb394696fad13cce (diff)
child 171578 53dbf19f2f8d5de981e24cd488e5a1cbb8d2b677
child 171628 4f7dc3feaf3178dd241d6b90543fc83196639f12
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
milestone30.0a1
Merge m-c to b2g-inbound
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -158,44 +158,70 @@ Site.prototype = {
   /**
    * Adds event handlers for the site and its buttons.
    */
   _addEventHandlers: function Site_addEventHandlers() {
     // Register drag-and-drop event handlers.
     this._node.addEventListener("dragstart", this, false);
     this._node.addEventListener("dragend", this, false);
     this._node.addEventListener("mouseover", this, false);
-
-    let controls = this.node.querySelectorAll(".newtab-control");
-    for (let i = 0; i < controls.length; i++)
-      controls[i].addEventListener("click", this, false);
+    this._node.addEventListener("click", this, false);
   },
 
   /**
    * Speculatively opens a connection to the current site.
    */
   _speculativeConnect: function Site_speculativeConnect() {
     let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
     let uri = Services.io.newURI(this.url, null, null);
     sc.speculativeConnect(uri, null);
   },
 
   /**
+   * Record interaction with site using telemetry.
+   */
+  _recordSiteClicked: function Site_recordSiteClicked(aIndex) {
+    if (Services.prefs.prefHasUserValue("browser.newtabpage.rows") ||
+        Services.prefs.prefHasUserValue("browser.newtabpage.columns") ||
+        aIndex > 8) {
+      // We only want to get indices for the default configuration, everything
+      // else goes in the same bucket.
+      aIndex = 9;
+    }
+    Services.telemetry.getHistogramById("NEWTAB_PAGE_SITE_CLICKED")
+                      .add(aIndex);
+  },
+
+  /**
+   * Handles site click events.
+   */
+  _onClick: function Site_onClick(aEvent) {
+    let target = aEvent.target;
+    if (target.classList.contains("newtab-link") ||
+        target.parentElement.classList.contains("newtab-link")) {
+      this._recordSiteClicked(this.cell.index);
+      return;
+    }
+
+    aEvent.preventDefault();
+    if (aEvent.target.classList.contains("newtab-control-block"))
+      this.block();
+    else if (this.isPinned())
+      this.unpin();
+    else
+      this.pin();
+  },
+
+  /**
    * Handles all site events.
    */
   handleEvent: function Site_handleEvent(aEvent) {
     switch (aEvent.type) {
       case "click":
-        aEvent.preventDefault();
-        if (aEvent.target.classList.contains("newtab-control-block"))
-          this.block();
-        else if (this.isPinned())
-          this.unpin();
-        else
-          this.pin();
+        this._onClick(aEvent);
         break;
       case "mouseover":
         this._node.removeEventListener("mouseover", this, false);
         this._speculativeConnect();
         break;
       case "dragstart":
         gDrag.start(this, aEvent);
         break;
--- a/chrome/src/nsChromeRegistryChrome.cpp
+++ b/chrome/src/nsChromeRegistryChrome.cpp
@@ -114,25 +114,24 @@ nsChromeRegistryChrome::Init()
 {
   nsresult rv = nsChromeRegistry::Init();
   if (NS_FAILED(rv))
     return rv;
 
   mSelectedLocale = NS_LITERAL_CSTRING("en-US");
   mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
 
-  if (!PL_DHashTableInit(&mPackagesHash, &kTableOps,
-                         nullptr, sizeof(PackageEntry), 16))
-    return NS_ERROR_FAILURE;
+  PL_DHashTableInit(&mPackagesHash, &kTableOps,
+                    nullptr, sizeof(PackageEntry), 16);
 
   bool safeMode = false;
   nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
   if (xulrun)
     xulrun->GetInSafeMode(&safeMode);
-  
+
   nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
   nsCOMPtr<nsIPrefBranch> prefs;
 
   if (safeMode)
     prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
   else
     prefs = do_QueryInterface(prefserv);
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -187,17 +187,16 @@ ContentListHashtableMatchEntry(PLDHashTa
 
   return list->MatchesKey(*ourKey);
 }
 
 already_AddRefed<nsContentList>
 NS_GetContentList(nsINode* aRootNode, 
                   int32_t  aMatchNameSpaceId,
                   const nsAString& aTagname)
-                  
 {
   NS_ASSERTION(aRootNode, "content list has to have a root");
 
   nsRefPtr<nsContentList> list;
   nsContentListKey hashKey(aRootNode, aMatchNameSpaceId, aTagname);
   uint32_t recentlyUsedCacheIndex = RecentlyUsedCacheIndex(hashKey);
   nsContentList* cachedList = sRecentlyUsedContentLists[recentlyUsedCacheIndex];
   if (cachedList && cachedList->MatchesKey(hashKey)) {
@@ -213,30 +212,26 @@ NS_GetContentList(nsINode* aRootNode,
     ContentListHashtableMatchEntry,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     PL_DHashFinalizeStub
   };
 
   // Initialize the hashtable if needed.
   if (!gContentListHashTable.ops) {
-    bool success = PL_DHashTableInit(&gContentListHashTable,
-                                       &hash_table_ops, nullptr,
-                                       sizeof(ContentListHashEntry),
-                                       16);
+    PL_DHashTableInit(&gContentListHashTable,
+                      &hash_table_ops, nullptr,
+                      sizeof(ContentListHashEntry),
+                      16);
+  }
 
-    if (!success) {
-      gContentListHashTable.ops = nullptr;
-    }
-  }
-  
   ContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
   if (gContentListHashTable.ops) {
-    
+
     // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
     // when the entry is already in the hashtable.
     entry = static_cast<ContentListHashEntry *>
                        (PL_DHashTableOperate(&gContentListHashTable,
                                              &hashKey,
                                              PL_DHASH_ADD));
     if (entry)
       list = entry->mContentList;
@@ -334,24 +329,20 @@ GetFuncStringContentList(nsINode* aRootN
     FuncStringContentListHashtableMatchEntry,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     PL_DHashFinalizeStub
   };
 
   // Initialize the hashtable if needed.
   if (!gFuncStringContentListHashTable.ops) {
-    bool success = PL_DHashTableInit(&gFuncStringContentListHashTable,
-                                       &hash_table_ops, nullptr,
-                                       sizeof(FuncStringContentListHashEntry),
-                                       16);
-
-    if (!success) {
-      gFuncStringContentListHashTable.ops = nullptr;
-    }
+    PL_DHashTableInit(&gFuncStringContentListHashTable,
+                      &hash_table_ops, nullptr,
+                      sizeof(FuncStringContentListHashEntry),
+                      16);
   }
 
   FuncStringContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
   if (gFuncStringContentListHashTable.ops) {
     nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString);
 
     // A PL_DHASH_ADD is equivalent to a PL_DHASH_LOOKUP for cases
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -408,22 +408,18 @@ nsContentUtils::Init()
       PL_DHashVoidPtrKeyStub,
       PL_DHashMatchEntryStub,
       PL_DHashMoveEntryStub,
       EventListenerManagerHashClearEntry,
       PL_DHashFinalizeStub,
       EventListenerManagerHashInitEntry
     };
 
-    if (!PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops,
-                           nullptr, sizeof(EventListenerManagerMapEntry), 16)) {
-      sEventListenerManagersHash.ops = nullptr;
-
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    PL_DHashTableInit(&sEventListenerManagersHash, &hash_table_ops,
+                      nullptr, sizeof(EventListenerManagerMapEntry), 16);
 
     RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
   }
 
   sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >;
 
   Preferences::AddBoolVarCache(&sAllowXULXBL_for_file,
                                "dom.allow_XUL_XBL_for_file");
--- a/content/xul/templates/src/nsContentSupportMap.cpp
+++ b/content/xul/templates/src/nsContentSupportMap.cpp
@@ -4,34 +4,33 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsContentSupportMap.h"
 #include "nsXULElement.h"
 
 void
 nsContentSupportMap::Init()
 {
-    if (!PL_DHashTableInit(&mMap, PL_DHashGetStubOps(), nullptr,
-                           sizeof(Entry), PL_DHASH_MIN_SIZE))
-        mMap.ops = nullptr;
+    PL_DHashTableInit(&mMap, PL_DHashGetStubOps(), nullptr,
+                      sizeof(Entry), PL_DHASH_MIN_SIZE);
 }
 
 void
 nsContentSupportMap::Finish()
 {
     if (mMap.ops)
         PL_DHashTableFinish(&mMap);
 }
 
 nsresult
 nsContentSupportMap::Remove(nsIContent* aElement)
 {
     if (!mMap.ops)
         return NS_ERROR_NOT_INITIALIZED;
-    
+
     nsIContent* child = aElement;    
     do {
         PL_DHashTableOperate(&mMap, child, PL_DHASH_REMOVE);
         child = child->GetNextNode(aElement);
     } while(child);
 
     return NS_OK;
 }
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -327,24 +327,26 @@ nsScriptNameSpaceManager::Init()
     GlobalNameHashHashKey,
     GlobalNameHashMatchEntry,
     PL_DHashMoveEntryStub,
     GlobalNameHashClearEntry,
     PL_DHashFinalizeStub,
     GlobalNameHashInitEntry
   };
 
-  mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops, nullptr,
-                                     sizeof(GlobalNameMapEntry), 
-                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE);
+  mIsInitialized = PL_DHashTableInit(&mGlobalNames, &hash_table_ops,
+                                     nullptr, sizeof(GlobalNameMapEntry),
+                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE,
+                                     fallible_t());
   NS_ENSURE_TRUE(mIsInitialized, NS_ERROR_OUT_OF_MEMORY);
 
-  mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops, nullptr,
-                                     sizeof(GlobalNameMapEntry), 
-                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE);
+  mIsInitialized = PL_DHashTableInit(&mNavigatorNames, &hash_table_ops,
+                                     nullptr, sizeof(GlobalNameMapEntry),
+                                     GLOBALNAME_HASHTABLE_INITIAL_SIZE,
+                                     fallible_t());
   if (!mIsInitialized) {
     PL_DHashTableFinish(&mGlobalNames);
 
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   RegisterWeakMemoryReporter(this);
 
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -32,19 +32,21 @@ skip-if = os == 'mac'
 [test_getUserMedia_stopVideoStream.html]
 [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
 [test_peerConnection_addCandidateInHaveLocalOffer.html]
 [test_peerConnection_basicAudio.html]
 [test_peerConnection_basicAudioVideo.html]
 [test_peerConnection_basicAudioVideoCombined.html]
 [test_peerConnection_basicVideo.html]
 [test_peerConnection_bug822674.html]
+[test_peerConnection_bug825703.html]
 [test_peerConnection_bug827843.html]
 [test_peerConnection_bug834153.html]
 [test_peerConnection_bug835370.html]
+[test_peerConnection_errorCallbacks.html]
 [test_peerConnection_offerRequiresReceiveAudio.html]
 [test_peerConnection_offerRequiresReceiveVideo.html]
 [test_peerConnection_offerRequiresReceiveVideoAudio.html]
 [test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
 [test_peerConnection_setLocalAnswerInStable.html]
 [test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInStable.html]
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1725,23 +1725,18 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
   if (!npp) {
     NS_ERROR("No npp passed to nsNPObjWrapper::GetNewOrUsed()!");
 
     return nullptr;
   }
 
   if (!sNPObjWrappers.ops) {
     // No hash yet (or any more), initialize it.
-
-    if (!PL_DHashTableInit(&sNPObjWrappers, PL_DHashGetStubOps(), nullptr,
-                           sizeof(NPObjWrapperHashEntry), 16)) {
-      NS_ERROR("Error initializing PLDHashTable!");
-
-      return nullptr;
-    }
+    PL_DHashTableInit(&sNPObjWrappers, PL_DHashGetStubOps(), nullptr,
+                      sizeof(NPObjWrapperHashEntry), 16);
   }
 
   NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *>
     (PL_DHashTableOperate(&sNPObjWrappers, npobj, PL_DHASH_ADD));
 
   if (!entry) {
     // Out of memory
     JS_ReportOutOfMemory(cx);
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -345,33 +345,31 @@ nsresult nsPluginStreamListenerPeer::Ini
   // SetUpStreamListener
   if (aListener) {
     mPStreamListener = aListener;
     mPStreamListener->SetStreamListenerPeer(this);
   }
 
   mPendingRequests = 1;
 
-  mDataForwardToRequest = new nsHashtable(16, false);
-  if (!mDataForwardToRequest)
-    return NS_ERROR_FAILURE;
+  mDataForwardToRequest = new nsHashtable();
 
   return NS_OK;
 }
 
 // SetupPluginCacheFile is called if we have to save the stream to disk.
 //
 // These files will be deleted when the host is destroyed.
 //
 // TODO? What if we fill up the the dest dir?
 nsresult
 nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
 {
   nsresult rv = NS_OK;
-  
+
   bool useExistingCacheFile = false;
   nsRefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
 
   // Look for an existing cache file for the URI.
   nsTArray< nsRefPtr<nsNPAPIPluginInstance> > *instances = pluginHost->InstanceArray();
   for (uint32_t i = 0; i < instances->Length(); i++) {
     // most recent streams are at the end of list
     nsTArray<nsPluginStreamListenerPeer*> *streamListeners = instances->ElementAt(i)->FileCachedStreamListeners();
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -151,21 +151,19 @@ RemoveObjectEntry(PLDHashTable& table, n
   PL_DHashTableOperate(&table, aKey, PL_DHASH_REMOVE);
 }
 
 static nsresult
 SetOrRemoveObject(PLDHashTable& table, nsIContent* aKey, nsISupports* aValue)
 {
   if (aValue) {
     // lazily create the table, but only when adding elements
-    if (!table.ops &&
-        !PL_DHashTableInit(&table, &ObjectTableOps, nullptr,
-                           sizeof(ObjectEntry), 16)) {
-      table.ops = nullptr;
-      return NS_ERROR_OUT_OF_MEMORY;
+    if (!table.ops) {
+      PL_DHashTableInit(&table, &ObjectTableOps, nullptr,
+                        sizeof(ObjectEntry), 16);
     }
     aKey->SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
     return AddObjectEntry(table, aKey, aValue);
   }
 
   // no value, so remove the key from the table
   if (table.ops) {
     ObjectEntry* entry =
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -467,20 +467,18 @@ nsXBLDocumentInfo::ReadPrototypeBindings
 
   while (1) {
     uint8_t flags;
     nsresult rv = stream->Read8(&flags);
     NS_ENSURE_SUCCESS(rv, rv);
     if (flags == XBLBinding_Serialize_NoMoreBindings)
       break;
 
-    nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding();
-    rv = binding->Read(stream, docInfo, doc, flags);
+    rv = nsXBLPrototypeBinding::ReadNewBinding(stream, docInfo, doc, flags);
     if (NS_FAILED(rv)) {
-      delete binding;
       return rv;
     }
   }
 
   docInfo.swap(*aDocInfo);
   return NS_OK;
 }
 
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -1034,16 +1034,33 @@ nsXBLPrototypeBinding::Read(nsIObjectInp
   if (isFirstBinding) {
     aDocInfo->SetFirstPrototypeBinding(this);
   }
 
   cleanup.Disconnect();
   return NS_OK;
 }
 
+// static
+nsresult
+nsXBLPrototypeBinding::ReadNewBinding(nsIObjectInputStream* aStream,
+                                      nsXBLDocumentInfo* aDocInfo,
+                                      nsIDocument* aDocument,
+                                      uint8_t aFlags)
+{
+  // If the Read() succeeds, |binding| will end up being owned by aDocInfo's
+  // binding table. Otherwise, we must manually delete it.
+  nsXBLPrototypeBinding* binding = new nsXBLPrototypeBinding();
+  nsresult rv = binding->Read(aStream, aDocInfo, aDocument, aFlags);
+  if (NS_FAILED(rv)) {
+    delete binding;
+  }
+  return rv;
+}
+
 static PLDHashOperator
 WriteInterfaceID(const nsIID& aKey, nsIContent* aData, void* aClosure)
 {
   // We can just write out the ids. The cache will be invalidated when a
   // different build is used, so we don't need to worry about ids changing.
   static_cast<nsIObjectOutputStream *>(aClosure)->WriteID(aKey);
   return PL_DHASH_NEXT;
 }
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -140,29 +140,36 @@ public:
     if (!mKeyHandlersRegistered) {
       CreateKeyHandlers();
       mKeyHandlersRegistered = true;
     }
 
     return &mKeyHandlers;
   }
 
+private:
+  nsresult Read(nsIObjectInputStream* aStream,
+                nsXBLDocumentInfo* aDocInfo,
+                nsIDocument* aDocument,
+                uint8_t aFlags);
+
   /**
-   * Read this binding from the stream aStream into the xbl document aDocument.
+   * Read a new binding from the stream aStream into the xbl document aDocument.
    * aDocInfo should be the xbl document info for the binding document.
    * aFlags can contain XBLBinding_Serialize_InheritStyle to indicate that
    * mInheritStyle flag should be set, and XBLBinding_Serialize_IsFirstBinding
    * to indicate the first binding in a document.
    * XBLBinding_Serialize_ChromeOnlyContent indicates that
    * nsXBLPrototypeBinding::mChromeOnlyContent should be true.
    */
-  nsresult Read(nsIObjectInputStream* aStream,
-                nsXBLDocumentInfo* aDocInfo,
-                nsIDocument* aDocument,
-                uint8_t aFlags);
+public:
+  static nsresult ReadNewBinding(nsIObjectInputStream* aStream,
+                                 nsXBLDocumentInfo* aDocInfo,
+                                 nsIDocument* aDocument,
+                                 uint8_t aFlags);
 
   /**
    * Write this binding to the stream.
    */
   nsresult Write(nsIObjectOutputStream* aStream);
 
   /**
    * Read a content node from aStream and return it in aChild.
--- a/embedding/components/commandhandler/src/nsCommandParams.cpp
+++ b/embedding/components/commandhandler/src/nsCommandParams.cpp
@@ -37,19 +37,18 @@ nsCommandParams::nsCommandParams()
 nsCommandParams::~nsCommandParams()
 {
   PL_DHashTableFinish(&mValuesHash);
 }
 
 nsresult
 nsCommandParams::Init()
 {
-  if (!PL_DHashTableInit(&mValuesHash, &sHashOps, (void *)this, sizeof(HashEntry), 4))
-    return NS_ERROR_FAILURE;
-    
+  PL_DHashTableInit(&mValuesHash, &sHashOps, (void *)this, sizeof(HashEntry), 4);
+
   return NS_OK;
 }
 
 #if 0
 #pragma mark -
 #endif
 
 /* short getValueType (in string name); */
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -600,22 +600,17 @@ public:
             StringHash,
             HashMatchEntry,
             MoveEntry,
             PL_DHashClearEntryStub,
             PL_DHashFinalizeStub,
             nullptr
         };
 
-        if (!PL_DHashTableInit(&mMap, &mOps, nullptr,
-                               sizeof(FNCMapEntry), 0))
-        {
-            mMap.ops = nullptr;
-            LOG(("initializing the map failed"));
-        }
+        PL_DHashTableInit(&mMap, &mOps, nullptr, sizeof(FNCMapEntry), 0);
 
         NS_ABORT_IF_FALSE(XRE_GetProcessType() == GeckoProcessType_Default,
                           "StartupCacheFontNameCache should only be used in chrome process");
         mCache = mozilla::scache::StartupCache::GetSingleton();
 
         Init();
     }
 
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -857,23 +857,30 @@ static inline JS_VALUE_CONSTEXPR JS::Val
  * bit pattern restrictions.
  */
 static MOZ_ALWAYS_INLINE double
 GenericNaN()
 {
   return mozilla::SpecificNaN<double>(0, 0x8000000000000ULL);
 }
 
+/* MSVC with PGO miscompiles this function. */
+#if defined(_MSC_VER)
+# pragma optimize("g", off)
+#endif
 static inline double
 CanonicalizeNaN(double d)
 {
     if (MOZ_UNLIKELY(mozilla::IsNaN(d)))
         return GenericNaN();
     return d;
 }
+#if defined(_MSC_VER)
+# pragma optimize("", on)
+#endif
 
 /*
  * JS::Value is the interface for a single JavaScript Engine value.  A few
  * general notes on JS::Value:
  *
  * - JS::Value has setX() and isX() members for X in
  *
  *     { Int32, Double, String, Boolean, Undefined, Null, Object, Magic }
--- a/js/src/frontend/ParseNode.h
+++ b/js/src/frontend/ParseNode.h
@@ -490,28 +490,36 @@ class ParseNode
     /* Boolean attributes. */
     bool isInParens() const                { return pn_parens; }
     void setInParens(bool enabled)         { pn_parens = enabled; }
     bool isUsed() const                    { return pn_used; }
     void setUsed(bool enabled)             { pn_used = enabled; }
     bool isDefn() const                    { return pn_defn; }
     void setDefn(bool enabled)             { pn_defn = enabled; }
 
+    static const unsigned NumDefinitionFlagBits = 10;
+    static const unsigned NumListFlagBits = 10;
+    static const unsigned NumBlockIdBits = 22;
+    static_assert(NumDefinitionFlagBits == NumListFlagBits,
+                  "Assumed below to achieve consistent blockid offset");
+    static_assert(NumDefinitionFlagBits + NumBlockIdBits <= 32,
+                  "This is supposed to fit in a single uint32_t");
+
     TokenPos            pn_pos;         /* two 16-bit pairs here, for 64 bits */
     int32_t             pn_offset;      /* first generated bytecode offset */
     ParseNode           *pn_next;       /* intrinsic link in parent PN_LIST */
     ParseNode           *pn_link;       /* def/use link (alignment freebie) */
 
     union {
         struct {                        /* list of next-linked nodes */
             ParseNode   *head;          /* first node in list */
             ParseNode   **tail;         /* ptr to ptr to last node in list */
             uint32_t    count;          /* number of nodes in list */
-            uint32_t    xflags:12,      /* extra flags, see below */
-                        blockid:20;     /* see name variant below */
+            uint32_t    xflags:NumListFlagBits, /* see PNX_* below */
+                        blockid:NumBlockIdBits; /* see name variant below */
         } list;
         struct {                        /* ternary: if, for(;;), ?: */
             ParseNode   *kid1;          /* condition, discriminant, etc. */
             ParseNode   *kid2;          /* then-part, case list, etc. */
             ParseNode   *kid3;          /* else-part, default case, etc. */
         } ternary;
         struct {                        /* two kids if binary */
             ParseNode   *left;
@@ -536,19 +544,19 @@ class ParseNode
                 ParseNode   *expr;      /* module or function body, var
                                            initializer, argument default, or
                                            base object of PNK_DOT */
                 Definition  *lexdef;    /* lexical definition for this use */
             };
             UpvarCookie cookie;         /* upvar cookie with absolute frame
                                            level (not relative skip), possibly
                                            in current frame */
-            uint32_t    dflags:12,      /* definition/use flags, see below */
-                        blockid:20;     /* block number, for subset dominance
-                                           computation */
+            uint32_t    dflags:NumDefinitionFlagBits, /* see PND_* below */
+                        blockid:NumBlockIdBits;  /* block number, for subset dominance
+                                                    computation */
         } name;
         struct {
             double      value;          /* aligned numeric literal value */
             DecimalPoint decimalPoint;  /* Whether the number has a decimal point */
         } number;
         class {
             friend class LoopControlStatement;
             PropertyName     *label;    /* target of break/continue statement */
@@ -638,48 +646,52 @@ class ParseNode
     Definition *maybeLexDef() { return pn_used ? lexdef() : nullptr; }
 
     Definition *resolve();
 
 /* PN_CODE and PN_NAME pn_dflags bits. */
 #define PND_LET                 0x01    /* let (block-scoped) binding */
 #define PND_CONST               0x02    /* const binding (orthogonal to let) */
 #define PND_ASSIGNED            0x04    /* set if ever LHS of assignment */
-#define PND_PLACEHOLDER         0x10    /* placeholder definition for lexdep */
-#define PND_BOUND               0x20    /* bound to a stack or global slot */
-#define PND_DEOPTIMIZED         0x40    /* former pn_used name node, pn_lexdef
+#define PND_PLACEHOLDER         0x08    /* placeholder definition for lexdep */
+#define PND_BOUND               0x10    /* bound to a stack or global slot */
+#define PND_DEOPTIMIZED         0x20    /* former pn_used name node, pn_lexdef
                                            still valid, but this use no longer
                                            optimizable via an upvar opcode */
-#define PND_CLOSED              0x80    /* variable is closed over */
-#define PND_DEFAULT            0x100    /* definition is an arg with a default */
-#define PND_IMPLICITARGUMENTS  0x200    /* the definition is a placeholder for
+#define PND_CLOSED              0x40    /* variable is closed over */
+#define PND_DEFAULT             0x80    /* definition is an arg with a default */
+#define PND_IMPLICITARGUMENTS  0x100    /* the definition is a placeholder for
                                            'arguments' that has been converted
                                            into a definition after the function
                                            body has been parsed. */
-#define PND_EMITTEDFUNCTION    0x400    /* hoisted function that was emitted */
+#define PND_EMITTEDFUNCTION    0x200    /* hoisted function that was emitted */
+
+    static_assert(PND_EMITTEDFUNCTION < (1 << NumDefinitionFlagBits), "Not enough bits");
 
 /* Flags to propagate from uses to definition. */
 #define PND_USE2DEF_FLAGS (PND_ASSIGNED | PND_CLOSED)
 
 /* PN_LIST pn_xflags bits. */
-#define PNX_POPVAR      0x04            /* PNK_VAR or PNK_CONST last result
+#define PNX_POPVAR      0x01            /* PNK_VAR or PNK_CONST last result
                                            needs popping */
-#define PNX_GROUPINIT   0x08            /* var [a, b] = [c, d]; unit list */
-#define PNX_FUNCDEFS    0x10            /* contains top-level function statements */
-#define PNX_SETCALL     0x20            /* call expression in lvalue context */
-#define PNX_DESTRUCT    0x40            /* destructuring special cases:
+#define PNX_GROUPINIT   0x02            /* var [a, b] = [c, d]; unit list */
+#define PNX_FUNCDEFS    0x04            /* contains top-level function statements */
+#define PNX_SETCALL     0x08            /* call expression in lvalue context */
+#define PNX_DESTRUCT    0x10            /* destructuring special cases:
                                            1. shorthand syntax used, at present
                                               object destructuring ({x,y}) only;
                                            2. code evaluating destructuring
                                               arguments occurs before function
                                               body */
-#define PNX_SPECIALARRAYINIT 0x80       /* one or more of
+#define PNX_SPECIALARRAYINIT 0x20       /* one or more of
                                            1. array initialiser has holes
                                            2. array initializer has spread node */
-#define PNX_NONCONST   0x100            /* initialiser has non-constants */
+#define PNX_NONCONST    0x40            /* initialiser has non-constants */
+
+    static_assert(PNX_NONCONST < (1 << NumListFlagBits), "Not enough bits");
 
     unsigned frameLevel() const {
         JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
         return pn_cookie.level();
     }
 
     uint32_t frameSlot() const {
         JS_ASSERT(pn_arity == PN_CODE || pn_arity == PN_NAME);
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -60,25 +60,27 @@ typedef Handle<NestedScopeObject*> Handl
 #define MUST_MATCH_TOKEN(tt, errno)                                                         \
     JS_BEGIN_MACRO                                                                          \
         if (tokenStream.getToken() != tt) {                                                 \
             report(ParseError, false, null(), errno);                                       \
             return null();                                                                  \
         }                                                                                   \
     JS_END_MACRO
 
+static const unsigned BlockIdLimit = 1 << ParseNode::NumBlockIdBits;
+
 template <typename ParseHandler>
 bool
 GenerateBlockId(TokenStream &ts, ParseContext<ParseHandler> *pc, uint32_t &blockid)
 {
-    if (pc->blockidGen == JS_BIT(20)) {
+    if (pc->blockidGen == BlockIdLimit) {
         ts.reportError(JSMSG_NEED_DIET, "program");
         return false;
     }
-    JS_ASSERT(pc->blockidGen < JS_BIT(20));
+    JS_ASSERT(pc->blockidGen < BlockIdLimit);
     blockid = pc->blockidGen++;
     return true;
 }
 
 template bool
 GenerateBlockId(TokenStream &ts, ParseContext<SyntaxParseHandler> *pc, uint32_t &blockid);
 
 template bool
@@ -5820,17 +5822,17 @@ BumpStaticLevel(TokenStream &ts, ParseNo
     return pn->pn_cookie.set(ts, level, pn->pn_cookie.slot());
 }
 
 template <typename ParseHandler>
 static bool
 AdjustBlockId(TokenStream &ts, ParseNode *pn, unsigned adjust, ParseContext<ParseHandler> *pc)
 {
     JS_ASSERT(pn->isArity(PN_LIST) || pn->isArity(PN_CODE) || pn->isArity(PN_NAME));
-    if (JS_BIT(20) - pn->pn_blockid <= adjust + 1) {
+    if (BlockIdLimit - pn->pn_blockid <= adjust + 1) {
         ts.reportError(JSMSG_NEED_DIET, "program");
         return false;
     }
     pn->pn_blockid += adjust;
     if (pn->pn_blockid >= pc->blockidGen)
         pc->blockidGen = pn->pn_blockid + 1;
     return true;
 }
--- a/js/src/jit-test/tests/basic/testBug773108.js
+++ b/js/src/jit-test/tests/basic/testBug773108.js
@@ -1,10 +1,11 @@
 // |jit-test| error:InternalError
 
 Function("\
 for each(l in[(let(c)([])\
 for each(l in[]))(let(c)w for(u in[]))(let(u)w for(l in[]))(let(c)w for(u in[]))\
 (let(u)w for each(l in[]))(let(c)w for(u in[]))(let(u)w for(l in[]))(let(c)w for(u in[]))\
+(let(u)w for each(l in[]))(let(c)w for(u in[]))(let(u)w for(l in[]))(let(c)w for(u in[]))\
 (let(l)w for(l in[]))(let(u)w for(l in['']))(let(c)w for(u in[]))(let(u)w for(l in[]))\
 (let(c)w for(l in[]))(let(l)w for(l in[]))(let(c)w for(l in[]))(let(u)w for(l in[]))\
 (let(c)w for(l in[]))(let(u)w for each(l in[x]))(let(w,x)w for(u in[]))]){}\
 ")
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-975959.js
@@ -0,0 +1,17 @@
+try {
+    y = z = [];
+    y[1] = x
+    for (var e, x = [];; d) {}
+} catch (e) {}
+try {
+    Object.defineProperty(this, "y", {
+        get: function() {
+            z.filterPar(function() {})
+        }
+    })(1 instanceof 2)
+} catch (e) {}
+y
+verifyprebarriers()
+y
+verifyprebarriers()
+y
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1836,39 +1836,16 @@ CodeGenerator::visitPostWriteBarrierV(LP
     masm.branchPtr(Assembler::Below, valuereg, ImmWord(nursery.heapEnd()), ool->entry());
 
     masm.bind(ool->rejoin());
 #endif
     return true;
 }
 
 bool
-CodeGenerator::visitPostWriteBarrierAllSlots(LPostWriteBarrierAllSlots *lir)
-{
-#ifdef JSGC_GENERATIONAL
-    OutOfLineCallPostWriteBarrier *ool = new(alloc()) OutOfLineCallPostWriteBarrier(lir, lir->object());
-    if (!addOutOfLineCode(ool))
-        return false;
-
-    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-
-    if (lir->object()->isConstant()) {
-        JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
-        return true;
-    }
-
-    Register objreg = ToRegister(lir->object());
-    masm.branchPtr(Assembler::Below, objreg, ImmWord(nursery.start()), ool->entry());
-    masm.branchPtr(Assembler::AboveOrEqual, objreg, ImmWord(nursery.heapEnd()), ool->entry());
-    masm.bind(ool->rejoin());
-#endif
-    return true;
-}
-
-bool
 CodeGenerator::visitCallNative(LCallNative *call)
 {
     JSFunction *target = call->getSingleTarget();
     JS_ASSERT(target);
     JS_ASSERT(target->isNative());
 
     int callargslot = call->argslot();
     int unusedStack = StackOffsetOfPassedArg(callargslot);
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -108,17 +108,16 @@ class CodeGenerator : public CodeGenerat
     bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
     bool visitMaybeToDoubleElement(LMaybeToDoubleElement *lir);
     bool visitGuardObjectIdentity(LGuardObjectIdentity *guard);
     bool visitTypeBarrierV(LTypeBarrierV *lir);
     bool visitTypeBarrierO(LTypeBarrierO *lir);
     bool visitMonitorTypes(LMonitorTypes *lir);
     bool visitPostWriteBarrierO(LPostWriteBarrierO *lir);
     bool visitPostWriteBarrierV(LPostWriteBarrierV *lir);
-    bool visitPostWriteBarrierAllSlots(LPostWriteBarrierAllSlots *lir);
     bool visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier *ool);
     bool visitCallNative(LCallNative *call);
     bool emitCallInvokeFunction(LInstruction *call, Register callereg,
                                 uint32_t argc, uint32_t unusedStack);
     bool visitCallGeneric(LCallGeneric *call);
     bool visitCallKnown(LCallKnown *call);
     bool emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize);
     void emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSpace);
--- a/js/src/jit/IonMacroAssembler.cpp
+++ b/js/src/jit/IonMacroAssembler.cpp
@@ -649,24 +649,23 @@ MacroAssembler::newGCThing(const Registe
 #endif
 
     // Don't execute the inline path if the compartment has an object metadata callback,
     // as the metadata to use for the object may vary between executions of the op.
     if (GetIonContext()->compartment->hasObjectMetadataCallback())
         jump(fail);
 
 #ifdef JSGC_GENERATIONAL
-    const Nursery &nursery = GetIonContext()->runtime->gcNursery();
-    if (nursery.isEnabled() &&
-        allocKind <= gc::FINALIZE_OBJECT_LAST &&
-        initialHeap != gc::TenuredHeap)
-    {
+    // Always use nursery allocation if it is possible to do so. The jit
+    // assumes a nursery pointer is returned to avoid barriers.
+    if (allocKind <= gc::FINALIZE_OBJECT_LAST && initialHeap != gc::TenuredHeap) {
         // Inline Nursery::allocate. No explicit check for nursery.isEnabled()
         // is needed, as the comparison with the nursery's end will always fail
         // in such cases.
+        const Nursery &nursery = GetIonContext()->runtime->gcNursery();
         loadPtr(AbsoluteAddress(nursery.addressOfPosition()), result);
         addPtr(Imm32(thingSize), result);
         branchPtr(Assembler::BelowOrEqual, AbsoluteAddress(nursery.addressOfCurrentEnd()), result, fail);
         storePtr(result, AbsoluteAddress(nursery.addressOfPosition()));
         subPtr(Imm32(thingSize), result);
         return;
     }
 #endif // JSGC_GENERATIONAL
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -5413,34 +5413,16 @@ class LPostWriteBarrierV : public LInstr
     const LAllocation *object() {
         return getOperand(0);
     }
     const LDefinition *temp() {
         return getTemp(0);
     }
 };
 
-// Generational write barrier used when writing to multiple slots in an object.
-class LPostWriteBarrierAllSlots : public LInstructionHelper<0, 1, 0>
-{
-  public:
-    LIR_HEADER(PostWriteBarrierAllSlots)
-
-    LPostWriteBarrierAllSlots(const LAllocation &obj) {
-        setOperand(0, obj);
-    }
-
-    const MPostWriteBarrier *mir() const {
-        return mir_->toPostWriteBarrier();
-    }
-    const LAllocation *object() {
-        return getOperand(0);
-    }
-};
-
 // Guard against an object's identity.
 class LGuardObjectIdentity : public LInstructionHelper<0, 1, 0>
 {
   public:
     LIR_HEADER(GuardObjectIdentity)
 
     LGuardObjectIdentity(const LAllocation &in) {
         setOperand(0, in);
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -174,17 +174,16 @@
     _(GuardObjectIdentity)          \
     _(GuardClass)                   \
     _(GuardThreadExclusive)         \
     _(TypeBarrierV)                 \
     _(TypeBarrierO)                 \
     _(MonitorTypes)                 \
     _(PostWriteBarrierO)            \
     _(PostWriteBarrierV)            \
-    _(PostWriteBarrierAllSlots)     \
     _(InitializedLength)            \
     _(SetInitializedLength)         \
     _(NeuterCheck)                  \
     _(BoundsCheck)                  \
     _(BoundsCheckRange)             \
     _(BoundsCheckLower)             \
     _(LoadElementV)                 \
     _(LoadElementT)                 \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -2259,21 +2259,16 @@ LIRGenerator::visitMonitorTypes(MMonitor
         return false;
     return assignSnapshot(lir, Bailout_Normal) && add(lir, ins);
 }
 
 bool
 LIRGenerator::visitPostWriteBarrier(MPostWriteBarrier *ins)
 {
 #ifdef JSGC_GENERATIONAL
-    if (!ins->hasValue()) {
-        LPostWriteBarrierAllSlots *lir =
-            new(alloc()) LPostWriteBarrierAllSlots(useRegisterOrConstant(ins->object()));
-        return add(lir, ins) && assignSafepoint(lir, ins);
-    }
     switch (ins->value()->type()) {
       case MIRType_Object: {
         LPostWriteBarrierO *lir = new(alloc()) LPostWriteBarrierO(useRegisterOrConstant(ins->object()),
                                                          useRegister(ins->value()));
         return add(lir, ins) && assignSafepoint(lir, ins);
       }
       case MIRType_Value: {
         LPostWriteBarrierV *lir =
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -8880,24 +8880,20 @@ class MMonitorTypes : public MUnaryInstr
     }
     AliasSet getAliasSet() const {
         return AliasSet::None();
     }
 };
 
 // Given a value being written to another object, update the generational store
 // buffer if the value is in the nursery and object is in the tenured heap.
-class MPostWriteBarrier
-  : public MBinaryInstruction,
-    public ObjectPolicy<0>
-{
-    bool hasValue_;
-
+class MPostWriteBarrier : public MBinaryInstruction, public ObjectPolicy<0>
+{
     MPostWriteBarrier(MDefinition *obj, MDefinition *value)
-      : MBinaryInstruction(obj, value), hasValue_(true)
+      : MBinaryInstruction(obj, value)
     {
         setGuard();
     }
 
   public:
     INSTRUCTION_HEADER(PostWriteBarrier)
 
     static MPostWriteBarrier *New(TempAllocator &alloc, MDefinition *obj, MDefinition *value) {
@@ -8907,22 +8903,20 @@ class MPostWriteBarrier
     TypePolicy *typePolicy() {
         return this;
     }
 
     MDefinition *object() const {
         return getOperand(0);
     }
 
-    bool hasValue() const {
-        return hasValue_;
-    }
     MDefinition *value() const {
         return getOperand(1);
     }
+
 #ifdef DEBUG
     bool isConsistentFloat32Use(MUse *use) const {
         // During lowering, values that neither have object nor value MIR type
         // are ignored, thus Float32 can show up at this point without any issue.
         return use->index() == 1;
     }
 #endif
 };
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -5518,22 +5518,22 @@ AutoMaybeTouchDeadZones::AutoMaybeTouchD
     inIncremental(JS::IsIncrementalGCInProgress(runtime)),
     manipulatingDeadZones(runtime->gcManipulatingDeadZones)
 {
     runtime->gcManipulatingDeadZones = true;
 }
 
 AutoMaybeTouchDeadZones::~AutoMaybeTouchDeadZones()
 {
+    runtime->gcManipulatingDeadZones = manipulatingDeadZones;
+
     if (inIncremental && runtime->gcObjectsMarkedInDeadZones != markCount) {
         JS::PrepareForFullGC(runtime);
         js::GC(runtime, GC_NORMAL, JS::gcreason::TRANSPLANT);
     }
-
-    runtime->gcManipulatingDeadZones = manipulatingDeadZones;
 }
 
 AutoSuppressGC::AutoSuppressGC(ExclusiveContext *cx)
   : suppressGC_(cx->perThreadData->suppressGC)
 {
     suppressGC_++;
 }
 
--- a/js/src/tests/js1_8_5/regress/regress-610026.js
+++ b/js/src/tests/js1_8_5/regress/regress-610026.js
@@ -7,17 +7,17 @@
 var expect = "pass";
 var actual;
 
 /*
  * We hardcode here that GenerateBlockId limits a program to 2^20 blocks. Start
  * with 2^19 blocks, then test 2^20 - 1 blocks, finally test the limit.
  */
 var s = "{}";
-for (var i = 0; i < 19; i++)
+for (var i = 0; i < 21; i++)
     s += s;
 
 try {
     eval(s);
     actual = "pass";
 } catch (e) {
     actual = "fail: " + e;
 }
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -164,21 +164,18 @@ nsFrameManager::GetPlaceholderFrameFor(c
 
 nsresult
 nsFrameManager::RegisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame)
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
   NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
                   "unexpected frame type");
   if (!mPlaceholderMap.ops) {
-    if (!PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps, nullptr,
-                           sizeof(PlaceholderMapEntry), 16)) {
-      mPlaceholderMap.ops = nullptr;
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
+    PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps, nullptr,
+                      sizeof(PlaceholderMapEntry), 16);
   }
   PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>(PL_DHashTableOperate(&mPlaceholderMap,
                               aPlaceholderFrame->GetOutOfFlowFrame(),
                               PL_DHASH_ADD));
   if (!entry)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -3197,17 +3197,17 @@ struct CascadeEnumData {
       mFontFaceRules(aFontFaceRules),
       mKeyframesRules(aKeyframesRules),
       mFontFeatureValuesRules(aFontFeatureValuesRules),
       mPageRules(aPageRules),
       mCacheKey(aKey),
       mSheetType(aSheetType)
   {
     if (!PL_DHashTableInit(&mRulesByWeight, &gRulesByWeightOps, nullptr,
-                          sizeof(RuleByWeightEntry), 64))
+                           sizeof(RuleByWeightEntry), 64, fallible_t()))
       mRulesByWeight.ops = nullptr;
 
     // Initialize our arena
     PL_INIT_ARENA_POOL(&mArena, "CascadeEnumDataArena",
                        NS_CASCADEENUMDATA_ARENA_BLOCK_SIZE);
   }
 
   ~CascadeEnumData()
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -472,22 +472,18 @@ nsHTMLStyleSheet::SetVisitedLinkColor(ns
 {
   return ImplLinkColorSetter(mVisitedRule, aColor);
 }
 
 already_AddRefed<nsMappedAttributes>
 nsHTMLStyleSheet::UniqueMappedAttributes(nsMappedAttributes* aMapped)
 {
   if (!mMappedAttrTable.ops) {
-    bool res = PL_DHashTableInit(&mMappedAttrTable, &MappedAttrTable_Ops,
-                                   nullptr, sizeof(MappedAttrTableEntry), 16);
-    if (!res) {
-      mMappedAttrTable.ops = nullptr;
-      return nullptr;
-    }
+    PL_DHashTableInit(&mMappedAttrTable, &MappedAttrTable_Ops,
+                      nullptr, sizeof(MappedAttrTableEntry), 16);
   }
   MappedAttrTableEntry *entry = static_cast<MappedAttrTableEntry*>
                                            (PL_DHashTableOperate(&mMappedAttrTable, aMapped, PL_DHASH_ADD));
   if (!entry)
     return nullptr;
   if (!entry->mAttributes) {
     // We added a new entry to the hashtable, so we have a new unique set.
     entry->mAttributes = aMapped;
@@ -510,23 +506,18 @@ nsHTMLStyleSheet::DropMappedAttributes(n
 
   NS_ASSERTION(entryCount == mMappedAttrTable.entryCount, "not removed");
 }
 
 nsIStyleRule*
 nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
 {
   if (!mLangRuleTable.ops) {
-    bool res = PL_DHashTableInit(&mLangRuleTable, &LangRuleTable_Ops,
-                                 nullptr, sizeof(LangRuleTableEntry), 16);
-    if (!res) {
-      NS_ASSERTION(false, "out of memory");
-      mLangRuleTable.ops = nullptr;
-      return nullptr;
-    }
+    PL_DHashTableInit(&mLangRuleTable, &LangRuleTable_Ops,
+                      nullptr, sizeof(LangRuleTableEntry), 16);
   }
   LangRuleTableEntry *entry = static_cast<LangRuleTableEntry*>
     (PL_DHashTableOperate(&mLangRuleTable, &aLanguage, PL_DHASH_ADD));
   if (!entry) {
     NS_ASSERTION(false, "out of memory");
     return nullptr;
   }
   return entry->mRule;
--- a/layout/tables/SpanningCellSorter.cpp
+++ b/layout/tables/SpanningCellSorter.cpp
@@ -70,22 +70,19 @@ SpanningCellSorter::AddCell(int32_t aCol
     i->row = aRow;
     i->col = aCol;
 
     if (UseArrayForSpan(aColSpan)) {
         int32_t index = SpanToIndex(aColSpan);
         i->next = mArray[index];
         mArray[index] = i;
     } else {
-        if (!mHashTable.entryCount &&
-            !PL_DHashTableInit(&mHashTable, &HashTableOps, nullptr,
-                               sizeof(HashTableEntry), PL_DHASH_MIN_SIZE)) {
-            NS_NOTREACHED("table init failed");
-            mHashTable.entryCount = 0;
-            return false;
+        if (!mHashTable.entryCount) {
+            PL_DHashTableInit(&mHashTable, &HashTableOps, nullptr,
+                              sizeof(HashTableEntry), PL_DHASH_MIN_SIZE);
         }
         HashTableEntry *entry = static_cast<HashTableEntry*>
                                            (PL_DHashTableOperate(&mHashTable, NS_INT32_TO_PTR(aColSpan),
                                  PL_DHASH_ADD));
         NS_ENSURE_TRUE(entry, false);
 
         NS_ASSERTION(entry->mColSpan == 0 || entry->mColSpan == aColSpan,
                      "wrong entry");
--- a/modules/libpref/src/prefapi.cpp
+++ b/modules/libpref/src/prefapi.cpp
@@ -144,18 +144,18 @@ enum {
 static nsresult pref_HashPref(const char *key, PrefValue value, PrefType type, uint32_t flags);
 
 #define PREF_HASHTABLE_INITIAL_SIZE	2048
 
 nsresult PREF_Init()
 {
     if (!gHashTable.ops) {
         if (!PL_DHashTableInit(&gHashTable, &pref_HashTableOps, nullptr,
-                               sizeof(PrefHashEntry),
-                               PREF_HASHTABLE_INITIAL_SIZE)) {
+                               sizeof(PrefHashEntry), PREF_HASHTABLE_INITIAL_SIZE,
+                               fallible_t())) {
             gHashTable.ops = nullptr;
             return NS_ERROR_OUT_OF_MEMORY;
         }
 
         PL_INIT_ARENA_POOL(&gPrefNameArena, "PrefNameArena",
                            PREFNAME_ARENA_SIZE);
     }
     return NS_OK;
--- a/netwerk/base/src/nsLoadGroup.cpp
+++ b/netwerk/base/src/nsLoadGroup.cpp
@@ -1163,21 +1163,17 @@ nsresult nsLoadGroup::Init()
         PL_DHashVoidPtrKeyStub,
         RequestHashMatchEntry,
         PL_DHashMoveEntryStub,
         RequestHashClearEntry,
         PL_DHashFinalizeStub,
         RequestHashInitEntry
     };
 
-    if (!PL_DHashTableInit(&mRequests, &hash_table_ops, nullptr,
-                           sizeof(RequestMapEntry), 16)) {
-        mRequests.ops = nullptr;
-
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
+    PL_DHashTableInit(&mRequests, &hash_table_ops, nullptr,
+                      sizeof(RequestMapEntry), 16);
 
     mConnectionInfo = new nsLoadGroupConnectionInfo();
 
     return NS_OK;
 }
 
 #undef LOG
--- a/netwerk/cache/nsCacheEntry.cpp
+++ b/netwerk/cache/nsCacheEntry.cpp
@@ -402,20 +402,21 @@ nsCacheEntryHashTable::~nsCacheEntryHash
 }
 
 
 nsresult
 nsCacheEntryHashTable::Init()
 {
     nsresult rv = NS_OK;
     initialized = PL_DHashTableInit(&table, &ops, nullptr,
-                                           sizeof(nsCacheEntryHashTableEntry), 512);
+                                    sizeof(nsCacheEntryHashTableEntry),
+                                    512, fallible_t());
 
     if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
-    
+
     return rv;
 }
 
 void
 nsCacheEntryHashTable::Shutdown()
 {
     if (initialized) {
         PL_DHashTableFinish(&table);
--- a/netwerk/cache/nsDiskCacheBinding.cpp
+++ b/netwerk/cache/nsDiskCacheBinding.cpp
@@ -145,20 +145,19 @@ nsDiskCacheBindery::~nsDiskCacheBindery(
     Reset();
 }
 
 
 nsresult
 nsDiskCacheBindery::Init()
 {
     nsresult rv = NS_OK;
-    initialized = PL_DHashTableInit(&table, &ops, nullptr, sizeof(HashTableEntry), 0);
+    PL_DHashTableInit(&table, &ops, nullptr, sizeof(HashTableEntry), 0);
+    initialized = true;
 
-    if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY;
-    
     return rv;
 }
 
 void
 nsDiskCacheBindery::Reset()
 {
     if (initialized) {
         PL_DHashTableFinish(&table);
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -103,18 +103,19 @@ nsHttp::CreateAtomTable()
 
     if (!sLock) {
         sLock = new Mutex("nsHttp.sLock");
     }
 
     // The capacity for this table is initialized to a value greater than the
     // number of known atoms (NUM_HTTP_ATOMS) because we expect to encounter a
     // few random headers right off the bat.
-    if (!PL_DHashTableInit(&sAtomTable, &ops, nullptr, sizeof(PLDHashEntryStub),
-                           NUM_HTTP_ATOMS + 10)) {
+    if (!PL_DHashTableInit(&sAtomTable, &ops, nullptr,
+                           sizeof(PLDHashEntryStub),
+                           NUM_HTTP_ATOMS + 10, fallible_t())) {
         sAtomTable.ops = nullptr;
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // fill the table with our known atoms
     const char *const atoms[] = {
 #define HTTP_ATOM(_name, _value) nsHttp::_name._val,
 #include "nsHttpAtomList.h"
--- a/parser/htmlparser/src/nsHTMLEntities.cpp
+++ b/parser/htmlparser/src/nsHTMLEntities.cpp
@@ -86,23 +86,25 @@ static const EntityNode gEntityArray[] =
 #define NS_HTML_ENTITY_COUNT ((int32_t)ArrayLength(gEntityArray))
 
 nsresult
 nsHTMLEntities::AddRefTable(void) 
 {
   if (!gTableRefCnt) {
     if (!PL_DHashTableInit(&gEntityToUnicode, &EntityToUnicodeOps,
                            nullptr, sizeof(EntityNodeEntry),
-                           uint32_t(NS_HTML_ENTITY_COUNT / 0.75))) {
+                           uint32_t(NS_HTML_ENTITY_COUNT / 0.75),
+                           fallible_t())) {
       gEntityToUnicode.ops = nullptr;
       return NS_ERROR_OUT_OF_MEMORY;
     }
     if (!PL_DHashTableInit(&gUnicodeToEntity, &UnicodeToEntityOps,
                            nullptr, sizeof(EntityNodeEntry),
-                           uint32_t(NS_HTML_ENTITY_COUNT / 0.75))) {
+                           uint32_t(NS_HTML_ENTITY_COUNT / 0.75),
+                           fallible_t())) {
       PL_DHashTableFinish(&gEntityToUnicode);
       gEntityToUnicode.ops = gUnicodeToEntity.ops = nullptr;
       return NS_ERROR_OUT_OF_MEMORY;
     }
     for (const EntityNode *node = gEntityArray,
                  *node_end = ArrayEnd(gEntityArray);
          node < node_end; ++node) {
 
--- a/rdf/base/src/nsInMemoryDataSource.cpp
+++ b/rdf/base/src/nsInMemoryDataSource.cpp
@@ -775,32 +775,27 @@ InMemoryDataSource::InMemoryDataSource(n
     mPropagateChanges = true;
     MOZ_COUNT_CTOR(InMemoryDataSource);
 }
 
 
 nsresult
 InMemoryDataSource::Init()
 {
-    if (!PL_DHashTableInit(&mForwardArcs,
-                           PL_DHashGetStubOps(),
-                           nullptr,
-                           sizeof(Entry),
-                           PL_DHASH_MIN_SIZE)) {
-        mForwardArcs.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (!PL_DHashTableInit(&mReverseArcs,
-                           PL_DHashGetStubOps(),
-                           nullptr,
-                           sizeof(Entry),
-                           PL_DHASH_MIN_SIZE)) {
-        mReverseArcs.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
+    PL_DHashTableInit(&mForwardArcs,
+                      PL_DHashGetStubOps(),
+                      nullptr,
+                      sizeof(Entry),
+                      PL_DHASH_MIN_SIZE);
+
+    PL_DHashTableInit(&mReverseArcs,
+                      PL_DHashGetStubOps(),
+                      nullptr,
+                      sizeof(Entry),
+                      PL_DHASH_MIN_SIZE);
 
 #ifdef PR_LOGGING
     if (! gLog)
         gLog = PR_NewLogModule("InMemoryDataSource");
 #endif
 
     return NS_OK;
 }
--- a/rdf/base/src/nsRDFService.cpp
+++ b/rdf/base/src/nsRDFService.cpp
@@ -751,41 +751,31 @@ RDFServiceImpl::Init()
                                         PL_HashString,
                                         PL_CompareStrings,
                                         PL_CompareValues,
                                         &dataSourceHashAllocOps, nullptr);
 
     if (! mNamedDataSources)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    if (!PL_DHashTableInit(&mResources, &gResourceTableOps, nullptr,
-                           sizeof(ResourceHashEntry), PL_DHASH_MIN_SIZE)) {
-        mResources.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (!PL_DHashTableInit(&mLiterals, &gLiteralTableOps, nullptr,
-                           sizeof(LiteralHashEntry), PL_DHASH_MIN_SIZE)) {
-        mLiterals.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (!PL_DHashTableInit(&mInts, &gIntTableOps, nullptr,
-                           sizeof(IntHashEntry), PL_DHASH_MIN_SIZE)) {
-        mInts.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (!PL_DHashTableInit(&mDates, &gDateTableOps, nullptr,
-                           sizeof(DateHashEntry), PL_DHASH_MIN_SIZE)) {
-        mDates.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (!PL_DHashTableInit(&mBlobs, &gBlobTableOps, nullptr,
-                           sizeof(BlobHashEntry), PL_DHASH_MIN_SIZE)) {
-        mBlobs.ops = nullptr;
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
+    PL_DHashTableInit(&mResources, &gResourceTableOps, nullptr,
+                      sizeof(ResourceHashEntry), PL_DHASH_MIN_SIZE);
+
+    PL_DHashTableInit(&mLiterals, &gLiteralTableOps, nullptr,
+                      sizeof(LiteralHashEntry), PL_DHASH_MIN_SIZE);
+
+    PL_DHashTableInit(&mInts, &gIntTableOps, nullptr,
+                      sizeof(IntHashEntry), PL_DHASH_MIN_SIZE);
+
+    PL_DHashTableInit(&mDates, &gDateTableOps, nullptr,
+                      sizeof(DateHashEntry), PL_DHASH_MIN_SIZE);
+
+    PL_DHashTableInit(&mBlobs, &gBlobTableOps, nullptr,
+                      sizeof(BlobHashEntry), PL_DHASH_MIN_SIZE);
+
     mDefaultResourceFactory = do_GetClassObject(kRDFDefaultResourceCID, &rv);
     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get default resource factory");
     if (NS_FAILED(rv)) return rv;
 
 #ifdef PR_LOGGING
     if (! gLog)
         gLog = PR_NewLogModule("nsRDFService");
 #endif
--- a/security/manager/ssl/src/nsCertTree.cpp
+++ b/security/manager/ssl/src/nsCertTree.cpp
@@ -182,17 +182,17 @@ void nsCertTree::ClearCompareHash()
     mCompareCache.ops = nullptr;
   }
 }
 
 nsresult nsCertTree::InitCompareHash()
 {
   ClearCompareHash();
   if (!PL_DHashTableInit(&mCompareCache, &gMapOps, nullptr,
-                         sizeof(CompareCacheHashEntryPtr), 128)) {
+                         sizeof(CompareCacheHashEntryPtr), 128, fallible_t())) {
     mCompareCache.ops = nullptr;
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 nsCertTree::~nsCertTree()
 {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -4006,16 +4006,22 @@
     "extended_statistics_ok": true,
     "description": "Number of sites blocked from the new tab page."
   },
   "NEWTAB_PAGE_SHOWN": {
     "expires_in_version": "35",
     "kind": "boolean",
     "description": "Number of times about:newtab was shown from opening a new tab or window."
   },
+  "NEWTAB_PAGE_SITE_CLICKED": {
+    "expires_in_version": "35",
+    "kind": "enumerated",
+    "n_values": 10,
+    "description": "Track click count on about:newtab tiles per index (0-8). For non-default row or column configurations all clicks into the '9' bucket."
+  },
   "PANORAMA_INITIALIZATION_TIME_MS": {
     "expires_in_version": "never",
     "kind": "exponential",
     "high": "10000",
     "n_buckets": 15,
     "extended_statistics_ok": true,
     "description": "Time it takes to initialize Panorama (ms)"
   },
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -123,20 +123,18 @@ nsDocLoader::nsDocLoader()
     PL_DHashVoidPtrKeyStub,
     PL_DHashMatchEntryStub,
     PL_DHashMoveEntryStub,
     RequestInfoHashClearEntry,
     PL_DHashFinalizeStub,
     RequestInfoHashInitEntry
   };
 
-  if (!PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, nullptr,
-                         sizeof(nsRequestInfo), 16)) {
-    mRequestInfoHash.ops = nullptr;
-  }
+  PL_DHashTableInit(&mRequestInfoHash, &hash_table_ops, nullptr,
+                    sizeof(nsRequestInfo), 16);
 
   ClearInternalProgress();
 
   PR_LOG(gDocLoaderLog, PR_LOG_DEBUG, 
          ("DocLoader:%p: created.\n", this));
 }
 
 nsresult
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -733,20 +733,18 @@ public:
         if (mPtrToNodeMap.ops) {
             PL_DHashTableFinish(&mPtrToNodeMap);
         }
     }
 
     void Init()
     {
         MOZ_ASSERT(IsEmpty(), "Failed to call GCGraph::Clear");
-        if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nullptr,
-                               sizeof(PtrToNodeEntry), 32768)) {
-            MOZ_CRASH();
-        }
+        PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nullptr,
+                          sizeof(PtrToNodeEntry), 32768);
     }
 
     void Clear()
     {
         mNodes.Clear();
         mEdges.Clear();
         mWeakMaps.Clear();
         mRootCount = 0;
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -501,21 +501,19 @@ NS_SizeOfAtomTablesIncludingThis(MallocS
   return n;
 }
 
 #define ATOM_HASHTABLE_INITIAL_SIZE  4096
 
 static inline void
 EnsureTableExists()
 {
-  if (!gAtomTable.ops &&
-      !PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0,
-                         sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_SIZE)) {
-    // Initialization failed.
-    NS_ABORT_OOM(ATOM_HASHTABLE_INITIAL_SIZE * sizeof(AtomTableEntry));
+  if (!gAtomTable.ops) {
+    PL_DHashTableInit(&gAtomTable, &AtomTableOps, 0,
+                      sizeof(AtomTableEntry), ATOM_HASHTABLE_INITIAL_SIZE);
   }
 }
 
 static inline AtomTableEntry*
 GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t& aHash)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
   EnsureTableExists();
--- a/xpcom/ds/nsHashtable.cpp
+++ b/xpcom/ds/nsHashtable.cpp
@@ -113,41 +113,39 @@ nsHashKey::~nsHashKey(void)
 
 nsresult
 nsHashKey::Write(nsIObjectOutputStream* aStream) const
 {
     NS_NOTREACHED("oops");
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-nsHashtable::nsHashtable(uint32_t aInitSize, bool threadSafe)
+nsHashtable::nsHashtable(uint32_t aInitSize, bool aThreadSafe)
   : mLock(nullptr), mEnumerating(false)
 {
     MOZ_COUNT_CTOR(nsHashtable);
 
     bool result = PL_DHashTableInit(&mHashtable, &hashtableOps, nullptr,
-                                      sizeof(HTEntry), aInitSize);
-
+                                    sizeof(HTEntry), aInitSize, fallible_t());
     NS_ASSERTION(result, "Hashtable failed to initialize");
 
     // make sure we detect this later
     if (!result)
         mHashtable.ops = nullptr;
 
-    if (threadSafe) {
+    if (aThreadSafe) {
         mLock = PR_NewLock();
         if (mLock == nullptr) {
             // Cannot create a lock. If running on a multiprocessing system
             // we are sure to die.
             PR_ASSERT(mLock != nullptr);
         }
     }
 }
 
-
 nsHashtable::~nsHashtable() {
     MOZ_COUNT_DTOR(nsHashtable);
     if (mHashtable.ops)
         PL_DHashTableFinish(&mHashtable);
     if (mLock) PR_DestroyLock(mLock);
 }
 
 bool nsHashtable::Exists(nsHashKey *aKey)
@@ -339,17 +337,18 @@ nsHashtable::nsHashtable(nsIObjectInputS
 
         if (NS_SUCCEEDED(rv)) {
             uint32_t count;
             rv = aStream->Read32(&count);
 
             if (NS_SUCCEEDED(rv)) {
                 bool status =
                     PL_DHashTableInit(&mHashtable, &hashtableOps,
-                                      nullptr, sizeof(HTEntry), count);
+                                      nullptr, sizeof(HTEntry), count,
+                                      fallible_t());
                 if (!status) {
                     mHashtable.ops = nullptr;
                     rv = NS_ERROR_OUT_OF_MEMORY;
                 } else {
                     for (uint32_t i = 0; i < count; i++) {
                         nsHashKey* key;
                         void *data;
 
--- a/xpcom/ds/nsHashtable.h
+++ b/xpcom/ds/nsHashtable.h
@@ -96,17 +96,17 @@ typedef nsresult
 class nsHashtable {
   protected:
     // members
     PRLock*         mLock;
     PLDHashTable    mHashtable;
     bool            mEnumerating;
 
   public:
-    nsHashtable(uint32_t aSize = 16, bool threadSafe = false);
+    nsHashtable(uint32_t aSize = 16, bool aThreadSafe = false);
     virtual ~nsHashtable();
 
     int32_t Count(void) { return mHashtable.entryCount; }
     bool Exists(nsHashKey *aKey);
     void *Put(nsHashKey *aKey, void *aData);
     void *Get(nsHashKey *aKey);
     void *Remove(nsHashKey *aKey);
     nsHashtable *Clone();
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -3,16 +3,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsArrayEnumerator.h"
 #include "nsID.h"
 #include "nsCOMArray.h"
 #include "nsUnicharInputStream.h"
 #include "nsPrintfCString.h"
+#include "nsAutoPtr.h"
 
 #define PL_ARENA_CONST_ALIGN_MASK 3
 #include "nsPersistentProperties.h"
 #include "nsIProperties.h"
 
 struct PropertyTableEntry : public PLDHashEntryHdr
 {
   // both of these are arena-allocated
@@ -333,19 +334,19 @@ bool nsPropertiesParser::ParseValueChara
 
 NS_METHOD nsPropertiesParser::SegmentWriter(nsIUnicharInputStream* aStream,
                                             void* aClosure,
                                             const char16_t *aFromSegment,
                                             uint32_t aToOffset,
                                             uint32_t aCount,
                                             uint32_t *aWriteCount)
 {
-  nsPropertiesParser *parser = 
+  nsPropertiesParser *parser =
     static_cast<nsPropertiesParser *>(aClosure);
-  
+
   parser->ParseBuffer(aFromSegment, aCount);
 
   *aWriteCount = aCount;
   return NS_OK;
 }
 
 nsresult nsPropertiesParser::ParseBuffer(const char16_t* aBuffer,
                                          uint32_t aBufferLength)
@@ -441,54 +442,37 @@ nsresult nsPropertiesParser::ParseBuffer
 
   return NS_OK;
 }
 
 nsPersistentProperties::nsPersistentProperties()
 : mIn(nullptr)
 {
   mSubclass = static_cast<nsIPersistentProperties*>(this);
-  mTable.ops = nullptr;
+
+  PL_DHashTableInit(&mTable, &property_HashTableOps, nullptr,
+                    sizeof(PropertyTableEntry), 20);
+
   PL_INIT_ARENA_POOL(&mArena, "PersistentPropertyArena", 2048);
 }
 
 nsPersistentProperties::~nsPersistentProperties()
 {
   PL_FinishArenaPool(&mArena);
   if (mTable.ops)
     PL_DHashTableFinish(&mTable);
 }
 
 nsresult
-nsPersistentProperties::Init()
-{
-  if (!PL_DHashTableInit(&mTable, &property_HashTableOps, nullptr,
-                         sizeof(PropertyTableEntry), 20)) {
-    mTable.ops = nullptr;
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_OK;
-}
-
-nsresult
 nsPersistentProperties::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
 {
   if (aOuter)
     return NS_ERROR_NO_AGGREGATION;
-  nsPersistentProperties* props = new nsPersistentProperties();
-  if (props == nullptr)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_ADDREF(props);
-  nsresult rv = props->Init();
-  if (NS_SUCCEEDED(rv))
-    rv = props->QueryInterface(aIID, aResult);
-
-  NS_RELEASE(props);
-  return rv;
+  nsRefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+  return props->QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ISUPPORTS2(nsPersistentProperties, nsIPersistentProperties, nsIProperties)
 
 NS_IMETHODIMP
 nsPersistentProperties::Load(nsIInputStream *aIn)
 {
   nsresult rv = nsSimpleUnicharStreamFactory::GetInstance()->
@@ -508,17 +492,17 @@ nsPersistentProperties::Load(nsIInputStr
          nProcessed != 0);
   mIn = nullptr;
   if (NS_FAILED(rv))
     return rv;
 
   // We may have an unprocessed value at this point
   // if the last line did not have a proper line ending.
   if (parser.GetState() == eParserState_Value) {
-    nsAutoString oldValue;  
+    nsAutoString oldValue;
     parser.FinishValueState(oldValue);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPersistentProperties::SetStringProperty(const nsACString& aKey,
@@ -657,23 +641,18 @@ nsPersistentProperties::GetKeys(uint32_t
 // PropertyElement
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_METHOD
 nsPropertyElement::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
 {
   if (aOuter)
     return NS_ERROR_NO_AGGREGATION;
-  nsPropertyElement* propElem = new nsPropertyElement();
-  if (propElem == nullptr)
-    return NS_ERROR_OUT_OF_MEMORY;
-  NS_ADDREF(propElem);
-  nsresult rv = propElem->QueryInterface(aIID, aResult);
-  NS_RELEASE(propElem);
-  return rv;
+  nsRefPtr<nsPropertyElement> propElem = new nsPropertyElement();
+  return propElem->QueryInterface(aIID, aResult);
 }
 
 NS_IMPL_ISUPPORTS1(nsPropertyElement, nsIPropertyElement)
 
 NS_IMETHODIMP
 nsPropertyElement::GetKey(nsACString& aReturnKey)
 {
   aReturnKey = mKey;
@@ -697,9 +676,8 @@ nsPropertyElement::SetKey(const nsACStri
 NS_IMETHODIMP
 nsPropertyElement::SetValue(const nsAString& aValue)
 {
   mValue = aValue;
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
-
--- a/xpcom/ds/nsPersistentProperties.h
+++ b/xpcom/ds/nsPersistentProperties.h
@@ -14,17 +14,16 @@
 #include "mozilla/Attributes.h"
 
 class nsIUnicharInputStream;
 
 class nsPersistentProperties MOZ_FINAL : public nsIPersistentProperties
 {
 public:
   nsPersistentProperties();
-  nsresult Init();
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIPROPERTIES
   NS_DECL_NSIPERSISTENTPROPERTIES
 
   static nsresult
   Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
--- a/xpcom/ds/nsStaticNameTable.cpp
+++ b/xpcom/ds/nsStaticNameTable.cpp
@@ -133,19 +133,19 @@ nsStaticCaseInsensitiveNameTable::Init(c
     NS_ASSERTION(aNames, "null name table");
     NS_ASSERTION(Count, "0 count");
 
     mNameArray = (nsDependentCString*)
                    nsMemory::Alloc(Count * sizeof(nsDependentCString));
     if (!mNameArray)
         return false;
 
-    if (!PL_DHashTableInit(&mNameTable,
-                           &nametable_CaseInsensitiveHashTableOps,
-                           nullptr, sizeof(NameTableEntry), Count)) {
+    if (!PL_DHashTableInit(&mNameTable, &nametable_CaseInsensitiveHashTableOps,
+                           nullptr, sizeof(NameTableEntry), Count,
+                           fallible_t())) {
         mNameTable.ops = nullptr;
         return false;
     }
 
     for (int32_t index = 0; index < Count; ++index) {
         const char* raw = aNames[index];
 #ifdef DEBUG
         {
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -399,19 +399,17 @@ nsTHashtable<EntryType>::Init(uint32_t a
     s_HashKey,
     s_MatchEntry,
     EntryType::ALLOW_MEMMOVE ? ::PL_DHashMoveEntryStub : s_CopyEntry,
     s_ClearEntry,
     ::PL_DHashFinalizeStub,
     s_InitEntry
   };
 
-  if (!PL_DHashTableInit(&mTable, &sOps, nullptr, sizeof(EntryType), aInitSize)) {
-    NS_ABORT_OOM(sizeof(EntryType) * aInitSize);
-  }
+  PL_DHashTableInit(&mTable, &sOps, nullptr, sizeof(EntryType), aInitSize);
 }
 
 // static definitions
 
 template<class EntryType>
 PLDHashNumber
 nsTHashtable<EntryType>::s_HashKey(PLDHashTable  *table,
                                    const void    *key)
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -168,33 +168,34 @@ SizeOfEntryStore(uint32_t capacity, uint
 
 PLDHashTable *
 PL_NewDHashTable(const PLDHashTableOps *ops, void *data, uint32_t entrySize,
                  uint32_t capacity)
 {
     PLDHashTable *table = (PLDHashTable *) malloc(sizeof *table);
     if (!table)
         return nullptr;
-    if (!PL_DHashTableInit(table, ops, data, entrySize, capacity)) {
+    if (!PL_DHashTableInit(table, ops, data, entrySize, capacity, fallible_t())) {
         free(table);
         return nullptr;
     }
     return table;
 }
 
 void
 PL_DHashTableDestroy(PLDHashTable *table)
 {
     PL_DHashTableFinish(table);
     free(table);
 }
 
 bool
-PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
-                  uint32_t entrySize, uint32_t capacity)
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops,
+                  void *data, uint32_t entrySize, uint32_t capacity,
+                  const fallible_t& )
 {
 #ifdef DEBUG
     if (entrySize > 16 * sizeof(void *)) {
         printf_stderr(
                 "pldhash: for the table at address %p, the given entrySize"
                 " of %lu definitely favors chaining over double hashing.\n",
                 (void *) table,
                 (unsigned long) entrySize);
@@ -227,16 +228,32 @@ PL_DHashTableInit(PLDHashTable *table, c
 
 #ifdef DEBUG
     table->recursionLevel = 0;
 #endif
 
     return true;
 }
 
+void
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+                  uint32_t entrySize, uint32_t capacity)
+{
+    if (!PL_DHashTableInit(table, ops, data, entrySize, capacity, fallible_t())) {
+        if (capacity > PL_DHASH_MAX_SIZE) {
+            MOZ_CRASH();
+        }
+        uint32_t nbytes;
+        if (!SizeOfEntryStore(capacity, entrySize, &nbytes)) {
+            MOZ_CRASH();
+        }
+        NS_ABORT_OOM(nbytes);
+    }
+}
+
 /*
  * Compute max and min load numbers (entry counts).  We have a secondary max
  * that allows us to overload a table reasonably if it cannot be grown further
  * (i.e. if ChangeTable() fails).  The table slows down drastically if the
  * secondary max is too close to 1, but 0.96875 gives only a slight slowdown
  * while allowing 1.3x more elements.
  */
 static inline uint32_t MaxLoad(uint32_t size) {
--- a/xpcom/glue/pldhash.h
+++ b/xpcom/glue/pldhash.h
@@ -3,16 +3,17 @@
  * 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 pldhash_h___
 #define pldhash_h___
 /*
  * Double hashing, a la Knuth 6.
  */
+#include "mozilla/fallible.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Types.h"
 #include "nscore.h"
 
 #if defined(__GNUC__) && defined(__i386__)
 #define PL_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
 #elif defined(XP_WIN)
 #define PL_DHASH_FASTCALL __fastcall
@@ -394,21 +395,32 @@ PL_NewDHashTable(const PLDHashTableOps *
  */
 NS_COM_GLUE void
 PL_DHashTableDestroy(PLDHashTable *table);
 
 /*
  * Initialize table with ops, data, entrySize, and capacity.  Capacity is a
  * guess for the smallest table size at which the table will usually be less
  * than 75% loaded (the table will grow or shrink as needed; capacity serves
- * only to avoid inevitable early growth from PL_DHASH_MIN_SIZE).
+ * only to avoid inevitable early growth from PL_DHASH_MIN_SIZE).  This will
+ * crash if it can't allocate enough memory, or if entrySize or capacity are
+ * too large.
+ */
+NS_COM_GLUE void
+PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
+                  uint32_t entrySize, uint32_t capacity);
+
+/*
+ * Initialize table. This is the same as PL_DHashTableInit, except that it
+ * returns a boolean indicating success, rather than crashing on failure.
  */
 NS_COM_GLUE bool
 PL_DHashTableInit(PLDHashTable *table, const PLDHashTableOps *ops, void *data,
-                  uint32_t entrySize, uint32_t capacity);
+                  uint32_t entrySize, uint32_t capacity,
+                  const mozilla::fallible_t& ) MOZ_WARN_UNUSED_RESULT;
 
 /*
  * Finalize table's data, free its entry storage using table->ops->freeTable,
  * and leave its members unchanged from their last live values (which leaves
  * pointers dangling).  If you want to burn cycles clearing table, it's up to
  * your code to call memset.
  */
 NS_COM_GLUE void
--- a/xpcom/tests/TestPLDHash.cpp
+++ b/xpcom/tests/TestPLDHash.cpp
@@ -16,29 +16,31 @@ namespace TestPLDHash {
 
 static bool test_pldhash_Init_capacity_ok()
 {
   // Try the largest allowed capacity.  With PL_DHASH_MAX_SIZE==1<<26, this
   // will allocate 0.5GB of entry store on 32-bit platforms and 1GB on 64-bit
   // platforms.
   PLDHashTable t;
   bool ok = PL_DHashTableInit(&t, PL_DHashGetStubOps(), nullptr,
-                              sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE);
+                              sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE,
+                              mozilla::fallible_t());
   if (ok)
     PL_DHashTableFinish(&t);
 
   return ok;
 }
 
 static bool test_pldhash_Init_capacity_too_large()
 {
   // Try the smallest too-large capacity.
   PLDHashTable t;
   bool ok = PL_DHashTableInit(&t, PL_DHashGetStubOps(), nullptr,
-                              sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE + 1);
+                              sizeof(PLDHashEntryStub), PL_DHASH_MAX_SIZE + 1,
+                              mozilla::fallible_t());
   // Don't call PL_DHashTableDestroy(), it's not safe after Init failure.
 
   return !ok;   // expected to fail
 }
 
 static bool test_pldhash_Init_overflow()
 {
   // Try an acceptable capacity, but one whose byte size overflows uint32_t.
@@ -51,17 +53,18 @@ static bool test_pldhash_Init_overflow()
   struct OneKBEntry {
       PLDHashEntryHdr hdr;
       char buf[1024 - sizeof(PLDHashEntryHdr)];
   };
 
   // |nullptr| for |ops| is ok because it's unused due to the failure.
   PLDHashTable t;
   bool ok = PL_DHashTableInit(&t, /* ops = */nullptr, nullptr,
-                              sizeof(OneKBEntry), PL_DHASH_MAX_SIZE);
+                              sizeof(OneKBEntry), PL_DHASH_MAX_SIZE,
+                              mozilla::fallible_t());
 
   return !ok;   // expected to fail
 }
 
 // See bug 931062, we skip this test on Android due to OOM.
 #ifndef MOZ_WIDGET_ANDROID
 // We insert the integers 0.., so this is has function is (a) as simple as
 // possible, and (b) collision-free.  Both of which are good, because we want
@@ -81,17 +84,18 @@ static bool test_pldhash_grow_to_max_cap
     PL_DHashMatchEntryStub,
     PL_DHashMoveEntryStub,
     PL_DHashClearEntryStub,
     PL_DHashFinalizeStub,
     nullptr
   };
 
   PLDHashTable t;
-  bool ok = PL_DHashTableInit(&t, &ops, nullptr, sizeof(PLDHashEntryStub), 256);
+  bool ok = PL_DHashTableInit(&t, &ops, nullptr, sizeof(PLDHashEntryStub), 256,
+                              mozilla::fallible_t());
   if (!ok)
     return false;
 
   // Keep inserting elements until failure occurs because the table is full.
   size_t numInserted = 0;
   while (true) {
     if (!PL_DHashTableOperate(&t, (const void*)numInserted, PL_DHASH_ADD)) {
       break;