Bug 1189156 (part 1) - Don't use enumeration style for PLDHashTable::SizeOf{In,Ex}cludingThis(). r=froydnj.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 29 Jul 2015 22:28:20 -0700
changeset 274558 525bb2034be22ff987ddc87cfeff8407ea2689e5
parent 274557 6efdf94d0b97bb3130ebc869c066c13071f4a36c
child 274559 8e247a5f9f976ae6749b255d1a71a4b74abc62d7
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-esr52@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1189156
milestone42.0a1
Bug 1189156 (part 1) - Don't use enumeration style for PLDHashTable::SizeOf{In,Ex}cludingThis(). r=froydnj. After this change, we have PLDHashTable::ShallowSizeOf{In,Ex}cludingThis(), which don't do anything to measure children. (They can be combined with iteration to measure children.) This patch also removes the PL_DHashTableSizeOf{In,Ex}cludingThis() functions. They're not necessary because the methods can be used instead. Finally, the patch deliberately converts some SizeOfExcludingThis() calls to SizeOfIncludingThis(). These are all done on heap pointers so this change is valid.
dom/base/nsContentUtils.cpp
dom/base/nsPropertyTable.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/base/nsScriptNameSpaceManager.h
js/xpconnect/src/XPCMaps.cpp
js/xpconnect/src/XPCMaps.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLStyleSheet.cpp
modules/libpref/Preferences.cpp
netwerk/dns/nsHostResolver.cpp
xpcom/ds/nsAtomTable.cpp
xpcom/glue/nsBaseHashtable.h
xpcom/glue/nsTHashtable.h
xpcom/glue/pldhash.cpp
xpcom/glue/pldhash.h
xpcom/tests/gtest/TestPLDHash.cpp
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -359,18 +359,18 @@ public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                             nsISupports* aData, bool aAnonymize) override
   {
     // We don't measure the |EventListenerManager| objects pointed to by the
     // entries because those references are non-owning.
     int64_t amount = sEventListenerManagersHash
-                   ? PL_DHashTableSizeOfExcludingThis(
-                       sEventListenerManagersHash, nullptr, MallocSizeOf)
+                   ? sEventListenerManagersHash->ShallowSizeOfIncludingThis(
+                       MallocSizeOf)
                    : 0;
 
     return MOZ_COLLECT_REPORT(
       "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
       amount,
       "Memory used by the event listener manager's hash table.");
   }
 };
--- a/dom/base/nsPropertyTable.cpp
+++ b/dom/base/nsPropertyTable.cpp
@@ -308,17 +308,17 @@ nsPropertyTable::PropertyList::DeletePro
 
   return true;
 }
 
 size_t
 nsPropertyTable::PropertyList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   size_t n = aMallocSizeOf(this);
-  n += PL_DHashTableSizeOfExcludingThis(&mObjectValueMap, nullptr, aMallocSizeOf);
+  n += mObjectValueMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
   return n;
 }
 
 size_t
 nsPropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
 
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -720,38 +720,40 @@ nsScriptNameSpaceManager::RegisterNaviga
     if (s->mType == nsGlobalNameStruct::eTypeNotInitialized) {
       s->mType = nsGlobalNameStruct::eTypeNewDOMBinding;
     }
     s->mConstructNavigatorProperty = aNavConstructor;
     s->mConstructorEnabled = aConstructorEnabled;
   }
 }
 
-static size_t
-SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, MallocSizeOf aMallocSizeOf,
-                         void *aArg)
-{
-  GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
-  return entry->SizeOfExcludingThis(aMallocSizeOf);
-}
-
 MOZ_DEFINE_MALLOC_SIZE_OF(ScriptNameSpaceManagerMallocSizeOf)
 
 NS_IMETHODIMP
 nsScriptNameSpaceManager::CollectReports(
   nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
 {
   return MOZ_COLLECT_REPORT(
     "explicit/script-namespace-manager", KIND_HEAP, UNITS_BYTES,
     SizeOfIncludingThis(ScriptNameSpaceManagerMallocSizeOf),
     "Memory used for the script namespace manager.");
 }
 
 size_t
-nsScriptNameSpaceManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+nsScriptNameSpaceManager::SizeOfIncludingThis(
+    mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
-  n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,
-         SizeOfEntryExcludingThis, aMallocSizeOf);
-  n += PL_DHashTableSizeOfExcludingThis(&mNavigatorNames,
-         SizeOfEntryExcludingThis, aMallocSizeOf);
+
+  n += mGlobalNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mGlobalNames.ConstIter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<GlobalNameMapEntry*>(iter.Get());
+    n += entry->SizeOfExcludingThis(aMallocSizeOf);
+  }
+
+  n += mNavigatorNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mNavigatorNames.ConstIter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<GlobalNameMapEntry*>(iter.Get());
+    n += entry->SizeOfExcludingThis(aMallocSizeOf);
+  }
+
   return n;
 }
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -201,17 +201,17 @@ public:
     NameIterator(const NameIterator&) = delete;
     NameIterator& operator=(const NameIterator&) = delete;
     NameIterator& operator=(const NameIterator&&) = delete;
   };
 
   NameIterator GlobalNameIter()    { return NameIterator(&mGlobalNames); }
   NameIterator NavigatorNameIter() { return NameIterator(&mNavigatorNames); }
 
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   virtual ~nsScriptNameSpaceManager();
 
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
--- a/js/xpconnect/src/XPCMaps.cpp
+++ b/js/xpconnect/src/XPCMaps.cpp
@@ -178,31 +178,27 @@ Native2WrappedNativeMap::Native2WrappedN
 }
 
 Native2WrappedNativeMap::~Native2WrappedNativeMap()
 {
     delete mTable;
 }
 
 size_t
-Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
+Native2WrappedNativeMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-    size_t n = 0;
-    n += mallocSizeOf(this);
-    n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
+    size_t n = mallocSizeOf(this);
+    n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
+    for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
+        auto entry = static_cast<Native2WrappedNativeMap::Entry*>(iter.Get());
+        n += mallocSizeOf(entry->value);
+    }
     return n;
 }
 
-/* static */ size_t
-Native2WrappedNativeMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
-                                                  mozilla::MallocSizeOf mallocSizeOf, void*)
-{
-    return mallocSizeOf(((Native2WrappedNativeMap::Entry*)hdr)->value);
-}
-
 /***************************************************************************/
 // implement IID2WrappedJSClassMap...
 
 const struct PLDHashTableOps IID2WrappedJSClassMap::Entry::sOps =
 {
     HashIIDPtrKey,
     MatchIIDPtrKey,
     PL_DHashMoveEntryStub,
@@ -250,32 +246,27 @@ IID2NativeInterfaceMap::IID2NativeInterf
 }
 
 IID2NativeInterfaceMap::~IID2NativeInterfaceMap()
 {
     delete mTable;
 }
 
 size_t
-IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
+IID2NativeInterfaceMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-    size_t n = 0;
-    n += mallocSizeOf(this);
-    n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
+    size_t n = mallocSizeOf(this);
+    n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
+    for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
+        auto entry = static_cast<IID2NativeInterfaceMap::Entry*>(iter.Get());
+        n += entry->value->SizeOfIncludingThis(mallocSizeOf);
+    }
     return n;
 }
 
-/* static */ size_t
-IID2NativeInterfaceMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
-                                                 mozilla::MallocSizeOf mallocSizeOf, void*)
-{
-    XPCNativeInterface* iface = ((IID2NativeInterfaceMap::Entry*)hdr)->value;
-    return iface->SizeOfIncludingThis(mallocSizeOf);
-}
-
 /***************************************************************************/
 // implement ClassInfo2NativeSetMap...
 
 // static
 ClassInfo2NativeSetMap*
 ClassInfo2NativeSetMap::newMap(int length)
 {
     return new ClassInfo2NativeSetMap(length);
@@ -289,20 +280,18 @@ ClassInfo2NativeSetMap::ClassInfo2Native
 ClassInfo2NativeSetMap::~ClassInfo2NativeSetMap()
 {
     delete mTable;
 }
 
 size_t
 ClassInfo2NativeSetMap::ShallowSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
 {
-    size_t n = 0;
-    n += mallocSizeOf(this);
-    // The second arg is nullptr because this is a "shallow" measurement of the map.
-    n += PL_DHashTableSizeOfIncludingThis(mTable, nullptr, mallocSizeOf);
+    size_t n = mallocSizeOf(this);
+    n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
     return n;
 }
 
 /***************************************************************************/
 // implement ClassInfo2WrappedNativeProtoMap...
 
 // static
 ClassInfo2WrappedNativeProtoMap*
@@ -317,31 +306,27 @@ ClassInfo2WrappedNativeProtoMap::ClassIn
 }
 
 ClassInfo2WrappedNativeProtoMap::~ClassInfo2WrappedNativeProtoMap()
 {
     delete mTable;
 }
 
 size_t
-ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
+ClassInfo2WrappedNativeProtoMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-    size_t n = 0;
-    n += mallocSizeOf(this);
-    n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
+    size_t n = mallocSizeOf(this);
+    n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
+    for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
+        auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(iter.Get());
+        n += mallocSizeOf(entry->value);
+    }
     return n;
 }
 
