Bug 1189156 (part 4) - Don't use enumeration style for nsBaseHashtable::SizeOf{In,Ex}cludingThis(). r=erahm,jfkthame.
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 30 Jul 2015 21:19:57 -0700
changeset 277602 909e4b1913a9ce70d5aead33e13261f288d87904
parent 277601 a998270ed671cb5a11b983479a462c117c6a8fa6
child 277605 b4a3696bed55dd325cdd13e22d1e8ed705dc1ecf
child 277658 5cf4d2f7f2f2b3df2f1edd31b8bdce7882f3875c
push idunknown
push userunknown
push dateunknown
reviewerserahm, jfkthame
bugs1189156
milestone42.0a1
Bug 1189156 (part 4) - Don't use enumeration style for nsBaseHashtable::SizeOf{In,Ex}cludingThis(). r=erahm,jfkthame. After this change, we have ShallowSizeOf{In,Ex}cludingThis(), which don't do anything to measure children. (They can be combined with iteration to measure children.)
dom/base/nsDOMAttributeMap.cpp
gfx/thebes/gfxDWriteFontList.cpp
gfx/thebes/gfxDWriteFonts.cpp
gfx/thebes/gfxGDIFont.cpp
gfx/thebes/gfxGDIFontList.cpp
gfx/thebes/gfxPlatformFontList.cpp
gfx/thebes/gfxPlatformFontList.h
js/xpconnect/loader/mozJSComponentLoader.cpp
layout/style/CSSVariableDeclarations.cpp
layout/style/Loader.cpp
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsHTMLCSSStyleSheet.cpp
modules/libpref/Preferences.cpp
netwerk/cache2/CacheFile.cpp
netwerk/cache2/CacheStorageService.cpp
startupcache/StartupCache.cpp
startupcache/StartupCache.h
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/components/nsCategoryManager.cpp
xpcom/components/nsComponentManager.cpp
xpcom/components/nsComponentManager.h
xpcom/glue/DeadlockDetector.h
xpcom/glue/nsBaseHashtable.h
xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
--- a/dom/base/nsDOMAttributeMap.cpp
+++ b/dom/base/nsDOMAttributeMap.cpp
@@ -551,30 +551,24 @@ nsDOMAttributeMap::Count() const
 uint32_t
 nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc,
                              void *aUserArg) const
 {
   return mAttributeCache.EnumerateRead(aFunc, aUserArg);
 }
 
 size_t
-AttrCacheSizeEnumerator(const nsAttrKey& aKey,
-                        const nsRefPtr<Attr>& aValue,
-                        MallocSizeOf aMallocSizeOf,
-                        void* aUserArg)
-{
-  return aMallocSizeOf(aValue.get());
-}
-
-size_t
 nsDOMAttributeMap::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
-  n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator,
-                                           aMallocSizeOf);
+
+  n += mAttributeCache.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mAttributeCache.ConstIter(); !iter.Done(); iter.Next()) {
+    n += aMallocSizeOf(iter.Data().get());
+  }
 
   // NB: mContent is non-owning and thus not counted.
   return n;
 }
 
 /* virtual */ JSObject*
 nsDOMAttributeMap::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
--- a/gfx/thebes/gfxDWriteFontList.cpp
+++ b/gfx/thebes/gfxDWriteFontList.cpp
@@ -1341,18 +1341,17 @@ gfxDWriteFontList::GetFontFamilyList(nsT
 
 void
 gfxDWriteFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                           FontListSizes* aSizes) const
 {
     gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
 
     aSizes->mFontListSize +=
-        mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
-                                             aMallocSizeOf);
+        SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
 
     aSizes->mFontListSize +=
         mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) {
         aSizes->mFontListSize +=
             mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     }
 }
--- a/gfx/thebes/gfxDWriteFonts.cpp
+++ b/gfx/thebes/gfxDWriteFonts.cpp
@@ -652,17 +652,17 @@ gfxDWriteFont::MeasureGlyphWidth(uint16_
 void
 gfxDWriteFont::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                       FontCacheSizes* aSizes) const
 {
     gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
     aSizes->mFontInstances += aMallocSizeOf(mMetrics);
     if (mGlyphWidths) {
         aSizes->mFontInstances +=
-            mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
+            mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
     }
 }
 
 void
 gfxDWriteFont::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
                                       FontCacheSizes* aSizes) const
 {
     aSizes->mFontInstances += aMallocSizeOf(this);
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -523,17 +523,17 @@ gfxGDIFont::GetGlyphWidth(DrawTarget& aD
 void
 gfxGDIFont::AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                    FontCacheSizes* aSizes) const
 {
     gfxFont::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
     aSizes->mFontInstances += aMallocSizeOf(mMetrics);
     if (mGlyphWidths) {
         aSizes->mFontInstances +=
-            mGlyphWidths->SizeOfIncludingThis(nullptr, aMallocSizeOf);
+            mGlyphWidths->ShallowSizeOfIncludingThis(aMallocSizeOf);
     }
 }
 
 void
 gfxGDIFont::AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                    FontCacheSizes* aSizes) const
 {
     aSizes->mFontInstances += aMallocSizeOf(this);
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -875,18 +875,17 @@ gfxGDIFontList::GetDefaultFont(const gfx
 }
 
 void
 gfxGDIFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                        FontListSizes* aSizes) const
 {
     gfxPlatformFontList::AddSizeOfExcludingThis(aMallocSizeOf, aSizes);
     aSizes->mFontListSize +=
-        mFontSubstitutes.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
-                                             aMallocSizeOf);
+        SizeOfFontFamilyTableExcludingThis(mFontSubstitutes, aMallocSizeOf);
     aSizes->mFontListSize +=
         mNonExistingFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (uint32_t i = 0; i < mNonExistingFonts.Length(); ++i) {
         aSizes->mFontListSize +=
             mNonExistingFonts[i].SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     }
 }
 
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -1037,98 +1037,83 @@ gfxPlatformFontList::RebuildLocalFonts()
 {
     for (auto it = mUserFontSetList.Iter(); !it.Done(); it.Next()) {
         it.Get()->GetKey()->RebuildLocalRules();
     }
 }
 
 // Support for memory reporting
 
