Bug 1438497 - Add bindings into memory report. r?bholley,njn draft
authorXidorn Quan <me@upsuper.org>
Fri, 16 Feb 2018 23:02:28 +1100
changeset 756880 69b43fcff05e897f1e5b312f1f0bc9ec40925ff3
parent 756879 60d623f92009c35b7476897eb1ad445b821fb4c7
push id99573
push userxquan@mozilla.com
push dateMon, 19 Feb 2018 04:25:04 +0000
reviewersbholley, njn
bugs1438497
milestone60.0a1
Bug 1438497 - Add bindings into memory report. r?bholley,njn MozReview-Commit-ID: FrFEUlrqcs8
dom/base/nsDocument.cpp
dom/base/nsNodeInfoManager.cpp
dom/base/nsNodeInfoManager.h
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowSizes.h
dom/xbl/nsBindingManager.cpp
dom/xbl/nsBindingManager.h
dom/xbl/nsXBLDocumentInfo.cpp
dom/xbl/nsXBLDocumentInfo.h
dom/xbl/nsXBLPrototypeBinding.cpp
dom/xbl/nsXBLPrototypeBinding.h
dom/xbl/nsXBLPrototypeResources.cpp
dom/xbl/nsXBLPrototypeResources.h
layout/style/ServoBindingList.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -11876,16 +11876,20 @@ nsIDocument::DocAddSizeOfExcludingThis(n
     aSizes.mPropertyTablesSize +=
       mExtraPropertyTables[i]->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
   }
 
   if (EventListenerManager* elm = GetExistingListenerManager()) {
     aSizes.mDOMEventListenersCount += elm->ListenerCount();
   }
 
+  if (mNodeInfoManager) {
+    mNodeInfoManager->AddSizeOfIncludingThis(aSizes);
+  }
+
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - many!
 }
 
 void
 nsIDocument::DocAddSizeOfIncludingThis(nsWindowSizes& aWindowSizes) const
 {
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -24,16 +24,17 @@
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsBindingManager.h"
 #include "nsHashKeys.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsNameSpaceManager.h"
 #include "nsDocument.h"
+#include "nsWindowSizes.h"
 #include "NullPrincipal.h"
 
 using namespace mozilla;
 using mozilla::dom::NodeInfo;
 
 #include "mozilla/Logging.h"
 
 static LazyLogModule gNodeInfoManagerLeakPRLog("NodeInfoManagerLeak");
@@ -499,8 +500,23 @@ nsNodeInfoManager::InternalMathMLEnabled
   // If the mathml.disabled pref. is true, convert all MathML nodes into
   // disabled MathML nodes by swapping the namespace.
   nsNameSpaceManager* nsmgr = nsNameSpaceManager::GetInstance();
   bool conclusion = ((nsmgr && !nsmgr->mMathMLDisabled) ||
                      nsContentUtils::IsSystemPrincipal(mPrincipal));
   mMathMLEnabled = conclusion ? eTriTrue : eTriFalse;
   return conclusion;
 }
+
+void
+nsNodeInfoManager::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const
+{
+  aSizes.mDOMOtherSize += aSizes.mState.mMallocSizeOf(this);
+
+  if (mBindingManager) {
+    aSizes.mBindingsSize +=
+      mBindingManager->SizeOfIncludingThis(aSizes.mState.mMallocSizeOf);
+  }
+
+  // Measurement of the following members may be added later if DMD finds it
+  // is worthwhile:
+  // - mNodeInfoHash
+}
--- a/dom/base/nsNodeInfoManager.h
+++ b/dom/base/nsNodeInfoManager.h
@@ -17,16 +17,17 @@
 #include "nsStringFwd.h"
 #include "plhash.h"                       // for typedef PLHashNumber
 
 class nsBindingManager;
 class nsAtom;
 class nsIDocument;
 class nsIDOMDocumentType;
 class nsIPrincipal;
