Bug 1438497 part 3 - Add XUL prototype cache to memory report. r=njn draft
authorXidorn Quan <me@upsuper.org>
Mon, 19 Feb 2018 21:07:44 +1100
changeset 757116 fe10ebd0d3b5538565e6e9692feb1cb993ef01a8
parent 757115 e696671d18970d710f6bfbca60c6014c51df9440
child 757173 02a8650e9375d615efbf8eeb7f70ba7c362e3d98
push id99670
push userxquan@mozilla.com
push dateTue, 20 Feb 2018 00:01:10 +0000
reviewersnjn
bugs1438497
milestone60.0a1
Bug 1438497 part 3 - Add XUL prototype cache to memory report. r=njn MozReview-Commit-ID: 7CSEJKFkm7B
dom/base/nsWindowMemoryReporter.cpp
dom/xul/nsXULPrototypeCache.cpp
dom/xul/nsXULPrototypeCache.h
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -15,16 +15,19 @@
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsNetCID.h"
 #include "nsPrintfCString.h"
 #include "XPCJSMemoryReporter.h"
 #include "js/MemoryMetrics.h"
 #include "nsQueryObject.h"
 #include "nsServiceManagerUtils.h"
+#ifdef MOZ_XUL
+#include "nsXULPrototypeCache.h"
+#endif
 
 using namespace mozilla;
 
 StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
 
 /**
  * Don't trigger a ghost window check when a DOM window is detached if we've
  * run it this recently.
@@ -625,16 +628,20 @@ nsWindowMemoryReporter::CollectReports(n
                          aData, aAnonymize);
   }
 
   // Report JS memory usage.  We do this from here because the JS memory
   // reporter needs to be passed |windowPaths|.
   xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
                                   aHandleReport, aData, aAnonymize);
 
+#ifdef MOZ_XUL
+  nsXULPrototypeCache::CollectMemoryReports(aHandleReport, aData);
+#endif
+
 #define REPORT(_path, _amount, _desc) \
   aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
                           KIND_OTHER, UNITS_BYTES, _amount, \
                           NS_LITERAL_CSTRING(_desc), aData);
 
   REPORT("window-objects/dom/element-nodes",
          windowTotalSizes.mDOMElementNodesSize,
          "This is the sum of all windows' 'dom/element-nodes' numbers.");
--- a/dom/xul/nsXULPrototypeCache.cpp
+++ b/dom/xul/nsXULPrototypeCache.cpp
@@ -7,16 +7,17 @@
 #include "nsXULPrototypeCache.h"
 
 #include "plstr.h"
 #include "nsXULPrototypeDocument.h"
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 
 #include "nsIFile.h"
+#include "nsIMemoryReporter.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 #include "nsIObserverService.h"
 #include "nsIStringStream.h"
 #include "nsIStorageStream.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 
@@ -627,8 +628,92 @@ nsXULPrototypeCache::MarkInCCGeneration(
 void
 nsXULPrototypeCache::MarkInGC(JSTracer* aTrc)
 {
     for (auto iter = mScriptTable.Iter(); !iter.Done(); iter.Next()) {
         JS::Heap<JSScript*>& script = iter.Data();
         JS::TraceEdge(aTrc, &script, "nsXULPrototypeCache script");
     }
 }
+
+MOZ_DEFINE_MALLOC_SIZE_OF(CacheMallocSizeOf)
+
+static void
+ReportSize(const nsCString& aPath, size_t aAmount,
+           const nsCString& aDescription,
+           nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+{
+  nsAutoCString path("explicit/xul-prototype-cache/");
+  path += aPath;
+  aHandleReport->Callback(EmptyCString(), path,
+                          nsIMemoryReporter::KIND_HEAP,
+                          nsIMemoryReporter::UNITS_BYTES,
+                          aAmount, aDescription, aData);
+}
+
+static void
+AppendURIForMemoryReport(nsIURI* aUri, nsACString& aOutput)
+{
+  nsCString spec = aUri->GetSpecOrDefault();
+  // A hack: replace forward slashes with '\\' so they aren't
+  // treated as path separators.  Users of the reporters
+  // (such as about:memory) have to undo this change.
+  spec.ReplaceChar('/', '\\');
+  aOutput += spec;
+}
+
+/* static */ void
+nsXULPrototypeCache::CollectMemoryReports(
+  nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+{
+  if (!sInstance) {
+    return;
+  }
+
+  MallocSizeOf mallocSizeOf = CacheMallocSizeOf;
+  size_t other = mallocSizeOf(sInstance);
+
+#define REPORT_SIZE(_path, _amount, _desc) \
+  ReportSize(_path, _amount, NS_LITERAL_CSTRING(_desc), aHandleReport, aData)
+
+  other += sInstance->
+    mPrototypeTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+  // TODO Report content in mPrototypeTable?
+
+  other += sInstance->
+    mGeckoStyleSheetTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+  // TODO Report content inside mGeckoStyleSheetTable?
+  other += sInstance->
+    mServoStyleSheetTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+  // TODO Report content inside mServoStyleSheetTable?
+
+  other += sInstance->
+    mScriptTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+  // TODO Report content inside mScriptTable?
+
+  auto reportXBLDocTable =
+    [&](const nsACString& prefix, const XBLDocTable& table) {
+      other += table.ShallowSizeOfExcludingThis(mallocSizeOf);
+      for (auto iter = table.ConstIter(); !iter.Done(); iter.Next()) {
+        nsAutoCString path(prefix);
+        path += "-xbl-docs/(";
+        AppendURIForMemoryReport(iter.Key(), path);
+        path += ")";
+        size_t size = iter.UserData()->SizeOfIncludingThis(mallocSizeOf);
+        REPORT_SIZE(path, size, "Memory used by this XBL document.");
+      }
+    };
+  reportXBLDocTable(NS_LITERAL_CSTRING("gecko"), sInstance->mGeckoXBLDocTable);
+  reportXBLDocTable(NS_LITERAL_CSTRING("servo"), sInstance->mServoXBLDocTable);
+
+  other += sInstance->
+    mStartupCacheURITable.ShallowSizeOfExcludingThis(mallocSizeOf);
+
+  other += sInstance->
+    mOutputStreamTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+  other += sInstance->
+    mInputStreamTable.ShallowSizeOfExcludingThis(mallocSizeOf);
+
+  REPORT_SIZE(NS_LITERAL_CSTRING("other"), other, "Memory used by "
+              "the instance and tables of the XUL prototype cache.");
+
+#undef REPORT_SIZE
+}
--- a/dom/xul/nsXULPrototypeCache.h
+++ b/dom/xul/nsXULPrototypeCache.h
@@ -14,16 +14,17 @@
 #include "nsRefPtrHashtable.h"
 #include "nsURIHashKey.h"
 #include "nsXULPrototypeDocument.h"
 #include "nsIInputStream.h"
 #include "nsIStorageStream.h"
 
 #include "mozilla/scache/StartupCache.h"
 
+class nsIHandleReportCallback;
 namespace mozilla {
 class StyleSheet;
 } // namespace mozilla
 
 /**
  * The XUL prototype cache can be used to store and retrieve shared data for
  * XUL documents, style sheets, XBL, and scripts.
  *
@@ -106,16 +107,20 @@ public:
     static void ReleaseGlobals()
     {
         NS_IF_RELEASE(sInstance);
     }
 
     void MarkInCCGeneration(uint32_t aGeneration);
     void MarkInGC(JSTracer* aTrc);
     void FlushScripts();
+
+    static void CollectMemoryReports(nsIHandleReportCallback* aHandleReport,
+                                     nsISupports* aData);
+
 protected:
     friend nsresult
     NS_NewXULPrototypeCache(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
     nsXULPrototypeCache();
     virtual ~nsXULPrototypeCache();
 
     static nsXULPrototypeCache* sInstance;