Bug 1131901 (part 1) - Make PL_DHashTableAdd() infallible by default, and add a fallible alternative. r=froydnj.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 02 Feb 2015 14:48:58 -0800
changeset 255887 ee592ac6cc90b1248f7d1a84bee4b64d85c8ba94
parent 255886 cae2905182387f3424e7092a4893a03dad263899
child 255888 9ccc4502a5f07e10f9cebf0304273643d7d65ce6
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1131901
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1131901 (part 1) - Make PL_DHashTableAdd() infallible by default, and add a fallible alternative. r=froydnj. I kept all the existing PL_DHashTableAdd() calls fallible, in order to be conservative, except for the ones in nsAtomTable.cpp which already were followed immediately by an abort on failure.
dom/base/nsContentList.cpp
dom/base/nsContentUtils.cpp
dom/base/nsDocument.cpp
dom/base/nsPropertyTable.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/plugins/base/nsJSNPRuntime.cpp
dom/xul/XULDocument.cpp
dom/xul/templates/nsContentSupportMap.h
dom/xul/templates/nsTemplateMap.h
embedding/components/commandhandler/nsCommandParams.cpp
gfx/thebes/gfxFT2FontList.cpp
js/xpconnect/src/XPCMaps.cpp
js/xpconnect/src/XPCMaps.h
layout/base/nsFrameManager.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsRuleNode.cpp
layout/tables/SpanningCellSorter.cpp
modules/libpref/prefapi.cpp
netwerk/base/nsLoadGroup.cpp
netwerk/cache/nsCacheEntry.cpp
netwerk/cache/nsDiskCacheBinding.cpp
netwerk/dns/nsHostResolver.cpp
netwerk/protocol/http/nsHttp.cpp
parser/htmlparser/nsHTMLEntities.cpp
rdf/base/nsInMemoryDataSource.cpp
rdf/base/nsRDFService.cpp
security/manager/boot/src/nsSecureBrowserUIImpl.cpp
security/manager/ssl/src/nsCertTree.cpp
security/manager/ssl/src/nsNSSShutDown.cpp
uriloader/base/nsDocLoader.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/ds/nsPersistentProperties.cpp
xpcom/ds/nsStaticNameTable.cpp
xpcom/glue/nsTHashtable.h
xpcom/glue/pldhash.cpp
xpcom/glue/pldhash.h
xpcom/tests/TestPLDHash.cpp
--- a/dom/base/nsContentList.cpp
+++ b/dom/base/nsContentList.cpp
@@ -219,17 +219,17 @@ NS_GetContentList(nsINode* aRootNode,
     PL_DHashTableInit(&gContentListHashTable, &hash_table_ops,
                       sizeof(ContentListHashEntry));
   }
 
   ContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
   if (gContentListHashTable.IsInitialized()) {
     entry = static_cast<ContentListHashEntry *>
-                       (PL_DHashTableAdd(&gContentListHashTable, &hashKey));
+      (PL_DHashTableAdd(&gContentListHashTable, &hashKey, fallible));
     if (entry)
       list = entry->mContentList;
   }
 
   if (!list) {
     // We need to create a ContentList and add it to our new entry, if
     // we have an entry
     nsCOMPtr<nsIAtom> xmlAtom = do_GetAtom(aTagname);
@@ -327,18 +327,17 @@ GetFuncStringContentList(nsINode* aRootN
   }
 
   FuncStringContentListHashEntry *entry = nullptr;
   // First we look in our hashtable.  Then we create a content list if needed
   if (gFuncStringContentListHashTable.IsInitialized()) {
     nsFuncStringCacheKey hashKey(aRootNode, aFunc, aString);
 
     entry = static_cast<FuncStringContentListHashEntry *>
-                       (PL_DHashTableAdd(&gFuncStringContentListHashTable,
-                                         &hashKey));
+      (PL_DHashTableAdd(&gFuncStringContentListHashTable, &hashKey, fallible));
     if (entry) {
       list = entry->mContentList;
 #ifdef DEBUG
       MOZ_ASSERT_IF(list, list->mType == ListType::sType);
 #endif
     }
   }
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -3958,17 +3958,17 @@ nsContentUtils::GetListenerManagerForNod
     // We're already shut down, don't bother creating an event listener
     // manager.
 
     return nullptr;
   }
 
   EventListenerManagerMapEntry *entry =
     static_cast<EventListenerManagerMapEntry *>
