Bug 730181 (part 1) - Merge the "dom+style" and "layout" memory reporter trees. r=khuey.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 21 Feb 2012 07:10:11 -0800
changeset 88143 c12cfaf9cd4e869363cc5aef1ee9ea7155c31f2d
parent 88142 412c948ce10019d15cde747af6db85a91d131d77
child 88144 4069a04e8e819e095c064c270e367bb8f8850234
push id22173
push userbmo@edmorley.co.uk
push dateSat, 03 Mar 2012 13:14:42 +0000
treeherdermozilla-central@ed57abebd328 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs730181
milestone13.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 730181 (part 1) - Merge the "dom+style" and "layout" memory reporter trees. r=khuey.
content/base/src/nsDocument.cpp
dom/base/nsDOMMemoryReporter.cpp
dom/base/nsDOMMemoryReporter.h
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
layout/base/nsPresShell.h
toolkit/components/aboutmemory/tests/test_memoryReporters.xul
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -9144,16 +9144,23 @@ nsDocument::GetMozVisibilityState(nsAStr
 }
 
 /* virtual */ void
 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!
 }
 
 void
 nsIDocument::DocSizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
 {
--- a/dom/base/nsDOMMemoryReporter.cpp
+++ b/dom/base/nsDOMMemoryReporter.cpp
@@ -83,28 +83,21 @@ AppendWindowURI(nsGlobalWindow *aWindow,
   // (such as about:memory) have to undo this change.
   spec.ReplaceChar('/', '\\');
 
   aStr += spec;
 
   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)
 {
   // DOM window objects fall into one of three categories:
   // - "active" windows are currently either displayed in an active
   //   tab, or a child of such a window.
   // - "cached" windows are in the fastback cache.
   // - "other" windows are closed (or navigated away from w/o being
@@ -121,17 +114,17 @@ CollectWindowReports(nsGlobalWindow *aWi
   // For outer windows we simply group them all together and just show
   // the combined count and amount of memory used, which is generally
   // a constant amount per window (since all the actual data lives in
   // the inner window).
   //
   // The path we give to the reporter callback for inner windows are
   // as follows:
   //
-  //   explicit/dom+style/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
+  //   explicit/window-objects/<category>/top=<top-outer-id> (inner=<top-inner-id>)/inner-window(id=<id>, uri=<uri>)
   //
   // Where:
   // - <category> is active, cached, or other, as described above.
   // - <top-outer-id> is the window id (nsPIDOMWindow::WindowID()) of
   //   the top outer window (i.e. tab, or top level chrome window).
   // - <top-inner-id> is the window id of the top window's inner
   //   window.
   // - <id> is the window id of the inner window in question.
@@ -140,22 +133,22 @@ CollectWindowReports(nsGlobalWindow *aWi
   // Exposing the window ids is done to get logical grouping in
   // about:memory, and also for debuggability since one can get to the
   // nsGlobalWindow for a window id by calling the static method
   // nsGlobalWindow::GetInnerWindowWithId(id) (or
   // GetOuterWindowWithId(id) in a debugger.
   //
   // For outer windows we simply use:
   // 
-  //   explicit/dom+style/window-objects/<category>/outer-windows
+  //   explicit/window-objects/<category>/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();
 
   nsGlobalWindow *top = aWindow->GetTop();
   nsWindowSizes windowSizes(DOMStyleMallocSizeOf);
   aWindow->SizeOfIncludingThis(&windowSizes);
 
   if (docShell && aWindow->IsFrozen()) {
@@ -194,55 +187,67 @@ 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 (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)
+
+  REPORT(windowPath, "/dom", windowSizes.mDOM,
+         "Memory used by a window and the DOM within it.");
+  aWindowTotalSizes->mDOM += windowSizes.mDOM;
 
-  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, "/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<nsGlobalWindow> > WindowArray;
 
 static
 PLDHashOperator
 GetWindows(const PRUint64& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   ((WindowArray *)aClosure)->AppendElement(aWindow);
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 nsDOMMemoryMultiReporter::GetName(nsACString &aName)
 {
-  aName.AssignLiteral("dom+style");
+  aName.AssignLiteral("window-objects");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
                                          nsISupports* aClosure)
 {
   nsGlobalWindow::WindowByIdTable* windowsById =
@@ -252,37 +257,52 @@ nsDOMMemoryMultiReporter::CollectReports
   // Hold on to every window in memory so that window objects can't be
   // destroyed while we're calling the memory reporter callback.
   WindowArray windows;
   windowsById->Enumerate(GetWindows, &windows);
 
   // Collect window memory usage.
   nsRefPtr<nsGlobalWindow> *w = windows.Elements();
   nsRefPtr<nsGlobalWindow> *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;
 }
 
 NS_IMETHODIMP
 nsDOMMemoryMultiReporter::GetExplicitNonHeap(PRInt64* aAmount)
 {
   // This reporter only measures heap memory.
   *aAmount = 0;
--- a/dom/base/nsDOMMemoryReporter.h
+++ b/dom/base/nsDOMMemoryReporter.h
@@ -44,24 +44,26 @@
 // 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;
 
 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
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEMORYMULTIREPORTER
 
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -139,18 +139,18 @@ typedef struct CapturingContentInfo {
   // capture should only be allowed during a mousedown event
   bool mAllowed;
   bool mRetargetToElement;
   bool mPreventDrag;
   nsIContent* mContent;
 } 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
 #define NS_PRESSHELL_SCROLL_BOTTOM   100
 #define NS_PRESSHELL_SCROLL_LEFT     0
 #define NS_PRESSHELL_SCROLL_RIGHT    100
 #define NS_PRESSHELL_SCROLL_CENTER   50
 #define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -1171,16 +1171,21 @@ public:
    * root pres shell.
    */
   virtual void DidPaint() = 0;
   virtual void ScheduleViewManagerFlush() = 0;
   virtual void ClearMouseCaptureOnView(nsIView* aView) = 0;
   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.
    */
 protected:
   virtual bool AddRefreshObserverExternal(nsARefreshObserver* aObserver,
                                             mozFlushType aFlushType);
   bool AddRefreshObserverInternal(nsARefreshObserver* aObserver,
                                     mozFlushType aFlushType);
@@ -1278,20 +1283,16 @@ protected:
   // re-use old pixels.
   PRUint32                  mRenderFlags;
 
   // Used to force allocation and rendering of proportionally more or
   // less pixels in the given dimension.
   float                     mXResolution;
   float                     mYResolution;
 
-  // Live pres shells, for memory and other tracking
-  typedef nsPtrHashKey<nsIPresShell> PresShellPtrKey;
-  static nsTHashtable<PresShellPtrKey> *sLiveShells;
-
   static nsIContent* gKeyDownTarget;
 };
 
 /**
  * Create a new empty presentation shell. Upon success, call Init
  * before attempting to use the shell.
  */
 nsresult
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -196,19 +196,16 @@
 #include "nsPlaceholderFrame.h"
 #include "nsCanvasFrame.h"
 
 // Content viewer interfaces
 #include "nsIContentViewer.h"
 #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"
 #include "sampler.h"
 
 #include "Layers.h"
 #include "nsAsyncDOMEvent.h"
 
@@ -603,123 +600,16 @@ struct nsCallbackEventRequest
 };
 
 // ----------------------------------------------------------------------------
 #define ASSERT_REFLOW_SCHEDULED_STATE()                                       \
   NS_ASSERTION(mReflowScheduled ==                                            \
                  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<PresShell*>(aEntry->GetKey());
-  MemoryReporterData *data = (MemoryReporterData*)userArg;
-
-  // Build the string "explicit/layout/shell(<uri of the document>)"
-  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:
   nsAutoCauseReflowNotifier(PresShell* aShell)
     : mShell(aShell)
   {
     mShell->WillCauseReflow();
   }
@@ -910,17 +800,16 @@ NS_NewPresShell(nsIPresShell** aInstance
     return NS_ERROR_NULL_POINTER;
 
   *aInstancePtrResult = new PresShell();
 
   NS_ADDREF(*aInstancePtrResult);
   return NS_OK;
 }
 
-nsTHashtable<PresShell::PresShellPtrKey> *nsIPresShell::sLiveShells = 0;
 static bool sSynthMouseMove = true;
 
 PresShell::PresShell()
   : mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
 {
   mSelection = nsnull;
 #ifdef MOZ_REFLOW_PERF
   mReflowCountMgr = new ReflowCountMgr();
@@ -938,36 +827,31 @@ PresShell::PresShell()
 #ifdef DEBUG
   mPresArenaAllocCount = 0;
 #endif
   mRenderFlags = 0;
   mXResolution = 1.0;
   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;
-  }
-
-  sLiveShells->PutEntry(this);
+    addedSynthMouseMove = true;
+  }
 }
 
 NS_IMPL_ISUPPORTS7(PresShell, nsIPresShell, nsIDocumentObserver,
                    nsISelectionController,
                    nsISelectionDisplay, nsIObserver, nsISupportsWeakReference,
                    nsIMutationObserver)
 
 PresShell::~PresShell()
 {
-  sLiveShells->RemoveEntry(this);
-
   if (!mHaveShutDown) {
     NS_NOTREACHED("Someone did not call nsIPresShell::destroy");
     Destroy();
   }
 
   NS_ASSERTION(mCurrentEventContentStack.Count() == 0,
                "Huh, event content left on the stack in pres shell dtor!");
   NS_ASSERTION(mFirstCallbackEventRequest == nsnull &&
@@ -9080,29 +8964,28 @@ nsIPresShell::IsAccessibilityActive()
 
 nsAccessibilityService*
 nsIPresShell::AccService()
 {
   return GetAccService();
 }
 #endif
 
+static bool inited = false;
+
 void nsIPresShell::InitializeStatics()
 {
-  NS_ASSERTION(sLiveShells == nsnull, "InitializeStatics called multiple times!");
-  sLiveShells = new nsTHashtable<PresShellPtrKey>();
-  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.
 void PresShell::QueryIsActive()
 {
   nsCOMPtr<nsISupports> container = mPresContext->GetContainer();
   if (mDocument) {
     nsIDocument* displayDoc = mDocument->GetDisplayDocument();
@@ -9198,18 +9081,33 @@ PresShell::GetRootPresShell()
     nsPresContext* rootPresContext = mPresContext->GetRootPresContext();
     if (rootPresContext) {
       return static_cast<PresShell*>(rootPresContext->PresShell());
     }
   }
   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) {
     return 0;
   }
 
   // clear the TEXT_RUN_MEMORY_ACCOUNTED flags
   nsLayoutUtils::SizeOfTextRunsForFrames(rootFrame, nsnull,
--- a/layout/base/nsPresShell.h
+++ b/layout/base/nsPresShell.h
@@ -896,36 +896,21 @@ private:
 private:
 #ifdef DEBUG
   // Ensure that every allocation from the PresArena is eventually freed.
   PRUint32 mPresArenaAllocCount;
 #endif
 
 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();
   nsresult UpdateImageLockingState();
 
 private:
   nscolor GetDefaultBackgroundColorToDraw();
 };
--- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
+++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul
@@ -39,18 +39,17 @@
   let vsizeAmounts = [];
   let residentAmounts = [];
   let jsGcHeapAmounts = [];
   let heapAllocatedAmounts = [];
   let storageSqliteAmounts = [];
 
   let areJsCompartmentsPresent = false;
   let isSandboxLocationShown = false;
-  let areLayoutShellsPresent = false;
-  let areDomInnerWindowsPresent = false;
+  let areInnerWindowsPresent = false;
   let isPlacesPresent = false;
   let isImagesPresent = false;
   let isXptiWorkingSetPresent = false;
   let isAtomTablePresent = false;
 
   let mySandbox = Components.utils.Sandbox(document.nodePrincipal,
                     { sandboxName: "this-is-a-sandbox-name" });
 
@@ -68,20 +67,18 @@
     } else if (aPath === "heap-allocated") {
       heapAllocatedAmounts.push(aAmount);
     } else if (aPath === "storage-sqlite") {
       storageSqliteAmounts.push(aAmount);
 
     // 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) {
       isImagesPresent = true;
     } else if (aPath.search(/^explicit\/xpti-working-set$/) >= 0) {
       isXptiWorkingSetPresent = true;
     } else if (aPath.search(/^explicit\/atom-table$/) >= 0) {
       isAtomTablePresent = true;
@@ -129,18 +126,17 @@
   checkSpecialReport("vsize",          vsizeAmounts);
   checkSpecialReport("resident",       residentAmounts);
   checkSpecialReport("js-gc-heap",     jsGcHeapAmounts);
   checkSpecialReport("heap-allocated", heapAllocatedAmounts);
   checkSpecialReport("storage-sqlite", storageSqliteAmounts);
 
   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");
   ok(isAtomTablePresent,        "atom-table is present");
 
   ]]>
   </script>
 </window>