Bug 705987 - Use mallocSizeOf in the layout memory reporters. r=khuey,bzbarsky
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 08 Dec 2011 21:01:52 -0800
changeset 82378 2d5421ea175817bce04d19ef9d165b97b8d0e4ba
parent 82377 e76f06f7e08dd32d654cc0077c41b065b58d59a1
child 82379 28fb37461530e0e51d365856aebd1eefac05531a
push id21592
push userbmo@edmorley.co.uk
push dateSun, 11 Dec 2011 04:01:06 +0000
treeherdermozilla-central@f5578fdc50ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey, bzbarsky
bugs705987
milestone11.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 705987 - Use mallocSizeOf in the layout memory reporters. r=khuey,bzbarsky
js/src/jsdhash.cpp
js/src/jsdhash.h
layout/base/nsPresArena.cpp
layout/base/nsPresArena.h
layout/base/nsPresContext.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
layout/style/AnimationCommon.cpp
layout/style/AnimationCommon.h
layout/style/nsAnimationManager.cpp
layout/style/nsAnimationManager.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
layout/style/nsHTMLCSSStyleSheet.cpp
layout/style/nsHTMLCSSStyleSheet.h
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
layout/style/nsIStyleRuleProcessor.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
xpcom/glue/pldhash.cpp
xpcom/glue/pldhash.h
--- a/js/src/jsdhash.cpp
+++ b/js/src/jsdhash.cpp
@@ -797,34 +797,35 @@ SizeOfEntryEnumerator(JSDHashTable *tabl
                       void *arg)
 {
     SizeOfEntryEnumeratorArg *e = (SizeOfEntryEnumeratorArg *)arg;
     e->total += e->sizeOfEntry(hdr, e->mallocSizeOf);
     return JS_DHASH_NEXT;
 }
 
 extern JS_PUBLIC_API(size_t)