+class nsWindowSizes;
 struct PLHashEntry;
 struct PLHashTable;
 template<class T> struct already_AddRefed;
 
 namespace mozilla {
 namespace dom {
 class NodeInfo;
 } // namespace dom
@@ -131,16 +132,18 @@ public:
    */
   bool MathMLEnabled()
   {
     return mMathMLEnabled == eTriTrue
              ? true
              : mMathMLEnabled == eTriFalse ? false : InternalMathMLEnabled();
   }
 
+  void AddSizeOfIncludingThis(nsWindowSizes& aSizes) const;
+
 protected:
   friend class nsDocument;
   friend class nsXULPrototypeDocument;
   friend nsresult NS_NewDOMDocumentType(nsIDOMDocumentType** ,
                                         nsNodeInfoManager *,
                                         nsAtom *,
                                         const nsAString& ,
                                         const nsAString& ,
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -426,16 +426,19 @@ CollectWindowReports(nsGlobalWindowInner
               "elements.");
 
   REPORT_SIZE("/layout/computed-values/visited", mLayoutComputedValuesVisited,
               "Memory used by ComputedValues objects used for visited styles.");
 
   REPORT_SIZE("/property-tables", mPropertyTablesSize,
               "Memory used for the property tables within a window.");
 
+  REPORT_SIZE("/bindings", mBindingsSize,
+              "Memory used by bindings within a window.");
+
   REPORT_COUNT("/dom/event-targets", mDOMEventTargetsCount,
                "Number of non-node event targets in the event targets table "
                "in a window's DOM, such as XHRs.");
 
   REPORT_COUNT("/dom/event-listeners", mDOMEventListenersCount,
                "Number of event listeners in a window, including event "
                "listeners on nodes and other event targets.");
 
--- a/dom/base/nsWindowSizes.h
+++ b/dom/base/nsWindowSizes.h
@@ -190,16 +190,17 @@ class nsWindowSizes
   macro(Style, mLayoutServoElementDataObjects) \
   macro(Other, mLayoutTextRunsSize) \
   macro(Other, mLayoutPresContextSize) \
   macro(Other, mLayoutFramePropertiesSize) \
   macro(Style, mLayoutComputedValuesDom) \
   macro(Style, mLayoutComputedValuesNonDom) \
   macro(Style, mLayoutComputedValuesVisited) \
   macro(Other, mPropertyTablesSize) \
+  macro(Other, mBindingsSize) \
 
 public:
   explicit nsWindowSizes(mozilla::SizeOfState& aState)
     :
       FOR_EACH_SIZE(ZERO_SIZE)
       mDOMEventTargetsCount(0),
       mDOMEventListenersCount(0),
       mArenaSizes(),
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -1109,8 +1109,32 @@ nsBindingManager::FindNestedSingleInsert
     if (newParent == parent) {
       break;
     }
     parent = newParent;
   }
 
   return parent;
 }
+
+size_t
+nsBindingManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+
+#define SHALLOW_SIZE_INCLUDING(field_) \
+  n += field_ ? field_->ShallowSizeOfIncludingThis(aMallocSizeOf) : 0;
+  SHALLOW_SIZE_INCLUDING(mBoundContentSet);
+  SHALLOW_SIZE_INCLUDING(mWrapperTable);
+  SHALLOW_SIZE_INCLUDING(mLoadingDocTable);
+#undef SHALLOW_SIZE_INCLUDING
+  n += mAttachedStack.ShallowSizeOfExcludingThis(aMallocSizeOf);
+
+  if (mDocumentTable) {
+    n += mDocumentTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
+    for (auto iter = mDocumentTable->Iter(); !iter.Done(); iter.Next()) {
+      nsXBLDocumentInfo* docInfo = iter.UserData();
+      n += docInfo->SizeOfIncludingThis(aMallocSizeOf);
+    }
+  }
+
+  return n;
+}
--- a/dom/xbl/nsBindingManager.h
+++ b/dom/xbl/nsBindingManager.h
@@ -14,16 +14,17 @@
 #include "nsInterfaceHashtable.h"
 #include "nsRefPtrHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsXBLBinding.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
 #include "mozilla/MediaFeatureChange.h"
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/EventStates.h"
 
 struct ElementDependentRuleProcessorData;
 class nsIXPConnectWrappedJS;
 class nsAtom;
 class nsIDOMNodeList;
 class nsIDocument;
@@ -168,16 +169,18 @@ public:
   // points and their insertion parents.
   void ClearInsertionPointsRecursively(nsIContent* aContent);
 
   // Called when the document is going away
   void DropDocumentReference();
 
   nsIContent* FindNestedSingleInsertionPoint(nsIContent* aContainer, bool* aMulti);
 
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
   // Enumerate each bound content's bindings (including its base bindings)
   // in mBoundContentSet. Return false from the callback to stop enumeration.
   using BoundContentBindingCallback = std::function<bool (nsXBLBinding*)>;
   bool EnumerateBoundContentBindings(
     const BoundContentBindingCallback& aCallback) const;
 
 protected:
   nsIXPConnectWrappedJS* GetWrappedJS(nsIContent* aContent);
--- a/dom/xbl/nsXBLDocumentInfo.cpp
+++ b/dom/xbl/nsXBLDocumentInfo.cpp
@@ -320,8 +320,22 @@ nsXBLDocumentInfo::FlushSkinStylesheets(
 #ifdef DEBUG
 void
 AssertInCompilationScope()
 {
   AutoJSContext cx;
   MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx));
 }
 #endif
