Bug 723799 - Use mallocSizeOf in the DOM memory reporters. r=mounir.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 01 Feb 2012 13:58:01 -0800
changeset 88332 c30b6943dc98e8b2d24f76fba20764eefbfb109a
parent 88331 1c238e6cf7a18516ad68accbbae5abebb3ff6fe3
child 88333 593ae548729340f0242f98468a6823acde8da0d1
push id157
push userMs2ger@gmail.com
push dateWed, 07 Mar 2012 19:27:10 +0000
reviewersmounir
bugs723799
milestone13.0a1
Bug 723799 - Use mallocSizeOf in the DOM memory reporters. r=mounir.
content/base/public/Element.h
content/base/public/nsIContent.h
content/base/public/nsIDocument.h
content/base/public/nsINode.h
content/base/src/nsAttrAndChildArray.cpp
content/base/src/nsAttrAndChildArray.h
content/base/src/nsAttrValue.cpp
content/base/src/nsAttrValue.h
content/base/src/nsCommentNode.cpp
content/base/src/nsDocument.cpp
content/base/src/nsDocument.h
content/base/src/nsGenericDOMDataNode.cpp
content/base/src/nsGenericDOMDataNode.h
content/base/src/nsGenericElement.cpp
content/base/src/nsGenericElement.h
content/base/src/nsMappedAttributeElement.h
content/base/src/nsMappedAttributes.cpp
content/base/src/nsMappedAttributes.h
content/base/src/nsStyledElement.h
content/base/src/nsTextFragment.cpp
content/base/src/nsTextFragment.h
content/base/src/nsTextNode.h
content/events/src/nsEventListenerManager.cpp
content/events/src/nsEventListenerManager.h
content/html/content/src/nsGenericHTMLElement.h
content/html/content/src/nsGenericHTMLFrameElement.cpp
content/html/content/src/nsGenericHTMLFrameElement.h
content/html/content/src/nsHTMLAnchorElement.cpp
content/html/content/src/nsHTMLAreaElement.cpp
content/html/content/src/nsHTMLDivElement.cpp
content/html/content/src/nsHTMLLinkElement.cpp
content/html/content/src/nsHTMLSpanElement.cpp
content/html/document/src/nsHTMLDocument.cpp
content/html/document/src/nsHTMLDocument.h
content/xml/content/src/nsXMLCDATASection.cpp
content/xml/content/src/nsXMLProcessingInstruction.h
content/xml/document/src/nsXMLDocument.cpp
content/xml/document/src/nsXMLDocument.h
dom/base/Navigator.cpp
dom/base/Navigator.h
dom/base/nsDOMMemoryReporter.cpp
dom/base/nsDOMMemoryReporter.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsIJSEventListener.h
dom/src/events/nsJSEventListener.h
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
xpcom/glue/nsTObserverArray.h
--- a/content/base/public/Element.h
+++ b/content/base/public/Element.h
@@ -100,18 +100,16 @@ public:
   Element(already_AddRefed<nsINodeInfo> aNodeInfo) :
     nsIContent(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
   {}
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(Element, nsIContent)
-
   /**
    * Method to get the full state of this element.  See nsEventStates.h for
    * the possible bits that could be set here.
    */
   nsEventStates State() const {
     // mState is maintained by having whoever might have changed it
     // call UpdateState() or one of the other mState mutators.
     return mState;
--- a/content/base/public/nsIContent.h
+++ b/content/base/public/nsIContent.h
@@ -99,18 +99,16 @@ public:
   {
     NS_ASSERTION(mNodeInfo,
                  "No nsINodeInfo passed to nsIContent, PREPARE TO CRASH!!!");
   }
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENT_IID)
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsIContent, nsINode);
-
   /**
    * Bind this content node to a tree.  If this method throws, the caller must
    * call UnbindFromTree() on the node.  In the typical case of a node being
    * appended to a parent, this will be called after the node has been added to
    * the parent's child list and before nsIDocumentObserver notifications for
    * the addition are dispatched.
    * @param aDocument The new document for the content node.  Must match the
    *                  current document of aParent, if aParent is not null.
@@ -994,14 +992,13 @@ public:
   };
 
   // Tab focus model bit field:
   static PRInt32 sTabFocusModel;
 
   // accessibility.tabfocus_applies_to_xul pref - if it is set to true,
   // the tabfocus bit field applies to xul elements.
   static bool sTabFocusModelAppliesToXUL;
-
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIContent, NS_ICONTENT_IID)
 
 #endif /* nsIContent_h___ */
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -106,16 +106,17 @@ class nsBindingManager;
 class nsIDOMNodeList;
 class mozAutoSubtreeModified;
 struct JSObject;
 class nsFrameLoader;
 class nsIBoxObject;
 class imgIRequest;
 class nsISHEntry;
 class nsDOMNavigationTiming;