-JS_DHashTableSizeOfExcludingThis(JSDHashTable *table,
+JS_DHashTableSizeOfExcludingThis(const JSDHashTable *table,
                                  JSDHashSizeOfEntryFun sizeOfEntry,
                                  JSMallocSizeOfFun mallocSizeOf)
 {
     size_t n = 0;
     n += mallocSizeOf(table->entryStore,
                       JS_DHASH_TABLE_SIZE(table) * table->entrySize +
                       ENTRY_STORE_EXTRA);
     if (sizeOfEntry) {
         SizeOfEntryEnumeratorArg arg = { 0, sizeOfEntry, mallocSizeOf };
-        JS_DHashTableEnumerate(table, SizeOfEntryEnumerator, &arg);
+        JS_DHashTableEnumerate(const_cast<JSDHashTable *>(table),
+                               SizeOfEntryEnumerator, &arg);
         n += arg.total;
     }
     return n;
 }
 
 extern JS_PUBLIC_API(size_t)
-JS_DHashTableSizeOfIncludingThis(JSDHashTable *table,
+JS_DHashTableSizeOfIncludingThis(const JSDHashTable *table,
                                  JSDHashSizeOfEntryFun sizeOfEntry,
                                  JSMallocSizeOfFun mallocSizeOf)
 {
     return mallocSizeOf(table, sizeof(JSDHashTable)) +
            JS_DHashTableSizeOfExcludingThis(table, sizeOfEntry, mallocSizeOf);
 }
 
 #ifdef DEBUG
--- a/js/src/jsdhash.h
+++ b/js/src/jsdhash.h
@@ -584,25 +584,25 @@ typedef size_t
 
 /**
  * Measure the size of the table's entry storage, and if |sizeOfEntry| is
  * non-NULL, measure the size of things pointed to by entries.  Doesn't measure
  * |ops| because it's often shared between tables, nor |data| because it's
  * opaque.
  */
 extern JS_PUBLIC_API(size_t)
-JS_DHashTableSizeOfExcludingThis(JSDHashTable *table,
+JS_DHashTableSizeOfExcludingThis(const JSDHashTable *table,
                                  JSDHashSizeOfEntryFun sizeOfEntry,
                                  JSMallocSizeOfFun mallocSizeOf);
 
 /**
  * Like JS_DHashTableSizeOfExcludingThis, but includes sizeof(*this).
  */
 extern JS_PUBLIC_API(size_t)
-JS_DHashTableSizeOfIncludingThis(JSDHashTable *table,
+JS_DHashTableSizeOfIncludingThis(const JSDHashTable *table,
                                  JSDHashSizeOfEntryFun sizeOfEntry,
                                  JSMallocSizeOfFun mallocSizeOf);
 
 #ifdef DEBUG
 /**
  * Mark a table as immutable for the remainder of its lifetime.  This
  * changes the implementation from ASSERTing one set of invariants to
  * ASSERTing a different set.
--- a/layout/base/nsPresArena.cpp
+++ b/layout/base/nsPresArena.cpp
@@ -381,30 +381,37 @@ struct nsPresArena::State {
     char* p = reinterpret_cast<char*>(aPtr);
     char* limit = p + list->mEntrySize;
     for (; p < limit; p += sizeof(PRUword)) {
       *reinterpret_cast<PRUword*>(p) = ARENA_POISON;
     }
 
     list->mEntries.AppendElement(aPtr);
   }
+
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+  {
+    size_t n = aMallocSizeOf(this, sizeof(*this));
+
+    // The first PLArena is within the PLArenaPool, i.e. within |this|, so we
+    // don't measure it.  Subsequent PLArenas are by themselves and must be
+    // measured.
+    const PLArena *arena = mPool.first.next;
+    while (arena) {
+      n += aMallocSizeOf(arena, arena->limit - arena->base);
+      arena = arena->next;
+    }
+    return n;
+  }
 };
 
-PRUint32
-nsPresArena::Size()
+size_t
+nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PLArena *arena = &mState->mPool.first;
-  PRUint32 result = 0;
-
-  while (arena) {
-    result += arena->limit - arena->base;
-    arena = arena->next;
-  }
-
-  return result;
+  return mState ? mState->SizeOfIncludingThis(aMallocSizeOf) : 0;
 }
 
 #else
 // Stub implementation that forwards everything to malloc and does not
 // poison allocations (it still initializes the poison value though,
 // for external use through GetPoisonValue()).
 
 struct nsPresArena::State
@@ -421,18 +428,18 @@ struct nsPresArena::State
   }
 
   void Free(PRUint32 /* unused */, void* aPtr)
   {
     PR_Free(aPtr);
   }
 };
 
-PRUint32
-nsPresArena::Size()
+size_t
+nsPresArena::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
   return 0;
 }
 
 #endif // DEBUG_TRACEMALLOC_PRESARENA
 
 // Public interface
 nsPresArena::nsPresArena()
--- a/layout/base/nsPresArena.h
+++ b/layout/base/nsPresArena.h
@@ -69,17 +69,17 @@ public:
   NS_HIDDEN_(void*) AllocateBySize(size_t aSize);
   NS_HIDDEN_(void)  FreeBySize(size_t aSize, void* aPtr);
 
   // Pool allocation with recycler lists indexed by object-type code.
   // Every type code must always be used with the same object size.
   NS_HIDDEN_(void*) AllocateByCode(nsQueryFrame::FrameIID aCode, size_t aSize);
   NS_HIDDEN_(void)  FreeByCode(nsQueryFrame::FrameIID aCode, void* aPtr);
 
-  PRUint32 Size();
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   /**
    * Get the poison value that can be used to fill a memory space with
    * an address that leads to a safe crash when dereferenced.
    *
    * The caller is responsible for ensuring that a pres shell has been
    * initialized before calling this.
    */
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -971,22 +971,26 @@ public:
   void SetContainsUpdatePluginGeometryFrame(bool aValue)
   {
     mContainsUpdatePluginGeometryFrame = aValue;
   }
 
   bool MayHaveFixedBackgroundFrames() { return mMayHaveFixedBackgroundFrames; }
   void SetHasFixedBackgroundFrame() { mMayHaveFixedBackgroundFrames = true; }
 
-  PRUint32 EstimateMemoryUsed() {
-    PRUint32 result = 0;
-
-    result += sizeof(nsPresContext);
-
-    return result;
+  virtual NS_MUST_OVERRIDE size_t
+        SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+    // XXX: lots of things hang off nsPresContext and should be included in
+    // this measurement.  Bug 671299 may add them.
+    return 0;
+  }
+  virtual NS_MUST_OVERRIDE size_t
+        SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+    return aMallocSizeOf(this, sizeof(nsPresContext)) +
+           SizeOfExcludingThis(aMallocSizeOf);
   }
 
   bool IsRootContentDocument();
 
 protected:
   friend class nsRunnableMethod<nsPresContext>;
   NS_HIDDEN_(void) ThemeChangedInternal();
   NS_HIDDEN_(void) SysColorChangedInternal();
@@ -1309,16 +1313,28 @@ public:
    */
   void AddWillPaintObserver(nsIRunnable* aRunnable);
 
   /**
    * Run all runnables that need to get called before the next paint.
    */
   void FlushWillPaintObservers();
 