+
+size_t
+nsXBLDocumentInfo::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+  if (mBindingTable) {
+    n += mBindingTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
+    for (auto iter = mBindingTable->Iter(); !iter.Done(); iter.Next()) {
+      nsXBLPrototypeBinding* binding = iter.UserData();
+      n += binding->SizeOfIncludingThis(aMallocSizeOf);
+    }
+  }
+  return n;
+}
--- a/dom/xbl/nsXBLDocumentInfo.h
+++ b/dom/xbl/nsXBLDocumentInfo.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXBLDocumentInfo_h__
 #define nsXBLDocumentInfo_h__
 
 #include "mozilla/Attributes.h"
+#include "mozilla/MemoryReporting.h"
 #include "nsCOMPtr.h"
 #include "nsAutoPtr.h"
 #include "nsWeakReference.h"
 #include "nsIDocument.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsXBLPrototypeBinding;
 
@@ -44,16 +45,18 @@ public:
 
   bool IsChrome() { return mIsChrome; }
 
   void MarkInCCGeneration(uint32_t aGeneration);
 
   static nsresult ReadPrototypeBindings(nsIURI* aURI, nsXBLDocumentInfo** aDocInfo,
                                         nsIDocument* aBoundDocument);
 
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsXBLDocumentInfo)
 
 private:
   virtual ~nsXBLDocumentInfo();
 
   nsCOMPtr<nsIDocument> mDocument;
   bool mScriptAccess;
   bool mIsChrome;
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -77,27 +77,41 @@ public:
 
   nsAtom* GetSrcAttribute() { return mSrcAttribute; }
   nsAtom* GetDstAttribute() { return mDstAttribute; }
   int32_t GetDstNameSpace() { return mDstNameSpace; }
 
   Element* GetElement() { return mElement; }
 
   nsXBLAttributeEntry* GetNext() { return mNext; }
+  const nsXBLAttributeEntry* GetNext() const { return mNext; }
   void SetNext(nsXBLAttributeEntry* aEntry) { mNext = aEntry; }
 
+  size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
+
 protected:
   Element* mElement;
 
   RefPtr<nsAtom> mSrcAttribute;
   RefPtr<nsAtom> mDstAttribute;
   int32_t mDstNameSpace;
   nsXBLAttributeEntry* mNext;
 };
 
+size_t
+nsXBLAttributeEntry::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = 0;
+  for (const nsXBLAttributeEntry* entry = this;
+       entry; entry = entry->GetNext()) {
+    n += aMallocSizeOf(entry);
+  }
+  return n;
+}
+
 // =============================================================================
 
 // Implementation /////////////////////////////////////////////////////////////////
 
 // Constructors/Destructors
 nsXBLPrototypeBinding::nsXBLPrototypeBinding()
 : mImplementation(nullptr),
   mBaseBinding(nullptr),
@@ -1693,8 +1707,39 @@ nsXBLPrototypeBinding::HasStyleSheets() 
 void
 nsXBLPrototypeBinding::AppendStyleSheetsTo(
                                       nsTArray<StyleSheet*>& aResult) const
 {
   if (mResources) {
     mResources->AppendStyleSheetsTo(aResult);
   }
 }
+
+size_t
+nsXBLPrototypeBinding::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+  n += mResources ? mResources->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+  if (mAttributeTable) {
+    n += mAttributeTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
+    for (auto iter = mAttributeTable->Iter(); !iter.Done(); iter.Next()) {
+      InnerAttributeTable* table = iter.UserData();
+      n += table->ShallowSizeOfIncludingThis(aMallocSizeOf);
+      for (auto iter2 = table->Iter(); !iter2.Done(); iter2.Next()) {
+        n += iter2.UserData()->SizeOfIncludingThis(aMallocSizeOf);
+      }
+    }
+  }
+
+  n += mInterfaceTable.ShallowSizeOfExcludingThis(aMallocSizeOf);
+  n += mKeyHandlers.ShallowSizeOfExcludingThis(aMallocSizeOf);
+
+  // Measurement of the following members may be added later if DMD finds it
+  // is worthwhile:
+  // - mBindingURI
+  // - mAlternateBindingURI
+  // - mPrototypeHandler
+  // - mBaseBindingURI
+  // - mImplementation
+
+  return n;
+}
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -14,16 +14,17 @@
 #include "nsICSSLoaderObserver.h"
 #include "nsInterfaceHashtable.h"
 #include "nsWeakReference.h"
 #include "nsXBLDocumentInfo.h"
 #include "nsXBLProtoImpl.h"
 #include "nsXBLProtoImplMethod.h"
 #include "nsXBLPrototypeHandler.h"
 #include "nsXBLPrototypeResources.h"
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/StyleSheet.h"
 
 class nsAtom;
 class nsIContent;
 class nsIDocument;
 class nsXBLAttributeEntry;
 class nsXBLBinding;