+class nsWindowSizes;
 
 namespace mozilla {
 namespace css {
 class Loader;
 } // namespace css
 
 namespace dom {
 class Link;
@@ -151,17 +152,16 @@ enum DocumentFlavor {
 // Gecko.
 class nsIDocument : public nsINode
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID)
   NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
 
 #ifdef MOZILLA_INTERNAL_API
   nsIDocument()
     : nsINode(nsnull),
       mCharacterSet(NS_LITERAL_CSTRING("ISO-8859-1")),
       mNodeInfoManager(nsnull),
       mCompatMode(eCompatibility_FullStandards),
       mIsInitialDocumentInWindow(false),
@@ -1612,17 +1612,25 @@ public:
 
   void SetNeedStyleFlush() {
     mNeedStyleFlush = true;
     if (mDisplayDocument) {
       mDisplayDocument->SetNeedStyleFlush();
     }
   }
 
-  virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const = 0;
+  // Note: nsIDocument is a sub-class of nsINode, which has a
+  // SizeOfExcludingThis function.  However, because nsIDocument objects can
+  // only appear at the top of the DOM tree, we have a specialized measurement
+  // function which returns multiple sizes.
+  virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
+  // DocSizeOfIncludingThis doesn't need to be overridden by sub-classes
+  // because nsIDocument inherits from nsINode;  see the comment above the
+  // declaration of nsINode::SizeOfIncludingThis.
+  virtual void DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const;
 
 private:
   PRUint64 mWarnedAbout;
 
 protected:
   ~nsIDocument()
   {
     // XXX The cleanup of mNodeInfoManager (calling DropDocumentReference and
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -297,17 +297,49 @@ private:
  * of nsIContent children and provides access to them.
  */
 class nsINode : public nsIDOMEventTarget,
                 public nsWrapperCache
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_INODE_IID)
 
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
+  // Among the sub-classes that inherit (directly or indirectly) from nsINode,
+  // measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - nsGenericHTMLElement:  mForm, mFieldSet
+  // - nsGenericHTMLFrameElement: mFrameLoader (bug 672539), mTitleChangedListener
+  // - nsHTMLBodyElement:     mContentStyleRule
+  // - nsHTMLDataListElement: mOptions
+  // - nsHTMLFieldSetElement: mElements, mDependentElements, mFirstLegend
+  // - nsHTMLFormElement:     many!
+  // - nsHTMLFrameSetElement: mRowSpecs, mColSpecs
+  // - nsHTMLInputElement:    mInputData, mFiles, mFileList, mStaticDocfileList
+  // - nsHTMLMapElement:      mAreas
+  // - nsHTMLMediaElement:    many!
+  // - nsHTMLOutputElement:   mDefaultValue, mTokenList
+  // - nsHTMLRowElement:      mCells
+  // - nsHTMLSelectElement:   mOptions, mRestoreState
+  // - nsHTMLTableElement:    mTBodies, mRows, mTableInheritedAttributes
+  // - nsHTMLTableSectionElement: mRows
+  // - nsHTMLTextAreaElement: mControllers, mState
+  //
+  // The following members don't need to be measured:
+  // - nsIContent: mPrimaryFrame, because it's non-owning and measured elsewhere
+  //
+  NS_DECL_SIZEOF_EXCLUDING_THIS
+
+  // SizeOfIncludingThis doesn't need to be overridden by sub-classes because
+  // sub-classes of nsINode are guaranteed to be laid out in memory in such a
+  // way that |this| points to the start of the allocated object, even in
+  // methods of nsINode's sub-classes, and so |aMallocSizeOf(this)| is always
+  // safe to call no matter which object it was invoked on.
+  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const {
+    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+  }
 
   friend class nsNodeUtils;
   friend class nsNodeWeakReference;
   friend class nsNodeSupportsWeakRefTearoff;
   friend class nsAttrAndChildArray;
 
 #ifdef MOZILLA_INTERNAL_API
   nsINode(already_AddRefed<nsINodeInfo> aNodeInfo)
@@ -1326,16 +1358,17 @@ protected:
   void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
   void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
   bool HasLockedStyleStates() const
     { return GetBoolFlag(ElementHasLockedStyleStates); }
 
 public:
   // Optimized way to get classinfo.
   virtual nsXPCClassInfo* GetClassInfo() = 0;
+
 protected:
 
   // Override this function to create a custom slots class.
   virtual nsINode::nsSlots* CreateSlots();
 
   bool HasSlots() const
   {
     return mSlots != nsnull;
--- a/content/base/src/nsAttrAndChildArray.cpp
+++ b/content/base/src/nsAttrAndChildArray.cpp
@@ -834,31 +834,27 @@ nsAttrAndChildArray::SetChildAtPos(void*
   }
   if (aIndex != aChildCount) {
     nsIContent* next = static_cast<nsIContent*>(*(aPos + 1));
     aChild->mNextSibling = next;
     next->mPreviousSibling = aChild;
   }
 }
 
-PRInt64
-nsAttrAndChildArray::SizeOf() const
+size_t
+nsAttrAndChildArray::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 size = sizeof(*this);
-
+  size_t n = 0;
   if (mImpl) {
     // Don't add the size taken by *mMappedAttrs because it's shared.
 
-    // mBuffer cointains InternalAttr and nsIContent* (even if it's void**)
-    // so, we just have to compute the size of *mBuffer given that this object
-    // doesn't own the children list.
-    size += mImpl->mBufferSize * sizeof(*(mImpl->mBuffer)) + NS_IMPL_EXTRA_SIZE;
+    n += aMallocSizeOf(mImpl);
 
     PRUint32 slotCount = AttrSlotCount();
     for (PRUint32 i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
       nsAttrValue* value = &ATTRS(mImpl)[i].mValue;
-      size += value->SizeOf() - sizeof(*value);
+      n += value->SizeOfExcludingThis(aMallocSizeOf);
     }
   }
 
-  return size;
+  return n;
 }
 
--- a/content/base/src/nsAttrAndChildArray.h
+++ b/content/base/src/nsAttrAndChildArray.h
@@ -130,17 +130,17 @@ public:
   void Compact();
 
   bool CanFitMoreAttrs() const
   {
     return AttrSlotCount() < ATTRCHILD_ARRAY_MAX_ATTR_COUNT ||
            !AttrSlotIsTaken(ATTRCHILD_ARRAY_MAX_ATTR_COUNT - 1);
   }
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
   bool HasMappedAttrs() const
   {
     return MappedAttrCount();
   }
 
 private:
   nsAttrAndChildArray(const nsAttrAndChildArray& aOther) MOZ_DELETE;
   nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) MOZ_DELETE;
--- a/content/base/src/nsAttrValue.cpp
+++ b/content/base/src/nsAttrValue.cpp
@@ -1762,64 +1762,55 @@ nsAttrValue::StringToInteger(const nsASt
     if (!value) {
       *aStrict = false;
     }
   }
 
   return value;
 }
 
-PRInt64
-nsAttrValue::SizeOf() const
+size_t
+nsAttrValue::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 size = sizeof(*this);
+  size_t n = 0;
 
   switch (BaseType()) {
     case eStringBase:
     {
-      // TODO: we might be counting the string size more than once.
-      // This should be fixed with bug 677487.
       nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr());
-      size += str ? str->StorageSize() : 0;
+      n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
       break;
     }
     case eOtherBase:
     {
       MiscContainer* container = GetMiscContainer();
-
       if (!container) {
         break;
       }
-
-      size += sizeof(*container);
+      n += aMallocSizeOf(container);
 
       void* otherPtr = MISC_STR_PTR(container);
       // We only count the size of the object pointed by otherPtr if it's a
       // string. When it's an atom, it's counted separatly.
       if (otherPtr &&
           static_cast<ValueBaseType>(container->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == eStringBase) {
-        // TODO: we might be counting the string size more than once.
-        // This should be fixed with bug 677487.
         nsStringBuffer* str = static_cast<nsStringBuffer*>(otherPtr);
-        size += str ? str->StorageSize() : 0;
+        n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
       }
 
-      // TODO: mCSSStyleRule might be owned by another object
-      // which would make us count them twice, bug 677493.
       if (Type() == eCSSStyleRule && container->mCSSStyleRule) {
-        // TODO: Add SizeOf() to StyleRule, bug 677503.
-        size += sizeof(*container->mCSSStyleRule);
+        // TODO: mCSSStyleRule might be owned by another object which would
+        //       make us count them twice, bug 677493.
+        //n += container->mCSSStyleRule->SizeOfIncludingThis(aMallocSizeOf);
       } else if (Type() == eAtomArray && container->mAtomArray) {
-        size += sizeof(container->mAtomArray) + sizeof(nsTArrayHeader);
-        size += container->mAtomArray->Capacity() * sizeof(nsCOMPtr<nsIAtom>);
-        // Don't count the size of each nsIAtom, they are counted separatly.
+        // Don't measure each nsIAtom, they are measured separatly.
+        n += container->mAtomArray->SizeOfIncludingThis(aMallocSizeOf);
       }
-
       break;
     }
-    case eAtomBase:    // Atoms are counted separatly.
+    case eAtomBase:    // Atoms are counted separately.
     case eIntegerBase: // The value is in mBits, nothing to do.
       break;
   }
 
-  return size;
+  return n;
 }
 
--- a/content/base/src/nsAttrValue.h
+++ b/content/base/src/nsAttrValue.h
@@ -371,17 +371,17 @@ public:
    * Parse a margin string of format 'top, right, bottom, left' into
    * an nsIntMargin.
    *
    * @param aString the string to parse
    * @return whether the value could be parsed
    */
   bool ParseIntMarginValue(const nsAString& aString);
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
 private:
   // These have to be the same as in ValueType
   enum ValueBaseType {
     eStringBase =    eString,    // 00
     eOtherBase =     0x01,       // 01
     eAtomBase =      eAtom,      // 10
     eIntegerBase =   0x03        // 11
--- a/content/base/src/nsCommentNode.cpp
+++ b/content/base/src/nsCommentNode.cpp
@@ -58,20 +58,16 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericDOMDataNode::)
 
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
 
-  // DOM Memory Reporter participant.
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsCommentNode,
-                                              nsGenericDOMDataNode)
-
   // nsIDOMComment
   // Empty interface
 
   // nsINode
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
                                               bool aCloneText) const;
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -8481,29 +8481,16 @@ nsDocument::CreateTouchList(nsIVariant* 
       nsMemory::Free(rawArray);
     }
   }
 
   *aRetVal = retval.forget().get();
   return NS_OK;
 }
 
