Bug 1517276 - thread callbacks through MemoryReportRequestClient; r=mccr8
authorNathan Froyd <froydnj@mozilla.com>
Wed, 02 Jan 2019 16:18:13 -0500
changeset 509416 7b71897ff6be49225613180bac536673a03bb7c0
parent 509415 72902d6e1c3feadefeee27fc2bb91f53864a5a9b
child 509417 fcf60924da90d2242cefc64d5ae83a85db395749
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs1517276
milestone66.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 1517276 - thread callbacks through MemoryReportRequestClient; r=mccr8 The guts of MemoryReportRequestClient's supporting runnables contain switches on the particular type of process we're running. If you're bringing up a new process type, having to add extra cases for your process type here is a bit onerous. These runnables really shouldn't know anything about the process types that they're running on, either. The easiest thing to do is modify MemoryReportRequestClient::Start to take callbacks for what to do when a report is created and when reporting is finished. Then all process-specific knowledge can be pushed out to the clients themselves, leaving MemoryReportRequestClient and friends process-type agnostic. We could even, at some later date, move this code into xpcom/base/ to sit near nsMemoryReporterManager, where it belongs.
dom/ipc/ContentChild.cpp
dom/ipc/MemoryReportRequest.cpp
dom/ipc/MemoryReportRequest.h
dom/media/ipc/RDDParent.cpp
gfx/ipc/GPUParent.cpp
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1232,17 +1232,23 @@ void ContentChild::InitXPCOM(
 mozilla::ipc::IPCResult ContentChild::RecvRequestMemoryReport(
     const uint32_t& aGeneration, const bool& aAnonymize,
     const bool& aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile) {
   nsCString process;
   GetProcessName(process);
   AppendProcessId(process);
 
   MemoryReportRequestClient::Start(aGeneration, aAnonymize,
-                                   aMinimizeMemoryUsage, aDMDFile, process);
+                                   aMinimizeMemoryUsage, aDMDFile, process,
+                                   [&](const MemoryReport& aReport) {
+                                     Unused << GetSingleton()->SendAddMemoryReport(aReport);
+                                   },
+                                   [&](const uint32_t& aGeneration) {
+                                     return GetSingleton()->SendFinishMemoryReport(aGeneration);
+                                   });
   return IPC_OK();
 }
 
 PCycleCollectWithLogsChild* ContentChild::AllocPCycleCollectWithLogsChild(
     const bool& aDumpAllTraces, const FileDescriptor& aGCLog,
     const FileDescriptor& aCCLog) {
   return do_AddRef(new CycleCollectWithLogsChild()).take();
 }
--- a/dom/ipc/MemoryReportRequest.cpp
+++ b/dom/ipc/MemoryReportRequest.cpp
@@ -1,19 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "MemoryReportRequest.h"
-#include "mozilla/RDDParent.h"
-#include "mozilla/Unused.h"
-#include "mozilla/dom/ContentChild.h"
-#include "mozilla/gfx/GPUParent.h"
 
 namespace mozilla {
 namespace dom {
 
 MemoryReportRequestHost::MemoryReportRequestHost(uint32_t aGeneration)
     : mGeneration(aGeneration), mSuccess(false) {
   MOZ_COUNT_CTOR(MemoryReportRequestHost);
   mReporterManager = nsMemoryReporterManager::GetOrCreate();
@@ -49,131 +45,119 @@ MemoryReportRequestHost::~MemoryReportRe
     mReporterManager = nullptr;
   }
 }
 
 NS_IMPL_ISUPPORTS(MemoryReportRequestClient, nsIRunnable)
 
 /* static */ void MemoryReportRequestClient::Start(
     uint32_t aGeneration, bool aAnonymize, bool aMinimizeMemoryUsage,
-    const MaybeFileDesc& aDMDFile, const nsACString& aProcessString) {
+    const MaybeFileDesc& aDMDFile, const nsACString& aProcessString,
+    const ReportCallback& aReportCallback,
+    const FinishCallback& aFinishCallback) {
   RefPtr<MemoryReportRequestClient> request = new MemoryReportRequestClient(
-      aGeneration, aAnonymize, aDMDFile, aProcessString);
+      aGeneration, aAnonymize, aDMDFile, aProcessString,
+      aReportCallback, aFinishCallback);
 
   DebugOnly<nsresult> rv;
   if (aMinimizeMemoryUsage) {
     nsCOMPtr<nsIMemoryReporterManager> mgr =
         do_GetService("@mozilla.org/memory-reporter-manager;1");
     rv = mgr->MinimizeMemoryUsage(request);
     // mgr will eventually call actor->Run()
   } else {
     rv = request->Run();
   }
 
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "actor operation failed");
 }
 
 MemoryReportRequestClient::MemoryReportRequestClient(
     uint32_t aGeneration, bool aAnonymize, const MaybeFileDesc& aDMDFile,
-    const nsACString& aProcessString)
+    const nsACString& aProcessString, const ReportCallback& aReportCallback,
+    const FinishCallback& aFinishCallback)
     : mGeneration(aGeneration),
       mAnonymize(aAnonymize),