+  virtual NS_MUST_OVERRIDE size_t
+        SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE {
+    // XXX: several things hang off an nsRootPresContext and should be included
+    // in this measurement.  Bug 671299 may do this.
+    return nsPresContext::SizeOfExcludingThis(aMallocSizeOf);
+  }
+  virtual NS_MUST_OVERRIDE size_t
+        SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE {
+    return aMallocSizeOf(this, sizeof(nsRootPresContext)) +
+           SizeOfExcludingThis(aMallocSizeOf);
+  }
+
 protected:
   class RunWillPaintObservers : public nsRunnable {
   public:
     RunWillPaintObservers(nsRootPresContext* aPresContext) : mPresContext(aPresContext) {}
     void Revoke() { mPresContext = nsnull; }
     NS_IMETHOD Run()
     {
       if (mPresContext) {
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -656,22 +656,22 @@ PresShell::MemoryReporter::SizeEnumerato
   NS_NAMED_LITERAL_CSTRING(kArenaDesc, "Memory used by layout PresShell, PresContext, and other related areas.");
   NS_NAMED_LITERAL_CSTRING(kStyleDesc, "Memory used by the style system.");
   NS_NAMED_LITERAL_CSTRING(kTextRunsDesc, "Memory used for text-runs (glyph layout) in the PresShell's frame tree.");
 
   nsCAutoString arenaPath = str + NS_LITERAL_CSTRING("/arenas");
   nsCAutoString stylePath = str + NS_LITERAL_CSTRING("/styledata");
   nsCAutoString textRunsPath = str + NS_LITERAL_CSTRING("/textruns");
 
-  PRUint32 arenasSize;
-  arenasSize = aShell->EstimateMemoryUsed();
-  arenasSize += aShell->mPresContext->EstimateMemoryUsed();
-
-  PRUint32 styleSize;
-  styleSize = aShell->StyleSet()->SizeOf();
+  PRInt64 arenasSize =
+    aShell->SizeOfIncludingThis(LayoutMallocSizeOf) +
+    aShell->mPresContext->SizeOfIncludingThis(LayoutMallocSizeOf);
+
+  PRInt64 styleSize =
+    aShell->StyleSet()->SizeOfIncludingThis(LayoutMallocSizeOf);
 
   PRInt64 textRunsSize = aShell->SizeOfTextRuns(LayoutMallocSizeOf);
 
   data->callback->
     Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
              nsIMemoryReporter::UNITS_BYTES, arenasSize, kArenaDesc,
              data->closure);
 
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -129,24 +129,25 @@ public:
 
   nsresult Init() { return mBlocks ? NS_OK : NS_ERROR_OUT_OF_MEMORY; }
 
   // Memory management functions
   void* Allocate(size_t aSize);
   void Push();
   void Pop();
 
-  PRUint32 Size() {
-    PRUint32 result = 0;
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+    size_t n = 0;
     StackBlock *block = mBlocks;
     while (block) {
-      result += sizeof(StackBlock);
+      n += aMallocSizeOf(block, sizeof(StackBlock));
       block = block->mNext;
     }
-    return result;
+    n += aMallocSizeOf(mMarks, mMarkLength * sizeof(StackMark));
+    return n;
   }
 
 private:
   // our current position in memory
   size_t mPos;
 
   // a list of memory block. Usually there is only one
   // but if we overrun our stack size we can get more memory.
@@ -875,24 +876,24 @@ private:
 private:
 #ifdef DEBUG
   // Ensure that every allocation from the PresArena is eventually freed.
   PRUint32 mPresArenaAllocCount;
 #endif
 
 public:
 
-  PRUint32 EstimateMemoryUsed() {
-    PRUint32 result = 0;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+    size_t n = 0;
 
-    result += sizeof(PresShell);
-    result += mStackArena.Size();
-    result += mFrameArena.Size();
+    n += aMallocSizeOf(this, sizeof(PresShell));
+    n += mStackArena.SizeOfExcludingThis(aMallocSizeOf);
+    n += mFrameArena.SizeOfExcludingThis(aMallocSizeOf);
 
-    return result;
+    return n;
   }
 
   size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf);
 
   class MemoryReporter : public nsIMemoryMultiReporter
   {
   public:
     NS_DECL_ISUPPORTS
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -121,20 +121,28 @@ CommonAnimationManager::HasAttributeDepe
 }
 
 /* virtual */ bool
 CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
 }
 
-/* virtual */ PRInt64
-CommonAnimationManager::SizeOf() const
+/* virtual */ size_t
+CommonAnimationManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  return sizeof(*this);
+  // XXX: could measure mProperytValuePairs here.  Bug 671299 may do this.
+  return 0;
+}
+
+/* virtual */ size_t
+CommonAnimationManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(CommonAnimationManager)) +
+         SizeOfExcludingThis(aMallocSizeOf);
 }
 
 /* static */ bool
 CommonAnimationManager::ExtractComputedValueForTransition(
                           nsCSSProperty aProperty,
                           nsStyleContext* aStyleContext,
                           nsStyleAnimation::Value& aComputedValue)
 {
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -66,17 +66,20 @@ public:
   NS_DECL_ISUPPORTS
 
   // nsIStyleRuleProcessor (parts)
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData);
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
   virtual nsRestyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
