NS_IMETHODIMP
nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
                                       nsISupports* aClosure)
{
  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  NS_ENSURE_TRUE(windowsById, NS_OK);

  // 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();
  nsWindowSizes windowTotalSizes(NULL);
  for (; w != end; ++w) {
    CollectWindowReports(*w, &windowTotalSizes, aCb, 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)

  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::CollectReports(nsIMemoryMultiReporterCallback* aCb,
                                         nsISupports* aClosure)
{
  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  NS_ENSURE_TRUE(windowsById, NS_OK);

  // 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;
  for (; w != end; ++w) {
    CollectWindowReports(*w, &windowTotals, 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);

  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);

  return NS_OK;
}
/* static */ void
nsWindowMemoryReporter::UnlinkGhostWindows()
{
  if (!sWindowReporter) {
    return;
  }

  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  if (!windowsById) {
    return;
  }

  // Hold on to every window in memory so that window objects can't be
  // destroyed while we're calling the UnlinkGhostWindows callback.
  WindowArray windows;
  for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
    windows.AppendElement(iter.Data());
  }

  // Get the IDs of all the "ghost" windows, and unlink them all.
  nsTHashtable<nsUint64HashKey> ghostWindows;
  sWindowReporter->CheckForGhostWindows(&ghostWindows);
  for (auto iter = ghostWindows.ConstIter(); !iter.Done(); iter.Next()) {
    nsGlobalWindow::WindowByIdTable* windowsById =
      nsGlobalWindow::GetWindowsTable();
    if (!windowsById) {
      continue;
    }

    RefPtr<nsGlobalWindow> window = windowsById->Get(iter.Get()->GetKey());
    if (window) {
      window->RiskyUnlink();
    }
  }
}
NS_IMETHODIMP
nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
                                       nsISupports* aClosure, bool aAnonymize)
{
  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  NS_ENSURE_TRUE(windowsById, NS_OK);

  // 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);

  // Get the IDs of all the "ghost" windows, and call aCb->Callback() for each
  // one.
  nsTHashtable<nsUint64HashKey> ghostWindows;
  CheckForGhostWindows(&ghostWindows);
  nsresult rv = NS_OK;
  for (auto iter = ghostWindows.ConstIter(); !iter.Done(); iter.Next()) {
    nsGlobalWindow::WindowByIdTable* windowsById =
      nsGlobalWindow::GetWindowsTable();
    if (!windowsById) {
      NS_WARNING("Couldn't get window-by-id hashtable?");
      continue;
    }

    nsGlobalWindow* window = windowsById->Get(iter.Get()->GetKey());
    if (!window) {
      NS_WARNING("Could not look up window?");
      continue;
    }

    nsAutoCString path;
    path.AppendLiteral("ghost-windows/");
    AppendWindowURI(window, path, aAnonymize);

    nsresult callbackRv = aCb->Callback(
      /* process = */ EmptyCString(),
      path,
      nsIMemoryReporter::KIND_OTHER,
      nsIMemoryReporter::UNITS_COUNT,
      /* amount = */ 1,
      /* description = */ NS_LITERAL_CSTRING("A ghost window."),
      aClosure);
    if (NS_FAILED(callbackRv) && NS_SUCCEEDED(rv)) {
      rv = callbackRv;
    }
  }
  NS_ENSURE_SUCCESS(rv, rv);

  WindowPaths windowPaths;
  WindowPaths topWindowPaths;

  // Collect window memory usage.
  nsWindowSizes windowTotalSizes(nullptr);
  nsCOMPtr<amIAddonManager> addonManager;
  if (XRE_IsParentProcess()) {
    // Only try to access the service from the main process.
    addonManager = do_GetService("@mozilla.org/addons/integration;1");
  }
  for (uint32_t i = 0; i < windows.Length(); i++) {
    rv = CollectWindowReports(windows[i], addonManager,
                              &windowTotalSizes, &ghostWindows,
                              &windowPaths, &topWindowPaths, aCb,
                              aClosure, aAnonymize);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Report JS memory usage.  We do this from here because the JS memory
  // reporter needs to be passed |windowPaths|.
  rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
                                       aCb, aClosure, aAnonymize);
  NS_ENSURE_SUCCESS(rv, rv);

#define REPORT(_path, _amount, _desc)                                         \
  do {                                                                        \
    nsresult rv;                                                              \
    rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),             \
                       KIND_OTHER, UNITS_BYTES, _amount,                      \
                       NS_LITERAL_CSTRING(_desc), aClosure);                  \
    NS_ENSURE_SUCCESS(rv, rv);                                                \
  } while (0)

  REPORT("window-objects/dom/element-nodes", windowTotalSizes.mDOMElementNodesSize,
         "This is the sum of all windows' 'dom/element-nodes' numbers.");

  REPORT("window-objects/dom/text-nodes", windowTotalSizes.mDOMTextNodesSize,
         "This is the sum of all windows' 'dom/text-nodes' numbers.");

  REPORT("window-objects/dom/cdata-nodes", windowTotalSizes.mDOMCDATANodesSize,
         "This is the sum of all windows' 'dom/cdata-nodes' numbers.");

  REPORT("window-objects/dom/comment-nodes", windowTotalSizes.mDOMCommentNodesSize,
         "This is the sum of all windows' 'dom/comment-nodes' numbers.");

  REPORT("window-objects/dom/event-targets", windowTotalSizes.mDOMEventTargetsSize,
         "This is the sum of all windows' 'dom/event-targets' numbers.");

  REPORT("window-objects/dom/other", windowTotalSizes.mDOMOtherSize,
         "This is the sum of all windows' 'dom/other' numbers.");

  REPORT("window-objects/property-tables",
         windowTotalSizes.mPropertyTablesSize,
         "This is the sum of all windows' 'property-tables' numbers.");

  REPORT("window-objects/style-sheets", windowTotalSizes.mStyleSheetsSize,
         "This is the sum of all windows' 'style-sheets' numbers.");

  REPORT("window-objects/layout/pres-shell", windowTotalSizes.mLayoutPresShellSize,
         "This is the sum of all windows' 'layout/arenas' numbers.");

  REPORT("window-objects/layout/line-boxes",
         windowTotalSizes.mArenaStats.mLineBoxes,
         "This is the sum of all windows' 'layout/line-boxes' numbers.");

  REPORT("window-objects/layout/rule-nodes",
         windowTotalSizes.mArenaStats.mRuleNodes,
         "This is the sum of all windows' 'layout/rule-nodes' numbers.");

  REPORT("window-objects/layout/style-contexts",
         windowTotalSizes.mArenaStats.mStyleContexts,
         "This is the sum of all windows' 'layout/style-contexts' numbers.");

  REPORT("window-objects/layout/style-structs",
         windowTotalSizes.mArenaStats.mStyleStructs,
         "This is the sum of all windows' 'layout/style-structs' numbers.");

  REPORT("window-objects/layout/style-sets", windowTotalSizes.mLayoutStyleSetsSize,
         "This is the sum of all windows' 'layout/style-sets' numbers.");

  REPORT("window-objects/layout/text-runs", windowTotalSizes.mLayoutTextRunsSize,
         "This is the sum of all windows' 'layout/text-runs' numbers.");

  REPORT("window-objects/layout/pres-contexts", windowTotalSizes.mLayoutPresContextSize,
         "This is the sum of all windows' 'layout/pres-contexts' numbers.");

  size_t frameTotal = 0;