-PRInt64
-nsIDocument::SizeOf() const
-{
-  PRInt64 size = MemoryReporter::GetBasicSize<nsIDocument, nsINode>(this);
-
-  for (nsIContent* node = GetFirstChild(); node;
-       node = node->GetNextNode(this)) {
-    size += node->SizeOf();
-  }
-
-  return size;
-}
-
 static void
 DispatchFullScreenChange(nsIDocument* aTarget)
 {
   nsRefPtr<nsAsyncDOMEvent> e =
     new nsAsyncDOMEvent(aTarget,
                         NS_LITERAL_STRING("mozfullscreenchange"),
                         true,
                         false);
@@ -9079,24 +9066,16 @@ nsDocument::IsFullScreenEnabled(bool aCa
       return false;
     }
     node = nsContentUtils::GetCrossDocParentNode(node);
   } while (node);
 
   return true;
 }
 
-PRInt64
-nsDocument::SizeOf() const
-{
-  PRInt64 size = MemoryReporter::GetBasicSize<nsDocument, nsIDocument>(this);
-  size += mAttrStyleSheet ? mAttrStyleSheet->DOMSizeOf() : 0;
-  return size;
-}
-
 #define EVENT(name_, id_, type_, struct_)                                 \
   NS_IMETHODIMP nsDocument::GetOn##name_(JSContext *cx, jsval *vp) {      \
     return nsINode::GetOn##name_(cx, vp);                                 \
   }                                                                       \
   NS_IMETHODIMP nsDocument::SetOn##name_(JSContext *cx, const jsval &v) { \
     return nsINode::SetOn##name_(cx, v);                                  \
   }
 #define TOUCH_EVENT EVENT
@@ -9159,22 +9138,70 @@ nsDocument::GetMozVisibilityState(nsAStr
     "hidden",
     "visible"
   };
   PR_STATIC_ASSERT(NS_ARRAY_LENGTH(states) == eVisibilityStateCount);
   aState.AssignASCII(states[mVisibilityState]);
   return NS_OK;
 }
 
+/* virtual */ void
+nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
+{
+  aWindowSizes->mDOM +=
+    nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf);
+
+  // Measurement of the following members may be added later if DMD finds it
+  // is worthwhile:
+  // - many!
+}
+
+void
+nsIDocument::DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
+{
+  aWindowSizes->mDOM += aWindowSizes->mMallocSizeOf(this);
+  DocSizeOfExcludingThis(aWindowSizes);
+}
+
 static size_t
 SizeOfStyleSheetsElementIncludingThis(nsIStyleSheet* aStyleSheet,
                                       nsMallocSizeOfFun aMallocSizeOf,
                                       void* aData)
 {
   return aStyleSheet->SizeOfIncludingThis(aMallocSizeOf);
 }
 
-/* virtual */ size_t
-nsDocument::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
-{
-  return mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
-                                          aMallocSizeOf); 
-}
+size_t
+nsDocument::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  // This SizeOfExcludingThis() overrides the one from nsINode.  But
+  // nsDocuments can only appear at the top of the DOM tree, and we use the
+  // specialized DocSizeOfExcludingThis() in that case.  So this should never
+  // be called.
+  MOZ_NOT_REACHED("nsDocument::SizeOfExcludingThis");
+  return 0;
+}
+
+void
+nsDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
+{
+  nsIDocument::DocSizeOfExcludingThis(aWindowSizes);
+
+  for (nsIContent* node = nsINode::GetFirstChild();
+       node;
+       node = node->GetNextNode(this))
+  {
+    aWindowSizes->mDOM +=
+      node->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
+  }
+
+  aWindowSizes->mStyleSheets +=
+    mStyleSheets.SizeOfExcludingThis(SizeOfStyleSheetsElementIncludingThis,
+                                     aWindowSizes->mMallocSizeOf); 
+  aWindowSizes->mDOM +=
+    mAttrStyleSheet ?
+    mAttrStyleSheet->DOMSizeOfIncludingThis(aWindowSizes->mMallocSizeOf) :
+    0;
+
+  // Measurement of the following members may be added later if DMD finds it
+  // is worthwhile:
+  // - many!
+}
--- a/content/base/src/nsDocument.h
+++ b/content/base/src/nsDocument.h
@@ -118,16 +118,17 @@ class nsIFormControl;
 struct nsRadioGroupStruct;
 class nsOnloadBlocker;
 class nsUnblockOnloadEvent;
 class nsChildContentList;
 class nsXMLEventsManager;
 class nsHTMLStyleSheet;
 class nsHTMLCSSStyleSheet;
 class nsDOMNavigationTiming;
+class nsWindowSizes;
 
 /**
  * Right now our identifier map entries contain information for 'name'
  * and 'id' mappings of a given string. This is so that
  * nsHTMLDocument::ResolveName only has to do one hash lookup instead
  * of two. It's not clear whether this still matters for performance.
  * 
  * We also store the document.all result list here. This is mainly so that
@@ -500,17 +501,18 @@ class nsDocument : public nsIDocument,
                    public nsStubMutationObserver,
                    public nsIDOMDocumentTouch,
                    public nsIInlineEventHandlers
 {
 public:
   typedef mozilla::dom::Element Element;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
+
+  NS_DECL_SIZEOF_EXCLUDING_THIS
 
   using nsINode::GetScriptTypeID;
 
   virtual void Reset(nsIChannel *aChannel, nsILoadGroup *aLoadGroup);
   virtual void ResetToURI(nsIURI *aURI, nsILoadGroup *aLoadGroup,
                           nsIPrincipal* aPrincipal);
 
   // StartDocumentLoad is pure virtual so that subclasses must override it.
@@ -985,17 +987,18 @@ public:
   Element* FullScreenStackTop();
 
   // This method may fire a DOM event; if it does so it will happen
   // synchronously.
   void UpdateVisibilityState();
   // Posts an event to call UpdateVisibilityState
   virtual void PostVisibilityUpdateEvent();
 
-  virtual size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
+  virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
+  // DocSizeOfIncludingThis is inherited from nsIDocument.
 
 protected:
   friend class nsNodeUtils;
 
   // Returns true if a request for DOM full-screen is currently enabled in
   // this document. This returns true if there are no windowed plugins in this
   // doc tree, and if the document is visible, and if the api is not
   // disabled by pref. aIsCallerChrome must contain the return value of
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -992,17 +992,16 @@ nsGenericDOMDataNode::GetAttributeChange
 }
 
 nsIAtom*
 nsGenericDOMDataNode::GetClassAttributeName() const
 {
   return nsnull;
 }
 
-PRInt64
-nsGenericDOMDataNode::SizeOf() const
+size_t
+nsGenericDOMDataNode::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 size = dom::MemoryReporter::GetBasicSize<nsGenericDOMDataNode,
-                                                   nsIContent>(this);
-  size += mText.SizeOf() - sizeof(mText);
-  return size;
+  size_t n = nsIContent::SizeOfExcludingThis(aMallocSizeOf);
+  n += mText.SizeOfExcludingThis(aMallocSizeOf);
+  return n;
 }
 
--- a/content/base/src/nsGenericDOMDataNode.h
+++ b/content/base/src/nsGenericDOMDataNode.h
@@ -74,17 +74,17 @@ class nsIDOMText;
 class nsINodeInfo;
 class nsURI;
 
 class nsGenericDOMDataNode : public nsIContent
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
+  NS_DECL_SIZEOF_EXCLUDING_THIS
 
   nsGenericDOMDataNode(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericDOMDataNode();
 
   // Implementation for nsIDOMNode
   nsresult GetNodeName(nsAString& aNodeName)
   {
     aNodeName = NodeName();
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -6192,39 +6192,42 @@ nsGenericElement::MozMatchesSelector(con
   NS_PRECONDITION(aReturn, "Null out param?");
 
   nsresult rv;
   *aReturn = MozMatchesSelector(aSelector, &rv);
 
   return rv;
 }
 
-PRInt64
-nsINode::SizeOf() const
-{
-  PRInt64 size = sizeof(*this);
-
+size_t
+nsINode::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  size_t n = 0;
   nsEventListenerManager* elm =
     const_cast<nsINode*>(this)->GetListenerManager(false);
   if (elm) {
-    size += elm->SizeOf();
-  }
-
-  return size;
-}
-
-PRInt64
-nsGenericElement::SizeOf() const
-{
-  PRInt64 size = MemoryReporter::GetBasicSize<nsGenericElement, Element>(this);
-
-  size -= sizeof(mAttrsAndChildren);
-  size += mAttrsAndChildren.SizeOf();
-
-  return size;
+    n += elm->SizeOfIncludingThis(aMallocSizeOf);
+  }
+
+  // Measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - mNodeInfo (Nb: allocated in nsNodeInfo.cpp with a nsFixedSizeAllocator)
+  // - mSlots
+  //
+  // The following members are not measured:
+  // - mParent, mNextSibling, mPreviousSibling, mFirstChild: because they're
+  //   non-owning
+  return n;
+}
+
+size_t
+nsGenericElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  return Element::SizeOfExcludingThis(aMallocSizeOf) +
+         mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf);
 }
 
 #define EVENT(name_, id_, type_, struct_)                                    \
   NS_IMETHODIMP nsINode::GetOn##name_(JSContext *cx, jsval *vp) {            \
     nsEventListenerManager *elm = GetListenerManager(false);              \
     if (elm) {                                                               \
       elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
     } else {                                                                 \
--- a/content/base/src/nsGenericElement.h
+++ b/content/base/src/nsGenericElement.h
@@ -242,17 +242,17 @@ public:
   nsGenericElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericElement();
 
   friend class nsTouchEventReceiverTearoff;
   friend class nsInlineEventHandlersTearoff;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
+  NS_DECL_SIZEOF_EXCLUDING_THIS
 
   /**
    * Called during QueryInterface to give the binding manager a chance to
    * get an interface for this element.
    */
   nsresult PostQueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   // nsINode interface methods