-  virtual PRInt64 SizeOf() const;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
   /**
    * Notify the manager that the pres context is going away.
    */
   void Disconnect();
 
   static bool ExtractComputedValueForTransition(
                   nsCSSProperty aProperty,
--- a/layout/style/nsAnimationManager.cpp
+++ b/layout/style/nsAnimationManager.cpp
@@ -427,16 +427,31 @@ nsAnimationManager::RulesMatching(AnonBo
 
 #ifdef MOZ_XUL
 /* virtual */ void
 nsAnimationManager::RulesMatching(XULTreeRuleProcessorData* aData)
 {
 }
 #endif
 
+/* virtual */ size_t
+nsAnimationManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  // XXX: various other members in nsAnimationManager could be measured here.
+  // Bug 671299 may do this.
+  return CommonAnimationManager::SizeOfExcludingThis(aMallocSizeOf);
+}
+
+/* virtual */ size_t
+nsAnimationManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(nsAnimationManager)) +
+         SizeOfExcludingThis(aMallocSizeOf);
+}
+
 nsIStyleRule*
 nsAnimationManager::CheckAnimationRule(nsStyleContext* aStyleContext,
                                        mozilla::dom::Element* aElement)
 {
   if (!mPresContext->IsProcessingAnimationStyleChange()) {
     // Everything that causes our animation data to change triggers a
     // style change, which in turn triggers a non-animation restyle.
     // Likewise, when we initially construct frames, we're not in a
--- a/layout/style/nsAnimationManager.h
+++ b/layout/style/nsAnimationManager.h
@@ -91,16 +91,20 @@ public:
 
   // nsIStyleRuleProcessor (parts)
   virtual void RulesMatching(ElementRuleProcessorData* aData);
   virtual void RulesMatching(PseudoElementRuleProcessorData* aData);
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData);
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData);
 #endif
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
   // nsARefreshObserver
   virtual void WillRefresh(mozilla::TimeStamp aTime);
 
   /**
    * Return the style rule that RulesMatching should add for
    * aStyleContext.  This might be different from what RulesMatching
    * actually added during aStyleContext's construction because the
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -140,24 +140,24 @@ struct RuleValue : RuleSelectorPair {
 
 // ------------------------------
 // Rule hash table
 //
 
 // Uses any of the sets of ops below.
 struct RuleHashTableEntry : public PLDHashEntryHdr {
   // If you add members that have heap allocated memory be sure to change the
-  // logic in RuleHashTableSizeOfEnumerator.
+  // logic in SizeOfRuleHashTableEntry().
   // Auto length 1, because we always have at least one entry in mRules.
   nsAutoTArray<RuleValue, 1> mRules;
 };
 
 struct RuleHashTagTableEntry : public RuleHashTableEntry {
   // If you add members that have heap allocated memory be sure to change the
-  // logic in RuleHash::SizeOf.
+  // logic in RuleHash::SizeOf{In,Ex}cludingThis.
   nsCOMPtr<nsIAtom> mTag;
 };
 
 static PLDHashNumber
 RuleHash_CIHashKey(PLDHashTable *table, const void *key)
 {
   nsIAtom *atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(key));
 
@@ -420,17 +420,18 @@ struct NodeMatchContext;
 class RuleHash {
 public:
   RuleHash(bool aQuirksMode);
   ~RuleHash();
   void AppendRule(const RuleSelectorPair &aRuleInfo);
   void EnumerateAllRules(Element* aElement, RuleProcessorData* aData,
                          NodeMatchContext& aNodeMatchContext);
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
 protected:
   typedef nsTArray<RuleValue> RuleValueList;
   void AppendRuleToTable(PLDHashTable* aTable, const void* aKey,
                          const RuleSelectorPair& aRuleInfo);
   void AppendUniversalRule(const RuleSelectorPair& aRuleInfo);
 
   PRInt32     mRuleCount;
@@ -722,55 +723,53 @@ void RuleHash::EnumerateAllRules(Element
     for (const RuleValue *value = mEnumList[0].mCurValue,
                          *end = mEnumList[0].mEnd;
          value != end; ++value) {
       ContentEnumFunc(value->mRule, value->mSelector, aData, aNodeContext);
     }
   }
 }
 
-static PLDHashOperator
-RuleHashTableSizeOfEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
-                              PRUint32 i, void* aClosure)
+static size_t
+SizeOfRuleHashTableEntry(PLDHashEntryHdr* aHdr, nsMallocSizeOfFun aMallocSizeOf)
 {
-  PRInt64* n = static_cast<PRInt64*>(aClosure);
   RuleHashTableEntry* entry = static_cast<RuleHashTableEntry*>(aHdr);
-
-  *n += entry->mRules.SizeOf();
-  // The size of the RuleHashTableEntry itself is accounted for already
-
-  return PL_DHASH_NEXT;
+  return entry->mRules.SizeOf();
 }
 
-PRInt64
-RuleHash::SizeOf() const
+size_t
+RuleHash::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 n = sizeof(*this);
-
-  n += PL_DHASH_TABLE_SIZE(&mIdTable) * sizeof(RuleHashTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mIdTable),
-                         RuleHashTableSizeOfEnumerator, &n);
-
-  n += PL_DHASH_TABLE_SIZE(&mClassTable) * sizeof(RuleHashTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mClassTable),
-                         RuleHashTableSizeOfEnumerator, &n);
-
-  n += PL_DHASH_TABLE_SIZE(&mTagTable) * sizeof(RuleHashTagTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mTagTable),
-                         RuleHashTableSizeOfEnumerator, &n);
-
-  n += PL_DHASH_TABLE_SIZE(&mNameSpaceTable) * sizeof(RuleHashTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mNameSpaceTable),
-                         RuleHashTableSizeOfEnumerator, &n);
+  size_t n = 0;
+
+  n += PL_DHashTableSizeOfExcludingThis(&mIdTable,
+                                        SizeOfRuleHashTableEntry,
+                                        aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mClassTable,
+                                        SizeOfRuleHashTableEntry,
+                                        aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mTagTable,
+                                        SizeOfRuleHashTableEntry,
+                                        aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mNameSpaceTable,
+                                        SizeOfRuleHashTableEntry,
+                                        aMallocSizeOf);
 
   n += mUniversalRules.SizeOf();
 
   return n;
 }
 
+size_t
+RuleHash::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(RuleHash)) +
+         SizeOfExcludingThis(aMallocSizeOf);
+}
+
 //--------------------------------
 
 // A hash table mapping atoms to lists of selectors
 struct AtomSelectorEntry : public PLDHashEntryHdr {
   nsIAtom *mAtom;
   // Auto length 2, because a decent fraction of these arrays ends up
   // with 2 elements, and each entry is cheap.
   nsAutoTArray<nsCSSSelector*, 2> mSelectors;
@@ -880,17 +879,17 @@ struct RuleCascadeData {
 #ifdef MOZ_XUL
     PL_DHashTableFinish(&mXULTreeRules);
 #endif
     for (PRUint32 i = 0; i < ArrayLength(mPseudoElementRuleHashes); ++i) {
       delete mPseudoElementRuleHashes[i];
     }
   }
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   RuleHash                 mRuleHash;
   RuleHash*
     mPseudoElementRuleHashes[nsCSSPseudoElements::ePseudo_PseudoElementCount];
   nsTArray<nsCSSRuleProcessor::StateSelector>  mStateSelectors;
   nsEventStates            mSelectorDocumentStates;
   PLDHashTable             mClassSelectors;
   PLDHashTable             mIdSelectors;
@@ -910,63 +909,51 @@ struct RuleCascadeData {
   nsTArray<nsCSSSelector*>* AttributeListFor(nsIAtom* aAttribute);
 
   nsMediaQueryResultCacheKey mCacheKey;
   RuleCascadeData*  mNext; // for a different medium
 
   const bool mQuirksMode;
 };
 
-static PLDHashOperator
-SelectorsSizeOfEnumerator(PLDHashTable* aTable, PLDHashEntryHdr* aHdr,
-                          PRUint32 i, void* aClosure)
+static size_t
+SizeOfSelectorsEntry(PLDHashEntryHdr* aHdr, nsMallocSizeOfFun aMallocSizeOf)
 {
-  PRInt64* n = (PRInt64*) aClosure;
-  AtomSelectorEntry* entry = (AtomSelectorEntry*)aHdr;
-
-  *n += entry->mSelectors.SizeOf();
-
-  return PL_DHASH_NEXT;
+  AtomSelectorEntry* entry = static_cast<AtomSelectorEntry*>(aHdr);
+  return entry->mSelectors.SizeOf();
 }
 
-PRInt64
-RuleCascadeData::SizeOf() const
+size_t
+RuleCascadeData::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 n = sizeof(*this);
-
-  n += mRuleHash.SizeOf();
+  size_t n = aMallocSizeOf(this, sizeof(RuleCascadeData));
+
+  n += mRuleHash.SizeOfExcludingThis(aMallocSizeOf);
   for (PRUint32 i = 0; i < ArrayLength(mPseudoElementRuleHashes); ++i) {
     if (mPseudoElementRuleHashes[i])
-      n += mPseudoElementRuleHashes[i]->SizeOf();
+      n += mPseudoElementRuleHashes[i]->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   n += mStateSelectors.SizeOf();
 
-  n += PL_DHASH_TABLE_SIZE(&mIdSelectors) * sizeof(AtomSelectorEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mIdSelectors),
-                         SelectorsSizeOfEnumerator, &n);
-  n += PL_DHASH_TABLE_SIZE(&mClassSelectors) * sizeof(AtomSelectorEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mClassSelectors),
-                         SelectorsSizeOfEnumerator, &n);
+  n += PL_DHashTableSizeOfExcludingThis(&mIdSelectors,
+                                        SizeOfSelectorsEntry, aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mClassSelectors,
+                                        SizeOfSelectorsEntry, aMallocSizeOf);
 
   n += mPossiblyNegatedClassSelectors.SizeOf();
   n += mPossiblyNegatedIDSelectors.SizeOf();
 
-  n += PL_DHASH_TABLE_SIZE(&mAttributeSelectors) * sizeof(AtomSelectorEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mAttributeSelectors),
-                         SelectorsSizeOfEnumerator, &n);
-
-  n += PL_DHASH_TABLE_SIZE(&mAnonBoxRules) * sizeof(RuleHashTagTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mAnonBoxRules),
-                         RuleHashTableSizeOfEnumerator, &n);
-
+  n += PL_DHashTableSizeOfExcludingThis(&mAttributeSelectors,
+                                        SizeOfSelectorsEntry, aMallocSizeOf);
+  n += PL_DHashTableSizeOfExcludingThis(&mAnonBoxRules,
+                                        SizeOfRuleHashTableEntry, aMallocSizeOf);
 #ifdef MOZ_XUL
-  n += PL_DHASH_TABLE_SIZE(&mXULTreeRules) * sizeof(RuleHashTagTableEntry);
-  PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mAnonBoxRules),
-                         RuleHashTableSizeOfEnumerator, &n);
+  n += PL_DHashTableSizeOfExcludingThis(&mXULTreeRules,
+                                        SizeOfRuleHashTableEntry, aMallocSizeOf);
 #endif
 
   n += mFontFaceRules.SizeOf();
   n += mKeyframesRules.SizeOf();
 
   return n;
 }
 
@@ -2544,30 +2531,36 @@ nsCSSRuleProcessor::MediumFeaturesChange
   // enabled).  And if there's nothing cached, it doesn't matter if
   // anything changed.  See bug 448281.
   if (old) {
     RefreshRuleCascade(aPresContext);
   }
   return (old != mRuleCascades);
 }
 
-/* virtual */ PRInt64
-nsCSSRuleProcessor::SizeOf() const
+/* virtual */ size_t
+nsCSSRuleProcessor::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 n = sizeof(*this);
-
+  size_t n = 0;
   n += mSheets.SizeOf();
   for (RuleCascadeData* cascade = mRuleCascades; cascade;
        cascade = cascade->mNext) {
-    n += cascade->SizeOf();
+    n += cascade->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   return n;
 }
 