-      mProcessString(aProcessString) {
+      mProcessString(aProcessString),
+      mReportCallback(aReportCallback),
+      mFinishCallback(aFinishCallback) {
   if (aDMDFile.type() == MaybeFileDesc::TFileDescriptor) {
     mDMDFile = aDMDFile.get_FileDescriptor();
   }
 }
 
 MemoryReportRequestClient::~MemoryReportRequestClient() {}
 
 class HandleReportCallback final : public nsIHandleReportCallback {
  public:
+  using ReportCallback = typename MemoryReportRequestClient::ReportCallback;
+
   NS_DECL_ISUPPORTS
 
   explicit HandleReportCallback(uint32_t aGeneration,
-                                const nsACString& aProcess)
-      : mGeneration(aGeneration), mProcess(aProcess) {}
+                                const nsACString& aProcess,
+                                const ReportCallback& aReportCallback)
+      : mGeneration(aGeneration),
+        mProcess(aProcess),
+        mReportCallback(aReportCallback) {}
 
   NS_IMETHOD Callback(const nsACString& aProcess, const nsACString& aPath,
                       int32_t aKind, int32_t aUnits, int64_t aAmount,
                       const nsACString& aDescription,
                       nsISupports* aUnused) override {
     MemoryReport memreport(mProcess, nsCString(aPath), aKind, aUnits, aAmount,
                            mGeneration, nsCString(aDescription));
-    switch (XRE_GetProcessType()) {
-      case GeckoProcessType_Content:
-        ContentChild::GetSingleton()->SendAddMemoryReport(memreport);
-        break;
-      case GeckoProcessType_GPU:
-        Unused << gfx::GPUParent::GetSingleton()->SendAddMemoryReport(
-            memreport);
-        break;
-      case GeckoProcessType_RDD:
-        Unused << RDDParent::GetSingleton()->SendAddMemoryReport(memreport);
-        break;
-      default:
-        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
-    }
+    mReportCallback(memreport);
     return NS_OK;
   }
 
  private:
   ~HandleReportCallback() = default;
 
   uint32_t mGeneration;
   const nsCString mProcess;
+  ReportCallback mReportCallback;
 };
 
 NS_IMPL_ISUPPORTS(HandleReportCallback, nsIHandleReportCallback)
 
 class FinishReportingCallback final : public nsIFinishReportingCallback {
  public:
+  using FinishCallback = typename MemoryReportRequestClient::FinishCallback;
+
   NS_DECL_ISUPPORTS
 
-  explicit FinishReportingCallback(uint32_t aGeneration)
-      : mGeneration(aGeneration) {}
+  explicit FinishReportingCallback(uint32_t aGeneration,
+                                   const FinishCallback& aFinishCallback)
+      : mGeneration(aGeneration),
+        mFinishCallback(aFinishCallback) {}
 
   NS_IMETHOD Callback(nsISupports* aUnused) override {
-    bool sent = false;
-    switch (XRE_GetProcessType()) {
-      case GeckoProcessType_Content:
-        sent =
-            ContentChild::GetSingleton()->SendFinishMemoryReport(mGeneration);
-        break;
-      case GeckoProcessType_GPU:
-        sent =
-            gfx::GPUParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
-        break;
-      case GeckoProcessType_RDD:
-        sent = RDDParent::GetSingleton()->SendFinishMemoryReport(mGeneration);
-        break;
-      default:
-        MOZ_ASSERT_UNREACHABLE("Unhandled process type");
-    }
-    return sent ? NS_OK : NS_ERROR_FAILURE;
+    return mFinishCallback(mGeneration) ? NS_OK : NS_ERROR_FAILURE;
   }
 
  private:
   ~FinishReportingCallback() = default;
 
   uint32_t mGeneration;
+  FinishCallback mFinishCallback;
 };
 
 NS_IMPL_ISUPPORTS(FinishReportingCallback, nsIFinishReportingCallback)
 
 NS_IMETHODIMP MemoryReportRequestClient::Run() {
   nsCOMPtr<nsIMemoryReporterManager> mgr =
       do_GetService("@mozilla.org/memory-reporter-manager;1");
 
   // Run the reporters.  The callback will turn each measurement into a
   // MemoryReport.
   RefPtr<HandleReportCallback> handleReport =
-      new HandleReportCallback(mGeneration, mProcessString);
+      new HandleReportCallback(mGeneration, mProcessString, mReportCallback);
   RefPtr<FinishReportingCallback> finishReporting =
-      new FinishReportingCallback(mGeneration);
+      new FinishReportingCallback(mGeneration, mFinishCallback);
 
   nsresult rv = mgr->GetReportsForThisProcessExtended(
       handleReport, nullptr, mAnonymize, FileDescriptorToFILE(mDMDFile, "wb"),
       finishReporting, nullptr);
   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
                        "GetReportsForThisProcessExtended failed");
   return rv;
 }