-/* static */ size_t
-ClassInfo2WrappedNativeProtoMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr,
-                                                          mozilla::MallocSizeOf mallocSizeOf, void*)
-{
-    return mallocSizeOf(((ClassInfo2WrappedNativeProtoMap::Entry*)hdr)->value);
-}
-
 /***************************************************************************/
 // implement NativeSetMap...
 
 bool
 NativeSetMap::Entry::Match(PLDHashTable* table,
                            const PLDHashEntryHdr* entry,
                            const void* key)
 {
@@ -433,31 +418,27 @@ NativeSetMap::NativeSetMap(int length)
 }
 
 NativeSetMap::~NativeSetMap()
 {
     delete mTable;
 }
 
 size_t
-NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf)
+NativeSetMap::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
-    size_t n = 0;
-    n += mallocSizeOf(this);
-    n += PL_DHashTableSizeOfIncludingThis(mTable, SizeOfEntryExcludingThis, mallocSizeOf);
+    size_t n = mallocSizeOf(this);
+    n += mTable->ShallowSizeOfIncludingThis(mallocSizeOf);
+    for (auto iter = mTable->Iter(); !iter.Done(); iter.Next()) {
+        auto entry = static_cast<NativeSetMap::Entry*>(iter.Get());
+        n += entry->key_value->SizeOfIncludingThis(mallocSizeOf);
+    }
     return n;
 }
 
-/* static */ size_t
-NativeSetMap::SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*)
-{
-    XPCNativeSet* set = ((NativeSetMap::Entry*)hdr)->key_value;
-    return set->SizeOfIncludingThis(mallocSizeOf);
-}
-
 /***************************************************************************/
 // implement IID2ThisTranslatorMap...
 
 bool
 IID2ThisTranslatorMap::Entry::Match(PLDHashTable* table,
                                     const PLDHashEntryHdr* entry,
                                     const void* key)
 {
--- a/js/xpconnect/src/XPCMaps.h
+++ b/js/xpconnect/src/XPCMaps.h
@@ -145,25 +145,23 @@ public:
                    "problems!");
 #endif
         PL_DHashTableRemove(mTable, wrapper->GetIdentityObject());
     }
 
     inline uint32_t Count() { return mTable->EntryCount(); }
 
     PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     ~Native2WrappedNativeMap();
 private:
     Native2WrappedNativeMap();    // no implementation
     explicit Native2WrappedNativeMap(int size);
 
-    static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
-
 private:
     PLDHashTable* mTable;
 };
 
 /*************************/
 
 class IID2WrappedJSClassMap
 {
@@ -258,25 +256,23 @@ public:
         NS_PRECONDITION(iface,"bad param");
         PL_DHashTableRemove(mTable, iface->GetIID());
     }
 
     inline uint32_t Count() { return mTable->EntryCount(); }
 
     PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     ~IID2NativeInterfaceMap();
 private:
     IID2NativeInterfaceMap();    // no implementation
     explicit IID2NativeInterfaceMap(int size);
 
-    static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
-
 private:
     PLDHashTable* mTable;
 };
 
 /*************************/
 
 class ClassInfo2NativeSetMap
 {
@@ -372,25 +368,23 @@ public:
         PL_DHashTableRemove(mTable, info);
     }
 
     inline uint32_t Count() { return mTable->EntryCount(); }
 
     PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
     PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     ~ClassInfo2WrappedNativeProtoMap();
 private:
     ClassInfo2WrappedNativeProtoMap();    // no implementation
     explicit ClassInfo2WrappedNativeProtoMap(int size);
 
-    static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
-
 private:
     PLDHashTable* mTable;
 };
 
 /*************************/
 
 class NativeSetMap
 {
@@ -443,25 +437,23 @@ public:
         PL_DHashTableRemove(mTable, &key);
     }
 
     inline uint32_t Count() { return mTable->EntryCount(); }
 
     PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
     PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
 
-    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+    size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
     ~NativeSetMap();
 private:
     NativeSetMap();    // no implementation
     explicit NativeSetMap(int size);
 
-    static size_t SizeOfEntryExcludingThis(PLDHashEntryHdr* hdr, mozilla::MallocSizeOf mallocSizeOf, void*);
-
 private:
     PLDHashTable* mTable;
 };
 
 /***************************************************************************/
 
 class IID2ThisTranslatorMap
 {
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -166,17 +166,17 @@ private:
 
 // ------------------------------
 // Rule hash table
 //
 
 // Uses any of the sets of ops below.
 struct RuleHashTableEntry : public PLDHashEntryHdr {
   // If you add members that have heap allocated memory be sure to change the
-  // logic in SizeOfRuleHashTableEntry().
+  // logic in SizeOfRuleHashTable().
   // Auto length 1, because we always have at least one entry in mRules.
   nsAutoTArray<RuleValue, 1> mRules;
 };
 
 struct RuleHashTagTableEntry : public RuleHashTableEntry {
   // If you add members that have heap allocated memory be sure to change the
   // logic in RuleHash::SizeOf{In,Ex}cludingThis.
   nsCOMPtr<nsIAtom> mTag;
@@ -741,42 +741,38 @@ void RuleHash::EnumerateAllRules(Element
                          *end = mEnumList[0].mEnd;
          value != end; ++value) {
       ContentEnumFunc(*value, value->mSelector, aData, aNodeContext, filter);
     }
   }
 }
 
 static size_t