+/* virtual */ size_t
+nsCSSRuleProcessor::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(nsCSSRuleProcessor)) +
+         SizeOfExcludingThis(aMallocSizeOf);
+}
+
 // Append all the currently-active font face rules to aArray.  Return
 // true for success and false for failure.
 bool
 nsCSSRuleProcessor::AppendFontFaceRules(
                               nsPresContext *aPresContext,
                               nsTArray<nsFontFaceRuleContainer>& aArray)
 {
   RuleCascadeData* cascade = GetRuleCascade(aPresContext);
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -133,25 +133,28 @@ public:
 
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
 
   virtual nsRestyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
 
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
 
-  virtual PRInt64 SizeOf() const;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun mallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf) const MOZ_OVERRIDE;
 
   // Append all the currently-active font face rules to aArray.  Return
   // true for success and false for failure.
   bool AppendFontFaceRules(nsPresContext* aPresContext,
-                             nsTArray<nsFontFaceRuleContainer>& aArray);
+                           nsTArray<nsFontFaceRuleContainer>& aArray);
 
   bool AppendKeyframesRules(nsPresContext* aPresContext,
-                              nsTArray<nsCSSKeyframesRule*>& aArray);
+                            nsTArray<nsCSSKeyframesRule*>& aArray);
 
 #ifdef DEBUG
   void AssertQuirksChangeOK() {
     NS_ASSERTION(!mRuleCascades, "can't toggle quirks style sheet without "
                                  "clearing rule cascades");
   }
 #endif
 
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -158,16 +158,28 @@ nsHTMLCSSStyleSheet::HasAttributeDepende
 }
 
 /* virtual */ bool
 nsHTMLCSSStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
 }
 