--- a/dom/ipc/MemoryReportRequest.h
+++ b/dom/ipc/MemoryReportRequest.h
@@ -6,22 +6,25 @@
 
 #ifndef mozilla_dom_MemoryReportRequest_h_
 #define mozilla_dom_MemoryReportRequest_h_
 
 #include "mozilla/dom/MemoryReportTypes.h"
 #include "mozilla/ipc/FileDescriptor.h"
 #include "nsISupports.h"
 
+#include <functional>
+
 class nsMemoryReporterManager;
 
 namespace mozilla {
 namespace dom {
 
 class MaybeFileDesc;
+class MemoryReport;
 
 class MemoryReportRequestHost final {
  public:
   explicit MemoryReportRequestHost(uint32_t aGeneration);
   ~MemoryReportRequestHost();
 
   void RecvReport(const MemoryReport& aReport);
   void Finish(uint32_t aGeneration);
@@ -30,34 +33,43 @@ class MemoryReportRequestHost final {
   const uint32_t mGeneration;
   // Non-null if we haven't yet called EndProcessReport() on it.
   RefPtr<nsMemoryReporterManager> mReporterManager;
   bool mSuccess;
 };
 
 class MemoryReportRequestClient final : public nsIRunnable {
  public:
+  using ReportCallback = std::function<void(const MemoryReport&)>;
+  using FinishCallback = std::function<bool(const uint32_t&)>;
+
   NS_DECL_ISUPPORTS
 
   static void Start(uint32_t aGeneration, bool aAnonymize,
                     bool aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile,
-                    const nsACString& aProcessString);
+                    const nsACString& aProcessString,
+                    const ReportCallback& aReportCallback,
+                    const FinishCallback& aFinishCallback);
 
   NS_IMETHOD Run() override;
 
  private:
   MemoryReportRequestClient(uint32_t aGeneration, bool aAnonymize,
                             const MaybeFileDesc& aDMDFile,
-                            const nsACString& aProcessString);
+                            const nsACString& aProcessString,
+                            const ReportCallback& aReportCallback,
+                            const FinishCallback& aFinishCallback);
 
  private:
   ~MemoryReportRequestClient();
 
   uint32_t mGeneration;
   bool mAnonymize;
   mozilla::ipc::FileDescriptor mDMDFile;
   nsCString mProcessString;
+  ReportCallback mReportCallback;
+  FinishCallback mFinishCallback;
 };
 
 }  // namespace dom
 }  // namespace mozilla
 
 #endif  // mozilla_dom_MemoryReportRequest_h_
--- a/dom/media/ipc/RDDParent.cpp
+++ b/dom/media/ipc/RDDParent.cpp
@@ -150,17 +150,23 @@ mozilla::ipc::IPCResult RDDParent::RecvN
 }
 
 mozilla::ipc::IPCResult RDDParent::RecvRequestMemoryReport(
     const uint32_t& aGeneration, const bool& aAnonymize,
     const bool& aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile) {
   nsPrintfCString processName("RDD (pid %u)", (unsigned)getpid());
 
   mozilla::dom::MemoryReportRequestClient::Start(
-      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName);
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
+      [&](const MemoryReport& aReport) {
+        Unused << GetSingleton()->SendAddMemoryReport(aReport);
+      },
+      [&](const uint32_t& aGeneration) {
+        return GetSingleton()->SendFinishMemoryReport(aGeneration);
+      });
   return IPC_OK();
 }
 
 void RDDParent::ActorDestroy(ActorDestroyReason aWhy) {
   if (AbnormalShutdown == aWhy) {
     NS_WARNING("Shutting down RDD process early due to a crash!");
     ProcessChild::QuickExit();
   }
--- a/gfx/ipc/GPUParent.cpp
+++ b/gfx/ipc/GPUParent.cpp
@@ -442,17 +442,23 @@ mozilla::ipc::IPCResult GPUParent::RecvN
 
 mozilla::ipc::IPCResult GPUParent::RecvRequestMemoryReport(
     const uint32_t& aGeneration, const bool& aAnonymize,
     const bool& aMinimizeMemoryUsage, const MaybeFileDesc& aDMDFile) {
   nsAutoCString processName;
   GetGPUProcessName(processName);
 
   mozilla::dom::MemoryReportRequestClient::Start(
-      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName);
+      aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile, processName,
+      [&](const MemoryReport& aReport) {
+        Unused << GetSingleton()->SendAddMemoryReport(aReport);
+      },
+      [&](const uint32_t& aGeneration) {
+        return GetSingleton()->SendFinishMemoryReport(aGeneration);
+      });
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult GPUParent::RecvShutdownVR() {
   if (gfxPrefs::VRProcessEnabled()) {
     VRGPUChild::ShutDown();
   }
   return IPC_OK();