--- a/content/base/src/nsMappedAttributeElement.h
+++ b/content/base/src/nsMappedAttributeElement.h
@@ -61,19 +61,16 @@ class nsMappedAttributeElement : public 
 
 protected:
 
   nsMappedAttributeElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsMappedAttributeElementBase(aNodeInfo)
   {}
 
 public:
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsMappedAttributeElement,
-                                              nsMappedAttributeElementBase)
-
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
 
   static void MapNoAttributesInto(const nsMappedAttributes* aAttributes, 
                                   nsRuleData* aRuleData);
--- a/content/base/src/nsMappedAttributes.cpp
+++ b/content/base/src/nsMappedAttributes.cpp
@@ -273,23 +273,21 @@ nsMappedAttributes::IndexOfAttr(nsIAtom*
         return i;
       }
     }
   }
 
   return -1;
 }
 
-PRInt64
-nsMappedAttributes::SizeOf() const
+size_t
+nsMappedAttributes::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
   NS_ASSERTION(mAttrCount == mBufferSize,
                "mBufferSize and mAttrCount are expected to be the same.");
 
-  PRInt64 size = sizeof(*this) - sizeof(void*) + mAttrCount * sizeof(InternalAttr);
-
+  size_t n = aMallocSizeOf(this);
   for (PRUint16 i = 0; i < mAttrCount; ++i) {
-    size += Attrs()[i].mValue.SizeOf() - sizeof(Attrs()[i].mValue);
+    n += Attrs()[i].mValue.SizeOfExcludingThis(aMallocSizeOf);
   }
-
-  return size;
+  return n;
 }
 
--- a/content/base/src/nsMappedAttributes.h
+++ b/content/base/src/nsMappedAttributes.h
@@ -103,17 +103,17 @@ public:
   
 
   // nsIStyleRule 
   virtual void MapRuleInfoInto(nsRuleData* aRuleData);
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
 private:
   nsMappedAttributes(const nsMappedAttributes& aCopy);
   ~nsMappedAttributes();
 
   struct InternalAttr
   {
     nsAttrName mName;
--- a/content/base/src/nsStyledElement.h
+++ b/content/base/src/nsStyledElement.h
@@ -63,20 +63,16 @@ class nsStyledElementNotElementCSSInline
 
 protected:
 
   inline nsStyledElementNotElementCSSInlineStyle(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsStyledElementBase(aNodeInfo)
   {}
 
 public:
-
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsStyledElementNotElementCSSInlineStyle,
-                                              nsStyledElementBase)
-
   // nsIContent interface methods
   virtual nsIAtom* GetClassAttributeName() const;
   virtual nsIAtom* GetIDAttributeName() const;
   virtual nsIAtom* DoGetID() const;
   virtual const nsAttrValue* DoGetClasses() const;
 
   virtual mozilla::css::StyleRule* GetInlineStyleRule();
   NS_IMETHOD SetInlineStyleRule(mozilla::css::StyleRule* aStyleRule, bool aNotify);
@@ -114,19 +110,15 @@ protected:
    * first put into a document.  Only has an effect if the old value is a
    * string.  If aForceInDataDoc is true, will reparse even if we're in a data
    * document.
    */
   nsresult  ReparseStyleAttribute(bool aForceInDataDoc);
 };
 
 class nsStyledElement : public nsStyledElementNotElementCSSInlineStyle {
-public:
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsStyledElement,
-                                              nsStyledElementNotElementCSSInlineStyle)
-
 protected:
   inline nsStyledElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsStyledElementNotElementCSSInlineStyle(aNodeInfo)
   {}
 };
 
 #endif // __NS_STYLEDELEMENT_H_
--- a/content/base/src/nsTextFragment.cpp
+++ b/content/base/src/nsTextFragment.cpp
@@ -424,16 +424,30 @@ nsTextFragment::Append(const PRUnichar* 
   LossyConvertEncoding16to8 converter(buff + mState.mLength);
   copy_string(aBuffer, aBuffer + aLength, converter);
 
   m1b = buff;
   mState.mLength += aLength;
 
 }
 
+/* virtual */ size_t
+nsTextFragment::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+  if (Is2b()) {
+    return aMallocSizeOf(m2b);
+  }
+
+  if (mState.mInHeap) {
+    return aMallocSizeOf(m1b);
+  }
+
+  return 0;
+}
+
 // To save time we only do this when we really want to know, not during
 // every allocation
 void
 nsTextFragment::UpdateBidiFlag(const PRUnichar* aBuffer, PRUint32 aLength)
 {
   if (mState.mIs2b && !mState.mIsBidi) {
     const PRUnichar* cp = aBuffer;
     const PRUnichar* end = cp + aLength;
--- a/content/base/src/nsTextFragment.h
+++ b/content/base/src/nsTextFragment.h
@@ -218,26 +218,17 @@ public:
     // which causes crashes because we assume this structure is no more than
     // 32 bits!
     PRUint32 mInHeap : 1;
     PRUint32 mIs2b : 1;
     PRUint32 mIsBidi : 1;
     PRUint32 mLength : 29;
   };
 
-  /**
-   * Returns the size taken in memory by this text fragment.
-   * @return the size taken in memory by this text fragment.
-   */
-  PRInt64 SizeOf() const
-  {
-    PRInt64 size = sizeof(*this);
-    size += GetLength() * (Is2b() ? sizeof(*m2b) : sizeof(*m1b));
-    return size;
-  }
+  size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
 private:
   void ReleaseText();
 
   /**
    * Scan the contents of the fragment and turn on mState.mIsBidi if it
    * includes any Bidi characters.
    */
--- a/content/base/src/nsTextNode.h
+++ b/content/base/src/nsTextNode.h
@@ -64,19 +64,16 @@ public:
   NS_FORWARD_NSIDOMNODE(nsGenericDOMDataNode::)
 
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
 
   // nsIDOMText
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)
 