+/* virtual */ size_t
+nsHTMLCSSStyleSheet::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return 0;
+}
+
+/* virtual */ size_t
+nsHTMLCSSStyleSheet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(nsHTMLCSSStyleSheet)) +
+         SizeOfExcludingThis(aMallocSizeOf);
+}
 
 void
 nsHTMLCSSStyleSheet::Reset(nsIURI* aURL)
 {
   mURL = aURL;
 }
 
 /* virtual */ nsIURI*
--- a/layout/style/nsHTMLCSSStyleSheet.h
+++ b/layout/style/nsHTMLCSSStyleSheet.h
@@ -79,17 +79,20 @@ public:
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData);
 #endif
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData);
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
   virtual nsRestyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
-  virtual PRInt64 SizeOf() const { return sizeof(*this); }
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
 private: 
   // These are not supported and are not implemented! 
   nsHTMLCSSStyleSheet(const nsHTMLCSSStyleSheet& aCopy); 
   nsHTMLCSSStyleSheet& operator=(const nsHTMLCSSStyleSheet& aCopy); 
 
 protected:
   nsCOMPtr<nsIURI> mURL;
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -306,18 +306,24 @@ nsHTMLStyleSheet::HasAttributeDependentS
 }
 
 /* virtual */ bool
 nsHTMLStyleSheet::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
 }
 