-static size_t
-SizeOfFamilyEntryExcludingThis(const nsAString&               aKey,
-                               const nsRefPtr<gfxFontFamily>& aFamily,
-                               MallocSizeOf                   aMallocSizeOf,
-                               void*                          aUserArg)
-{
-    FontListSizes *sizes = static_cast<FontListSizes*>(aUserArg);
-    aFamily->AddSizeOfExcludingThis(aMallocSizeOf, sizes);
-
-    sizes->mFontListSize += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-
-    // we return zero here because the measurements have been added directly
-    // to the relevant fields of the FontListSizes record
-    return 0;
-}
-
-// this is also used by subclasses that hold additional hashes of family names
+// this is also used by subclasses that hold additional font tables
 /*static*/ size_t
-gfxPlatformFontList::SizeOfFamilyNameEntryExcludingThis
-    (const nsAString&               aKey,
-     const nsRefPtr<gfxFontFamily>& aFamily,
-     MallocSizeOf                   aMallocSizeOf,
-     void*                          aUserArg)
+gfxPlatformFontList::SizeOfFontFamilyTableExcludingThis(
+    const FontFamilyTable& aTable,
+    MallocSizeOf aMallocSizeOf)
 {
-    // we don't count the size of the family here, because this is an *extra*
-    // reference to a family that will have already been counted in the main list
-    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-}
-
-static size_t
-SizeOfFontNameEntryExcludingThis(const nsAString&              aKey,
-                                 const nsRefPtr<gfxFontEntry>& aFont,
-                                 MallocSizeOf                  aMallocSizeOf,
-                                 void*                         aUserArg)
-{
-    // the font itself is counted by its owning family; here we only care about
-    // the name stored in the hashtable key
-    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-}
-
-static size_t
-SizeOfPrefFontEntryExcludingThis
-    (const uint32_t&                           aKey,
-     const nsTArray<nsRefPtr<gfxFontFamily> >& aList,
-     MallocSizeOf                              aMallocSizeOf,
-     void*                                     aUserArg)
-{
-    // again, we only care about the size of the array itself; we don't follow
-    // the refPtrs stored in it, because they point to entries already owned
-    // and accounted-for by the main font list
-    return aList.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
+        // We don't count the size of the family here, because this is an
+        // *extra* reference to a family that will have already been counted in
+        // the main list.
+        n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    }
+    return n;
 }
 
 void
 gfxPlatformFontList::AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
                                             FontListSizes* aSizes) const
 {
     aSizes->mFontListSize +=
-        mFontFamilies.SizeOfExcludingThis(SizeOfFamilyEntryExcludingThis,
-                                          aMallocSizeOf, aSizes);
+        mFontFamilies.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = mFontFamilies.ConstIter(); !iter.Done(); iter.Next()) {
+        aSizes->mFontListSize +=
+            iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+        iter.Data()->AddSizeOfIncludingThis(aMallocSizeOf, aSizes);
+    }
 
     aSizes->mFontListSize +=
-        mOtherFamilyNames.SizeOfExcludingThis(SizeOfFamilyNameEntryExcludingThis,
-                                              aMallocSizeOf);
+        SizeOfFontFamilyTableExcludingThis(mOtherFamilyNames, aMallocSizeOf);
 
     if (mExtraNames) {
+        // For these two tables, the font itself is counted by its owning
+        // family; here we only care about the names stored in the hashtable
+        // keys.
         aSizes->mFontListSize +=
-            mExtraNames->mFullnames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
-                                                        aMallocSizeOf);
+            mExtraNames->mFullnames.ShallowSizeOfExcludingThis(aMallocSizeOf);
+        for (auto iter = mExtraNames->mFullnames.ConstIter();
+             !iter.Done();
+             iter.Next()) {
+            aSizes->mFontListSize +=
+                iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+        }
         aSizes->mFontListSize +=
-            mExtraNames->mPostscriptNames.SizeOfExcludingThis(SizeOfFontNameEntryExcludingThis,
-                                                              aMallocSizeOf);
+            mExtraNames->mPostscriptNames.ShallowSizeOfExcludingThis(aMallocSizeOf);
+        for (auto iter = mExtraNames->mPostscriptNames.ConstIter();
+             !iter.Done();
+             iter.Next()) {
+            aSizes->mFontListSize +=
+                iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+        }
     }
 
     aSizes->mFontListSize +=
         mCodepointsWithNoFonts.SizeOfExcludingThis(aMallocSizeOf);
     aSizes->mFontListSize +=
         mFontFamiliesToLoad.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
     aSizes->mFontListSize +=