-               (PL_DHashTableAdd(&sEventListenerManagersHash, aNode));
+      (PL_DHashTableAdd(&sEventListenerManagersHash, aNode, fallible));
 
   if (!entry) {
     return nullptr;
   }
 
   if (!entry->mListenerManager) {
     entry->mListenerManager = new EventListenerManager(aNode);
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -4002,19 +4002,18 @@ nsDocument::SetSubDocumentFor(Element* a
 
       mSubDocuments = PL_NewDHashTable(&hash_table_ops, sizeof(SubDocMapEntry));
       if (!mSubDocuments) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
     }
 
     // Add a mapping to the hash table
-    SubDocMapEntry *entry =
-      static_cast<SubDocMapEntry*>
-                 (PL_DHashTableAdd(mSubDocuments, aElement));
+    SubDocMapEntry *entry = static_cast<SubDocMapEntry*>
+      (PL_DHashTableAdd(mSubDocuments, aElement, fallible));
 
     if (!entry) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (entry->mSubDocument) {
       entry->mSubDocument->SetParentDocument(nullptr);
 
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -225,17 +225,17 @@ nsPropertyTable::SetPropertyInternal(nsP
     propertyList->mNext = mPropertyList;
     mPropertyList = propertyList;
   }
 
   // The current property value (if there is one) is replaced and the current
   // value is destroyed
   nsresult result = NS_OK;
   PropertyListMapEntry *entry = static_cast<PropertyListMapEntry*>
-                                           (PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject));
+    (PL_DHashTableAdd(&propertyList->mObjectValueMap, aObject, fallible));
   if (!entry)
     return NS_ERROR_OUT_OF_MEMORY;
   // A nullptr entry->key is the sign that the entry has just been allocated
   // for us.  If it's non-nullptr then we have an existing entry.
   if (entry->key) {
     if (aOldValue)
       *aOldValue = entry->value;
     else if (propertyList->mDtorFunc)
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -135,19 +135,18 @@ nsScriptNameSpaceManager::~nsScriptNameS
   }
   MOZ_COUNT_DTOR(nsScriptNameSpaceManager);
 }
 
 nsGlobalNameStruct *
 nsScriptNameSpaceManager::AddToHash(PLDHashTable *aTable, const nsAString *aKey,
                                     const char16_t **aClassName)
 {
-  GlobalNameMapEntry *entry =
-    static_cast<GlobalNameMapEntry *>
-               (PL_DHashTableAdd(aTable, aKey));
+  GlobalNameMapEntry *entry = static_cast<GlobalNameMapEntry *>
+    (PL_DHashTableAdd(aTable, aKey, fallible));
 
   if (!entry) {
     return nullptr;
   }
 
   if (aClassName) {
     *aClassName = entry->mKey.get();
   }
--- a/dom/plugins/base/nsJSNPRuntime.cpp
+++ b/dom/plugins/base/nsJSNPRuntime.cpp
@@ -1867,17 +1867,17 @@ nsNPObjWrapper::GetNewOrUsed(NPP npp, JS
   if (!sNPObjWrappers.IsInitialized()) {
     // No hash yet (or any more), initialize it.
     if (!CreateNPObjWrapperTable()) {
       return nullptr;
     }
   }
 
   NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *>
-    (PL_DHashTableAdd(&sNPObjWrappers, npobj));
+    (PL_DHashTableAdd(&sNPObjWrappers, npobj, fallible));
 
   if (!entry) {
     // Out of memory
     JS_ReportOutOfMemory(cx);
 
     return nullptr;
   }
 
@@ -2030,17 +2030,17 @@ static NPP
 LookupNPP(NPObject *npobj)
 {
   if (npobj->_class == &nsJSObjWrapper::sJSObjWrapperNPClass) {
     nsJSObjWrapper* o = static_cast<nsJSObjWrapper*>(npobj);
     return o->mNpp;
   }
 
   NPObjWrapperHashEntry *entry = static_cast<NPObjWrapperHashEntry *>
-    (PL_DHashTableAdd(&sNPObjWrappers, npobj));
+    (PL_DHashTableAdd(&sNPObjWrappers, npobj, fallible));
 
   if (!entry) {
     return nullptr;
   }
 
   NS_ASSERTION(entry->mNpp, "Live NPObject entry w/o an NPP!");
 
   return entry->mNpp;
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -776,19 +776,18 @@ XULDocument::AddBroadcastListenerFor(Ele
         }
     }
 
     BroadcasterMapEntry* entry =
         static_cast<BroadcasterMapEntry*>
                    (PL_DHashTableSearch(mBroadcasterMap, &aBroadcaster));
 
     if (!entry) {
-        entry =
-            static_cast<BroadcasterMapEntry*>
-                       (PL_DHashTableAdd(mBroadcasterMap, &aBroadcaster));
+        entry = static_cast<BroadcasterMapEntry*>
+            (PL_DHashTableAdd(mBroadcasterMap, &aBroadcaster, fallible));
 
         if (! entry) {
             aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
             return;
         }
 
         entry->mBroadcaster = &aBroadcaster;
 
--- a/dom/xul/templates/nsContentSupportMap.h
+++ b/dom/xul/templates/nsContentSupportMap.h
@@ -23,17 +23,18 @@ class nsContentSupportMap {
 public:
     nsContentSupportMap() { Init(); }
     ~nsContentSupportMap() { Finish(); }
 
     nsresult Put(nsIContent* aElement, nsTemplateMatch* aMatch) {
         if (!mMap.IsInitialized())
             return NS_ERROR_NOT_INITIALIZED;
 
-        PLDHashEntryHdr* hdr = PL_DHashTableAdd(&mMap, aElement);
+        PLDHashEntryHdr* hdr =
+            PL_DHashTableAdd(&mMap, aElement, mozilla::fallible);
         if (!hdr)
             return NS_ERROR_OUT_OF_MEMORY;
 
         Entry* entry = static_cast<Entry*>(hdr);
         NS_ASSERTION(entry->mMatch == nullptr, "over-writing entry");
         entry->mContent = aElement;
         entry->mMatch   = aMatch;
         return NS_OK;
--- a/dom/xul/templates/nsTemplateMap.h
+++ b/dom/xul/templates/nsTemplateMap.h
@@ -32,17 +32,18 @@ public:
 
     ~nsTemplateMap() { Finish(); }
 
     void
     Put(nsIContent* aContent, nsIContent* aTemplate) {
         NS_ASSERTION(!PL_DHashTableSearch(&mTable, aContent),
                      "aContent already in map");
 
-        Entry* entry = static_cast<Entry*>(PL_DHashTableAdd(&mTable, aContent));
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(&mTable, aContent, fallible));
 
         if (entry) {
             entry->mContent = aContent;
             entry->mTemplate = aTemplate;
         }
     }
 
     void
--- a/embedding/components/commandhandler/nsCommandParams.cpp
+++ b/embedding/components/commandhandler/nsCommandParams.cpp
@@ -225,17 +225,18 @@ nsCommandParams::GetOrMakeEntry(const ch
 {
   HashEntry *foundEntry =
     (HashEntry *)PL_DHashTableSearch(&mValuesHash, (void *)aName);
   if (foundEntry) { // reuse existing entry
     foundEntry->Reset(entryType);
     return foundEntry;
   }
 
-  foundEntry = (HashEntry *)PL_DHashTableAdd(&mValuesHash, (void *)aName);
+  foundEntry = static_cast<HashEntry*>
+    (PL_DHashTableAdd(&mValuesHash, (void *)aName, fallible));
   if (!foundEntry) {
     return nullptr;
   }
 
   // Use placement new. Our ctor does not clobber keyHash, which is important.
   new (foundEntry) HashEntry(entryType, aName);
   return foundEntry;
 }
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -683,19 +683,18 @@ public:
             }
             uint32_t timestamp = strtoul(beginning, nullptr, 10);
             beginning = end + 1;
             if (!(end = strchr(beginning, ';'))) {
                 break;
             }
             uint32_t filesize = strtoul(beginning, nullptr, 10);
 
-            FNCMapEntry* mapEntry =
-                static_cast<FNCMapEntry*>
-                (PL_DHashTableAdd(&mMap, filename.get()));
+            FNCMapEntry* mapEntry = static_cast<FNCMapEntry*>
+                (PL_DHashTableAdd(&mMap, filename.get(), fallible));
             if (mapEntry) {
                 mapEntry->mFilename.Assign(filename);
                 mapEntry->mTimestamp = timestamp;
                 mapEntry->mFilesize = filesize;
                 mapEntry->mFaces.Assign(faceList);
                 // entries from the startupcache are marked "non-existing"
                 // until we have confirmed that the file still exists
                 mapEntry->mFileExists = false;
@@ -732,19 +731,18 @@ public:
 
     virtual void
     CacheFileInfo(const nsCString& aFileName, const nsCString& aFaceList,
                   uint32_t aTimestamp, uint32_t aFilesize)
     {
         if (!mMap.IsInitialized()) {
             return;
         }
-        FNCMapEntry* entry =
-            static_cast<FNCMapEntry*>
-            (PL_DHashTableAdd(&mMap, aFileName.get()));
+        FNCMapEntry* entry = static_cast<FNCMapEntry*>
+            (PL_DHashTableAdd(&mMap, aFileName.get(), fallible));
         if (entry) {
             entry->mFilename.Assign(aFileName);
             entry->mTimestamp = aTimestamp;
             entry->mFilesize = aFilesize;
             entry->mFaces.Assign(aFaceList);
             entry->mFileExists = true;
         }
         mWriteNeeded = true;
--- a/js/xpconnect/src/XPCMaps.cpp
+++ b/js/xpconnect/src/XPCMaps.cpp
@@ -621,17 +621,18 @@ bool
 XPCNativeScriptableSharedMap::GetNewOrUsed(uint32_t flags,
                                            char* name,
                                            XPCNativeScriptableInfo* si)
 {
     NS_PRECONDITION(name,"bad param");
     NS_PRECONDITION(si,"bad param");
 
     XPCNativeScriptableShared key(flags, name);
-    Entry* entry = (Entry*) PL_DHashTableAdd(mTable, &key);
+    Entry* entry = static_cast<Entry*>
+        (PL_DHashTableAdd(mTable, &key, fallible));
     if (!entry)
         return false;
 
     XPCNativeScriptableShared* shared = entry->key;
 
     if (!shared) {
         entry->key = shared =
             new XPCNativeScriptableShared(flags, key.TransferNameOwnership());
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -115,17 +115,18 @@ public:
         return entry ? entry->value : nullptr;
     }
 
     inline XPCWrappedNative* Add(XPCWrappedNative* wrapper)
     {
         NS_PRECONDITION(wrapper,"bad param");
         nsISupports* obj = wrapper->GetIdentityObject();
         MOZ_ASSERT(!Find(obj), "wrapper already in new scope!");
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, obj);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, obj, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = obj;
         entry->value = wrapper;
         return wrapper;
     }
@@ -180,17 +181,18 @@ public:
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, &iid);
         return entry ? entry->value : nullptr;
     }
 
     inline nsXPCWrappedJSClass* Add(nsXPCWrappedJSClass* clazz)
     {
         NS_PRECONDITION(clazz,"bad param");
         const nsIID* iid = &clazz->GetIID();
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, iid);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, iid, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = iid;
         entry->value = clazz;
         return clazz;
     }
@@ -233,17 +235,18 @@ public:
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, &iid);
         return entry ? entry->value : nullptr;
     }
 
     inline XPCNativeInterface* Add(XPCNativeInterface* iface)
     {
         NS_PRECONDITION(iface,"bad param");
         const nsIID* iid = iface->GetIID();
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, iid);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, iid, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = iid;
         entry->value = iface;
         return iface;
     }