-SizeOfRuleHashTableEntry(PLDHashEntryHdr* aHdr, MallocSizeOf aMallocSizeOf, void *)
+SizeOfRuleHashTable(const PLDHashTable& aTable, MallocSizeOf aMallocSizeOf)
 {
-  RuleHashTableEntry* entry = static_cast<RuleHashTableEntry*>(aHdr);
-  return entry->mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<RuleHashTableEntry*>(iter.Get());
+    n += entry->mRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  }
+  return n;
 }
 
 size_t
 RuleHash::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
 
-  n += PL_DHashTableSizeOfExcludingThis(&mIdTable,
-                                        SizeOfRuleHashTableEntry,
-                                        aMallocSizeOf);
-
-  n += PL_DHashTableSizeOfExcludingThis(&mClassTable,
-                                        SizeOfRuleHashTableEntry,
-                                        aMallocSizeOf);
-
-  n += PL_DHashTableSizeOfExcludingThis(&mTagTable,
-                                        SizeOfRuleHashTableEntry,
-                                        aMallocSizeOf);
-
-  n += PL_DHashTableSizeOfExcludingThis(&mNameSpaceTable,
-                                        SizeOfRuleHashTableEntry,
-                                        aMallocSizeOf);
+  n += SizeOfRuleHashTable(mIdTable, aMallocSizeOf);
+
+  n += SizeOfRuleHashTable(mClassTable, aMallocSizeOf);
+
+  n += SizeOfRuleHashTable(mTagTable, aMallocSizeOf);
+
+  n += SizeOfRuleHashTable(mNameSpaceTable, aMallocSizeOf);
 
   n += mUniversalRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   return n;
 }
 
 size_t
 RuleHash::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
@@ -918,20 +914,24 @@ struct RuleCascadeData {
 
   nsMediaQueryResultCacheKey mCacheKey;
   RuleCascadeData*  mNext; // for a different medium
 
   const bool mQuirksMode;
 };
 
 static size_t