-  // DOM Memory Reporter participant.
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsTextNode, nsGenericDOMDataNode)
-
   // nsINode
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
                                               bool aCloneText) const;
 
   nsresult BindToAttribute(nsIAttribute* aAttr);
   nsresult UnbindFromAttribute();
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -999,30 +999,30 @@ nsEventListenerManager::GetJSEventListen
     
   if (ls->mHandlerIsString) {
     CompileEventHandlerInternal(ls, true, nsnull);
   }
 
   *vp = OBJECT_TO_JSVAL(listener->GetHandler());
 }
 
-PRInt64
-nsEventListenerManager::SizeOf() const
+size_t
+nsEventListenerManager::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf)
+  const
 {
-  PRInt64 size = sizeof(*this);
+  size_t n = aMallocSizeOf(this);
+  n += mListeners.SizeOfExcludingThis(aMallocSizeOf);
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; ++i) {
-    const nsListenerStruct& ls = mListeners.ElementAt(i);
-    size += sizeof(ls);
-    nsIJSEventListener* jsl = ls.GetJSListener();
+    nsIJSEventListener* jsl = mListeners.ElementAt(i).GetJSListener();
     if (jsl) {
-      size += jsl->SizeOf();
+      n += jsl->SizeOfIncludingThis(aMallocSizeOf);
     }
   }
-  return size;
+  return n;
 }
 
 void
 nsEventListenerManager::UnmarkGrayJSListeners()
 {
   PRUint32 count = mListeners.Length();
   for (PRUint32 i = 0; i < count; ++i) {
     const nsListenerStruct& ls = mListeners.ElementAt(i);
--- a/content/events/src/nsEventListenerManager.h
+++ b/content/events/src/nsEventListenerManager.h
@@ -238,17 +238,17 @@ public:
   /**
    * Returns true if there may be a touch event listener registered,
    * false if there definitely isn't.
    */
   bool MayHaveTouchEventListener() { return mMayHaveTouchEventListener; }
 
   bool MayHaveMouseEnterLeaveEventListener() { return mMayHaveMouseEnterLeaveEventListener; }
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   void UnmarkGrayJSListeners();
 
   nsISupports* GetTarget() { return mTarget; }
 protected:
   nsresult HandleEventSubType(nsListenerStruct* aListenerStruct,
                               nsIDOMEventListener* aListener,
                               nsIDOMEvent* aDOMEvent,
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -77,19 +77,16 @@ class nsGenericHTMLElement : public nsGe
 public:
   nsGenericHTMLElement(already_AddRefed<nsINodeInfo> aNodeInfo)
     : nsGenericHTMLElementBase(aNodeInfo)
   {
     NS_ASSERTION(mNodeInfo->NamespaceID() == kNameSpaceID_XHTML,
                  "Unexpected namespace");
   }
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsGenericHTMLElement,
-                                              nsGenericHTMLElementBase)
-
   /** Typesafe, non-refcounting cast from nsIContent.  Cheaper than QI. **/
   static nsGenericHTMLElement* FromContent(nsIContent *aContent)
   {
     if (aContent->IsHTML())
       return static_cast<nsGenericHTMLElement*>(aContent);
     return nsnull;
   }
 
@@ -869,19 +866,16 @@ class nsHTMLFieldSetElement;
  */
 class nsGenericHTMLFormElement : public nsGenericHTMLElement,
                                  public nsIFormControl
 {
 public:
   nsGenericHTMLFormElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsGenericHTMLFormElement();
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsGenericHTMLFormElement,
-                                              nsGenericHTMLElement)
-
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
   virtual void SaveSubtreeState();
 
   // nsIFormControl
   virtual mozilla::dom::Element* GetFormElement();
   virtual void SetForm(nsIDOMHTMLFormElement* aForm);
--- a/content/html/content/src/nsGenericHTMLFrameElement.cpp
+++ b/content/html/content/src/nsGenericHTMLFrameElement.cpp
@@ -264,26 +264,16 @@ nsGenericHTMLFrameElement::IsHTMLFocusab
 
   if (!*aIsFocusable && aTabIndex) {
     *aTabIndex = -1;
   }
 
   return false;
 }
 
-PRInt64
-nsGenericHTMLFrameElement::SizeOf() const
-{
-  PRInt64 size = MemoryReporter::GetBasicSize<nsGenericHTMLFrameElement,
-                                              nsGenericHTMLElement>(this);
-  // TODO: need to implement SizeOf() in nsFrameLoader, bug 672539.
-  size += mFrameLoader ? sizeof(*mFrameLoader.get()) : 0;
-  return size;
-}
-
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::GetMozbrowser(bool *aValue)
 {
   return GetBoolAttr(nsGkAtoms::mozbrowser, aValue);
 }
 
 NS_IMETHODIMP
 nsGenericHTMLFrameElement::SetMozbrowser(bool aValue)
--- a/content/html/content/src/nsGenericHTMLFrameElement.h
+++ b/content/html/content/src/nsGenericHTMLFrameElement.h
@@ -29,17 +29,16 @@ public:
   }
 
   virtual ~nsGenericHTMLFrameElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
   NS_DECL_NSIFRAMELOADEROWNER
   NS_DECL_NSIDOMMOZBROWSERFRAME
   NS_DECL_NSIWEBPROGRESSLISTENER
-  NS_DECL_DOM_MEMORY_REPORTER_SIZEOF
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, PRInt32 *aTabIndex);
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true);
--- a/content/html/content/src/nsHTMLAnchorElement.cpp
+++ b/content/html/content/src/nsHTMLAnchorElement.cpp
@@ -92,20 +92,18 @@ public:
   }
   NS_SCRIPTABLE NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML) {
     return nsGenericHTMLElement::SetInnerHTML(aInnerHTML);
   }
 
   // nsIDOMHTMLAnchorElement
   NS_DECL_NSIDOMHTMLANCHORELEMENT  
 
-  // TODO: we do not really count Link::mCachedURI but given that it's a
-  // nsCOMPtr<nsIURI>, that would be required adding SizeOf() to the interface.
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsHTMLAnchorElement,
-                                              nsGenericHTMLElement)
+  // TODO: nsHTMLAnchorElement::SizeOfAnchorElement should call
+  // Link::SizeOfExcludingThis().  See bug 682431.
 
   // nsILink
   NS_IMETHOD LinkAdded() { return NS_OK; }
   NS_IMETHOD LinkRemoved() { return NS_OK; }
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
--- a/content/html/content/src/nsHTMLAreaElement.cpp
+++ b/content/html/content/src/nsHTMLAreaElement.cpp
@@ -56,16 +56,19 @@ class nsHTMLAreaElement : public nsGener
 {
 public:
   nsHTMLAreaElement(already_AddRefed<nsINodeInfo> aNodeInfo);
   virtual ~nsHTMLAreaElement();
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
+  // TODO: nsHTMLAreaElement::SizeOfAnchorElement should call
+  // Link::SizeOfExcludingThis().  See bug 682431.
+
   // nsIDOMNode
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT_BASIC(nsGenericHTMLElement::)
--- a/content/html/content/src/nsHTMLDivElement.cpp
+++ b/content/html/content/src/nsHTMLDivElement.cpp
@@ -64,19 +64,16 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLDivElement
   NS_DECL_NSIDOMHTMLDIVELEMENT
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsHTMLDivElement,
-                                              nsGenericHTMLElement)
-
   virtual bool ParseAttribute(PRInt32 aNamespaceID,
                                 nsIAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
--- a/content/html/content/src/nsHTMLLinkElement.cpp
+++ b/content/html/content/src/nsHTMLLinkElement.cpp
@@ -79,16 +79,19 @@ public:
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLLinkElement
   NS_DECL_NSIDOMHTMLLINKELEMENT
 
+  // TODO: nsHTMLLinkElement::SizeOfAnchorElement should call
+  // Link::SizeOfExcludingThis().  See bug 682431.
+
   // nsILink
   NS_IMETHOD    LinkAdded();
   NS_IMETHOD    LinkRemoved();
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers);
   virtual void UnbindFromTree(bool aDeep = true,
--- a/content/html/content/src/nsHTMLSpanElement.cpp
+++ b/content/html/content/src/nsHTMLSpanElement.cpp
@@ -57,19 +57,16 @@ public:
   NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
 
   // nsIDOMElement
   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
 
   // nsIDOMHTMLElement
   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
 
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsHTMLSpanElement,
-                                              nsGenericHTMLElement)
-
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
 };
 
 
 NS_IMPL_NS_NEW_HTML_ELEMENT(Span)
 