@@ -265,16 +266,18 @@ public:
                 nsXBLDocumentInfo* aInfo,
                 mozilla::dom::Element* aElement,
                 bool aFirstBinding = false);
 
   void Traverse(nsCycleCollectionTraversalCallback &cb) const;
   void Unlink();
   void Trace(const TraceCallbacks& aCallbacks, void *aClosure) const;
 
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
 // Internal member functions.
 public:
   /**
    * GetImmediateChild locates the immediate child of our binding element which
    * has the localname given by aTag and is in the XBL namespace.
    */
   mozilla::dom::Element* GetImmediateChild(nsAtom* aTag);
   mozilla::dom::Element* LocateInstance(mozilla::dom::Element* aBoundElt,
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -231,8 +231,32 @@ nsXBLPrototypeResources::InsertStyleShee
 }
 
 void
 nsXBLPrototypeResources::AppendStyleSheetsTo(
                                       nsTArray<StyleSheet*>& aResult) const
 {
   aResult.AppendElements(mStyleSheetList);
 }
+
+MOZ_DEFINE_MALLOC_SIZE_OF(ServoAuthorStylesMallocSizeOf)
+MOZ_DEFINE_MALLOC_ENCLOSING_SIZE_OF(ServoAuthorStylesMallocEnclosingSizeOf)
+
+size_t
+nsXBLPrototypeResources::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
+{
+  size_t n = aMallocSizeOf(this);
+  n += mStyleSheetList.ShallowSizeOfExcludingThis(aMallocSizeOf);
+#ifdef MOZ_OLD_STYLE
+  n += mRuleProcessor ? mRuleProcessor->SizeOfIncludingThis(aMallocSizeOf) : 0;
+#endif
+  n += mServoStyles ? Servo_AuthorStyles_SizeOfIncludingThis(
+      ServoAuthorStylesMallocSizeOf,
+      ServoAuthorStylesMallocEnclosingSizeOf,
+      mServoStyles.get()) : 0;
+  n += mStyleRuleMap ? mStyleRuleMap->SizeOfIncludingThis(aMallocSizeOf) : 0;
+
+  // Measurement of the following members may be added later if DMD finds it
+  // is worthwhile:
+  // - mLoader
+
+  return n;
+}
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -2,16 +2,17 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsXBLPrototypeResources_h__
 #define nsXBLPrototypeResources_h__
 
+#include "mozilla/MemoryReporting.h"
 #include "mozilla/StyleSheet.h"
 #include "mozilla/ServoStyleRuleMap.h"
 #include "nsICSSLoaderObserver.h"
 
 class nsCSSRuleProcessor;
 class nsAtom;
 class nsIContent;
 class nsXBLPrototypeBinding;
@@ -84,16 +85,18 @@ public:
 
   mozilla::ServoStyleRuleMap* GetServoStyleRuleMap();
 
   // Updates the ServoStyleSet object that holds the result of cascading the
   // sheets in mStyleSheetList. Equivalent to GatherRuleProcessor(), but for
   // the Servo style backend.
   void ComputeServoStyles(const mozilla::ServoStyleSet& aMasterStyleSet);
 
+  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
+
 private:
   // A loader object. Exists only long enough to load resources, and then it dies.
   RefPtr<nsXBLResourceLoader> mLoader;
 
   // A list of loaded stylesheets for this binding.
   //
   // FIXME(emilio): Remove when the old style system is gone, defer to
   // mServoStyles.
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -187,16 +187,20 @@ SERVO_BINDING_FUNC(Servo_AuthorStyles_Ap
                    const mozilla::ServoStyleSheet* gecko_sheet)
 SERVO_BINDING_FUNC(Servo_AuthorStyles_ForceDirty, void,
                    RawServoAuthorStylesBorrowedMut self)
 // TODO(emilio): This will need to take an element to implement invalidation for
 // Shadow DOM.
 SERVO_BINDING_FUNC(Servo_AuthorStyles_Flush, void,
                    RawServoAuthorStylesBorrowedMut self,
                    RawServoStyleSetBorrowed document_styles)
+SERVO_BINDING_FUNC(Servo_AuthorStyles_SizeOfIncludingThis, size_t,
+                   mozilla::MallocSizeOf malloc_size_of,
+                   mozilla::MallocSizeOf malloc_enclosing_size_of,
+                   RawServoAuthorStylesBorrowed self)
 
 SERVO_BINDING_FUNC(Servo_StyleContext_AddRef, void, ServoStyleContextBorrowed ctx);
 SERVO_BINDING_FUNC(Servo_StyleContext_Release, void, ServoStyleContextBorrowed ctx);
 
 SERVO_BINDING_FUNC(Servo_StyleSet_MightHaveAttributeDependency, bool,
                    RawServoStyleSetBorrowed set,
                    RawGeckoElementBorrowed element,
                    nsAtom* local_name)