-SizeOfSelectorsEntry(PLDHashEntryHdr* aHdr, MallocSizeOf aMallocSizeOf, void *)
+SizeOfSelectorsHashTable(const PLDHashTable& aTable, MallocSizeOf aMallocSizeOf)
 {
-  AtomSelectorEntry* entry = static_cast<AtomSelectorEntry*>(aHdr);
-  return entry->mSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<AtomSelectorEntry*>(iter.Get());
+    n += entry->mSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  }
+  return n;
 }
 
 static size_t
 SizeOfKeyframesRuleEntryExcludingThis(nsStringHashKey::KeyType aKey,
                                       nsCSSKeyframesRule* const& aData,
                                       mozilla::MallocSizeOf aMallocSizeOf,
                                       void* aUserArg)
 {
@@ -953,31 +953,26 @@ RuleCascadeData::SizeOfIncludingThis(Mal
   n += mRuleHash.SizeOfExcludingThis(aMallocSizeOf);
   for (uint32_t i = 0; i < ArrayLength(mPseudoElementRuleHashes); ++i) {
     if (mPseudoElementRuleHashes[i])
       n += mPseudoElementRuleHashes[i]->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   n += mStateSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
-  n += PL_DHashTableSizeOfExcludingThis(&mIdSelectors,
-                                        SizeOfSelectorsEntry, aMallocSizeOf);
-  n += PL_DHashTableSizeOfExcludingThis(&mClassSelectors,
-                                        SizeOfSelectorsEntry, aMallocSizeOf);
+  n += SizeOfSelectorsHashTable(mIdSelectors, aMallocSizeOf);
+  n += SizeOfSelectorsHashTable(mClassSelectors, aMallocSizeOf);
 
   n += mPossiblyNegatedClassSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mPossiblyNegatedIDSelectors.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
-  n += PL_DHashTableSizeOfExcludingThis(&mAttributeSelectors,
-                                        SizeOfSelectorsEntry, aMallocSizeOf);
-  n += PL_DHashTableSizeOfExcludingThis(&mAnonBoxRules,
-                                        SizeOfRuleHashTableEntry, aMallocSizeOf);
+  n += SizeOfSelectorsHashTable(mAttributeSelectors, aMallocSizeOf);
+  n += SizeOfRuleHashTable(mAnonBoxRules, aMallocSizeOf);
 #ifdef MOZ_XUL
-  n += PL_DHashTableSizeOfExcludingThis(&mXULTreeRules,
-                                        SizeOfRuleHashTableEntry, aMallocSizeOf);
+  n += SizeOfRuleHashTable(mXULTreeRules, aMallocSizeOf);
 #endif
 
   n += mFontFaceRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mKeyframesRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mFontFeatureValuesRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mPageRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mCounterStyleRules.ShallowSizeOfExcludingThis(aMallocSizeOf);
   n += mKeyframesRuleTable.SizeOfExcludingThis(SizeOfKeyframesRuleEntryExcludingThis,
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -503,36 +503,26 @@ nsHTMLStyleSheet::LangRuleFor(const nsSt
     (PL_DHashTableAdd(&mLangRuleTable, &aLanguage, fallible));
   if (!entry) {
     NS_ASSERTION(false, "out of memory");
     return nullptr;
   }
   return entry->mRule;
 }
 
-static size_t
-SizeOfAttributesEntryExcludingThis(PLDHashEntryHdr* aEntry,
-                                   MallocSizeOf aMallocSizeOf,
-                                   void* aArg)
-{
-  NS_PRECONDITION(aEntry, "The entry should not be null!");
-
-  MappedAttrTableEntry* entry = static_cast<MappedAttrTableEntry*>(aEntry);
-  NS_ASSERTION(entry->mAttributes, "entry->mAttributes should not be null!");
-  return entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
-}
-
 size_t
 nsHTMLStyleSheet::DOMSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
-  n += PL_DHashTableSizeOfExcludingThis(&mMappedAttrTable,
-                                        SizeOfAttributesEntryExcludingThis,
-                                        aMallocSizeOf);
+  n += mMappedAttrTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mMappedAttrTable.ConstIter(); !iter.Done(); iter.Next()) {
+    auto entry = static_cast<MappedAttrTableEntry*>(iter.Get());
+    n += entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
+  }
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mURL
   // - mLinkRule
   // - mVisitedRule
   // - mActiveRule
   // - mTableQuirkColorRule
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -236,17 +236,17 @@ SizeOfObserverEntryExcludingThis(ValueOb
 Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), 0);
 
   size_t n = aMallocSizeOf(sPreferences);
   if (gHashTable) {
     // pref keys are allocated in a private arena, which we count elsewhere.
     // pref stringvals are allocated out of the same private arena.
-    n += PL_DHashTableSizeOfExcludingThis(gHashTable, nullptr, aMallocSizeOf);
+    n += gHashTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
   }
   if (gCacheData) {
     n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
     for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
       n += aMallocSizeOf((*gCacheData)[i]);
     }
   }
   if (gObserverTable) {
--- a/netwerk/dns/nsHostResolver.cpp
+++ b/netwerk/dns/nsHostResolver.cpp
@@ -1351,32 +1351,28 @@ nsHostResolver::CancelAsyncRequest(const
             if (recPtr->next != recPtr) {
                 PR_REMOVE_LINK(recPtr);
                 NS_RELEASE(recPtr);
             }
         }
     }
 }
 
-static size_t
-SizeOfHostDBEntExcludingThis(PLDHashEntryHdr* hdr, MallocSizeOf mallocSizeOf,
-                             void*)
-{
-    nsHostDBEnt* ent = static_cast<nsHostDBEnt*>(hdr);
-    return ent->rec->SizeOfIncludingThis(mallocSizeOf);
-}
-
 size_t
 nsHostResolver::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
 {
     MutexAutoLock lock(mLock);
 
     size_t n = mallocSizeOf(this);
-    n += PL_DHashTableSizeOfExcludingThis(&mDB, SizeOfHostDBEntExcludingThis,
-                                          mallocSizeOf);
+
+    n += mDB.ShallowSizeOfExcludingThis(mallocSizeOf);
+    for (auto iter = mDB.ConstIter(); !iter.Done(); iter.Next()) {
+        auto entry = static_cast<nsHostDBEnt*>(iter.Get());
+        n += entry->rec->SizeOfIncludingThis(mallocSizeOf);
+    }
 
     // The following fields aren't measured.
     // - mHighQ, mMediumQ, mLowQ, mEvictionQ, because they just point to
     //   nsHostRecords that also pointed to by entries |mDB|, and measured when
     //   |mDB| is measured.
 
     return n;
 }
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -498,34 +498,28 @@ AtomImpl::SizeOfIncludingThis(MallocSize
     n += nsStringBuffer::FromData(mString)->SizeOfIncludingThisIfUnshared(
            aMallocSizeOf);
   }
   return n;
 }
 
 //----------------------------------------------------------------------
 