--- a/content/html/document/src/nsHTMLDocument.cpp
+++ b/content/html/document/src/nsHTMLDocument.cpp
@@ -3444,8 +3444,27 @@ nsHTMLDocument::IsEditingOnAfterFlush()
 }
 
 void
 nsHTMLDocument::RemovedFromDocShell()
 {
   mEditingState = eOff;
   nsDocument::RemovedFromDocShell();
 }
+
+/* virtual */ void
+nsHTMLDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
+{
+  nsDocument::DocSizeOfExcludingThis(aWindowSizes);
+
+  // Measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - mImages
+  // - mApplets
+  // - mEmbeds
+  // - mLinks
+  // - mAnchors
+  // - mScripts
+  // - mForms
+  // - mFormControls
+  // - mWyciwygChannel
+  // - mMidasCommandManager
+}
--- a/content/html/document/src/nsHTMLDocument.h
+++ b/content/html/document/src/nsHTMLDocument.h
@@ -199,16 +199,20 @@ public:
   virtual NS_HIDDEN_(void) RemovedFromDocShell();
 
   virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId)
   {
     return nsDocument::GetElementById(aElementId);
   }
 
   virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
+  // DocSizeOfIncludingThis is inherited from nsIDocument.
+
 protected:
   nsresult GetBodySize(PRInt32* aWidth,
                        PRInt32* aHeight);
 
   nsIContent *MatchId(nsIContent *aContent, const nsAString& aId);
 
   static bool MatchLinks(nsIContent *aContent, PRInt32 aNamespaceID,
                            nsIAtom* aAtom, void* aData);
--- a/content/xml/content/src/nsXMLCDATASection.cpp
+++ b/content/xml/content/src/nsXMLCDATASection.cpp
@@ -57,20 +57,16 @@ public:
   NS_FORWARD_NSIDOMNODE(nsGenericDOMDataNode::)
 
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
 
   // nsIDOMText
   NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::)
 
-  // DOM Memory Reporter participant.
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsXMLCDATASection,
-                                              nsGenericDOMDataNode)
-
   // nsIDOMCDATASection
   // Empty interface
 
   // nsINode
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
                                               bool aCloneText) const;
--- a/content/xml/content/src/nsXMLProcessingInstruction.h
+++ b/content/xml/content/src/nsXMLProcessingInstruction.h
@@ -60,20 +60,16 @@ public:
   NS_FORWARD_NSIDOMNODE(nsGenericDOMDataNode::)
 
   // nsIDOMCharacterData
   NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::)
 
   // nsIDOMProcessingInstruction
   NS_DECL_NSIDOMPROCESSINGINSTRUCTION
 
-  // DOM Memory Reporter participant.
-  NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsXMLProcessingInstruction,
-                                              nsGenericDOMDataNode)
-
   // nsINode
   virtual bool IsNodeOfType(PRUint32 aFlags) const;
 
   virtual nsGenericDOMDataNode* CloneDataNode(nsINodeInfo *aNodeInfo,
                                               bool aCloneText) const;
 
 #ifdef DEBUG
   virtual void List(FILE* out, PRInt32 aIndent) const;
--- a/content/xml/document/src/nsXMLDocument.cpp
+++ b/content/xml/document/src/nsXMLDocument.cpp
@@ -590,16 +590,22 @@ nsXMLDocument::EndLoad()
     // document was loaded as pure data without any presentation
     // attached to it.
     nsEvent event(true, NS_LOAD);
     nsEventDispatcher::Dispatch(static_cast<nsIDocument*>(this), nsnull,
                                 &event);
   }    
 }
  
+/* virtual */ void
+nsXMLDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const
+{
+  nsDocument::DocSizeOfExcludingThis(aWindowSizes);
+}
+
 // nsIDOMDocument interface
 
 nsresult
 nsXMLDocument::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
 {
   NS_ASSERTION(aNodeInfo->NodeInfoManager() == mNodeInfoManager,
                "Can't import this document into another document!");
 
--- a/content/xml/document/src/nsXMLDocument.h
+++ b/content/xml/document/src/nsXMLDocument.h
@@ -71,16 +71,20 @@ public:
   // nsIDOMXMLDocument
   NS_DECL_NSIDOMXMLDOCUMENT
 
   virtual nsresult Init();
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   virtual nsXPCClassInfo* GetClassInfo();
+
+  virtual void DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const;
+  // DocSizeOfIncludingThis is inherited from nsIDocument.
+
 protected:
   // mChannelIsPending indicates whether we're currently asynchronously loading
   // data from mChannel (via document.load() or normal load).  It's set to true
   // when we first find out about the channel (StartDocumentLoad) and set to
   // false in EndLoad or if ResetToURI() is called.  In the latter case our
   // mChannel is also cancelled.  Note that if this member is true, mChannel
   // cannot be null.
   bool mChannelIsPending;
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1144,31 +1144,27 @@ Navigator::GetMozBluetooth(nsIDOMBluetoo
     bluetooth = mBluetooth;
   }
 
   bluetooth.forget(aBluetooth);
   return NS_OK;
 }
 #endif //MOZ_B2G_BT
 
-PRInt64
-Navigator::SizeOf() const
+size_t
+Navigator::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 size = sizeof(*this);
+  size_t n = aMallocSizeOf(this);
 
-  // TODO: add SizeOf() to nsMimeTypeArray, bug 674113.
-  size += mMimeTypes ? sizeof(*mMimeTypes.get()) : 0;
-  // TODO: add SizeOf() to nsPluginArray, bug 674114.
-  size += mPlugins ? sizeof(*mPlugins.get()) : 0;
-  // TODO: add SizeOf() to nsGeolocation, bug 674115.
-  size += mGeolocation ? sizeof(*mGeolocation.get()) : 0;
-  // TODO: add SizeOf() to nsDesktopNotificationCenter, bug 674116.
-  size += mNotification ? sizeof(*mNotification.get()) : 0;
+  // TODO: add SizeOfIncludingThis() to nsMimeTypeArray, bug 674113.
+  // TODO: add SizeOfIncludingThis() to nsPluginArray, bug 674114.
+  // TODO: add SizeOfIncludingThis() to nsGeolocation, bug 674115.
+  // TODO: add SizeOfIncludingThis() to nsDesktopNotificationCenter, bug 674116.
 
