Bug 913260 (part 2) - Tweak ghost window reporters. r=mccr8.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 18 Sep 2013 19:01:29 -0700
changeset 148630 753597994318ad97681db5b904e0556763b0dad0
parent 148629 1d72ff0f809ffa7477441729782a0be7ecb2a24c
child 148631 fec6f224f37895f7f84a94b2a6e509ce720b40b9
push id25349
push userryanvm@gmail.com
push dateWed, 25 Sep 2013 18:52:12 +0000
treeherdermozilla-central@39f30376058c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs913260
milestone27.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 913260 (part 2) - Tweak ghost window reporters. r=mccr8.
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowMemoryReporter.h
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -4,59 +4,58 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "amIAddonManager.h"
 #include "nsWindowMemoryReporter.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
 #include "nsIEffectiveTLDService.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
-#include "mozilla/Preferences.h"
+#include "mozilla/StaticPtr.h"
 #include "nsNetCID.h"
 #include "nsPrintfCString.h"
 #include "XPCJSMemoryReporter.h"
 #include "js/MemoryMetrics.h"
 #include "nsServiceManagerUtils.h"
 
 using namespace mozilla;
 
+StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
+
 nsWindowMemoryReporter::nsWindowMemoryReporter()
   : mCheckForGhostWindowsCallbackPending(false)
 {
 }
 
 NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
                    nsSupportsWeakReference)
 
 /* static */
 void
 nsWindowMemoryReporter::Init()
 {
-  // The memory reporter manager will own this object.
-  nsRefPtr<nsWindowMemoryReporter> windowReporter = new nsWindowMemoryReporter();
-  NS_RegisterMemoryReporter(windowReporter);
+  MOZ_ASSERT(!sWindowReporter);
+  sWindowReporter = new nsWindowMemoryReporter();
+  ClearOnShutdown(&sWindowReporter);
+  NS_RegisterMemoryReporter(sWindowReporter);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
   if (os) {
     // DOM_WINDOW_DESTROYED_TOPIC announces what we call window "detachment",
     // when a window's docshell is set to NULL.
-    os->AddObserver(windowReporter, DOM_WINDOW_DESTROYED_TOPIC,
+    os->AddObserver(sWindowReporter, DOM_WINDOW_DESTROYED_TOPIC,
                     /* weakRef = */ true);
-    os->AddObserver(windowReporter, "after-minimize-memory-usage",
+    os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
                     /* weakRef = */ true);
   }
 
-  nsRefPtr<GhostURLsReporter> ghostURLsReporter =
-    new GhostURLsReporter(windowReporter);
-  NS_RegisterMemoryReporter(ghostURLsReporter);
-
-  nsRefPtr<NumGhostsReporter> numGhostsReporter =
-    new NumGhostsReporter(windowReporter);
-  NS_RegisterMemoryReporter(numGhostsReporter);
+  NS_RegisterMemoryReporter(new GhostWindowsReporter());
 }
 
 static already_AddRefed<nsIURI>
 GetWindowURI(nsIDOMWindow *aWindow)
 {
   nsCOMPtr<nsPIDOMWindow> pWindow = do_QueryInterface(aWindow);
   NS_ENSURE_TRUE(pWindow, nullptr);
 
@@ -306,16 +305,62 @@ static
 PLDHashOperator
 GetWindows(const uint64_t& aId, nsGlobalWindow*& aWindow, void* aClosure)
 {
   ((WindowArray *)aClosure)->AppendElement(aWindow);
 
   return PL_DHASH_NEXT;
 }
 
+struct ReportGhostWindowsEnumeratorData
+{
+  nsIMemoryReporterCallback* callback;
+  nsISupports* closure;
+  nsresult rv;
+};
+
+static PLDHashOperator
+ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure)
+{
+  ReportGhostWindowsEnumeratorData *data =
+    static_cast<ReportGhostWindowsEnumeratorData*>(aClosure);
+
+  nsGlobalWindow::WindowByIdTable* windowsById =
+    nsGlobalWindow::GetWindowsTable();
+  if (!windowsById) {
+    NS_WARNING("Couldn't get window-by-id hashtable?");
+    return PL_DHASH_NEXT;
+  }
+
+  nsGlobalWindow* window = windowsById->Get(aIDHashKey->GetKey());
+  if (!window) {
+    NS_WARNING("Could not look up window?");
+    return PL_DHASH_NEXT;
+  }
+
+  nsAutoCString path;
+  path.AppendLiteral("ghost-windows/");
+  AppendWindowURI(window, path);
+
+  nsresult rv = data->callback->Callback(
+    /* process = */ EmptyCString(),
+    path,
+    nsIMemoryReporter::KIND_OTHER,
+    nsIMemoryReporter::UNITS_COUNT,
+    /* amount = */ 1,
+    /* description = */ NS_LITERAL_CSTRING("A ghost window."),
+    data->closure);
+
+  if (NS_FAILED(rv) && NS_SUCCEEDED(data->rv)) {
+    data->rv = rv;
+  }
+
+  return PL_DHASH_NEXT;
+}
+
 NS_IMETHODIMP
 nsWindowMemoryReporter::GetName(nsACString &aName)
 {
   aName.AssignLiteral("window-objects");
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -326,40 +371,46 @@ nsWindowMemoryReporter::CollectReports(n
     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.
+  // 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(NULL);
   nsCOMPtr<amIAddonManager> addonManager =
     do_GetService("@mozilla.org/addons/integration;1");
   for (uint32_t i = 0; i < windows.Length(); i++) {
-    nsresult rv = CollectWindowReports(windows[i], addonManager,
-                                       &windowTotalSizes, &ghostWindows,
-                                       &windowPaths, &topWindowPaths, aCb,
-                                       aClosure);
+    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|.
-  nsresult rv = xpc::JSReporter::CollectReports(&windowPaths, &topWindowPaths,
-                                                aCb, aClosure);
+  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),             \
                        nsIMemoryReporter::KIND_OTHER,                         \
                        nsIMemoryReporter::UNITS_BYTES, _amount,               \
@@ -657,99 +708,15 @@ nsWindowMemoryReporter::CheckForGhostWin
   // if it's not null.
   CheckForGhostWindowsEnumeratorData ghostEnumData =
     { &nonDetachedWindowDomains, aOutGhostIDs, tldService,
       GetGhostTimeout(), TimeStamp::Now() };
   mDetachedWindows.Enumerate(CheckForGhostWindowsEnumerator,
                              &ghostEnumData);
 }
 
-NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostURLsReporter,
-                   nsIMemoryReporter)
-
-nsWindowMemoryReporter::
-GhostURLsReporter::GhostURLsReporter(
-  nsWindowMemoryReporter* aWindowReporter)
-  : mWindowReporter(aWindowReporter)
-{
-}
-
-NS_IMETHODIMP
-nsWindowMemoryReporter::
-GhostURLsReporter::GetName(nsACString& aName)
-{
-  aName.AssignLiteral("ghost-windows-multi");
-  return NS_OK;
-}
-
-struct ReportGhostWindowsEnumeratorData
-{
-  nsIMemoryReporterCallback* callback;
-  nsISupports* closure;
-  nsresult rv;
-};
-
-static PLDHashOperator
-ReportGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void* aClosure)
-{
-  ReportGhostWindowsEnumeratorData *data =
-    static_cast<ReportGhostWindowsEnumeratorData*>(aClosure);
-
-  nsGlobalWindow::WindowByIdTable* windowsById =
-    nsGlobalWindow::GetWindowsTable();
-  if (!windowsById) {
-    NS_WARNING("Couldn't get window-by-id hashtable?");
-    return PL_DHASH_NEXT;
-  }
-
-  nsGlobalWindow* window = windowsById->Get(aIDHashKey->GetKey());
-  if (!window) {
-    NS_WARNING("Could not look up window?");
-    return PL_DHASH_NEXT;
-  }
-
-  nsAutoCString path;
-  path.AppendLiteral("ghost-windows/");
-  AppendWindowURI(window, path);
-
-  nsresult rv = data->callback->Callback(
-    /* process = */ EmptyCString(),
-    path,
-    nsIMemoryReporter::KIND_OTHER,
-    nsIMemoryReporter::UNITS_COUNT,
-    /* amount = */ 1,
-    /* description = */ NS_LITERAL_CSTRING("A ghost window."),
-    data->closure);
-
-  if (NS_FAILED(rv) && NS_SUCCEEDED(data->rv)) {
-    data->rv = rv;
-  }
-
-  return PL_DHASH_NEXT;
-}
-
-NS_IMETHODIMP
-nsWindowMemoryReporter::
-GhostURLsReporter::CollectReports(
-  nsIMemoryReporterCallback* aCb,
-  nsISupports* aClosure)
-{
-  // Get the IDs of all the ghost windows in existance.
-  nsTHashtable<nsUint64HashKey> ghostWindows;
-  mWindowReporter->CheckForGhostWindows(&ghostWindows);
-
-  ReportGhostWindowsEnumeratorData reportGhostWindowsEnumData =
-    { aCb, aClosure, NS_OK };
-
-  // Call aCb->Callback() for each ghost window.
-  ghostWindows.EnumerateEntries(ReportGhostWindowsEnumerator,
-                                &reportGhostWindowsEnumData);
-
-  return reportGhostWindowsEnumData.rv;
-}
-
 int64_t
