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 287693 909e4b1913a9ce70d5aead33e13261f288d87904
parent 287692 a998270ed671cb5a11b983479a462c117c6a8fa6
child 287694 5cf4d2f7f2f2b3df2f1edd31b8bdce7882f3875c
child 287721 b4a3696bed55dd325cdd13e22d1e8ed705dc1ecf
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm, jfkthame
bugs1189156
milestone42.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 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)