#define FRAME_ID(classname)                \
  frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
#include "nsFrameIdList.h"
#undef FRAME_ID

  REPORT("window-objects/layout/frames", frameTotal,
         "Memory used for layout frames within windows. "
         "This is the sum of all windows' 'layout/frames/' numbers.");

#undef REPORT

  return NS_OK;
}
示例#5
0
NS_IMETHODIMP
nsWindowMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
                                       nsISupports* aClosure)
{
  nsGlobalWindow::WindowByIdTable* windowsById =
    nsGlobalWindow::GetWindowsTable();
  NS_ENSURE_TRUE(windowsById, NS_OK);

  // 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);

  // Get the IDs of all the "ghost" windows, and call aCb->Callback() for each
  // one.
  nsTHashtable<nsUint64HashKey> ghostWindows;
  CheckForGhostWindows(&ghostWindows);
  ReportGhostWindowsEnumeratorData reportGhostWindowsEnumData =
    { aCb, aClosure, NS_OK };
  ghostWindows.EnumerateEntries(ReportGhostWindowsEnumerator,
                                &reportGhostWindowsEnumData);
  nsresult rv = reportGhostWindowsEnumData.rv;
  NS_ENSURE_SUCCESS(rv, rv);

  WindowPaths windowPaths;
  WindowPaths topWindowPaths;

  // Collect window memory usage.
  nsWindowSizes windowTotalSizes(nullptr);
  nsCOMPtr<amIAddonManager> addonManager;
  if (XRE_GetProcessType() == GeckoProcessType_Default) {
    // Only try to access the service from the main process.
    addonManager = do_GetService("@mozilla.org/addons/integration;1");
  }
  for (uint32_t i = 0; i < windows.Length(); i++) {
    rv = CollectWindowReports(windows[i], addonManager,
                              &windowTotalSizes, &ghostWindows,
                              &windowPaths, &topWindowPaths, aCb,
                              aClosure);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  // Report JS memory usage.  We do this from here because the JS memory
  // reporter needs to be passed |windowPaths|.
  rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
                                       aCb, aClosure);
  NS_ENSURE_SUCCESS(rv, rv);

#define REPORT(_path, _amount, _desc)                                         \
  do {                                                                        \
    nsresult rv;                                                              \
    rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),             \
                       KIND_OTHER, UNITS_BYTES, _amount,                      \
                       NS_LITERAL_CSTRING(_desc), aClosure);                  \
    NS_ENSURE_SUCCESS(rv, rv);                                                \
  } while (0)

  REPORT("window-objects/dom/element-nodes", windowTotalSizes.mDOMElementNodesSize,
         "This is the sum of all windows' 'dom/element-nodes' numbers.");

  REPORT("window-objects/dom/text-nodes", windowTotalSizes.mDOMTextNodesSize,
         "This is the sum of all windows' 'dom/text-nodes' numbers.");

  REPORT("window-objects/dom/cdata-nodes", windowTotalSizes.mDOMCDATANodesSize,
         "This is the sum of all windows' 'dom/cdata-nodes' numbers.");

  REPORT("window-objects/dom/comment-nodes", windowTotalSizes.mDOMCommentNodesSize,
         "This is the sum of all windows' 'dom/comment-nodes' numbers.");

  REPORT("window-objects/dom/event-targets", windowTotalSizes.mDOMEventTargetsSize,
         "This is the sum of all windows' 'dom/event-targets' numbers.");

  REPORT("window-objects/dom/other", windowTotalSizes.mDOMOtherSize,
         "This is the sum of all windows' 'dom/other' numbers.");

  REPORT("window-objects/property-tables",
         windowTotalSizes.mPropertyTablesSize,
         "This is the sum of all windows' 'property-tables' numbers.");

  REPORT("window-objects/style-sheets", windowTotalSizes.mStyleSheetsSize,
         "This is the sum of all windows' 'style-sheets' numbers.");

  REPORT("window-objects/layout/pres-shell", windowTotalSizes.mLayoutPresShellSize,
         "This is the sum of all windows' 'layout/arenas' numbers.");

  REPORT("window-objects/layout/line-boxes",
         windowTotalSizes.mArenaStats.mLineBoxes,
         "This is the sum of all windows' 'layout/line-boxes' numbers.");

  REPORT("window-objects/layout/rule-nodes",
         windowTotalSizes.mArenaStats.mRuleNodes,
         "This is the sum of all windows' 'layout/rule-nodes' numbers.");

  REPORT("window-objects/layout/style-contexts",
         windowTotalSizes.mArenaStats.mStyleContexts,
         "This is the sum of all windows' 'layout/style-contexts' numbers.");

  REPORT("window-objects/layout/style-sets", windowTotalSizes.mLayoutStyleSetsSize,
         "This is the sum of all windows' 'layout/style-sets' numbers.");

  REPORT("window-objects/layout/text-runs", windowTotalSizes.mLayoutTextRunsSize,
         "This is the sum of all windows' 'layout/text-runs' numbers.");

  REPORT("window-objects/layout/pres-contexts", windowTotalSizes.mLayoutPresContextSize,
         "This is the sum of all windows' 'layout/pres-contexts' numbers.");

  size_t frameTotal = 0;