-        mPrefFonts.SizeOfExcludingThis(SizeOfPrefFontEntryExcludingThis,
-                                       aMallocSizeOf);
+        mPrefFonts.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = mPrefFonts.ConstIter(); !iter.Done(); iter.Next()) {
+        // Again, we only care about the size of the array itself; we don't
+        // follow the refPtrs stored in it, because they point to entries
+        // already owned and accounted-for by the main font list.
+        aSizes->mFontListSize +=
+            iter.Data().ShallowSizeOfExcludingThis(aMallocSizeOf);
+    }
 
     aSizes->mFontListSize +=
         mBadUnderlineFamilyNames.SizeOfExcludingThis(aMallocSizeOf);
 
     aSizes->mFontListSize +=
         mSharedCmaps.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (auto iter = mSharedCmaps.ConstIter(); !iter.Done(); iter.Next()) {
         aSizes->mCharMapsSize +=
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -293,22 +293,20 @@ protected:
 
     // for font list changes that affect all documents
     void ForceGlobalReflow();
 
     void RebuildLocalFonts();
 
     typedef nsRefPtrHashtable<nsStringHashKey, gfxFontFamily> FontFamilyTable;
 
-    // used by memory reporter to accumulate sizes of family names in the hash
+    // used by memory reporter to accumulate sizes of family names in the table
     static size_t
-    SizeOfFamilyNameEntryExcludingThis(const nsAString&               aKey,
-                                       const nsRefPtr<gfxFontFamily>& aFamily,
-                                       mozilla::MallocSizeOf          aMallocSizeOf,
-                                       void*                          aUserArg);
+    SizeOfFontFamilyTableExcludingThis(const FontFamilyTable& aTable,
+                                       mozilla::MallocSizeOf aMallocSizeOf);
 
     // canonical family name ==> family entry (unique, one name per family entry)
     FontFamilyTable mFontFamilies;
 
 #if defined(XP_MACOSX)
     // hidden system fonts used within UI elements
     FontFamilyTable mSystemFontFamilies;
 #endif
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -436,44 +436,38 @@ mozJSComponentLoader::FindTargetObject(J
         // Our targetObject is the caller's global object. Let's get it.
         targetObject = CurrentGlobalOrNull(aCx);
     }
 
     aTargetObject.set(targetObject);
     return NS_OK;
 }
 
-/* static */ size_t
-mozJSComponentLoader::DataEntrySizeOfExcludingThis(const nsACString& aKey,
-                                                   ModuleEntry* const& aData,
-                                                   MallocSizeOf aMallocSizeOf, void*)
+// This requires that the keys be strings and the values be pointers.
+template <class Key, class Data, class UserData>
+static size_t
+SizeOfTableExcludingThis(const nsBaseHashtable<Key, Data, UserData>& aTable,
+                         MallocSizeOf aMallocSizeOf)
 {
-    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
-        aData->SizeOfIncludingThis(aMallocSizeOf);
-}
-
-/* static */ size_t
-mozJSComponentLoader::ClassEntrySizeOfExcludingThis(const nsACString& aKey,
-                                                    const nsAutoPtr<ModuleEntry>& aData,
-                                                    MallocSizeOf aMallocSizeOf, void*)
-{
-    return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf) +
-        aData->SizeOfIncludingThis(aMallocSizeOf);
+    size_t n = aTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = aTable.ConstIter(); !iter.Done(); iter.Next()) {
+        n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+        n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
+    }
+    return n;
 }
 
 size_t
 mozJSComponentLoader::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
 {
-    size_t amount = aMallocSizeOf(this);
-
-    amount += mModules.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
-    amount += mImports.SizeOfExcludingThis(ClassEntrySizeOfExcludingThis, aMallocSizeOf);
-    amount += mInProgressImports.SizeOfExcludingThis(DataEntrySizeOfExcludingThis, aMallocSizeOf);
-
-    return amount;
+    size_t n = aMallocSizeOf(this);
+    n += SizeOfTableExcludingThis(mModules, aMallocSizeOf);
+    n += SizeOfTableExcludingThis(mImports, aMallocSizeOf);
+    n += SizeOfTableExcludingThis(mInProgressImports, aMallocSizeOf);
+    return n;
 }
 
 // Some stack based classes for cleaning up on early return
 #ifdef HAVE_PR_MEMMAP
 class FileAutoCloser
 {
  public:
     explicit FileAutoCloser(PRFileDesc* file) : mFile(file) {}
--- a/layout/style/CSSVariableDeclarations.cpp
+++ b/layout/style/CSSVariableDeclarations.cpp
@@ -199,30 +199,22 @@ CSSVariableDeclarations::EnumerateVariab
 void
 CSSVariableDeclarations::AddVariablesToResolver(
                                            CSSVariableResolver* aResolver) const
 {
   mVariables.EnumerateRead(EnumerateVariableForAddVariablesToResolver,
                            aResolver);
 }
 
-static size_t
-SizeOfTableEntry(const nsAString& aKey,
-                 const nsString& aValue,
-                 MallocSizeOf aMallocSizeOf,
-                 void* aUserArg)
-{
-  size_t n = 0;
-  n += aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-  n += aValue.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-  return n;
-}
-
 size_t
 CSSVariableDeclarations::SizeOfIncludingThis(
                                       mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
-  n += mVariables.SizeOfExcludingThis(SizeOfTableEntry, aMallocSizeOf);
+  n += mVariables.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mVariables.ConstIter(); !iter.Done(); iter.Next()) {
+    n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+    n += iter.Data().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+  }
   return n;
 }
 
 } // namespace mozilla
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -2542,55 +2542,45 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Lo
     tmp->mSheets->mCompleteSheets.Clear();
   }
   tmp->mObservers.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(Loader, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(Loader, Release)
 
-struct SheetMemoryCounter {
-  size_t size;
-  mozilla::MallocSizeOf mallocSizeOf;
-};
-
-static size_t
-CountSheetMemory(URIPrincipalReferrerPolicyAndCORSModeHashKey* /* unused */,
-                 const nsRefPtr<CSSStyleSheet>& aSheet,
-                 mozilla::MallocSizeOf aMallocSizeOf,
-                 void* /* unused */)
-{
-  // If aSheet has a parent, then its parent will report it so we don't
-  // have to worry about it here.
-  // Likewise, if aSheet has an owning node, then the document that
-  // node is in will report it.
-  if (aSheet->GetOwnerNode() || aSheet->GetParentSheet()) {
-    return 0;
-  }
-  return aSheet->SizeOfIncludingThis(aMallocSizeOf);
-}
-
 size_t
 Loader::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
-  size_t s = aMallocSizeOf(this);
+  size_t n = aMallocSizeOf(this);
 
   if (mSheets) {
-    s += mSheets->mCompleteSheets.SizeOfExcludingThis(CountSheetMemory, aMallocSizeOf);
+    n += mSheets->mCompleteSheets.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = mSheets->mCompleteSheets.ConstIter();
+         !iter.Done();
+         iter.Next()) {
+      // If aSheet has a parent, then its parent will report it so we don't
+      // have to worry about it here. Likewise, if aSheet has an owning node,
+      // then the document that node is in will report it.
+      const nsRefPtr<CSSStyleSheet>& aSheet = iter.Data();
+      n += (aSheet->GetOwnerNode() || aSheet->GetParentSheet())
+         ? 0
+         : aSheet->SizeOfIncludingThis(aMallocSizeOf);
+    }
   }