-static size_t
-SizeOfAtomTableEntryExcludingThis(PLDHashEntryHdr* aHdr,
-                                  MallocSizeOf aMallocSizeOf,
-                                  void* aArg)
-{
-  AtomTableEntry* entry = static_cast<AtomTableEntry*>(aHdr);
-  return entry->mAtom->SizeOfIncludingThis(aMallocSizeOf);
-}
-
 void
 NS_SizeOfAtomTablesIncludingThis(MallocSizeOf aMallocSizeOf,
                                  size_t* aMain, size_t* aStatic)
 {
-  *aMain = gAtomTable
-         ? PL_DHashTableSizeOfExcludingThis(gAtomTable,
-                                            SizeOfAtomTableEntryExcludingThis,
-                                            aMallocSizeOf)
-         : 0;
+  *aMain = 0;
+  if (gAtomTable) {
+    *aMain += gAtomTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
+    for (auto iter = gAtomTable->Iter(); !iter.Done(); iter.Next()) {
+      auto entry = static_cast<AtomTableEntry*>(iter.Get());
+      *aMain += entry->mAtom->SizeOfIncludingThis(aMallocSizeOf);
+    }
+  }
 
   // The atoms in the this table are almost certainly stored in static data, so
   // we don't need a SizeOfEntry function.
   *aStatic = gStaticAtomTable
            ? gStaticAtomTable->SizeOfIncludingThis(nullptr, aMallocSizeOf)
            : 0;
 }
 
--- a/xpcom/glue/nsBaseHashtable.h
+++ b/xpcom/glue/nsBaseHashtable.h
@@ -313,39 +313,30 @@ public:
    * @param     aUserArg a pointer to pass to the
    *            <code>SizeOfEntryExcludingThisFun</code> function
    * @return    the summed size of all the entries
    */
   size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
                              mozilla::MallocSizeOf aMallocSizeOf,
                              void* aUserArg = nullptr) const
   {
+    size_t n = 0;
+    n += this->mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
     if (aSizeOfEntryExcludingThis) {
-      s_SizeOfArgs args = { aSizeOfEntryExcludingThis, aUserArg };
-      return PL_DHashTableSizeOfExcludingThis(&this->mTable, s_SizeOfStub,
-                                              aMallocSizeOf, &args);
+      for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
+        n += aSizeOfEntryExcludingThis(iter.Key(), iter.Data(), aMallocSizeOf,
+                                       aUserArg);
+      }
     }
-    return PL_DHashTableSizeOfExcludingThis(&this->mTable, nullptr,
-                                            aMallocSizeOf);
+    return n;
   }
 
 #ifdef DEBUG
   using nsTHashtable<EntryType>::MarkImmutable;
 #endif
-
-protected:
-  struct s_SizeOfArgs
-  {
-    SizeOfEntryExcludingThisFun func;
-    void* userArg;
-  };
-
-  static size_t s_SizeOfStub(PLDHashEntryHdr* aEntry,
-                             mozilla::MallocSizeOf aMallocSizeOf,
-                             void* aArg);
 };
 
 //
 // nsBaseHashtableET definitions
 //
 
 template<class KeyClass, class DataType>
 nsBaseHashtableET<KeyClass, DataType>::nsBaseHashtableET(KeyTypePointer aKey)
@@ -362,25 +353,9 @@ nsBaseHashtableET<KeyClass, DataType>::n
 {
 }
 
 template<class KeyClass, class DataType>
 nsBaseHashtableET<KeyClass, DataType>::~nsBaseHashtableET()
 {
 }
 
-
-//
-// nsBaseHashtable definitions
-//
-
-template<class KeyClass, class DataType, class UserDataType>
-size_t
-nsBaseHashtable<KeyClass, DataType, UserDataType>::s_SizeOfStub(
-    PLDHashEntryHdr* aHdr, mozilla::MallocSizeOf aMallocSizeOf, void* aArg)
-{
-  EntryType* ent = static_cast<EntryType*>(aHdr);
-  s_SizeOfArgs* eargs = static_cast<s_SizeOfArgs*>(aArg);
-
-  return (eargs->func)(ent->GetKey(), ent->mData, aMallocSizeOf, eargs->userArg);
-}
-
 #endif // nsBaseHashtable_h__
--- a/xpcom/glue/nsTHashtable.h
+++ b/xpcom/glue/nsTHashtable.h
@@ -295,22 +295,24 @@ public:
    * @param     userArg a pointer to pass to the
    *            <code>SizeOfEntryExcludingThisFun</code> function
    * @return    the summed size of all the entries
    */
   size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
                              mozilla::MallocSizeOf aMallocSizeOf,
                              void* aUserArg = nullptr) const
   {
+    size_t n = 0;
+    n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
     if (aSizeOfEntryExcludingThis) {
-      s_SizeOfArgs args = { aSizeOfEntryExcludingThis, aUserArg };
-      return PL_DHashTableSizeOfExcludingThis(&mTable, s_SizeOfStub,
-                                              aMallocSizeOf, &args);
+      for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
+        n += aSizeOfEntryExcludingThis(iter.Get(), aMallocSizeOf, aUserArg);
+      }
     }
