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