-  s += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  n += mObservers.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mLoadingDatas: transient, and should be small
   // - mPendingDatas: transient, and should be small
   // - mParsingDatas: transient, and should be small
   // - mPostedEvents: transient, and should be small
   //
   // The following members aren't measured:
   // - mDocument, because it's a weak backpointer
   // - mPreferredSheet, because it can be a shared string
 
-  return s;
+  return n;
 }
 
 } // namespace css
 } // namespace mozilla
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -925,32 +925,16 @@ SizeOfSelectorsHashTable(const PLDHashTa
   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)
-{
-  // We don't own the nsCSSKeyframesRule objects so we don't count them. We do
-  // care about the size of the keys' nsAString members' buffers though.
-  //
-  // Note that we depend on nsStringHashKey::GetKey() returning a reference,
-  // since otherwise aKey would be a copy of the string key and we would not be
-  // measuring the right object here.
-
-  return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-}
-
 size_t
 RuleCascadeData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   n += mRuleHash.SizeOfExcludingThis(aMallocSizeOf);
   for (uint32_t i = 0; i < ArrayLength(mPseudoElementRuleHashes); ++i) {
     if (mPseudoElementRuleHashes[i])
@@ -971,19 +955,27 @@ RuleCascadeData::SizeOfIncludingThis(Mal
   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,
-                                               aMallocSizeOf,
-                                               nullptr);
+
+  n += mKeyframesRuleTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mKeyframesRuleTable.ConstIter(); !iter.Done(); iter.Next()) {
+    // We don't own the nsCSSKeyframesRule objects so we don't count them. We
+    // do care about the size of the keys' nsAString members' buffers though.
+    //
+    // Note that we depend on nsStringHashKey::GetKey() returning a reference,
+    // since otherwise aKey would be a copy of the string key and we would not
+    // be measuring the right object here.
+    n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+  }
 
   return n;
 }
 
 nsTArray<nsCSSSelector*>*
 RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
 {
   AtomSelectorEntry *entry =
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -156,36 +156,31 @@ nsHTMLCSSStyleSheet::HasAttributeDepende
 }
 
 /* virtual */ bool
 nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
 }
 
-size_t
-SizeOfCachedStyleAttrsEntryExcludingThis(nsStringHashKey::KeyType& aKey,
-                                         MiscContainer* const& aData,
-                                         mozilla::MallocSizeOf aMallocSizeOf,
-                                         void* userArg)
-{
-  // We don't own the MiscContainers so we don't count them. We do care about
-  // the size of the nsString members in the keys though.
-  return aKey.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-}
-
 /* virtual */ size_t
 nsHTMLCSSStyleSheet::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   // The size of mCachedStyleAttrs's mTable member (a PLDHashTable) is
   // significant in itself, but more significant is the size of the nsString
   // members of the nsStringHashKeys.
-  return mCachedStyleAttrs.SizeOfExcludingThis(SizeOfCachedStyleAttrsEntryExcludingThis,
-                                               aMallocSizeOf,
-                                               nullptr);
+  size_t n = 0;
+  n += mCachedStyleAttrs.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mCachedStyleAttrs.ConstIter(); !iter.Done(); iter.Next()) {
+    // We don't own the MiscContainers (the hash table values) so we don't
+    // count them. We do care about the size of the nsString members in the
+    // keys though.
+    n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+  }
+  return n;
 }
 
 /* virtual */ size_t
 nsHTMLCSSStyleSheet::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -213,28 +213,16 @@ AssertNotAlreadyCached(const char* aPref
       "Attempt to add a %s pref cache for preference '%s' at address '%p'"
       "was made. However, a pref was already cached at this address.\n",
       aPrefType, aPref, aPtr);
     MOZ_ASSERT(false, "Should not have an existing pref cache for this address");
   }
 }
 #endif
 
-static size_t
-SizeOfObserverEntryExcludingThis(ValueObserverHashKey* aKey,
-                                 const nsRefPtr<ValueObserver>& aData,
-                                 mozilla::MallocSizeOf aMallocSizeOf,
-                                 void*)
-{
-  size_t n = 0;
-  n += aKey->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-  n += aData->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  return n;
-}
-
 // Although this is a member of Preferences, it measures sPreferences and
 // several other global structures.
 /* static */ int64_t
 Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), 0);
 
   size_t n = aMallocSizeOf(sPreferences);