-/* virtual */ PRInt64
-nsHTMLStyleSheet::SizeOf() const
+/* virtual */ size_t
+nsHTMLStyleSheet::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return 0; // nsHTMLStyleSheets are charged to the DOM, not layout
+}
+
+/* virtual */ size_t
+nsHTMLStyleSheet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
   return 0; // nsHTMLStyleSheets are charged to the DOM, not layout
 }
 
 /* virtual */ void
 nsHTMLStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
 {
 }
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -84,17 +84,20 @@ public:
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData);
 #endif
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData);
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
   virtual nsRestyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
-  virtual PRInt64 SizeOf() const;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
   nsresult Init(nsIURI* aURL, nsIDocument* aDocument);
   void Reset(nsIURI* aURL);
   nsresult SetLinkColor(nscolor aColor);
   nsresult SetActiveLinkColor(nscolor aColor);
   nsresult SetVisitedLinkColor(nscolor aColor);
 
   // Mapped Attribute management methods
--- a/layout/style/nsIStyleRuleProcessor.h
+++ b/layout/style/nsIStyleRuleProcessor.h
@@ -56,20 +56,20 @@ struct AnonBoxRuleProcessorData;
 #ifdef MOZ_XUL
 struct XULTreeRuleProcessorData;
 #endif
 struct StateRuleProcessorData;
 struct AttributeRuleProcessorData;
 class nsPresContext;
 
 // IID for the nsIStyleRuleProcessor interface
-// {32612c0e-3d34-4a6f-89d9-464f6811ac13}
+// {c1d6001e-4fcb-4c40-bce1-5eba80bfd8f3}
 #define NS_ISTYLE_RULE_PROCESSOR_IID     \
-{ 0x32612c0e, 0x3d34, 0x4a6f, \
-  {0x89, 0xd9, 0x46, 0x4f, 0x68, 0x11, 0xac, 0x13} }
+{ 0xc1d6001e, 0x4fcb, 0x4c40, \
+  {0xbc, 0xe1, 0x5e, 0xba, 0x80, 0xbf, 0xd8, 0xf3} }
 
 
 /* The style rule processor interface is a mechanism to separate the matching
  * of style rules from style sheet instances.
  * Simple style sheets can and will act as their own processor. 
  * Sheets where rule ordering interlaces between multiple sheets, will need to 
  * share a single rule processor between them (CSS sheets do this for cascading order)
  *
@@ -154,15 +154,16 @@ public:
    * processor's rules have changed (e.g., because of media queries).
    */
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) = 0;
 
   /**
    * Report the size of this style rule processor to about:memory.  A
    * processor may return 0.
    */
-  virtual PRInt64 SizeOf() const = 0;
+  virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun mallocSizeOf) const = 0;
+  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun mallocSizeOf) const = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIStyleRuleProcessor,
                               NS_ISTYLE_RULE_PROCESSOR_IID)
 
 #endif /* nsIStyleRuleProcessor_h___ */
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -141,23 +141,23 @@ nsStyleSet::nsStyleSet()
     mInShutdown(false),
     mAuthorStyleDisabled(false),
     mInReconstruct(false),
     mDirty(0)
 {
 }
 
 size_t
