diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 376420990f1b..451cfe23c116 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -9149,6 +9149,13 @@ nsIDocument::DocSizeOfExcludingThis(nsWindowSizes* aWindowSizes) const aWindowSizes->mDOM += nsINode::SizeOfExcludingThis(aWindowSizes->mMallocSizeOf); + if (mPresShell) { + mPresShell->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf, + &aWindowSizes->mLayoutArenas, + &aWindowSizes->mLayoutStyleSets, + &aWindowSizes->mLayoutTextRuns); + } + // Measurement of the following members may be added later if DMD finds it // is worthwhile: // - many! diff --git a/dom/base/nsDOMMemoryReporter.cpp b/dom/base/nsDOMMemoryReporter.cpp index 1afd158faf53..2b2f0cccdd59 100644 --- a/dom/base/nsDOMMemoryReporter.cpp +++ b/dom/base/nsDOMMemoryReporter.cpp @@ -88,18 +88,11 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr) return true; } -struct WindowTotals -{ - WindowTotals() : mDom(0), mStyleSheets(0) {} - size_t mDom; - size_t mStyleSheets; -}; - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "dom+style") +NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows") static void CollectWindowReports(nsGlobalWindow *aWindow, - WindowTotals *aWindowTotals, + nsWindowSizes *aWindowTotalSizes, nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure) { @@ -126,7 +119,7 @@ CollectWindowReports(nsGlobalWindow *aWindow, // The path we give to the reporter callback for inner windows are // as follows: // - // explicit/dom+style/window-objects//top= (inner=)/inner-window(id=, uri=) + // explicit/window-objects//top= (inner=)/inner-window(id=, uri=) // // Where: // - is active, cached, or other, as described above. @@ -145,12 +138,12 @@ CollectWindowReports(nsGlobalWindow *aWindow, // // For outer windows we simply use: // - // explicit/dom+style/window-objects//outer-windows + // explicit/window-objects//outer-windows // // Which gives us simple counts of how many outer windows (and their // combined sizes) per category. - nsCAutoString windowPath("explicit/dom+style/window-objects/"); + nsCAutoString windowPath("explicit/window-objects/"); nsIDocShell *docShell = aWindow->GetDocShell(); @@ -199,28 +192,40 @@ CollectWindowReports(nsGlobalWindow *aWindow, windowPath += NS_LITERAL_CSTRING("outer-windows"); } - 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, windowSizes.mDOM, - kWindowDesc, aClosure); - aWindowTotals->mDom += windowSizes.mDOM; - } +#define REPORT(_path1, _path2, _amount, _desc) \ + do { \ + if (_amount > 0) { \ + nsCAutoString path(_path1); \ + path += _path2; \ + aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + } \ + } while (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, windowSizes.mStyleSheets, - kStyleSheetsDesc, aClosure); - aWindowTotals->mStyleSheets += windowSizes.mStyleSheets; - } + REPORT(windowPath, "/dom", windowSizes.mDOM, + "Memory used by a window and the DOM within it."); + aWindowTotalSizes->mDOM += windowSizes.mDOM; + + REPORT(windowPath, "/style-sheets", windowSizes.mStyleSheets, + "Memory used by style sheets within a window."); + aWindowTotalSizes->mStyleSheets += windowSizes.mStyleSheets; + + REPORT(windowPath, "/layout/arenas", windowSizes.mLayoutArenas, + "Memory used by layout PresShell, PresContext, and other related " + "areas within a window."); + aWindowTotalSizes->mLayoutArenas += windowSizes.mLayoutArenas; + + REPORT(windowPath, "/layout/style-sets", windowSizes.mLayoutStyleSets, + "Memory used by style sets within a window."); + aWindowTotalSizes->mLayoutStyleSets += windowSizes.mLayoutStyleSets; + + REPORT(windowPath, "/layout/text-runs", windowSizes.mLayoutTextRuns, + "Memory used for text-runs (glyph layout) in the PresShell's frame " + "tree, within a window."); + aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns; + +#undef REPORT } typedef nsTArray< nsRefPtr > WindowArray; @@ -237,7 +242,7 @@ GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure) NS_IMETHODIMP nsDOMMemoryMultiReporter::GetName(nsACString &aName) { - aName.AssignLiteral("dom+style"); + aName.AssignLiteral("window-objects"); return NS_OK; } @@ -257,27 +262,42 @@ nsDOMMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, // Collect window memory usage. nsRefPtr *w = windows.Elements(); nsRefPtr *end = w + windows.Length(); - WindowTotals windowTotals; + nsWindowSizes windowTotalSizes(NULL); for (; w != end; ++w) { - CollectWindowReports(*w, &windowTotals, aCb, aClosure); + CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure); } - NS_NAMED_LITERAL_CSTRING(kDomTotalWindowsDesc, - "Memory used for the DOM within windows. This is the sum of all windows' " - "'dom' numbers."); - aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("dom-total-window"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, windowTotals.mDom, - kDomTotalWindowsDesc, aClosure); +#define REPORT(_path, _amount, _desc) \ + do { \ + aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_OTHER, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + } while (0) - NS_NAMED_LITERAL_CSTRING(kLayoutTotalWindowStyleSheetsDesc, - "Memory used for style sheets within windows. This is the sum of all windows' " - "'style-sheets' numbers."); - aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING("style-sheets-total-window"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, windowTotals.mStyleSheets, - kLayoutTotalWindowStyleSheetsDesc, aClosure); + REPORT("window-objects-dom", windowTotalSizes.mDOM, + "Memory used for the DOM within windows. " + "This is the sum of all windows' 'dom' numbers."); + + REPORT("window-objects-style-sheets", windowTotalSizes.mStyleSheets, + "Memory used for style sheets within windows. " + "This is the sum of all windows' 'style-sheets' numbers."); + + REPORT("window-objects-layout-arenas", windowTotalSizes.mLayoutArenas, + "Memory used by layout PresShell, PresContext, and other related " + "areas within windows. This is the sum of all windows' " + "'layout/arenas' numbers."); + + REPORT("window-objects-layout-style-sets", windowTotalSizes.mLayoutStyleSets, + "Memory used for style sets within windows. " + "This is the sum of all windows' 'layout/style-sets' numbers."); + + REPORT("window-objects-layout-text-runs", windowTotalSizes.mLayoutTextRuns, + "Memory used for text runs within windows. " + "This is the sum of all windows' 'layout/text-runs' numbers."); +#undef REPORT + return NS_OK; } diff --git a/dom/base/nsDOMMemoryReporter.h b/dom/base/nsDOMMemoryReporter.h index 8ffed5515c42..e266e8ae0b37 100644 --- a/dom/base/nsDOMMemoryReporter.h +++ b/dom/base/nsDOMMemoryReporter.h @@ -49,14 +49,16 @@ class nsWindowSizes { public: - nsWindowSizes(nsMallocSizeOfFun aMallocSizeOf) - : mMallocSizeOf(aMallocSizeOf), - mDOM(0), - mStyleSheets(0) - {} + nsWindowSizes(nsMallocSizeOfFun aMallocSizeOf) { + memset(this, 0, sizeof(nsWindowSizes)); + mMallocSizeOf = aMallocSizeOf; + } nsMallocSizeOfFun mMallocSizeOf; size_t mDOM; size_t mStyleSheets; + size_t mLayoutArenas; + size_t mLayoutStyleSets; + size_t mLayoutTextRuns; }; class nsDOMMemoryMultiReporter: public nsIMemoryMultiReporter diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 61b2f8c3250d..c1e83efee4b7 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -144,8 +144,8 @@ typedef struct CapturingContentInfo { } CapturingContentInfo; #define NS_IPRESSHELL_IID \ - { 0x87719fd6, 0xe50c, 0x4d72, \ - { 0xbd, 0x55, 0x05, 0xf9, 0x5f, 0x33, 0x9e, 0xf2 } } + { 0x4dc4db09, 0x03d4, 0x4427, \ + { 0xbe, 0xfb, 0xc9, 0x29, 0xac, 0x5c, 0x62, 0xab } } // Constants for ScrollContentIntoView() function #define NS_PRESSHELL_SCROLL_TOP 0 @@ -1176,6 +1176,11 @@ public: virtual bool IsVisible() = 0; virtual void DispatchSynthMouseMove(nsGUIEvent *aEvent, bool aFlushOnHoverChange) = 0; + virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + size_t *aArenasSize, + size_t *aStyleSetsSize, + size_t *aTextRunsSize) const = 0; + /** * Refresh observer management. */ @@ -1283,10 +1288,6 @@ protected: float mXResolution; float mYResolution; - // Live pres shells, for memory and other tracking - typedef nsPtrHashKey PresShellPtrKey; - static nsTHashtable *sLiveShells; - static nsIContent* gKeyDownTarget; }; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index c45502efd854..e5724c138942 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -201,9 +201,6 @@ #include "imgIEncoder.h" #include "gfxPlatform.h" -/* for NS_MEMORY_REPORTER_IMPLEMENT */ -#include "nsIMemoryReporter.h" - #include "mozilla/FunctionTimer.h" #include "mozilla/Preferences.h" #include "mozilla/Telemetry.h" @@ -608,113 +605,6 @@ struct nsCallbackEventRequest GetPresContext()->RefreshDriver()-> \ IsLayoutFlushObserver(this), "Unexpected state") -NS_IMPL_ISUPPORTS1(PresShell::MemoryReporter, nsIMemoryMultiReporter) - -namespace { - -struct MemoryReporterData -{ - nsIMemoryMultiReporterCallback* callback; - nsISupports* closure; -}; - -} // anonymous namespace - -NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(LayoutMallocSizeOf, "layout") - -/* static */ PLDHashOperator -PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry, - void *userArg) -{ - PresShell *aShell = static_cast(aEntry->GetKey()); - MemoryReporterData *data = (MemoryReporterData*)userArg; - - // Build the string "explicit/layout/shell()" - nsCAutoString str("explicit/layout/shell("); - - nsIDocument* doc = aShell->GetDocument(); - if (doc) { - nsIURI* docURI = doc->GetDocumentURI(); - - if (docURI) { - nsCString spec; - docURI->GetSpec(spec); - - // 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('/', '\\'); - - str += spec; - } - } - - str += NS_LITERAL_CSTRING(")"); - - NS_NAMED_LITERAL_CSTRING(kArenaDesc, "Memory used by layout PresShell, PresContext, and other related areas."); - NS_NAMED_LITERAL_CSTRING(kStyleDesc, "Memory used by the style system."); - NS_NAMED_LITERAL_CSTRING(kTextRunsDesc, "Memory used for text-runs (glyph layout) in the PresShell's frame tree."); - - nsCAutoString arenaPath = str + NS_LITERAL_CSTRING("/arenas"); - nsCAutoString stylePath = str + NS_LITERAL_CSTRING("/styledata"); - nsCAutoString textRunsPath = str + NS_LITERAL_CSTRING("/textruns"); - - PRInt64 arenasSize = - aShell->SizeOfIncludingThis(LayoutMallocSizeOf) + - aShell->mPresContext->SizeOfIncludingThis(LayoutMallocSizeOf); - - PRInt64 styleSize = - aShell->StyleSet()->SizeOfIncludingThis(LayoutMallocSizeOf); - - PRInt64 textRunsSize = aShell->SizeOfTextRuns(LayoutMallocSizeOf); - - data->callback-> - Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, arenasSize, kArenaDesc, - data->closure); - - data->callback-> - Callback(EmptyCString(), stylePath, nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, styleSize, kStyleDesc, - data->closure); - - if (textRunsSize) { - data->callback-> - Callback(EmptyCString(), textRunsPath, nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, textRunsSize, kTextRunsDesc, - data->closure); - } - - return PL_DHASH_NEXT; -} - -NS_IMETHODIMP -PresShell::MemoryReporter::GetName(nsACString &aName) -{ - aName.AssignLiteral("layout"); - return NS_OK; -} - -NS_IMETHODIMP -PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, - nsISupports* aClosure) -{ - MemoryReporterData data; - data.callback = aCb; - data.closure = aClosure; - - sLiveShells->EnumerateEntries(SizeEnumerator, &data); - - return NS_OK; -} - -NS_IMETHODIMP -PresShell::MemoryReporter::GetExplicitNonHeap(PRInt64 *aAmount) { - // This reporter doesn't do any KIND_NONHEAP measurements. - *aAmount = 0; - return NS_OK; -} - class nsAutoCauseReflowNotifier { public: @@ -915,7 +805,6 @@ NS_NewPresShell(nsIPresShell** aInstancePtrResult) return NS_OK; } -nsTHashtable *nsIPresShell::sLiveShells = 0; static bool sSynthMouseMove = true; PresShell::PresShell() @@ -943,15 +832,12 @@ PresShell::PresShell() mYResolution = 1.0; mViewportOverridden = false; - static bool registeredReporter = false; - if (!registeredReporter) { - NS_RegisterMemoryMultiReporter(new MemoryReporter); + static bool addedSynthMouseMove = false; + if (!addedSynthMouseMove) { Preferences::AddBoolVarCache(&sSynthMouseMove, "layout.reflow.synthMouseMove", true); - registeredReporter = true; + addedSynthMouseMove = true; } - - sLiveShells->PutEntry(this); } NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver, @@ -961,8 +847,6 @@ NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver, PresShell::~PresShell() { - sLiveShells->RemoveEntry(this); - if (!mHaveShutDown) { NS_NOTREACHED("Someone did not call nsIPresShell::destroy"); Destroy(); @@ -9085,19 +8969,18 @@ nsIPresShell::AccService() } #endif +static bool inited = false; + void nsIPresShell::InitializeStatics() { - NS_ASSERTION(sLiveShells == nsnull, "InitializeStatics called multiple times!"); - sLiveShells = new nsTHashtable(); - sLiveShells->Init(); + NS_ASSERTION(!inited, "InitializeStatics called multiple times!"); gCaptureTouchList.Init(); + inited = true; } void nsIPresShell::ReleaseStatics() { - NS_ASSERTION(sLiveShells, "ReleaseStatics called without Initialize!"); - delete sLiveShells; - sLiveShells = nsnull; + NS_ASSERTION(inited, "ReleaseStatics called without Initialize!"); } // Asks our docshell whether we're active. @@ -9203,8 +9086,23 @@ PresShell::GetRootPresShell() return nsnull; } +void +PresShell::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + size_t *aArenasSize, + size_t *aStyleSetsSize, + size_t *aTextRunsSize) const +{ + *aArenasSize = aMallocSizeOf(this); + *aArenasSize += mStackArena.SizeOfExcludingThis(aMallocSizeOf); + *aArenasSize += mFrameArena.SizeOfExcludingThis(aMallocSizeOf); + + *aStyleSetsSize = StyleSet()->SizeOfIncludingThis(aMallocSizeOf); + + *aTextRunsSize = SizeOfTextRuns(aMallocSizeOf); +} + size_t -PresShell::SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) +PresShell::SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const { nsIFrame* rootFrame = mFrameConstructor->GetRootFrame(); if (!rootFrame) { diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index cc271570da79..dd8e3c19a60f 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -901,26 +901,11 @@ private: public: - size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const { - size_t n = 0; - - n += aMallocSizeOf(this); - n += mStackArena.SizeOfExcludingThis(aMallocSizeOf); - n += mFrameArena.SizeOfExcludingThis(aMallocSizeOf); - - return n; - } - - size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf); - - class MemoryReporter : public nsIMemoryMultiReporter - { - public: - NS_DECL_ISUPPORTS - NS_DECL_NSIMEMORYMULTIREPORTER - protected: - static PLDHashOperator SizeEnumerator(PresShellPtrKey *aEntry, void *userArg); - }; + void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf, + size_t *aArenasSize, + size_t *aStyleSetsSize, + size_t *aTextRunsSize) const; + size_t SizeOfTextRuns(nsMallocSizeOfFun aMallocSizeOf) const; protected: void QueryIsActive(); diff --git a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul index 7302a4857d97..27774929ce35 100644 --- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul +++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul @@ -44,8 +44,7 @@ let areJsCompartmentsPresent = false; let isSandboxLocationShown = false; - let areLayoutShellsPresent = false; - let areDomInnerWindowsPresent = false; + let areInnerWindowsPresent = false; let isPlacesPresent = false; let isImagesPresent = false; let isXptiWorkingSetPresent = false; @@ -73,10 +72,8 @@ // Check the presence of some other notable reporters. } else if (aPath.search(/^explicit\/js\/compartment\(/) >= 0) { areJsCompartmentsPresent = true; - } else if (aPath.search(/^explicit\/layout\/shell\(/) >= 0) { - areLayoutShellsPresent = true; - } else if (aPath.search(/^explicit\/dom\+style\/window-objects\/.*inner-window\(/) >= 0) { - areDomInnerWindowsPresent = true; + } else if (aPath.search(/^explicit\/window-objects\/.*inner-window\(/) >= 0) { + areInnerWindowsPresent = true; } else if (aPath.search(/^explicit\/storage\/sqlite\/places.sqlite/) >= 0) { isPlacesPresent = true; } else if (aPath.search(/^explicit\/images/) >= 0) { @@ -134,8 +131,7 @@ ok(areJsCompartmentsPresent, "js compartments are present"); ok(isSandboxLocationShown, "sandbox locations are present"); - ok(areLayoutShellsPresent, "layout shells are present"); - ok(areDomInnerWindowsPresent, "dom inner-windows are present"); + ok(areInnerWindowsPresent, "inner-windows are present"); ok(isPlacesPresent, "places is present"); ok(isImagesPresent, "images is present"); ok(isXptiWorkingSetPresent, "xpti-working-set is present");