@@ -246,18 +234,21 @@ Preferences::SizeOfIncludingThisAndOther
   if (gCacheData) {
     n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
     for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
       n += aMallocSizeOf((*gCacheData)[i]);
     }
   }
   if (gObserverTable) {
     n += aMallocSizeOf(gObserverTable);
-    n += gObserverTable->SizeOfExcludingThis(SizeOfObserverEntryExcludingThis,
-                                             aMallocSizeOf);
+    n += gObserverTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
+    for (auto iter = gObserverTable->Iter(); !iter.Done(); iter.Next()) {
+      n += iter.Key()->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
+      n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    }
   }
   // We don't measure sRootBranch and sDefaultRootBranch here because
   // DMD indicates they are not significant.
   n += pref_SizeOfPrivateData(aMallocSizeOf);
   return n;
 }
 
 class PreferenceServiceReporter final : public nsIMemoryReporter
--- a/netwerk/cache2/CacheFile.cpp
+++ b/netwerk/cache2/CacheFile.cpp
@@ -1976,56 +1976,48 @@ CacheFile::InitIndexEntry()
   mMetadata->GetFrecency(&frecency);
 
   rv = CacheFileIOManager::UpdateIndexEntry(mHandle, &frecency, &expTime);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
-// Memory reporting
-
-namespace {
-
-size_t
-CollectChunkSize(uint32_t const & aIdx,
-                 nsRefPtr<mozilla::net::CacheFileChunk> const & aChunk,
-                 mozilla::MallocSizeOf mallocSizeOf, void* aClosure)
-{
-  return aChunk->SizeOfIncludingThis(mallocSizeOf);
-}
-
-} // namespace
-
 size_t
 CacheFile::SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
   CacheFileAutoLock lock(const_cast<CacheFile*>(this));
 
   size_t n = 0;
   n += mKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
-  n += mChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
-  n += mCachedChunks.SizeOfExcludingThis(CollectChunkSize, mallocSizeOf);
+  n += mChunks.ShallowSizeOfExcludingThis(mallocSizeOf);
+  for (auto iter = mChunks.ConstIter(); !iter.Done(); iter.Next()) {
+      n += iter.Data()->SizeOfIncludingThis(mallocSizeOf);
+  }
+  n += mCachedChunks.ShallowSizeOfExcludingThis(mallocSizeOf);
+  for (auto iter = mCachedChunks.ConstIter(); !iter.Done(); iter.Next()) {
+      n += iter.Data()->SizeOfIncludingThis(mallocSizeOf);
+  }
   if (mMetadata) {
     n += mMetadata->SizeOfIncludingThis(mallocSizeOf);
   }
 
   // Input streams are not elsewhere reported.
   n += mInputs.ShallowSizeOfExcludingThis(mallocSizeOf);
   for (uint32_t i = 0; i < mInputs.Length(); ++i) {
     n += mInputs[i]->SizeOfIncludingThis(mallocSizeOf);
   }
 
   // Output streams are not elsewhere reported.
   if (mOutput) {
     n += mOutput->SizeOfIncludingThis(mallocSizeOf);
   }
 
   // The listeners are usually classes reported just above.
-  n += mChunkListeners.SizeOfExcludingThis(nullptr, mallocSizeOf);
+  n += mChunkListeners.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += mObjsToRelease.ShallowSizeOfExcludingThis(mallocSizeOf);
 
   // mHandle reported directly from CacheFileIOManager.
 
   return n;
 }
 
 size_t