-nsStyleSet::SizeOf() const
+nsStyleSet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  size_t n = sizeof(*this);
+  size_t n = aMallocSizeOf(this, sizeof(nsStyleSet));
 
   for (int i = 0; i < eSheetTypeCount; i++) {
     if (mRuleProcessors[i]) {
-      n += mRuleProcessors[i]->SizeOf();
+      n += mRuleProcessors[i]->SizeOfIncludingThis(aMallocSizeOf);
     }
   }
 
   return n;
 }
 
 nsresult
 nsStyleSet::Init(nsPresContext *aPresContext)
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -87,17 +87,17 @@ class nsInitialStyleRule : public nsISty
 // then handed off to the PresShell.  Only the PresShell should delete a
 // style set.
 
 class nsStyleSet
 {
  public:
   nsStyleSet();
 
-  size_t SizeOf() const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   // Initialize the object.  You must check the return code and not use
   // the nsStyleSet if Init() fails.
 
   nsresult Init(nsPresContext *aPresContext);
 
   // For getting the cached default data in case we hit out-of-memory.
   // To be used only by nsRuleNode.
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -710,16 +710,29 @@ nsTransitionManager::RulesMatching(AnonB
 
 #ifdef MOZ_XUL
 /* virtual */ void
 nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData)
 {
 }
 #endif
 
+/* virtual */ size_t
+nsTransitionManager::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return CommonAnimationManager::SizeOfExcludingThis(aMallocSizeOf);
+}
+
+/* virtual */ size_t
+nsTransitionManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return aMallocSizeOf(this, sizeof(nsTransitionManager)) +
+         SizeOfExcludingThis(aMallocSizeOf);
+}
+
 struct TransitionEventInfo {
   nsCOMPtr<nsIContent> mElement;
   nsTransitionEvent mEvent;
 
   TransitionEventInfo(nsIContent *aElement, nsCSSProperty aProperty,
                       TimeDuration aDuration)
     : mElement(aElement),
       mEvent(true, NS_TRANSITION_END,
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -80,16 +80,20 @@ public:
 
   // nsIStyleRuleProcessor (parts)
   virtual void RulesMatching(ElementRuleProcessorData* aData);
   virtual void RulesMatching(PseudoElementRuleProcessorData* aData);
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData);
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData);
 #endif
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  virtual NS_MUST_OVERRIDE size_t
+    SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
 
   // nsARefreshObserver
   virtual void WillRefresh(mozilla::TimeStamp aTime);
 
 private:
   void ConsiderStartingTransition(nsCSSProperty aProperty,
                                   const nsTransition& aTransition,
                                   mozilla::dom::Element *aElement,
--- a/xpcom/glue/pldhash.cpp
+++ b/xpcom/glue/pldhash.cpp
@@ -806,34 +806,35 @@ SizeOfEntryEnumerator(PLDHashTable *tabl
                       PRUint32 number, void *arg)
 {
     SizeOfEntryEnumeratorArg *e = (SizeOfEntryEnumeratorArg *)arg;
     e->total += e->sizeOfEntry(hdr, e->mallocSizeOf);
     return PL_DHASH_NEXT;
 }
 
 size_t
-PL_DHashTableSizeOfExcludingThis(PLDHashTable *table,
+PL_DHashTableSizeOfExcludingThis(const PLDHashTable *table,
                                  PLDHashSizeOfEntryFun sizeOfEntry,
                                  nsMallocSizeOfFun mallocSizeOf)
 {
     size_t n = 0;
     n += mallocSizeOf(table->entryStore,
                       PL_DHASH_TABLE_SIZE(table) * table->entrySize +
                       ENTRY_STORE_EXTRA);
     if (sizeOfEntry) {
         SizeOfEntryEnumeratorArg arg = { 0, sizeOfEntry, mallocSizeOf };
-        PL_DHashTableEnumerate(table, SizeOfEntryEnumerator, &arg);
+        PL_DHashTableEnumerate(const_cast<PLDHashTable *>(table),
+                               SizeOfEntryEnumerator, &arg);
         n += arg.total;
     }
     return n;
 }
 
 size_t
-PL_DHashTableSizeOfIncludingThis(PLDHashTable *table,
+PL_DHashTableSizeOfIncludingThis(const PLDHashTable *table,
                                  PLDHashSizeOfEntryFun sizeOfEntry,
                                  nsMallocSizeOfFun mallocSizeOf)
 {
     return mallocSizeOf(table, sizeof(PLDHashTable)) +
            PL_DHashTableSizeOfExcludingThis(table, sizeOfEntry, mallocSizeOf);
 }
 
 #ifdef DEBUG
--- a/xpcom/glue/pldhash.h
+++ b/xpcom/glue/pldhash.h
@@ -583,25 +583,25 @@ typedef size_t
 
 /**
  * Measure the size of the table's entry storage, and if |sizeOfEntry| is
  * non-NULL, measure the size of things pointed to by entries.  Doesn't measure
  * |ops| because it's often shared between tables, nor |data| because it's
  * opaque.
  */
 NS_COM_GLUE size_t
-PL_DHashTableSizeOfExcludingThis(PLDHashTable *table,
+PL_DHashTableSizeOfExcludingThis(const PLDHashTable *table,
                                  PLDHashSizeOfEntryFun sizeOfEntry,
                                  nsMallocSizeOfFun mallocSizeOf);
 
 /**
  * Like PL_DHashTableSizeOfExcludingThis, but includes sizeof(*this).
  */
 NS_COM_GLUE size_t
-PL_DHashTableSizeOfIncludingThis(PLDHashTable *table,
+PL_DHashTableSizeOfIncludingThis(const PLDHashTable *table,
                                  PLDHashSizeOfEntryFun sizeOfEntry,
                                  nsMallocSizeOfFun mallocSizeOf);
 
 #ifdef DEBUG
 /**
  * Mark a table as immutable for the remainder of its lifetime.  This
  * changes the implementation from ASSERTing one set of invariants to
  * ASSERTing a different set.