Bug 1438497 part 3 - Add XUL prototype cache to memory report. r=njn
MozReview-Commit-ID: 7CSEJKFkm7B
--- 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;