-  return size;
+  return n;
 }
 
 void
 Navigator::SetWindow(nsPIDOMWindow *aInnerWindow)
 {
   NS_ASSERTION(aInnerWindow->IsInnerWindow(),
                "Navigator must get an inner window!");
   mWindow = do_GetWeakReference(aInnerWindow);
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -131,17 +131,17 @@ public:
 
   void Invalidate();
   nsPIDOMWindow *GetWindow();
 
   void RefreshMIMEArray();
 
   static bool HasDesktopNotificationSupport();
 
-  PRInt64 SizeOf() const;
+  size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   /**
    * For use during document.write where our inner window changes.
    */
   void SetWindow(nsPIDOMWindow *aInnerWindow);
 
 private:
   bool IsSmsAllowed() const;
--- a/dom/base/nsDOMMemoryReporter.cpp
+++ b/dom/base/nsDOMMemoryReporter.cpp
@@ -90,18 +90,17 @@ AppendWindowURI(nsGlobalWindow *aWindow,
 
 struct WindowTotals
 {
   WindowTotals() : mDom(0), mStyleSheets(0) {}
   size_t mDom;
   size_t mStyleSheets;
 };
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WindowStyleSheetsMallocSizeOf,
-                                     "window/style-sheets")
+NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "dom+style")
 
 static void
 CollectWindowReports(nsGlobalWindow *aWindow,
                      WindowTotals *aWindowTotals,
                      nsIMemoryMultiReporterCallback *aCb,
                      nsISupports *aClosure)
 {
   // DOM window objects fall into one of three categories:
@@ -151,18 +150,18 @@ CollectWindowReports(nsGlobalWindow *aWi
   // Which gives us simple counts of how many outer windows (and their
   // combined sizes) per category.
 
   nsCAutoString windowPath("explicit/dom+style/window-objects/");
 
   nsIDocShell *docShell = aWindow->GetDocShell();
 
   nsGlobalWindow *top = aWindow->GetTop();
-  PRInt64 windowDOMSize = aWindow->SizeOf();
-  PRInt64 styleSheetsSize = aWindow->SizeOfStyleSheets(WindowStyleSheetsMallocSizeOf);
+  nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
+  aWindow->SizeOfIncludingThis(&windowSizes);
 
   if (docShell && aWindow->IsFrozen()) {
     windowPath += NS_LITERAL_CSTRING("cached/");
   } else if (docShell) {
     windowPath += NS_LITERAL_CSTRING("active/");
   } else {
     windowPath += NS_LITERAL_CSTRING("other/");
   }
@@ -195,37 +194,37 @@ CollectWindowReports(nsGlobalWindow *aWi
   } else {
     // Combine all outer windows per section (active/cached/other) as
     // they basically never contain anything of interest, and are
     // always pretty much the same size.
 
     windowPath += NS_LITERAL_CSTRING("outer-windows");
   }
 
-  if (windowDOMSize > 0) {
+  if (windowSizes.mDOM > 0) {
     nsCAutoString domPath(windowPath);
     domPath += "/dom";
     NS_NAMED_LITERAL_CSTRING(kWindowDesc,
                              "Memory used by a window and the DOM within it.");
     aCb->Callback(EmptyCString(), domPath, nsIMemoryReporter::KIND_HEAP,
-                  nsIMemoryReporter::UNITS_BYTES, windowDOMSize, kWindowDesc,
-                  aClosure);
-    aWindowTotals->mDom += windowDOMSize;
+                  nsIMemoryReporter::UNITS_BYTES, windowSizes.mDOM,
+                  kWindowDesc, aClosure);
+    aWindowTotals->mDom += windowSizes.mDOM;
   }
 
-  if (styleSheetsSize > 0) {
+  if (windowSizes.mStyleSheets > 0) {
     nsCAutoString styleSheetsPath(windowPath);
     styleSheetsPath += "/style-sheets";
     NS_NAMED_LITERAL_CSTRING(kStyleSheetsDesc,
                              "Memory used by style sheets within a window.");
     aCb->Callback(EmptyCString(), styleSheetsPath,
                   nsIMemoryReporter::KIND_HEAP,
-                  nsIMemoryReporter::UNITS_BYTES, styleSheetsSize,
+                  nsIMemoryReporter::UNITS_BYTES, windowSizes.mStyleSheets,
                   kStyleSheetsDesc, aClosure);
-    aWindowTotals->mStyleSheets += styleSheetsSize;
+    aWindowTotals->mStyleSheets += windowSizes.mStyleSheets;
   }
 }
 
 typedef nsTArray< nsRefPtr<nsGlobalWindow> > WindowArray;
 
 static
 PLDHashOperator
 GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
--- a/dom/base/nsDOMMemoryReporter.h
+++ b/dom/base/nsDOMMemoryReporter.h
@@ -35,50 +35,34 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsDOMMemoryReporter_h__
 #define nsDOMMemoryReporter_h__
 
 #include "nsIMemoryReporter.h"
 
+// This should be used for any nsINode sub-class that has fields of its own
+// that it needs to measure;  any sub-class that doesn't use it will inherit
+// SizeOfExcludingThis from its super-class.  SizeOfIncludingThis() need not be
+// defined, it is inherited from nsINode.
+#define NS_DECL_SIZEOF_EXCLUDING_THIS \
+  virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
-/**
- * Helper methods for the DOM Memory Reporter.
- */
-namespace mozilla {
-  namespace dom {
-    namespace MemoryReporter {
-      /**
-       * It will compute the basic size of an object. This means the size of the
-       * object itself plus everything owned by its superclasses.  This will not
-       * include the size of objects owned by this objects (which have to be
-       * manually added to ::SizeOf), but does include the size of any pointers
-       * to those objects stored in this object.
-       */
-      template <class TypeCurrent, class TypeParent>
-      inline PRInt64 GetBasicSize(const TypeCurrent* const obj) {
-        return obj->TypeParent::SizeOf() - sizeof(TypeParent)
-                                         + sizeof(TypeCurrent);
-      }
-    }
-  }
-}
-
-/**
- * Helper macros to declare/implement SizeOf() method for DOM objects.
- */
-#define NS_DECL_DOM_MEMORY_REPORTER_SIZEOF  \
-  virtual PRInt64 SizeOf() const;
-
-#define NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(TypeCurrent, TypeParent) \
-  virtual PRInt64 SizeOf() const {                                           \
-    return mozilla::dom::MemoryReporter::GetBasicSize<TypeCurrent,           \
-                                                      TypeParent>(this);     \
-  }
+class nsWindowSizes {
+public:
+    nsWindowSizes(nsMallocSizeOfFun aMallocSizeOf)
+    : mMallocSizeOf(aMallocSizeOf),
+      mDOM(0),
+      mStyleSheets(0)
+    {}
+    nsMallocSizeOfFun mMallocSizeOf;
+    size_t mDOM;
+    size_t mStyleSheets;
+};
 
 class nsDOMMemoryMultiReporter: public nsIMemoryMultiReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEMORYMULTIREPORTER
 
   static void Init();
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -10192,45 +10192,36 @@ nsGlobalWindow::HasIndexedDBSupport()
 
 // static
 bool
 nsGlobalWindow::HasPerformanceSupport() 
 {
   return Preferences::GetBool("dom.enable_performance", false);
 }
 
-PRInt64
-nsGlobalWindow::SizeOf() const
-{
-  PRInt64 size = sizeof(*this);
+void
+nsGlobalWindow::SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
+{
+  aWindowSizes->mDOM += aWindowSizes->mMallocSizeOf(this);
 
   if (IsInnerWindow()) {
     nsEventListenerManager* elm =
       const_cast<nsGlobalWindow*>(this)->GetListenerManager(false);
     if (elm) {
-      size += elm->SizeOf();
+      aWindowSizes->mDOM +=
+        elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
     }
     if (mDoc) {
-      size += mDoc->SizeOf();
-    }
-  }
-
-  size += mNavigator ? mNavigator->SizeOf() : 0;
-
-  return size;
-}
-
-size_t
-nsGlobalWindow::SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const
-{
-  size_t n = 0;
-  if (IsInnerWindow() && mDoc) {
-    n += mDoc->SizeOfStyleSheets(aMallocSizeOf);
-  }
-  return n;
+      mDoc->DocSizeOfIncludingThis(aWindowSizes);
+    }
+  }
+
+  aWindowSizes->mDOM +=
+    mNavigator ?
+      mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf) : 0;
 }
 
 // nsGlobalChromeWindow implementation
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
                                                   nsGlobalWindow)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow)
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -137,16 +137,18 @@ class nsRunnable;
 
 class nsDOMOfflineResourceList;
 class nsDOMMozURLProperty;
 
 #ifdef MOZ_DISABLE_DOMCRYPTO
 class nsIDOMCrypto;
 #endif
 