@@ -288,17 +291,18 @@ public:
     {
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, info);
         return entry ? entry->value : nullptr;
     }
 
     inline XPCNativeSet* Add(nsIClassInfo* info, XPCNativeSet* set)
     {
         NS_PRECONDITION(info,"bad param");
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, info);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, info, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = info;
         entry->value = set;
         return set;
     }
@@ -344,17 +348,18 @@ public:
     {
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, info);
         return entry ? entry->value : nullptr;
     }
 
     inline XPCWrappedNativeProto* Add(nsIClassInfo* info, XPCWrappedNativeProto* proto)
     {
         NS_PRECONDITION(info,"bad param");
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, info);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, info, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return entry->value;
         entry->key = info;
         entry->value = proto;
         return proto;
     }
@@ -406,17 +411,18 @@ public:
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, key);
         return entry ? entry->key_value : nullptr;
     }
 
     inline XPCNativeSet* Add(const XPCNativeSetKey* key, XPCNativeSet* set)
     {
         NS_PRECONDITION(key,"bad param");
         NS_PRECONDITION(set,"bad param");
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, key);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, key, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key_value)
             return entry->key_value;
         entry->key_value = set;
         return set;
     }
 
@@ -478,18 +484,18 @@ public:
     {
         Entry* entry = (Entry*) PL_DHashTableSearch(mTable, &iid);
         return entry ? entry->value : nullptr;
     }
 
     inline nsIXPCFunctionThisTranslator* Add(REFNSIID iid,
                                              nsIXPCFunctionThisTranslator* obj)
     {
-
-        Entry* entry = (Entry*) PL_DHashTableAdd(mTable, &iid);
+        Entry* entry = static_cast<Entry*>
+            (PL_DHashTableAdd(mTable, &iid, mozilla::fallible));
         if (!entry)
             return nullptr;
         entry->value = obj;
         entry->key = iid;
         return obj;
     }
 
     inline void Remove(REFNSIID iid)
@@ -550,18 +556,18 @@ private:
 class XPCWrappedNativeProtoMap
 {
 public:
     static XPCWrappedNativeProtoMap* newMap(int length);
 
     inline XPCWrappedNativeProto* Add(XPCWrappedNativeProto* proto)
     {
         NS_PRECONDITION(proto,"bad param");
-        PLDHashEntryStub* entry = (PLDHashEntryStub*)
-            PL_DHashTableAdd(mTable, proto);
+        PLDHashEntryStub* entry = static_cast<PLDHashEntryStub*>
+            (PL_DHashTableAdd(mTable, proto, mozilla::fallible));
         if (!entry)
             return nullptr;
         if (entry->key)
             return (XPCWrappedNativeProto*) entry->key;
         entry->key = proto;
         return proto;
     }
 
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -170,18 +170,19 @@ nsFrameManager::RegisterPlaceholderFrame
 {
   NS_PRECONDITION(aPlaceholderFrame, "null param unexpected");
   NS_PRECONDITION(nsGkAtoms::placeholderFrame == aPlaceholderFrame->GetType(),
                   "unexpected frame type");
   if (!mPlaceholderMap.IsInitialized()) {
     PL_DHashTableInit(&mPlaceholderMap, &PlaceholderMapOps,
                       sizeof(PlaceholderMapEntry));
   }
-  PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>(PL_DHashTableAdd(&mPlaceholderMap,
-                              aPlaceholderFrame->GetOutOfFlowFrame()));
+  PlaceholderMapEntry *entry = static_cast<PlaceholderMapEntry*>
+    (PL_DHashTableAdd(&mPlaceholderMap,
+                      aPlaceholderFrame->GetOutOfFlowFrame(), fallible));
   if (!entry)
     return NS_ERROR_OUT_OF_MEMORY;
 
   NS_ASSERTION(!entry->placeholderFrame, "Registering a placeholder for a frame that already has a placeholder!");
   entry->placeholderFrame = aPlaceholderFrame;
 
   return NS_OK;
 }
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -564,29 +564,29 @@ RuleHash::~RuleHash()
   }
 }
 
 void RuleHash::AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
                                  const RuleSelectorPair& aRuleInfo)
 {
   // Get a new or existing entry.
   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
-                                         (PL_DHashTableAdd(aTable, aKey));
+    (PL_DHashTableAdd(aTable, aKey, fallible));
   if (!entry)
     return;
   entry->mRules.AppendElement(RuleValue(aRuleInfo, mRuleCount++, mQuirksMode));
 }
 
 static void
 AppendRuleToTagTable(PLDHashTable* aTable, nsIAtom* aKey,
                      const RuleValue& aRuleInfo)
 {
   // Get a new or exisiting entry
   RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
-    (PL_DHashTableAdd(aTable, aKey));
+    (PL_DHashTableAdd(aTable, aKey, fallible));
   if (!entry)
     return;
 
   entry->mRules.AppendElement(aRuleInfo);
 }
 
 void RuleHash::AppendUniversalRule(const RuleSelectorPair& aRuleInfo)
 {
@@ -1030,17 +1030,17 @@ RuleCascadeData::SizeOfIncludingThis(Mal
   return n;
 }
 
 nsTArray<nsCSSSelector*>*
 RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
 {
   AtomSelectorEntry *entry =
     static_cast<AtomSelectorEntry*>
-               (PL_DHashTableAdd(&mAttributeSelectors, aAttribute));
+               (PL_DHashTableAdd(&mAttributeSelectors, aAttribute, fallible));
   if (!entry)
     return nullptr;
   return &entry->mSelectors;
 }
 
 // -------------------------------
 // CSS Style rule processor implementation
 //
@@ -3123,34 +3123,33 @@ AddSelector(RuleCascadeData* aCascade,
         nsCSSRuleProcessor::StateSelector(dependentStates,
                                           aSelectorInTopLevel));
     }
 
     // Build mIDSelectors
     if (negation == aSelectorInTopLevel) {
       for (nsAtomList* curID = negation->mIDList; curID;
            curID = curID->mNext) {
-        AtomSelectorEntry *entry =
-          static_cast<AtomSelectorEntry*>(PL_DHashTableAdd(&aCascade->mIdSelectors,
-                                                           curID->mAtom));
+        AtomSelectorEntry *entry = static_cast<AtomSelectorEntry*>
+          (PL_DHashTableAdd(&aCascade->mIdSelectors, curID->mAtom, fallible));
         if (entry) {
           entry->mSelectors.AppendElement(aSelectorInTopLevel);
         }
       }
     } else if (negation->mIDList) {
       aCascade->mPossiblyNegatedIDSelectors.AppendElement(aSelectorInTopLevel);
     }
 
     // Build mClassSelectors
     if (negation == aSelectorInTopLevel) {
       for (nsAtomList* curClass = negation->mClassList; curClass;
            curClass = curClass->mNext) {
-        AtomSelectorEntry *entry =
-          static_cast<AtomSelectorEntry*>(PL_DHashTableAdd(&aCascade->mClassSelectors,
-                                                           curClass->mAtom));
+        AtomSelectorEntry *entry = static_cast<AtomSelectorEntry*>
+          (PL_DHashTableAdd(&aCascade->mClassSelectors, curClass->mAtom,
+                            fallible));
         if (entry) {
           entry->mSelectors.AppendElement(aSelectorInTopLevel);
         }
       }
     } else if (negation->mClassList) {
       aCascade->mPossiblyNegatedClassSelectors.AppendElement(aSelectorInTopLevel);
     }
 