-    return PL_DHashTableSizeOfExcludingThis(&mTable, nullptr, aMallocSizeOf);
+    return n;
   }
 
   /**
    * If the EntryType defines SizeOfExcludingThis, there's no need to define a new
    * SizeOfEntryExcludingThisFun.
    */
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   {
@@ -372,32 +374,16 @@ protected:
 
   static void s_CopyEntry(PLDHashTable* aTable, const PLDHashEntryHdr* aFrom,
                           PLDHashEntryHdr* aTo);
 
   static void s_ClearEntry(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
 
   static void s_InitEntry(PLDHashEntryHdr* aEntry, const void* aKey);
 
-  /**
-   * passed internally during sizeOf counting.  Allocated on the stack.
-   *
-   * @param userFunc the SizeOfEntryExcludingThisFun passed to
-   *                 SizeOf{In,Ex}cludingThis by the client
-   * @param userArg the userArg passed unaltered
-   */
-  struct s_SizeOfArgs
-  {
-    SizeOfEntryExcludingThisFun userFunc;
-    void* userArg;
-  };
-
-  static size_t s_SizeOfStub(PLDHashEntryHdr* aEntry,
-                             mozilla::MallocSizeOf aMallocSizeOf, void* aArg);
-
 private:
   // copy constructor, not implemented
   nsTHashtable(nsTHashtable<EntryType>& aToCopy) = delete;
 
   /**
    * Gets the table's ops.
    */
   static const PLDHashTableOps* Ops();
@@ -504,29 +490,16 @@ nsTHashtable<EntryType>::s_ClearEntry(PL
 template<class EntryType>
 void
 nsTHashtable<EntryType>::s_InitEntry(PLDHashEntryHdr* aEntry,
                                      const void* aKey)
 {
   new (aEntry) EntryType(reinterpret_cast<KeyTypePointer>(aKey));
 }
 
-template<class EntryType>
-size_t
-nsTHashtable<EntryType>::s_SizeOfStub(PLDHashEntryHdr* aEntry,
-                                      mozilla::MallocSizeOf aMallocSizeOf,
-                                      void* aArg)
-{
-  // dereferences the function-pointer to the user's enumeration function
-  return (*reinterpret_cast<s_SizeOfArgs*>(aArg)->userFunc)(
-    static_cast<EntryType*>(aEntry),
-    aMallocSizeOf,
-    reinterpret_cast<s_SizeOfArgs*>(aArg)->userArg);
-}
-
 class nsCycleCollectionTraversalCallback;
 
 template<class EntryType>
 inline void
 ImplCycleCollectionUnlink(nsTHashtable<EntryType>& aField)
 {
   aField.Clear();
 }
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -743,66 +743,30 @@ PLDHashTable::ShrinkIfAppropriate()
 
     int32_t deltaLog2 = log2 - (kHashBits - mHashShift);
     MOZ_ASSERT(deltaLog2 <= 0);
 
     (void) ChangeTable(deltaLog2);
   }
 }
 
-MOZ_ALWAYS_INLINE size_t
-PLDHashTable::SizeOfExcludingThis(
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
+size_t
+PLDHashTable::ShallowSizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
 #ifdef DEBUG
   AutoReadOp op(mChecker);
 #endif
 
-  if (!mEntryStore.Get()) {
-    return 0;
-  }
-
-  size_t n = aMallocSizeOf(mEntryStore.Get());
-  if (aSizeOfEntryExcludingThis) {
-    for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
-      n += aSizeOfEntryExcludingThis(iter.Get(), aMallocSizeOf, aArg);
-    }
-  }
-
-  return n;
-}
-
-MOZ_ALWAYS_INLINE size_t
-PLDHashTable::SizeOfIncludingThis(
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */) const
-{
-  return aMallocSizeOf(this) +
-         SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf, aArg);
+  return aMallocSizeOf(mEntryStore.Get());
 }
 
 size_t
-PL_DHashTableSizeOfExcludingThis(
-    const PLDHashTable* aTable,
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
+PLDHashTable::ShallowSizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
-  return aTable->SizeOfExcludingThis(aSizeOfEntryExcludingThis,
-                                     aMallocSizeOf, aArg);
-}
-
-size_t
-PL_DHashTableSizeOfIncludingThis(
-    const PLDHashTable* aTable,
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    MallocSizeOf aMallocSizeOf, void* aArg /* = nullptr */)
-{
-  return aTable->SizeOfIncludingThis(aSizeOfEntryExcludingThis,
-                                     aMallocSizeOf, aArg);
+  return aMallocSizeOf(this) + ShallowSizeOfExcludingThis(aMallocSizeOf);
 }
 
 PLDHashTable::Iterator::Iterator(Iterator&& aOther)
   : mTable(aOther.mTable)
   , mStart(aOther.mStart)
   , mLimit(aOther.mLimit)
   , mCurrent(aOther.mCurrent)
   , mNexts(aOther.mNexts)