+class nsWindowSizes;
+
 namespace mozilla {
 namespace dom {
 class Navigator;
 } // namespace dom
 } // namespace mozilla
 
 extern nsresult
 NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow,
@@ -571,18 +573,17 @@ public:
   static bool HasIndexedDBSupport();
 
   static bool HasPerformanceSupport();
 
   static WindowByIdTable* GetWindowsTable() {
     return sWindowsById;
   }
 
-  PRInt64 SizeOf() const;
-  size_t SizeOfStyleSheets(nsMallocSizeOfFun aMallocSizeOf) const;
+  void SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const;
 
   void UnmarkGrayTimers();
 private:
   // Enable updates for the accelerometer.
   void EnableDeviceMotionUpdates();
 
   // Disables updates for the accelerometer.
   void DisableDeviceMotionUpdates();
--- a/dom/base/nsIJSEventListener.h
+++ b/dom/base/nsIJSEventListener.h
@@ -94,17 +94,40 @@ public:
     return mHandler;
   }
 
   // Set a handler for this event listener.  Must not be called if
   // there is already a handler!  The handler must already be bound to
   // the right target.
   virtual void SetHandler(JSObject *aHandler) = 0;
 
-  virtual PRInt64 SizeOf() const = 0;
+  // Among the sub-classes that inherit (directly or indirectly) from nsINode,
+  // measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - nsIJSEventListener: mEventName
+  //
+  virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+  {
+    return 0;
+
+    // Measurement of the following members may be added later if DMD finds it
+    // is worthwhile:
+    // - mContext
+    // - mTarget
+    //
+    // The following members are not measured:
+    // - mScopeObject, mHandler: because they're measured by the JS memory
+    //   reporters
+  }
+
+  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+  {
+    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+  }
+
 protected:
   virtual ~nsIJSEventListener()
   {
     NS_ASSERTION(!mTarget, "Should have called Disconnect()!");
   }
   nsCOMPtr<nsIScriptContext> mContext;
   JSObject* mScopeObject;
   nsISupports* mTarget;
--- a/dom/src/events/nsJSEventListener.h
+++ b/dom/src/events/nsJSEventListener.h
@@ -59,19 +59,19 @@ public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMEventListener interface
   NS_DECL_NSIDOMEVENTLISTENER
 
   // nsIJSEventListener
   virtual void SetHandler(JSObject *aHandler);
 
-  virtual PRInt64 SizeOf() const
+  virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
   {
-    return sizeof(*this);
+    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsJSEventListener)
 
 protected:
   bool IsBlackForCC();
 
   nsCOMPtr<nsIAtom> mEventName;
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -534,51 +534,52 @@ nsHTMLStyleSheet::List(FILE* out, PRInt3
   mURL->GetSpec(urlSpec);
   if (!urlSpec.IsEmpty()) {
     fputs(urlSpec.get(), out);
   }
   fputs("\n", out);
 }
 #endif
 
-static
-PLDHashOperator
-GetHashEntryAttributesSize(PLDHashTable* aTable, PLDHashEntryHdr* aEntry,
-                           PRUint32 number, void* aArg)
+static size_t
+SizeOfAttributesEntryExcludingThis(PLDHashEntryHdr* aEntry,
+                                   nsMallocSizeOfFun aMallocSizeOf,
+                                   void* aArg)
 {
   NS_PRECONDITION(aEntry, "The entry should not be null!");
-  NS_PRECONDITION(aArg, "The passed argument should not be null!");
 
   MappedAttrTableEntry* entry = static_cast<MappedAttrTableEntry*>(aEntry);
-  PRInt64 size = *static_cast<PRInt64*>(aArg);
-
   NS_ASSERTION(entry->mAttributes, "entry->mAttributes should not be null!");
-  size += entry->mAttributes->SizeOf();
-
-  return PL_DHASH_NEXT;
+  return entry->mAttributes->SizeOfIncludingThis(aMallocSizeOf);
 }
 
-PRInt64
-nsHTMLStyleSheet::DOMSizeOf() const
+size_t
+nsHTMLStyleSheet::DOMSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
 {
-  PRInt64 size = sizeof(*this);
-
-  size += mLinkRule ? sizeof(*mLinkRule.get()) : 0;
-  size += mVisitedRule ? sizeof(*mVisitedRule.get()) : 0;
-  size += mActiveRule ? sizeof(*mActiveRule.get()) : 0;
-  size += mTableQuirkColorRule ? sizeof(*mTableQuirkColorRule.get()) : 0;
-  size += mTableTHRule ? sizeof(*mTableTHRule.get()) : 0;
+  size_t n = aMallocSizeOf(this);
 
   if (mMappedAttrTable.ops) {
-    size += PL_DHASH_TABLE_SIZE(&mMappedAttrTable) * sizeof(MappedAttrTableEntry);
-    PL_DHashTableEnumerate(const_cast<PLDHashTable*>(&mMappedAttrTable),
-                           GetHashEntryAttributesSize, &size);
+    n += PL_DHashTableSizeOfExcludingThis(&mMappedAttrTable,
+                                          SizeOfAttributesEntryExcludingThis,
+                                          aMallocSizeOf);
   }
 
-  return size;
+  // Measurement of the following members may be added later if DMD finds it is
+  // worthwhile:
+  // - mURL
+  // - mLinkRule
+  // - mVisitedRule
+  // - mActiveRule
+  // - mTableQuirkColorRule
+  // - mTableTHRule
+  //
+  // The following members are not measured:
+  // - mDocument, because it's non-owning
+
+  return n;
 }
 
 // XXX For convenience and backwards compatibility
 nsresult
 NS_NewHTMLStyleSheet(nsHTMLStyleSheet** aInstancePtrResult, nsIURI* aURL, 
                      nsIDocument* aDocument)
 {
   nsresult rv;
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -90,29 +90,29 @@ public:
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData);
   virtual nsRestyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext);
   virtual NS_MUST_OVERRIDE size_t
     SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
   virtual NS_MUST_OVERRIDE size_t
     SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE;
+  size_t DOMSizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
 
   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
   already_AddRefed<nsMappedAttributes>
     UniqueMappedAttributes(nsMappedAttributes* aMapped);
   void DropMappedAttributes(nsMappedAttributes* aMapped);
 
-  PRInt64 DOMSizeOf() const;
 private: 
   nsHTMLStyleSheet(const nsHTMLStyleSheet& aCopy) MOZ_DELETE;
   nsHTMLStyleSheet& operator=(const nsHTMLStyleSheet& aCopy) MOZ_DELETE;
 
   ~nsHTMLStyleSheet();
 
   class HTMLColorRule;
   friend class HTMLColorRule;
--- a/xpcom/glue/nsTObserverArray.h
+++ b/xpcom/glue/nsTObserverArray.h
@@ -240,17 +240,17 @@ class nsAutoTObserverArray : protected n
     // in the array.
     void Clear() {
       mArray.Clear();
       ClearIterators();
     }
 
     // Returns the number of bytes on the heap taken up by this object, not
     // including sizeof(*this).
-    size_t SizeOfExcludingThis(nsMallocSizeOfFun mallocSizeOf) {
+    size_t SizeOfExcludingThis(nsMallocSizeOfFun mallocSizeOf) const {
       return mArray.SizeOfExcludingThis(mallocSizeOf);
     }
 
     //
     // Iterators
     //
 
     // Base class for iterators. Do not use this directly.