-nsWindowMemoryReporter::NumGhostsReporter::Amount()
+nsWindowMemoryReporter::GhostWindowsReporter::Amount()
 {
   nsTHashtable<nsUint64HashKey> ghostWindows;
-  mWindowReporter->CheckForGhostWindows(&ghostWindows);
+  sWindowReporter->CheckForGhostWindows(&ghostWindows);
   return ghostWindows.Count();
 }
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -116,56 +116,36 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEMORYREPORTER
   NS_DECL_NSIOBSERVER
 
   static void Init();
 
 private:
   /**
-   * GhostURLsReporter generates the list of all ghost windows' URLs.  If
-   * you're only interested in this list, running this report is faster than
-   * running nsWindowMemoryReporter.
-   */
-  class GhostURLsReporter MOZ_FINAL : public nsIMemoryReporter
-  {
-  public:
-    GhostURLsReporter(nsWindowMemoryReporter* aWindowReporter);
-
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIMEMORYREPORTER
-
-  private:
-    nsRefPtr<nsWindowMemoryReporter> mWindowReporter;
-  };
-
-  /**
    * nsGhostWindowReporter generates the "ghost-windows" report, which counts
    * the number of ghost windows present.
    */
-  class NumGhostsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
+  class GhostWindowsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
   {
   public:
-    NumGhostsReporter(nsWindowMemoryReporter* aWindowReporter)
+    GhostWindowsReporter()
       : MemoryUniReporter("ghost-windows", KIND_OTHER, UNITS_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, does not share a domain 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.")
-      , mWindowReporter(aWindowReporter)
     {}
 
   private:
     int64_t Amount() MOZ_OVERRIDE;
-
-    nsRefPtr<nsWindowMemoryReporter> mWindowReporter;
   };
 
   // Protect ctor, use Init() instead.
   nsWindowMemoryReporter();
 
   /**
    * Get the number of seconds for which a window must satisfy ghost criteria
    * (1) and (2) before we deem that it satisfies criterion (3).