--- a/netwerk/cache2/CacheStorageService.cpp
+++ b/netwerk/cache2/CacheStorageService.cpp
@@ -1971,17 +1971,17 @@ CacheStorageService::SizeOfExcludingThis
   size_t n = 0;
   // The elemets are referenced by sGlobalEntryTables and are reported from there
   n += Pool(true).mFrecencyArray.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += Pool(true).mExpirationArray.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += Pool(false).mFrecencyArray.ShallowSizeOfExcludingThis(mallocSizeOf);
   n += Pool(false).mExpirationArray.ShallowSizeOfExcludingThis(mallocSizeOf);
   // Entries reported manually in CacheStorageService::CollectReports callback
   if (sGlobalEntryTables) {
-    n += sGlobalEntryTables->SizeOfIncludingThis(nullptr, mallocSizeOf);
+    n += sGlobalEntryTables->ShallowSizeOfIncludingThis(mallocSizeOf);
   }
 
   return n;
 }
 
 size_t
 CacheStorageService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
 {
@@ -1992,46 +1992,38 @@ namespace {
 
 class ReportStorageMemoryData
 {
 public:
   nsIMemoryReporterCallback *mHandleReport;
   nsISupports *mData;
 };
 
-size_t CollectEntryMemory(nsACString const & aKey,
-                          nsRefPtr<mozilla::net::CacheEntry> const & aEntry,
-                          mozilla::MallocSizeOf mallocSizeOf,
-                          void * aClosure)
-{
-  CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
-
-  CacheEntryTable* aTable = static_cast<CacheEntryTable*>(aClosure);
-
-  size_t n = 0;
-  n += aKey.SizeOfExcludingThisIfUnshared(mallocSizeOf);
-
-  // Bypass memory-only entries, those will be reported when iterating
-  // the memory only table. Memory-only entries are stored in both ALL_ENTRIES
-  // and MEMORY_ONLY hashtables.
-  if (aTable->Type() == CacheEntryTable::MEMORY_ONLY || aEntry->IsUsingDisk())
-    n += aEntry->SizeOfIncludingThis(mallocSizeOf);
-
-  return n;
-}
-
 PLDHashOperator ReportStorageMemory(const nsACString& aKey,
                                     CacheEntryTable* aTable,
                                     void* aClosure)
 {
   CacheStorageService::Self()->Lock().AssertCurrentThreadOwns();
 
-  size_t size = aTable->SizeOfIncludingThis(&CollectEntryMemory,
-                                            CacheStorageService::MallocSizeOf,
-                                            aTable);
+  size_t size = 0;
+  mozilla::MallocSizeOf mallocSizeOf = CacheStorageService::MallocSizeOf;
+
+  size += aTable->ShallowSizeOfIncludingThis(mallocSizeOf);
+  for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
+    size += iter.Key().SizeOfExcludingThisIfUnshared(mallocSizeOf);
+
+    // Bypass memory-only entries, those will be reported when iterating
+    // the memory only table. Memory-only entries are stored in both ALL_ENTRIES
+    // and MEMORY_ONLY hashtables.
+    nsRefPtr<mozilla::net::CacheEntry> const& entry = iter.Data();
+    if (aTable->Type() == CacheEntryTable::MEMORY_ONLY ||
+        entry->IsUsingDisk()) {
+      size += entry->SizeOfIncludingThis(mallocSizeOf);
+    }
+  }
 
   ReportStorageMemoryData& data =
     *static_cast<ReportStorageMemoryData*>(aClosure);
   // These key names are not privacy-sensitive.
   data.mHandleReport->Callback(
     EmptyCString(),
     nsPrintfCString("explicit/network/cache2/%s-storage(%s)",
       aTable->Type() == CacheEntryTable::MEMORY_ONLY ? "memory" : "disk",
--- a/startupcache/StartupCache.cpp
+++ b/startupcache/StartupCache.cpp
@@ -372,30 +372,31 @@ StartupCache::PutBuffer(const char* id, 
 
 size_t
 StartupCache::SizeOfMapping()
 {
     return mArchive ? mArchive->SizeOfMapping() : 0;
 }
 
 size_t
-StartupCache::HeapSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+StartupCache::HeapSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
     // This function could measure more members, but they haven't been found by
     // DMD to be significant.  They can be added later if necessary.
-    return aMallocSizeOf(this) +
-           mTable.SizeOfExcludingThis(SizeOfEntryExcludingThis, aMallocSizeOf) +
-           mPendingWrites.ShallowSizeOfExcludingThis(aMallocSizeOf);
-}
+
+    size_t n = aMallocSizeOf(this);
 
-/* static */ size_t
-StartupCache::SizeOfEntryExcludingThis(const nsACString& key, const nsAutoPtr<CacheEntry>& data,
-                                       mozilla::MallocSizeOf mallocSizeOf, void *)
-{
-    return data->SizeOfExcludingThis(mallocSizeOf);
+    n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
+        n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
+    }
+
+    n += mPendingWrites.ShallowSizeOfExcludingThis(aMallocSizeOf);
+
+    return n;
 }
 
 struct CacheWriteHolder
 {
   nsCOMPtr<nsIZipWriter> writer;
   nsCOMPtr<nsIStringInputStream> stream;
   PRTime time;
 };
--- a/startupcache/StartupCache.h
+++ b/startupcache/StartupCache.h
@@ -80,18 +80,18 @@ struct CacheEntry
 
   // Takes possession of buf
   CacheEntry(char* buf, uint32_t len) : data(buf), size(len) { }
 
   ~CacheEntry()
   {
   }
 
-  size_t SizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
-    return mallocSizeOf(data);
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) {
+    return mallocSizeOf(this) + mallocSizeOf(data);
   }
 };
 
 // We don't want to refcount StartupCache, and ObserverService wants to
 // refcount its listeners, so we'll let it refcount this instead.
 class StartupCacheListener final : public nsIObserver
 {
   ~StartupCacheListener() {}
@@ -130,17 +130,17 @@ public:
 
   nsresult RecordAgesAlways();
 
   static StartupCache* GetSingleton();
   static void DeleteSingleton();
 
   // This measures all the heap memory used by the StartupCache, i.e. it
   // excludes the mapping.
-  size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
+  size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
   size_t SizeOfMapping();
 
 private:
   StartupCache();
   virtual ~StartupCache();
 
   enum TelemetrifyAge {
@@ -154,21 +154,16 @@ private:
   void WriteToDisk();
   nsresult ResetStartupWriteTimer();
   void WaitOnWriteThread();
 
   static nsresult InitSingleton();
   static void WriteTimeout(nsITimer *aTimer, void *aClosure);
   static void ThreadedWrite(void *aClosure);
 
-  static size_t SizeOfEntryExcludingThis(const nsACString& key,
-                                         const nsAutoPtr<CacheEntry>& data,
-                                         mozilla::MallocSizeOf mallocSizeOf,
-                                         void *);
-
   nsClassHashtable<nsCStringHashKey, CacheEntry> mTable;
   nsTArray<nsCString> mPendingWrites;
   nsRefPtr<nsZipArchive> mArchive;
   nsCOMPtr<nsIFile> mFile;
 
   nsCOMPtr<nsIObserverService> mObserverService;
   nsRefPtr<StartupCacheListener> mListener;
   nsCOMPtr<nsITimer> mTimer;
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -450,19 +450,19 @@ CycleCollectedJSRuntime::~CycleCollected
   mozilla::dom::DestroyScriptSettings();
 }
 
 size_t
 CycleCollectedJSRuntime::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t n = 0;
 
-  // nullptr for the second arg;  we're not measuring anything hanging off the
-  // entries in mJSHolders.
-  n += mJSHolders.SizeOfExcludingThis(nullptr, aMallocSizeOf);
+  // We're deliberately not measuring anything hanging off the entries in
+  // mJSHolders.
+  n += mJSHolders.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   return n;
 }
 
 void
 CycleCollectedJSRuntime::UnmarkSkippableJSHolders()
 {
   for (auto iter = mJSHolders.Iter(); !iter.Done(); iter.Next()) {
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -450,36 +450,28 @@ nsCategoryManager::CollectReports(nsIHan
                                   nsISupports* aData, bool aAnonymize)
 {
   return MOZ_COLLECT_REPORT("explicit/xpcom/category-manager",
                             KIND_HEAP, UNITS_BYTES,
                             SizeOfIncludingThis(CategoryManagerMallocSizeOf),
                             "Memory used for the XPCOM category manager.");
 }
 
-static size_t
-SizeOfCategoryManagerTableEntryExcludingThis(nsDepCharHashKey::KeyType aKey,
-                                             const nsAutoPtr<CategoryNode>& aData,
-                                             MallocSizeOf aMallocSizeOf,
-                                             void* aUserArg)
-{
-  // We don't measure the string pointed to by aKey because it's a non-owning
-  // pointer.
-  return aData.get()->SizeOfExcludingThis(aMallocSizeOf);
-}
-
 size_t
 nsCategoryManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   size_t n = aMallocSizeOf(this);
 
   n += PL_SizeOfArenaPoolExcludingPool(&mArena, aMallocSizeOf);
 
-  n += mTable.SizeOfExcludingThis(SizeOfCategoryManagerTableEntryExcludingThis,
-                                  aMallocSizeOf);
+  n += mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mTable.ConstIter(); !iter.Done(); iter.Next()) {
+    // We don't measure the key string because it's a non-owning pointer.
+    n += iter.Data().get()->SizeOfExcludingThis(aMallocSizeOf);
+  }
 
   return n;
 }
 
 namespace {
 
 class CategoryNotificationRunnable : public nsRunnable
 {
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -1810,63 +1810,53 @@ nsComponentManagerImpl::ContractIDToCID(
       **aResult = *entry->mCIDEntry->cid;
       return NS_OK;
     }
   }
   *aResult = nullptr;
   return NS_ERROR_FACTORY_NOT_REGISTERED;
 }
 
-static size_t
-SizeOfFactoriesEntryExcludingThis(nsIDHashKey::KeyType aKey,
-                                  nsFactoryEntry* const& aData,
-                                  MallocSizeOf aMallocSizeOf,
-                                  void* aUserArg)
-{
-  return aData->SizeOfIncludingThis(aMallocSizeOf);
-}
-
-static size_t
-SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey,
-                                    nsFactoryEntry* const& aData,
-                                    MallocSizeOf aMallocSizeOf,
-                                    void* aUserArg)
-{
-  // We don't measure the nsFactoryEntry data because its owned by mFactories
-  // (which measures them in SizeOfFactoriesEntryExcludingThis).
-  return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
-}
-
 MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
 
 NS_IMETHODIMP
 nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
                                        nsISupports* aData, bool aAnonymize)
 {
   return MOZ_COLLECT_REPORT("explicit/xpcom/component-manager",
                             KIND_HEAP, UNITS_BYTES,
                             SizeOfIncludingThis(ComponentManagerMallocSizeOf),
                             "Memory used for the XPCOM component manager.");
 }
 
 size_t
 nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
