Bug 962608 - Make PL_DHashTableInit infallible by default. r=briansmith,bsmedberg,ehsan,froydnj,jduell,jfkthame,roc,smaug
authorAndrew McCreight <continuation@gmail.com>
Thu, 27 Feb 2014 10:04:09 -0800
changeset 171340 c95f331f043df4c2c9396f685826cdd07d12810d
parent 171339 efa6f63f06b9a9c005db190d81d3b54f57608e85
child 171341 d3e372d1c88a048f580cccd7a2ba90efa7baf8bb
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbriansmith, bsmedberg, ehsan, froydnj, jduell, jfkthame, roc, smaug
bugs962608
milestone30.0a1
Bug 962608 - Make PL_DHashTableInit infallible by default. r=briansmith,bsmedberg,ehsan,froydnj,jduell,jfkthame,roc,smaug
chrome/src/nsChromeRegistryChrome.cpp
content/base/src/nsContentList.cpp
content/base/src/nsContentUtils.cpp
content/xul/templates/src/nsContentSupportMap.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/plugins/base/nsPluginStreamListenerPeer.cpp
dom/xbl/nsBindingManager.cpp
embedding/components/commandhandler/src/nsCommandParams.cpp
gfx/thebes/gfxFT2FontList.cpp
layout/base/nsFrameManager.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/tables/SpanningCellSorter.cpp
modules/libpref/src/prefapi.cpp
netwerk/base/src/nsLoadGroup.cpp
netwerk/cache/nsCacheEntry.cpp
netwerk/cache/nsDiskCacheBinding.cpp
netwerk/protocol/http/nsHttp.cpp
parser/htmlparser/src/nsHTMLEntities.cpp
rdf/base/src/nsInMemoryDataSource.cpp
rdf/base/src/nsRDFService.cpp
security/manager/ssl/src/nsCertTree.cpp
uriloader/base/nsDocLoader.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsHashtable.cpp
xpcom/ds/nsHashtable.h
xpcom/ds/nsPersistentProperties.cpp
xpcom/ds/nsPersistentProperties.h
xpcom/ds/nsStaticNameTable.cpp
xpcom/glue/nsTHashtable.h
xpcom/glue/pldhash.cpp
xpcom/glue/pldhash.h
xpcom/tests/TestPLDHash.cpp
--- 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/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/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/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/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
@@ -452,40 +452,35 @@ nsPersistentProperties::nsPersistentProp
 
 nsPersistentProperties::~nsPersistentProperties()
 {
   PL_FinishArenaPool(&mArena);
   if (mTable.ops)
     PL_DHashTableFinish(&mTable);
 }
 
-nsresult
+void
 nsPersistentProperties::Init()
 {
-  if (!PL_DHashTableInit(&mTable, &property_HashTableOps, nullptr,
-                         sizeof(PropertyTableEntry), 20)) {
-    mTable.ops = nullptr;
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  return NS_OK;
+  PL_DHashTableInit(&mTable, &property_HashTableOps, nullptr,
+                    sizeof(PropertyTableEntry), 20);
 }
 
 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);
+  props->Init();
+  nsresult rv = props->QueryInterface(aIID, aResult);
 
   NS_RELEASE(props);
   return rv;
 }
 
 NS_IMPL_ISUPPORTS2(nsPersistentProperties, nsIPersistentProperties, nsIProperties)
 
 NS_IMETHODIMP
--- a/xpcom/ds/nsPersistentProperties.h
+++ b/xpcom/ds/nsPersistentProperties.h
@@ -14,17 +14,17 @@
 #include "mozilla/Attributes.h"
 
 class nsIUnicharInputStream;
 
 class nsPersistentProperties MOZ_FINAL : public nsIPersistentProperties
 {
 public:
   nsPersistentProperties();
-  nsresult Init();
+  void 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;