#define FRAME_ID(classname)                \
  frameTotal += windowTotalSizes.mArenaStats.FRAME_ID_STAT_FIELD(classname);
#include "nsFrameIdList.h"
#undef FRAME_ID

  REPORT("window-objects/layout/frames", frameTotal,
         "Memory used for layout frames within windows. "
         "This is the sum of all windows' 'layout/frames/' numbers.");

#undef REPORT

  return NS_OK;
}
NS_IMETHODIMP
nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
                                       nsISupports* aData, bool aAnonymize)
{
  nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
    nsGlobalWindowInner::GetWindowsTable();
  NS_ENSURE_TRUE(windowsById, NS_OK);

  // 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;
  for (auto iter = windowsById->Iter(); !iter.Done(); iter.Next()) {
    windows.AppendElement(iter.Data());
  }

  // Get the IDs of all the "ghost" windows, and call aHandleReport->Callback()
  // for each one.
  nsTHashtable<nsUint64HashKey> ghostWindows;
  CheckForGhostWindows(&ghostWindows);
  for (auto iter = ghostWindows.ConstIter(); !iter.Done(); iter.Next()) {
    nsGlobalWindowInner::InnerWindowByIdTable* windowsById =
      nsGlobalWindowInner::GetWindowsTable();
    if (!windowsById) {
      NS_WARNING("Couldn't get window-by-id hashtable?");
      continue;
    }

    nsGlobalWindowInner* window = windowsById->Get(iter.Get()->GetKey());
    if (!window) {
      NS_WARNING("Could not look up window?");
      continue;
    }

    nsAutoCString path;
    path.AppendLiteral("ghost-windows/");
    AppendWindowURI(window, path, aAnonymize);

    aHandleReport->Callback(
      /* process = */ EmptyCString(),
      path,
      nsIMemoryReporter::KIND_OTHER,
      nsIMemoryReporter::UNITS_COUNT,
      /* amount = */ 1,
      /* description = */ NS_LITERAL_CSTRING("A ghost window."),
      aData);
  }

  MOZ_COLLECT_REPORT(
    "ghost-windows", KIND_OTHER, UNITS_COUNT, ghostWindows.Count(),
"The number of ghost windows present (the number of nodes underneath "
"explicit/window-objects/top(none)/ghost, modulo race conditions).  A ghost "
"window is not shown in any tab, is not in a tab group with any "
"non-detached windows, and has met these criteria for at least "
"memory.ghost_window_timeout_seconds, or has survived a round of "
"about:memory's minimize memory usage button.\n\n"
"Ghost windows can happen legitimately, but they are often indicative of "
"leaks in the browser or add-ons.");

  WindowPaths windowPaths;
  WindowPaths topWindowPaths;

  // Collect window memory usage.
  SizeOfState fakeState(nullptr);   // this won't be used
  nsWindowSizes windowTotalSizes(fakeState);
  for (uint32_t i = 0; i < windows.Length(); i++) {
    CollectWindowReports(windows[i],
                         &windowTotalSizes, &ghostWindows,
                         &windowPaths, &topWindowPaths, aHandleReport,
                         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.");

  REPORT("window-objects/dom/text-nodes", windowTotalSizes.mDOMTextNodesSize,
         "This is the sum of all windows' 'dom/text-nodes' numbers.");

  REPORT("window-objects/dom/cdata-nodes", windowTotalSizes.mDOMCDATANodesSize,
         "This is the sum of all windows' 'dom/cdata-nodes' numbers.");

  REPORT("window-objects/dom/comment-nodes", windowTotalSizes.mDOMCommentNodesSize,
         "This is the sum of all windows' 'dom/comment-nodes' numbers.");

  REPORT("window-objects/dom/event-targets", windowTotalSizes.mDOMEventTargetsSize,
         "This is the sum of all windows' 'dom/event-targets' numbers.");

  REPORT("window-objects/dom/performance",
         windowTotalSizes.mDOMPerformanceUserEntries +
         windowTotalSizes.mDOMPerformanceResourceEntries,
         "This is the sum of all windows' 'dom/performance/' numbers.");

  REPORT("window-objects/dom/other", windowTotalSizes.mDOMOtherSize,
         "This is the sum of all windows' 'dom/other' numbers.");

  REPORT("window-objects/layout/style-sheets",
         windowTotalSizes.mLayoutStyleSheetsSize,
         "This is the sum of all windows' 'layout/style-sheets' numbers.");

  REPORT("window-objects/layout/pres-shell",
         windowTotalSizes.mLayoutPresShellSize,
         "This is the sum of all windows' 'layout/arenas' numbers.");

  REPORT("window-objects/layout/style-sets",
         windowTotalSizes.mLayoutStyleSetsStylistRuleTree +
         windowTotalSizes.mLayoutStyleSetsStylistElementAndPseudosMaps +
         windowTotalSizes.mLayoutStyleSetsStylistInvalidationMap +
         windowTotalSizes.mLayoutStyleSetsStylistRevalidationSelectors +
         windowTotalSizes.mLayoutStyleSetsStylistOther +
         windowTotalSizes.mLayoutStyleSetsOther,
         "This is the sum of all windows' 'layout/style-sets/' numbers.");

  REPORT("window-objects/layout/element-data-objects",
         windowTotalSizes.mLayoutElementDataObjects,
         "This is the sum of all windows' 'layout/element-data-objects' "
         "numbers.");

  REPORT("window-objects/layout/text-runs", windowTotalSizes.mLayoutTextRunsSize,
         "This is the sum of all windows' 'layout/text-runs' numbers.");

  REPORT("window-objects/layout/pres-contexts",
         windowTotalSizes.mLayoutPresContextSize,
         "This is the sum of all windows' 'layout/pres-contexts' numbers.");

  REPORT("window-objects/layout/frame-properties",
         windowTotalSizes.mLayoutFramePropertiesSize,
         "This is the sum of all windows' 'layout/frame-properties' numbers.");

  REPORT("window-objects/layout/computed-values",
         windowTotalSizes.mLayoutComputedValuesDom +
         windowTotalSizes.mLayoutComputedValuesNonDom +
         windowTotalSizes.mLayoutComputedValuesVisited,
         "This is the sum of all windows' 'layout/computed-values/' numbers.");

  REPORT("window-objects/property-tables",
         windowTotalSizes.mPropertyTablesSize,
         "This is the sum of all windows' 'property-tables' numbers.");

  REPORT("window-objects/layout/line-boxes",
         windowTotalSizes.mArenaSizes.mLineBoxes,
         "This is the sum of all windows' 'layout/line-boxes' numbers.");

  REPORT("window-objects/layout/rule-nodes",
         windowTotalSizes.mArenaSizes.mRuleNodes,
         "This is the sum of all windows' 'layout/rule-nodes' numbers.");

  REPORT("window-objects/layout/style-contexts",
         windowTotalSizes.mArenaSizes.mComputedStyles,
         "This is the sum of all windows' 'layout/style-contexts' numbers.");

  size_t frameTotal = 0;
#define FRAME_ID(classname, ...) \
  frameTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname);
#define ABSTRACT_FRAME_ID(...)
#include "nsFrameIdList.h"
#undef FRAME_ID
#undef ABSTRACT_FRAME_ID

  REPORT("window-objects/layout/frames", frameTotal,
         "Memory used for layout frames within windows. "
         "This is the sum of all windows' 'layout/frames/' numbers.");

  size_t styleTotal = 0;
#define STYLE_STRUCT(name_) \
  styleTotal += \
    windowTotalSizes.mStyleSizes.NS_STYLE_SIZES_FIELD(name_);
#include "nsStyleStructList.h"
#undef STYLE_STRUCT

  REPORT("window-objects/layout/style-structs", styleTotal,
         "Memory used for style structs within windows. This is the sum of "
         "all windows' 'layout/style-structs/' numbers.");

#undef REPORT

  return NS_OK;
}