+  const
 {
   size_t n = aMallocSizeOf(this);
-  n += mLoaderMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
-  n += mFactories.SizeOfExcludingThis(SizeOfFactoriesEntryExcludingThis,
-                                      aMallocSizeOf);
-  n += mContractIDs.SizeOfExcludingThis(SizeOfContractIDsEntryExcludingThis,
-                                        aMallocSizeOf);
+
+  n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
+
+  n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mFactories.ConstIter(); !iter.Done(); iter.Next()) {
+    n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
+  }
+
+  n += mContractIDs.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  for (auto iter = mContractIDs.ConstIter(); !iter.Done(); iter.Next()) {
+    // We don't measure the nsFactoryEntry data because it's owned by
+    // mFactories (which is measured above).
+    n += iter.Key().SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
+  }
 
   n += sStaticModules->ShallowSizeOfIncludingThis(aMallocSizeOf);
   n += sModuleLocations->ShallowSizeOfIncludingThis(aMallocSizeOf);
 
   n += mKnownStaticModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
-  n += mKnownModules.SizeOfExcludingThis(nullptr, aMallocSizeOf);
+  n += mKnownModules.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   n += PL_SizeOfArenaPoolExcludingPool(&mArena, aMallocSizeOf);
 
   n += mPendingServices.ShallowSizeOfExcludingThis(aMallocSizeOf);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - mLoaderMap's keys and values
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -332,17 +332,17 @@ public:
 
   inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID,
                                                PRThread* aThread);
   inline void RemovePendingService(const nsCID& aServiceCID);
   inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;
 
   nsTArray<PendingServiceInfo> mPendingServices;
 
-  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 #ifdef MOZ_B2G_LOADER
   // Preload XPT interface info for B2G loader.
   // This function is called before XPCOM has been initialized.
   static void PreloadXPT(nsIFile* aFile);
 #endif
 
 #ifdef MOZ_B2G_LOADER