@@ -3397,17 +3396,18 @@ CascadeRuleEnumFunc(css::Rule* aRule, vo
 
   if (css::Rule::STYLE_RULE == type) {
     css::StyleRule* styleRule = static_cast<css::StyleRule*>(aRule);
 
     for (nsCSSSelectorList *sel = styleRule->Selector();
          sel; sel = sel->mNext) {
       int32_t weight = sel->mWeight;
       RuleByWeightEntry *entry = static_cast<RuleByWeightEntry*>(
-        PL_DHashTableAdd(&data->mRulesByWeight, NS_INT32_TO_PTR(weight)));
+        PL_DHashTableAdd(&data->mRulesByWeight, NS_INT32_TO_PTR(weight),
+                         fallible));
       if (!entry)
         return false;
       entry->data.mWeight = weight;
       // entry->data.mRuleSelectorPairs should be linked in forward order;
       // entry->data.mTail is the slot to write to.
       PerWeightDataListItem *newItem =
         new (data->mArena) PerWeightDataListItem(styleRule, sel->mSelectors);
       if (newItem) {
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -475,18 +475,19 @@ nsHTMLStyleSheet::SetVisitedLinkColor(ns
 
 already_AddRefed<nsMappedAttributes>
 nsHTMLStyleSheet::UniqueMappedAttributes(nsMappedAttributes* aMapped)
 {
   if (!mMappedAttrTable.IsInitialized()) {
     PL_DHashTableInit(&mMappedAttrTable, &MappedAttrTable_Ops,
                       sizeof(MappedAttrTableEntry));
   }
-  MappedAttrTableEntry *entry = static_cast<MappedAttrTableEntry*>
-                                           (PL_DHashTableAdd(&mMappedAttrTable, aMapped));
+  MappedAttrTableEntry *entry =
+    static_cast<MappedAttrTableEntry*>
+               (PL_DHashTableAdd(&mMappedAttrTable, aMapped, fallible));
   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;
   }
   nsRefPtr<nsMappedAttributes> ret = entry->mAttributes;
   return ret.forget();
@@ -510,17 +511,17 @@ nsHTMLStyleSheet::DropMappedAttributes(n
 nsIStyleRule*
 nsHTMLStyleSheet::LangRuleFor(const nsString& aLanguage)
 {
   if (!mLangRuleTable.IsInitialized()) {
     PL_DHashTableInit(&mLangRuleTable, &LangRuleTable_Ops,
                       sizeof(LangRuleTableEntry));
   }
   LangRuleTableEntry *entry = static_cast<LangRuleTableEntry*>
-    (PL_DHashTableAdd(&mLangRuleTable, &aLanguage));
+    (PL_DHashTableAdd(&mLangRuleTable, &aLanguage, fallible));
   if (!entry) {
     NS_ASSERTION(false, "out of memory");
     return nullptr;
   }
   return entry->mRule;
 }
 
 static size_t
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -1528,17 +1528,17 @@ nsRuleNode::Transition(nsIStyleRule* aRu
     if (curr)
       next = curr;
     else if (numKids >= kMaxChildrenInList)
       ConvertChildrenToHash(numKids);
   }
 
   if (ChildrenAreHashed()) {
     ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>
-                                          (PL_DHashTableAdd(ChildrenHash(), &key));
+      (PL_DHashTableAdd(ChildrenHash(), &key, fallible));
     if (!entry) {
       NS_WARNING("out of memory");
       return this;
     }
     if (entry->mRuleNode)
       next = entry->mRuleNode;
     else {
       next = entry->mRuleNode = new (mPresContext)
@@ -1606,17 +1606,17 @@ nsRuleNode::ConvertChildrenToHash(int32_
   PLDHashTable *hash = PL_NewDHashTable(&ChildrenHashOps,
                                         sizeof(ChildrenHashEntry),
                                         aNumKids);
   if (!hash)
     return;
   for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) {
     // This will never fail because of the initial size we gave the table.
     ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(
-      PL_DHashTableAdd(hash, curr->mRule));
+      PL_DHashTableAdd(hash, curr->mRule, fallible));
     NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list");
     entry->mRuleNode = curr;
   }
   SetChildrenHash(hash);
 }
 
 inline void
 nsRuleNode::PropagateNoneBit(uint32_t aBit, nsRuleNode* aHighestNode)
--- a/layout/tables/SpanningCellSorter.cpp
+++ b/layout/tables/SpanningCellSorter.cpp
@@ -70,17 +70,18 @@ SpanningCellSorter::AddCell(int32_t aCol
         i->next = mArray[index];
         mArray[index] = i;
     } else {
         if (!mHashTable.IsInitialized()) {
             PL_DHashTableInit(&mHashTable, &HashTableOps,
                               sizeof(HashTableEntry));
         }
         HashTableEntry *entry = static_cast<HashTableEntry*>
-                                           (PL_DHashTableAdd(&mHashTable, NS_INT32_TO_PTR(aColSpan)));
+            (PL_DHashTableAdd(&mHashTable, NS_INT32_TO_PTR(aColSpan),
+                              fallible));
         NS_ENSURE_TRUE(entry, false);
 
         NS_ASSERTION(entry->mColSpan == 0 || entry->mColSpan == aColSpan,
                      "wrong entry");
         NS_ASSERTION((entry->mColSpan == 0) == (entry->mItems == nullptr),
                      "entry should be either new or properly initialized");
         entry->mColSpan = aColSpan;
 
--- a/modules/libpref/prefapi.cpp
+++ b/modules/libpref/prefapi.cpp
@@ -735,17 +735,18 @@ nsresult pref_HashPref(const char *key, 
 {
 #ifndef MOZ_B2G
     MOZ_ASSERT(NS_IsMainThread());
 #endif
 
     if (!gHashTable.IsInitialized())
         return NS_ERROR_OUT_OF_MEMORY;
 
-    PrefHashEntry* pref = static_cast<PrefHashEntry*>(PL_DHashTableAdd(&gHashTable, key));
+    PrefHashEntry* pref = static_cast<PrefHashEntry*>
+        (PL_DHashTableAdd(&gHashTable, key, fallible));
 
     if (!pref)
         return NS_ERROR_OUT_OF_MEMORY;
 
     // new entry, better initialize
     if (!pref->key) {
 
         // initialize the pref entry
--- a/netwerk/base/nsLoadGroup.cpp
+++ b/netwerk/base/nsLoadGroup.cpp
@@ -504,19 +504,18 @@ nsLoadGroup::AddRequest(nsIRequest *requ
     else
         rv = MergeLoadFlags(request, flags);
     if (NS_FAILED(rv)) return rv;
     
     //
     // Add the request to the list of active requests...
     //
 
-    RequestMapEntry *entry =
-        static_cast<RequestMapEntry *>
-                   (PL_DHashTableAdd(&mRequests, request));
+    RequestMapEntry *entry = static_cast<RequestMapEntry *>
+        (PL_DHashTableAdd(&mRequests, request, fallible));
 
     if (!entry) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
     if (mPriority != 0)
         RescheduleRequest(request, mPriority);
 
--- a/netwerk/cache/nsCacheEntry.cpp
+++ b/netwerk/cache/nsCacheEntry.cpp
@@ -438,17 +438,17 @@ nsresult
 nsCacheEntryHashTable::AddEntry( nsCacheEntry *cacheEntry)
 {
     PLDHashEntryHdr    *hashEntry;
 
     NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
     if (!initialized)  return NS_ERROR_NOT_INITIALIZED;
     if (!cacheEntry)   return NS_ERROR_NULL_POINTER;
 
-    hashEntry = PL_DHashTableAdd(&table, &(cacheEntry->mKey));
+    hashEntry = PL_DHashTableAdd(&table, &(cacheEntry->mKey), fallible);
 #ifndef DEBUG_dougt
     NS_ASSERTION(((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry == 0,
                  "### nsCacheEntryHashTable::AddEntry - entry already used");
 #endif
     ((nsCacheEntryHashTableEntry *)hashEntry)->cacheEntry = cacheEntry;
 
     return NS_OK;
 }
--- a/netwerk/cache/nsDiskCacheBinding.cpp
+++ b/netwerk/cache/nsDiskCacheBinding.cpp
@@ -231,17 +231,18 @@ nsDiskCacheBindery::AddBinding(nsDiskCac
 {
     NS_ENSURE_ARG_POINTER(binding);
     NS_ASSERTION(initialized, "nsDiskCacheBindery not initialized");
 
     // find hash entry for key
     HashTableEntry * hashEntry;
     hashEntry = (HashTableEntry *)
       PL_DHashTableAdd(&table,
-                       (void *)(uintptr_t) binding->mRecord.HashNumber());
+                       (void *)(uintptr_t) binding->mRecord.HashNumber(),
+                       fallible);
     if (!hashEntry) return NS_ERROR_OUT_OF_MEMORY;
     
     if (hashEntry->mBinding == nullptr) {
         hashEntry->mBinding = binding;
         if (binding->mGeneration == 0)
             binding->mGeneration = 1;   // if generation uninitialized, set it to 1
             
         return NS_OK;
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -760,17 +760,17 @@ nsHostResolver::ResolveHost(const char  
             // in the hash table.  if so, then check to see if we can't
             // just reuse the lookup result.  otherwise, if there are
             // any pending callbacks, then add to pending callbacks queue,
             // and return.  otherwise, add ourselves as first pending
             // callback, and proceed to do the lookup.
 
             nsHostKey key = { host, flags, af };
             nsHostDBEnt *he = static_cast<nsHostDBEnt *>
-                                         (PL_DHashTableAdd(&mDB, &key));
+                (PL_DHashTableAdd(&mDB, &key, fallible));
 
             // if the record is null, the hash table OOM'd.
             if (!he) {
                 LOG(("  Out of memory: no cache entry for [%s].\n", host));
                 rv = NS_ERROR_OUT_OF_MEMORY;
             }
             // do we have a cached result that we can reuse?
             else if (!(flags & RES_BYPASS_CACHE) &&
--- a/netwerk/protocol/http/nsHttp.cpp
+++ b/netwerk/protocol/http/nsHttp.cpp
@@ -115,17 +115,17 @@ nsHttp::CreateAtomTable()
 #define HTTP_ATOM(_name, _value) nsHttp::_name._val,
 #include "nsHttpAtomList.h"
 #undef HTTP_ATOM
         nullptr
     };
 
     for (int i = 0; atoms[i]; ++i) {
         PLDHashEntryStub *stub = reinterpret_cast<PLDHashEntryStub *>
-                                                 (PL_DHashTableAdd(&sAtomTable, atoms[i]));
+            (PL_DHashTableAdd(&sAtomTable, atoms[i], fallible));
         if (!stub)
             return NS_ERROR_OUT_OF_MEMORY;
 
         MOZ_ASSERT(!stub->key, "duplicate static atom");
         stub->key = atoms[i];
     }
 
     return NS_OK;
@@ -163,17 +163,17 @@ nsHttp::ResolveAtom(const char *str)
     nsHttpAtom atom = { nullptr };
 
     if (!str || !sAtomTable.IsInitialized())
         return atom;
 
     MutexAutoLock lock(*sLock);
 
     PLDHashEntryStub *stub = reinterpret_cast<PLDHashEntryStub *>
-                                             (PL_DHashTableAdd(&sAtomTable, str));
+        (PL_DHashTableAdd(&sAtomTable, str, fallible));
     if (!stub)
         return atom;  // out of memory
 
     if (stub->key) {
         atom._val = reinterpret_cast<const char *>(stub->key);
         return atom;
     }
 
--- a/parser/htmlparser/nsHTMLEntities.cpp
+++ b/parser/htmlparser/nsHTMLEntities.cpp
@@ -96,26 +96,27 @@ nsHTMLEntities::AddRefTable(void)
     }
     for (const EntityNode *node = gEntityArray,
                  *node_end = ArrayEnd(gEntityArray);
          node < node_end; ++node) {
 
       // add to Entity->Unicode table
       EntityNodeEntry* entry =
         static_cast<EntityNodeEntry*>
-                   (PL_DHashTableAdd(&gEntityToUnicode, node->mStr));
+                   (PL_DHashTableAdd(&gEntityToUnicode, node->mStr, fallible));
       NS_ASSERTION(entry, "Error adding an entry");
       // Prefer earlier entries when we have duplication.
       if (!entry->node)
         entry->node = node;
 
       // add to Unicode->Entity table
       entry = static_cast<EntityNodeEntry*>
                          (PL_DHashTableAdd(&gUnicodeToEntity,
-                                           NS_INT32_TO_PTR(node->mUnicode)));
+                                           NS_INT32_TO_PTR(node->mUnicode),
+                                           fallible));
       NS_ASSERTION(entry, "Error adding an entry");
       // Prefer earlier entries when we have duplication.
       if (!entry->node)
         entry->node = node;
     }
 #ifdef DEBUG
     PL_DHashMarkTableImmutable(&gUnicodeToEntity);
     PL_DHashMarkTableImmutable(&gEntityToUnicode);
--- a/rdf/base/nsInMemoryDataSource.cpp
+++ b/rdf/base/nsInMemoryDataSource.cpp
@@ -327,31 +327,33 @@ public:
     GetReverseArcs(nsIRDFNode* v) {
         PLDHashEntryHdr* hdr = PL_DHashTableSearch(&mReverseArcs, v);
         return hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
     }
 
     void
     SetForwardArcs(nsIRDFResource* u, Assertion* as) {
         if (as) {
-            Entry* entry = static_cast<Entry*>(PL_DHashTableAdd(&mForwardArcs, u));
+            Entry* entry = static_cast<Entry*>
+                (PL_DHashTableAdd(&mForwardArcs, u, mozilla::fallible));
             if (entry) {
                 entry->mNode = u;
                 entry->mAssertions = as;
             }
         }
         else {
             PL_DHashTableRemove(&mForwardArcs, u);
         }
     }
 
     void
     SetReverseArcs(nsIRDFNode* v, Assertion* as) {
         if (as) {
-            Entry* entry = static_cast<Entry*>(PL_DHashTableAdd(&mReverseArcs, v));
+            Entry* entry = static_cast<Entry*>
+                (PL_DHashTableAdd(&mReverseArcs, v, mozilla::fallible));
             if (entry) {
                 entry->mNode = v;
                 entry->mAssertions = as;
             }
         }
         else {
             PL_DHashTableRemove(&mReverseArcs, v);
         }
@@ -1179,17 +1181,18 @@ InMemoryDataSource::LockedAssert(nsIRDFR
             hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
         if (asRef)
         {
             as->mNext = asRef->mNext;
             asRef->mNext = as;
         }
         else
         {
-            hdr = PL_DHashTableAdd(next->u.hash.mPropertyHash, aProperty);
+            hdr = PL_DHashTableAdd(next->u.hash.mPropertyHash, aProperty,
+                                   mozilla::fallible);
             if (hdr)
             {
                 Entry* entry = static_cast<Entry*>(hdr);
                 entry->mNode = aProperty;
                 entry->mAssertions = as;
             }
         }
     }
@@ -1290,18 +1293,19 @@ InMemoryDataSource::LockedUnassert(nsIRD
             return NS_OK;
 
         as = next;
 
         if (first) {
             PL_DHashTableRawRemove(root->u.hash.mPropertyHash, hdr);
 
             if (next && next->mNext) {
-                PLDHashEntryHdr* hdr = PL_DHashTableAdd(root->u.hash.mPropertyHash,
-                                     aProperty);
+                PLDHashEntryHdr* hdr =
+                    PL_DHashTableAdd(root->u.hash.mPropertyHash, aProperty,
+                                     mozilla::fallible);
                 if (hdr) {
                     Entry* entry = static_cast<Entry*>(hdr);
                     entry->mNode = aProperty;
                     entry->mAssertions = next->mNext;
                 }
             }
             else {
                 // If this second-level hash empties out, clean it up.
@@ -1735,17 +1739,18 @@ InMemoryDataSource::EnsureFastContainmen
 
         PLDHashEntryHdr* hdr = PL_DHashTableSearch(table, prop);
         Assertion* val = hdr ? static_cast<Entry*>(hdr)->mAssertions : nullptr;
         if (val) {
             first->mNext = val->mNext;
             val->mNext = first;
         }
         else {
-            PLDHashEntryHdr* hdr = PL_DHashTableAdd(table, prop);
+            PLDHashEntryHdr* hdr = PL_DHashTableAdd(table, prop,
+                                                    mozilla::fallible);
             if (hdr) {
                 Entry* entry = static_cast<Entry*>(hdr);
                 entry->mNode = prop;
                 entry->mAssertions = first;
                 first->mNext = nullptr;
             }
         }
         first = nextRef;
--- a/rdf/base/nsRDFService.cpp
+++ b/rdf/base/nsRDFService.cpp
@@ -1157,17 +1157,17 @@ RDFServiceImpl::RegisterResource(nsIRDFR
         // it.
 
         PR_LOG(gLog, PR_LOG_DEBUG,
                ("rdfserv   replace-resource [%p] <-- [%p] %s",
                 static_cast<ResourceHashEntry *>(hdr)->mResource,
                 aResource, (const char*) uri));
     }
     else {
-        hdr = PL_DHashTableAdd(&mResources, uri);
+        hdr = PL_DHashTableAdd(&mResources, uri, fallible);
         if (! hdr)
             return NS_ERROR_OUT_OF_MEMORY;
 
         PR_LOG(gLog, PR_LOG_DEBUG,
                ("rdfserv   register-resource [%p] %s",
                 aResource, (const char*) uri));
     }
 
@@ -1394,17 +1394,17 @@ nsresult
 RDFServiceImpl::RegisterLiteral(nsIRDFLiteral* aLiteral)
 {
     const char16_t* value;
     aLiteral->GetValueConst(&value);
 
     NS_ASSERTION(!PL_DHashTableSearch(&mLiterals, value),
                  "literal already registered");
 
-    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mLiterals, value);
+    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mLiterals, value, fallible);
     if (! hdr)
         return NS_ERROR_OUT_OF_MEMORY;
 
     LiteralHashEntry *entry = static_cast<LiteralHashEntry *>(hdr);
 
     // N.B., we only hold a weak reference to the literal: that
     // way, the literal can be destroyed when the last refcount
     // goes away. The single addref that the CreateLiteral() call
@@ -1446,17 +1446,17 @@ nsresult
 RDFServiceImpl::RegisterInt(nsIRDFInt* aInt)
 {
     int32_t value;
     aInt->GetValue(&value);
 
     NS_ASSERTION(!PL_DHashTableSearch(&mInts, &value),
                  "int already registered");
 
-    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mInts, &value);
+    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mInts, &value, fallible);
     if (! hdr)
         return NS_ERROR_OUT_OF_MEMORY;
 
     IntHashEntry *entry = static_cast<IntHashEntry *>(hdr);
 
     // N.B., we only hold a weak reference to the literal: that
     // way, the literal can be destroyed when the last refcount
     // goes away. The single addref that the CreateInt() call
@@ -1498,17 +1498,17 @@ nsresult
 RDFServiceImpl::RegisterDate(nsIRDFDate* aDate)
 {
     PRTime value;
     aDate->GetValue(&value);
 
     NS_ASSERTION(!PL_DHashTableSearch(&mDates, &value),
                  "date already registered");
 
-    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mDates, &value);
+    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mDates, &value, fallible);
     if (! hdr)
         return NS_ERROR_OUT_OF_MEMORY;
 
     DateHashEntry *entry = static_cast<DateHashEntry *>(hdr);
 
     // N.B., we only hold a weak reference to the literal: that
     // way, the literal can be destroyed when the last refcount
     // goes away. The single addref that the CreateDate() call
@@ -1545,17 +1545,17 @@ RDFServiceImpl::UnregisterDate(nsIRDFDat
 }
 
 nsresult
 RDFServiceImpl::RegisterBlob(BlobImpl *aBlob)
 {
     NS_ASSERTION(!PL_DHashTableSearch(&mBlobs, &aBlob->mData),
                  "blob already registered");
 
-    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mBlobs, &aBlob->mData);
+    PLDHashEntryHdr *hdr = PL_DHashTableAdd(&mBlobs, &aBlob->mData, fallible);
     if (! hdr)
         return NS_ERROR_OUT_OF_MEMORY;
 
     BlobHashEntry *entry = static_cast<BlobHashEntry *>(hdr);
 
     // N.B., we only hold a weak reference to the literal: that
     // way, the literal can be destroyed when the last refcount
     // goes away. The single addref that the CreateInt() call
--- a/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
+++ b/security/manager/boot/src/nsSecureBrowserUIImpl.cpp
@@ -855,18 +855,18 @@ nsSecureBrowserUIImpl::OnStateChange(nsI
   if (aProgressStateFlags & STATE_TRANSFERRING
       &&
       aProgressStateFlags & STATE_IS_REQUEST)
   {
     // The listing of a request in mTransferringRequests
     // means, there has already been data transfered.
 
     ReentrantMonitorAutoEnter lock(mReentrantMonitor);
-    PL_DHashTableAdd(&mTransferringRequests, aRequest);
-    
+    PL_DHashTableAdd(&mTransferringRequests, aRequest, fallible);
+
     return NS_OK;
   }
 
   bool requestHasTransferedData = false;
 
   if (aProgressStateFlags & STATE_STOP
       &&
       aProgressStateFlags & STATE_IS_REQUEST)
--- a/security/manager/ssl/src/nsCertTree.cpp
+++ b/security/manager/ssl/src/nsCertTree.cpp
@@ -194,19 +194,18 @@ nsCertTree::FreeCertArray()
 {
   mDispInfo.Clear();
 }
 
 CompareCacheHashEntry *
 nsCertTree::getCacheEntry(void *cache, void *aCert)
 {
   PLDHashTable &aCompareCache = *reinterpret_cast<PLDHashTable*>(cache);
-  CompareCacheHashEntryPtr *entryPtr = 
-    static_cast<CompareCacheHashEntryPtr*>
-               (PL_DHashTableAdd(&aCompareCache, aCert));
+  CompareCacheHashEntryPtr *entryPtr = static_cast<CompareCacheHashEntryPtr*>
+    (PL_DHashTableAdd(&aCompareCache, aCert, fallible));
   return entryPtr ? entryPtr->entry : nullptr;
 }
 
 void nsCertTree::RemoveCacheEntry(void *key)
 {
   PL_DHashTableRemove(&mCompareCache, key);
 }
 
--- a/security/manager/ssl/src/nsNSSShutDown.cpp
+++ b/security/manager/ssl/src/nsNSSShutDown.cpp
@@ -63,17 +63,17 @@ nsNSSShutDownList::~nsNSSShutDownList()
 
 void nsNSSShutDownList::remember(nsNSSShutDownObject *o)
 {
   if (!singleton)
     return;
   
   PR_ASSERT(o);
   MutexAutoLock lock(singleton->mListLock);
-  PL_DHashTableAdd(&singleton->mObjects, o);
+  PL_DHashTableAdd(&singleton->mObjects, o, fallible);
 }
 
 void nsNSSShutDownList::forget(nsNSSShutDownObject *o)
 {
   if (!singleton)
     return;
   
   PR_ASSERT(o);
@@ -83,17 +83,17 @@ void nsNSSShutDownList::forget(nsNSSShut
 
 void nsNSSShutDownList::remember(nsOnPK11LogoutCancelObject *o)
 {
   if (!singleton)
     return;
   
   PR_ASSERT(o);
   MutexAutoLock lock(singleton->mListLock);
-  PL_DHashTableAdd(&singleton->mPK11LogoutCancelObjects, o);
+  PL_DHashTableAdd(&singleton->mPK11LogoutCancelObjects, o, fallible);
 }
 
 void nsNSSShutDownList::forget(nsOnPK11LogoutCancelObject *o)
 {
   if (!singleton)
     return;
   
   PR_ASSERT(o);
--- a/uriloader/base/nsDocLoader.cpp
+++ b/uriloader/base/nsDocLoader.cpp
@@ -1333,17 +1333,17 @@ nsDocLoader::RefreshAttempted(nsIWebProg
       mParent->RefreshAttempted(aWebProgress, aURI, aDelay, aSameURI);
   }
 
   return allowRefresh;
 }
 
 nsresult nsDocLoader::AddRequestInfo(nsIRequest *aRequest)
 {
-  if (!PL_DHashTableAdd(&mRequestInfoHash, aRequest)) {
+  if (!PL_DHashTableAdd(&mRequestInfoHash, aRequest, mozilla::fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   return NS_OK;
 }
 
 void nsDocLoader::RemoveRequestInfo(nsIRequest *aRequest)
 {
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -895,18 +895,18 @@ CCGraph::FindNode(void* aPtr)
     static_cast<PtrToNodeEntry*>(PL_DHashTableSearch(&mPtrToNodeMap, aPtr));
   return e ? e->mNode : nullptr;
 }
 
 PtrToNodeEntry*
 CCGraph::AddNodeToMap(void* aPtr)
 {
   JS::AutoSuppressGCAnalysis suppress;
-  PtrToNodeEntry* e =
-    static_cast<PtrToNodeEntry*>(PL_DHashTableAdd(&mPtrToNodeMap, aPtr));
+  PtrToNodeEntry* e = static_cast<PtrToNodeEntry*>
+    (PL_DHashTableAdd(&mPtrToNodeMap, aPtr, fallible));
   if (!e) {
     // Caller should track OOMs
     return nullptr;
   }
   return e;
 }
 
 void
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -548,36 +548,28 @@ EnsureTableExists()
 }
 
 static inline AtomTableEntry*
 GetAtomHashEntry(const char* aString, uint32_t aLength, uint32_t* aHashOut)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
   EnsureTableExists();
   AtomTableKey key(aString, aLength, aHashOut);
-  AtomTableEntry* e = static_cast<AtomTableEntry*>(
-    PL_DHashTableAdd(&gAtomTable, &key));
-  if (!e) {
-    NS_ABORT_OOM(gAtomTable.EntryCount() * gAtomTable.EntrySize());
-  }
-  return e;
+  // This is an infallible add.
+  return static_cast<AtomTableEntry*>(PL_DHashTableAdd(&gAtomTable, &key));
 }
 
 static inline AtomTableEntry*
 GetAtomHashEntry(const char16_t* aString, uint32_t aLength, uint32_t* aHashOut)
 {
   MOZ_ASSERT(NS_IsMainThread(), "wrong thread");
   EnsureTableExists();
   AtomTableKey key(aString, aLength, aHashOut);
-  AtomTableEntry* e = static_cast<AtomTableEntry*>(
-    PL_DHashTableAdd(&gAtomTable, &key));
-  if (!e) {
-    NS_ABORT_OOM(gAtomTable.EntryCount() * gAtomTable.EntrySize());
-  }
-  return e;
+  // This is an infallible add.
+  return static_cast<AtomTableEntry*>(PL_DHashTableAdd(&gAtomTable, &key));
 }
 
 class CheckStaticAtomSizes
 {
   CheckStaticAtomSizes()
   {
     static_assert((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
                    sizeof(nsStringBuffer().mRefCount)) &&
--- a/xpcom/ds/nsPersistentProperties.cpp
+++ b/xpcom/ds/nsPersistentProperties.cpp
@@ -523,17 +523,17 @@ nsPersistentProperties::Load(nsIInputStr
 
 NS_IMETHODIMP
 nsPersistentProperties::SetStringProperty(const nsACString& aKey,
                                           const nsAString& aNewValue,
                                           nsAString& aOldValue)
 {
   const nsAFlatCString&  flatKey = PromiseFlatCString(aKey);
   PropertyTableEntry* entry = static_cast<PropertyTableEntry*>(
-    PL_DHashTableAdd(&mTable, flatKey.get()));
+    PL_DHashTableAdd(&mTable, flatKey.get(), mozilla::fallible));
 
   if (entry->mKey) {
     aOldValue = entry->mValue;
     NS_WARNING(nsPrintfCString("the property %s already exists\n",
                                flatKey.get()).get());
   } else {
     aOldValue.Truncate();
   }
--- a/xpcom/ds/nsStaticNameTable.cpp
+++ b/xpcom/ds/nsStaticNameTable.cpp
@@ -159,18 +159,18 @@ nsStaticCaseInsensitiveNameTable::Init(c
     }
 #endif
     // use placement-new to initialize the string object
     nsDependentCString* strPtr = &mNameArray[index];
     new (strPtr) nsDependentCString(raw);
 
     NameTableKey key(strPtr);
 
-    NameTableEntry* entry =
-      static_cast<NameTableEntry*>(PL_DHashTableAdd(&mNameTable, &key));
+    NameTableEntry* entry = static_cast<NameTableEntry*>
+      (PL_DHashTableAdd(&mNameTable, &key, fallible));
     if (!entry) {
       continue;
     }
 
     NS_ASSERTION(entry->mString == 0, "Entry already exists!");
 
     entry->mString = strPtr;      // not owned!
     entry->mIndex = index;
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -144,29 +144,31 @@ public:
   /**
    * Get the entry associated with a key, or create a new entry,
    * @param     aKey the key to retrieve
    * @return    pointer to the entry class retreived; nullptr only if memory
                 can't be allocated
    */
   EntryType* PutEntry(KeyType aKey)
   {
-    EntryType* e = PutEntry(aKey, mozilla::fallible);
-    if (!e) {
-      NS_ABORT_OOM(mTable.EntrySize() * mTable.EntryCount());
-    }
-    return e;
-  }
-
-  EntryType* PutEntry(KeyType aKey, const fallible_t&) NS_WARN_UNUSED_RESULT {
     NS_ASSERTION(mTable.IsInitialized(),
                  "nsTHashtable was not initialized properly.");
 
-    return static_cast<EntryType*>(PL_DHashTableAdd(
-      &mTable, EntryType::KeyToPointer(aKey)));
+    return static_cast<EntryType*>  // infallible add
+      (PL_DHashTableAdd(&mTable, EntryType::KeyToPointer(aKey)));
+  }
+
+  EntryType* PutEntry(KeyType aKey, const fallible_t&) NS_WARN_UNUSED_RESULT
+  {
+    NS_ASSERTION(mTable.IsInitialized(),
+                 "nsTHashtable was not initialized properly.");
+
+    return static_cast<EntryType*>
+      (PL_DHashTableAdd(&mTable, EntryType::KeyToPointer(aKey),
+                        mozilla::fallible));
   }
 
   /**
    * Remove the entry associated with a key.
    * @param     aKey of the entry to remove
    */
   void RemoveEntry(KeyType aKey)
   {
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -565,17 +565,17 @@ PLDHashTable::Search(const void* aKey)
   PLDHashEntryHdr* entry = SearchTable<ForSearchOrRemove>(aKey, keyHash);
 
   DECREMENT_RECURSION_LEVEL(this);
 
   return entry;
 }
 
 MOZ_ALWAYS_INLINE PLDHashEntryHdr*
-PLDHashTable::Add(const void* aKey)
+PLDHashTable::Add(const void* aKey, const mozilla::fallible_t&)
 {
   PLDHashNumber keyHash;
   PLDHashEntryHdr* entry;
 
   MOZ_ASSERT(mRecursionLevel == 0);
   INCREMENT_RECURSION_LEVEL(this);
 
   /*
@@ -667,19 +667,33 @@ PLDHashTable::Remove(const void* aKey)
 
 PLDHashEntryHdr* PL_DHASH_FASTCALL
 PL_DHashTableSearch(PLDHashTable* aTable, const void* aKey)
 {
   return aTable->Search(aKey);
 }
 
 PLDHashEntryHdr* PL_DHASH_FASTCALL
+PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey,
+                 const fallible_t& aFallible)
+{
+  return aTable->Add(aKey, aFallible);
+}
+
+PLDHashEntryHdr* PL_DHASH_FASTCALL
 PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey)
 {
-  return aTable->Add(aKey);
+  PLDHashEntryHdr* entry = PL_DHashTableAdd(aTable, aKey, fallible);
+  if (!entry) {
+    // There are two ways the Add could fail: (a) a entry storage reallocation
+    // failed, or (b) mOps->initEntry failed. The number we're reporting here
+    // is the one for case (a), which is the more likely of the two.
+    NS_ABORT_OOM(aTable->EntrySize() * aTable->EntryCount());
+  }
+  return entry;
 }
 
 void PL_DHASH_FASTCALL
 PL_DHashTableRemove(PLDHashTable* aTable, const void* aKey)
 {
   aTable->Remove(aKey);
 }
 
--- a/xpcom/glue/pldhash.h
+++ b/xpcom/glue/pldhash.h
@@ -239,17 +239,17 @@ public:
   uint32_t Generation() const { return mGeneration; }
 
   bool Init(const PLDHashTableOps* aOps, uint32_t aEntrySize,
             const mozilla::fallible_t&, uint32_t aLength);
 
   void Finish();
 
   PLDHashEntryHdr* Search(const void* aKey);
-  PLDHashEntryHdr* Add(const void* aKey);
+  PLDHashEntryHdr* Add(const void* aKey, const mozilla::fallible_t&);
   void Remove(const void* aKey);
 
   void RawRemove(PLDHashEntryHdr* aEntry);
 
   uint32_t Enumerate(PLDHashEnumerator aEtor, void* aArg);
 
   size_t SizeOfIncludingThis(
     PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
@@ -476,30 +476,38 @@ void PL_DHashTableFinish(PLDHashTable* a
  * found.
  */
 PLDHashEntryHdr* PL_DHASH_FASTCALL
 PL_DHashTableSearch(PLDHashTable* aTable, const void* aKey);
 
 /*
  * To add an entry identified by key to table, call:
  *
- *  entry = PL_DHashTableAdd(table, key);
+ *  entry = PL_DHashTableAdd(table, key, mozilla::fallible);
  *
  * If entry is null upon return, then either (a) the table is severely
  * overloaded and memory can't be allocated for entry storage, or (b)
  * aTable->mOps->initEntry is non-null and aTable->mOps->initEntry op has
  * returned false.
  *
  * Otherwise, aEntry->mKeyHash has been set so that
  * PLDHashTable::EntryIsFree(entry) is false, and it is up to the caller to
  * initialize the key and value parts of the entry sub-type, if they have not
  * been set already (i.e. if entry was not already in the table, and if the
  * optional initEntry hook was not used).
  */
 PLDHashEntryHdr* PL_DHASH_FASTCALL
+PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey,
+                 const mozilla::fallible_t&);
+
+/*
+ * This is like the other PL_DHashTableAdd() function, but infallible, and so
+ * never returns null.
+ */
+PLDHashEntryHdr* PL_DHASH_FASTCALL
 PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey);
 
 /*
  * To remove an entry identified by key from table, call:
  *
  *  PL_DHashTableRemove(table, key);
  *
  * If key's entry is found, it is cleared (via table->mOps->clearEntry) and
--- a/xpcom/tests/TestPLDHash.cpp
+++ b/xpcom/tests/TestPLDHash.cpp
@@ -133,17 +133,17 @@ static bool test_pldhash_grow_to_max_cap
   // Check that New() sets |t->ops|.
   if (!t->IsInitialized()) {
     return false;
   }
 
   // Keep inserting elements until failure occurs because the table is full.
   size_t numInserted = 0;
   while (true) {
-    if (!PL_DHashTableAdd(t, (const void*)numInserted)) {
+    if (!PL_DHashTableAdd(t, (const void*)numInserted, mozilla::fallible)) {
       break;
     }
     numInserted++;
   }
 
   // We stop when the element count is 96.875% of PL_DHASH_MAX_SIZE (see
   // MaxLoadOnGrowthFailure()).
   if (numInserted != PL_DHASH_MAX_CAPACITY - (PL_DHASH_MAX_CAPACITY >> 5)) {