--- a/xpcom/glue/pldhash.h
+++ b/xpcom/glue/pldhash.h
@@ -47,19 +47,16 @@ struct PLDHashTableOps;
 struct PLDHashEntryHdr
 {
 private:
   friend class PLDHashTable;
 
   PLDHashNumber mKeyHash;
 };
 
-typedef size_t (*PLDHashSizeOfEntryExcludingThisFun)(
-  PLDHashEntryHdr* aHdr, mozilla::MallocSizeOf aMallocSizeOf, void* aArg);
-
 #ifdef DEBUG
 
 // This class does three kinds of checking:
 //
 // - that calls to one of |mOps| or to an enumerator do not cause re-entry into
 //   the table in an unsafe way;
 //
 // - that multiple threads do not access the table in an unsafe way;
@@ -370,27 +367,23 @@ public:
   // first element is added the entry storage that gets allocated will have a
   // capacity large enough to fit |aLength| elements without rehashing.
   //
   // It's conceptually the same as calling the destructor and then re-calling
   // the constructor with the original |aOps| and |aEntrySize| arguments, and
   // a new |aLength| argument.
   void ClearAndPrepareForLength(uint32_t aLength);
 
-  // Measure the size of the table's entry storage, and if
-  // |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
-  // pointed to by entries.
-  size_t SizeOfIncludingThis(
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
+  // Measure the size of the table's entry storage. If the entries contain
+  // pointers to other heap blocks, you have to iterate over the table and
+  // measure those separately; hence the "Shallow" prefix.
+  size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
-  // Like SizeOfExcludingThis(), but includes sizeof(*this).
-  size_t SizeOfExcludingThis(
-    PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-    mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr) const;
+  // Like ShallowSizeOfExcludingThis(), but includes sizeof(*this).
+  size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 #ifdef DEBUG
   // Mark a table as immutable for the remainder of its lifetime. This
   // changes the implementation from asserting one set of invariants to
   // asserting a different set.
   void MarkImmutable();
 #endif
 
@@ -630,26 +623,14 @@ PLDHashEntryHdr* PL_DHASH_FASTCALL
 PL_DHashTableAdd(PLDHashTable* aTable, const void* aKey);
 
 void PL_DHASH_FASTCALL
 PL_DHashTableRemove(PLDHashTable* aTable, const void* aKey);
 
 void
 PL_DHashTableRawRemove(PLDHashTable* aTable, PLDHashEntryHdr* aEntry);
 
-size_t
-PL_DHashTableSizeOfExcludingThis(
-  const PLDHashTable* aTable,
-  PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-  mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr);
-
-size_t
-PL_DHashTableSizeOfIncludingThis(
-  const PLDHashTable* aTable,
-  PLDHashSizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-  mozilla::MallocSizeOf aMallocSizeOf, void* aArg = nullptr);
-
 #ifdef DEBUG
 void
 PL_DHashMarkTableImmutable(PLDHashTable* aTable);
 #endif
 
 #endif /* pldhash_h___ */
--- a/xpcom/tests/gtest/TestPLDHash.cpp
+++ b/xpcom/tests/gtest/TestPLDHash.cpp
@@ -132,20 +132,17 @@ TEST(PLDHashTableTest, LazyStorage)
 
   // No result to check here, but call it to make sure it doesn't crash.
   PL_DHashTableRemove(&t, (const void*)2);
 
   for (auto iter = t.Iter(); !iter.Done(); iter.Next()) {
     ASSERT_TRUE(false); // shouldn't hit this on an empty table
   }
 
-  // Using a null |mallocSizeOf| should be fine because it shouldn't be called
-  // for an empty table.
-  mozilla::MallocSizeOf mallocSizeOf = nullptr;
-  ASSERT_EQ(PL_DHashTableSizeOfExcludingThis(&t, nullptr, mallocSizeOf), 0u);
+  ASSERT_EQ(t.ShallowSizeOfExcludingThis(moz_malloc_size_of), 0u);
 }
 
 // A trivial hash function is good enough here. It's also super-fast for
 // test_pldhash_grow_to_max_capacity() because we insert the integers 0..,
 // which means it's collision-free.
 static PLDHashNumber
 TrivialHash(PLDHashTable *table, const void *key)
 {