--- a/xpcom/glue/DeadlockDetector.h
+++ b/xpcom/glue/DeadlockDetector.h
@@ -139,33 +139,28 @@ public:
    *
    * *NOT* thread safe.
    */
   ~DeadlockDetector()
   {
     PR_DestroyLock(mLock);
   }
 
-  static size_t
-  SizeOfEntryExcludingThis(const T* aKey, const nsAutoPtr<OrderingEntry>& aEntry,
-                           MallocSizeOf aMallocSizeOf, void* aUserArg)
-  {
-    // NB: Key is accounted for in the entry.
-    size_t n = aEntry->SizeOfIncludingThis(aMallocSizeOf);
-    return n;
-  }
-
   size_t
   SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
   {
     size_t n = aMallocSizeOf(this);
 
     {
       PRAutoLock _(mLock);
-      n += mOrdering.SizeOfExcludingThis(SizeOfEntryExcludingThis, aMallocSizeOf);
+      n += mOrdering.ShallowSizeOfExcludingThis(aMallocSizeOf);
+      for (auto iter = mOrdering.ConstIter(); !iter.Done(); iter.Next()) {
+        // NB: Key is accounted for in the entry.
+        n += iter.Data()->SizeOfIncludingThis(aMallocSizeOf);
+      }
     }
 
     return n;
   }
 
   /**
    * Add
    * Make the deadlock detector aware of |aResource|.
--- a/xpcom/glue/nsBaseHashtable.h
+++ b/xpcom/glue/nsBaseHashtable.h
@@ -262,76 +262,33 @@ public:
   }
 
   /**
    * reset the hashtable, removing all entries
    */
   void Clear() { nsTHashtable<EntryType>::Clear(); }
 
   /**
-   * client must provide a SizeOfEntryExcludingThisFun function for
-   *   SizeOfExcludingThis.
-   * @param     aKey the key being enumerated
-   * @param     aData Reference to data being enumerated.
-   * @param     aMallocSizeOf the function used to measure heap-allocated blocks
-   * @param     aUserArg passed unchanged from SizeOf{In,Ex}cludingThis
-   * @return    summed size of the things pointed to by the entries
+   * Measure the size of the table's entry storage. The size of things pointed
+   * to by entries must be measured separately; hence the "Shallow" prefix.
+   *
+   * @param   aMallocSizeOf the function used to measure heap-allocated blocks
+   * @return  the summed size of the table's storage
    */
-  typedef size_t
-    (*SizeOfEntryExcludingThisFun)(KeyType aKey,
-                                   const DataType& aData,
-                                   mozilla::MallocSizeOf aMallocSizeOf,
-                                   void* aUserArg);
-
-  /**
-   * Measure the size of the table's entry storage and the table itself.
-   * If |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
-   * pointed to by entries.
-   *
-   * @param    aSizeOfEntryExcludingThis
-   *           the <code>SizeOfEntryExcludingThisFun</code> function to call
-   * @param    aMallocSizeOf the function used to meeasure heap-allocated blocks
-   * @param    aUserArg a point to pass to the
-   *           <code>SizeOfEntryExcludingThisFun</code> function
-   * @return   the summed size of the entries, the table, and the table's storage
-   */
-  size_t SizeOfIncludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-                             mozilla::MallocSizeOf aMallocSizeOf,
-                             void* aUserArg = nullptr)
+  size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   {
-    return aMallocSizeOf(this) +
-      this->SizeOfExcludingThis(aSizeOfEntryExcludingThis, aMallocSizeOf,
-                                aUserArg);
+    return this->mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
   }
 
   /**
-   * Measure the size of the table's entry storage, and if
-   * |aSizeOfEntryExcludingThis| is non-nullptr, measure the size of things
-   * pointed to by entries.
-   *
-   * @param     aSizeOfEntryExcludingThis the
-   *            <code>SizeOfEntryExcludingThisFun</code> function to call
-   * @param     aMallocSizeOf the function used to measure heap-allocated blocks
-   * @param     aUserArg a pointer to pass to the
-   *            <code>SizeOfEntryExcludingThisFun</code> function
-   * @return    the summed size of all the entries
+   * Like ShallowSizeOfExcludingThis, but includes sizeof(*this).
    */
-  size_t SizeOfExcludingThis(SizeOfEntryExcludingThisFun aSizeOfEntryExcludingThis,
-                             mozilla::MallocSizeOf aMallocSizeOf,
-                             void* aUserArg = nullptr) const
+  size_t ShallowSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
   {
-    size_t n = 0;
-    n += this->mTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
-    if (aSizeOfEntryExcludingThis) {
-      for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
-        n += aSizeOfEntryExcludingThis(iter.Key(), iter.Data(), aMallocSizeOf,
-                                       aUserArg);
-      }
-    }
-    return n;
+    return aMallocSizeOf(this) + ShallowSizeOfExcludingThis(aMallocSizeOf);
   }
 
 #ifdef DEBUG
   using nsTHashtable<EntryType>::MarkImmutable;
 #endif
 };
 
 //
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
@@ -31,18 +31,18 @@ static StaticRefPtr<XPTInterfaceInfoMana
 
 size_t
 XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
     size_t n = aMallocSizeOf(this);
     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     // The entries themselves are allocated out of an arena accounted
     // for elsewhere, so don't measure them
-    n += mWorkingSet.mIIDTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
-    n += mWorkingSet.mNameTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
+    n += mWorkingSet.mIIDTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+    n += mWorkingSet.mNameTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
     return n;
 }
 
 MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
 
 NS_IMETHODIMP
 XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
                                         nsISupports* aData, bool aAnonymize)