Backed out changeset 9f9ee7372552 (bug 946407) for mochitest-other failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 04 Mar 2014 16:54:00 -0500
changeset 171948 f933ff8712fe66f764e79fbf815b6fbf5023c876
parent 171947 9f9ee7372552232fdcce77ab1da09e64a4713620
child 171949 eb8228a9ad6dd3f00d7931c010c6948bf7a465ee
push id26343
push usercbook@mozilla.com
push dateWed, 05 Mar 2014 12:27:10 +0000
treeherdermozilla-central@714c8927d6af [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs946407
milestone30.0a1
backs out9f9ee7372552232fdcce77ab1da09e64a4713620
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
Backed out changeset 9f9ee7372552 (bug 946407) for mochitest-other failures. CLOSED TREE
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
js/xpconnect/src/XPCJSRuntime.cpp
mobile/android/chrome/content/MemoryObserver.js
xpcom/base/nsIMemoryInfoDumper.idl
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryInfoDumper.cpp
xpcom/base/nsMemoryInfoDumper.h
xpcom/base/nsMemoryReporterManager.cpp
xpcom/base/nsMemoryReporterManager.h
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -167,34 +167,24 @@ static bool sNuwaForking = false;
 
 // A sentinel value for checking whether RESERVED_INT_STACK is large enough.
 #define STACK_SENTINEL_VALUE 0xdeadbeef
 #endif
 
 namespace mozilla {
 namespace dom {
 
-class MemoryReportRequestChild : public PMemoryReportRequestChild,
-                                 public nsIRunnable
+class MemoryReportRequestChild : public PMemoryReportRequestChild
 {
 public:
-    NS_DECL_ISUPPORTS
-
-    MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent);
+    MemoryReportRequestChild();
     virtual ~MemoryReportRequestChild();
-    NS_IMETHOD Run();
-private:
-    uint32_t mGeneration;
-    nsString mDMDDumpIdent;
 };
 
-NS_IMPL_ISUPPORTS1(MemoryReportRequestChild, nsIRunnable)
-
-MemoryReportRequestChild::MemoryReportRequestChild(uint32_t aGeneration, const nsAString& aDMDDumpIdent)
-: mGeneration(aGeneration), mDMDDumpIdent(aDMDDumpIdent)
+MemoryReportRequestChild::MemoryReportRequestChild()
 {
     MOZ_COUNT_CTOR(MemoryReportRequestChild);
 }
 
 MemoryReportRequestChild::~MemoryReportRequestChild()
 {
     MOZ_COUNT_DTOR(MemoryReportRequestChild);
 }
@@ -523,23 +513,19 @@ ContentChild::InitXPCOM()
     sysMsgObserver->Init();
 
 #ifndef MOZ_NUWA_PROCESS
     InitOnContentProcessCreated();
 #endif
 }
 
 PMemoryReportRequestChild*
-ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation,
-                                             const bool &minimizeMemoryUsage,
-                                             const nsString& aDMDDumpIdent)
+ContentChild::AllocPMemoryReportRequestChild(const uint32_t& generation)
 {
-    MemoryReportRequestChild *actor = new MemoryReportRequestChild(generation, aDMDDumpIdent);
-    actor->AddRef();
-    return actor;
+    return new MemoryReportRequestChild();
 }
 
 // This is just a wrapper for InfallibleTArray<MemoryReport> that implements
 // nsISupports, so it can be passed to nsIMemoryReporter::CollectReports.
 class MemoryReportsWrapper MOZ_FINAL : public nsISupports {
 public:
     NS_DECL_ISUPPORTS
     MemoryReportsWrapper(InfallibleTArray<MemoryReport> *r) : mReports(r) { }
@@ -576,71 +562,64 @@ private:
 NS_IMPL_ISUPPORTS1(
   MemoryReportCallback
 , nsIMemoryReporterCallback
 )
 
 bool
 ContentChild::RecvPMemoryReportRequestConstructor(
     PMemoryReportRequestChild* child,
-    const uint32_t& generation,
-    const bool& minimizeMemoryUsage,
-    const nsString& aDMDDumpIdent)
+    const uint32_t& generation)
 {
-    MemoryReportRequestChild *actor = static_cast<MemoryReportRequestChild*>(child);
-    nsresult rv;
-
-    if (minimizeMemoryUsage) {
-        nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
-        rv = mgr->MinimizeMemoryUsage(actor);
-        // mgr will eventually call actor->Run()
-    } else {
-        rv = actor->Run();
-    }
-
-    return !NS_WARN_IF(NS_FAILED(rv));
-}
-
-NS_IMETHODIMP MemoryReportRequestChild::Run()
-{
-    ContentChild *child = static_cast<ContentChild*>(Manager());
     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
 
     InfallibleTArray<MemoryReport> reports;
 
     nsCString process;
-    child->GetProcessName(process);
-    child->AppendProcessId(process);
+    GetProcessName(process);
+    AppendProcessId(process);
 
     // Run the reporters.  The callback will turn each measurement into a
     // MemoryReport.
     nsRefPtr<MemoryReportsWrapper> wrappedReports =
         new MemoryReportsWrapper(&reports);
     nsRefPtr<MemoryReportCallback> cb = new MemoryReportCallback(process);
-    mgr->GetReportsForThisProcessExtended(cb, wrappedReports, mDMDDumpIdent);
+    mgr->GetReportsForThisProcess(cb, wrappedReports);
 
-    bool sent = Send__delete__(this, mGeneration, reports);
-    return sent ? NS_OK : NS_ERROR_FAILURE;
+    child->Send__delete__(child, generation, reports);
+    return true;
 }
 
 bool
 ContentChild::RecvAudioChannelNotify()
 {
     nsRefPtr<AudioChannelService> service =
         AudioChannelService::GetAudioChannelService();
     if (service) {
         service->Notify();
     }
     return true;
 }
 
 bool
 ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
 {
-    static_cast<MemoryReportRequestChild*>(actor)->Release();
+    delete actor;
+    return true;
+}
+
+bool
+ContentChild::RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier,
+                                          const bool& aMinimizeMemoryUsage,
+                                          const bool& aDumpChildProcesses)
+{
+    nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
+
+    dumper->DumpMemoryInfoToTempDir(aIdentifier, aMinimizeMemoryUsage,
+                                    aDumpChildProcesses);
     return true;
 }
 
 bool
 ContentChild::RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
                                         const bool& aDumpAllTraces,
                                         const bool& aDumpChildProcesses)
 {
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -110,32 +110,33 @@ public:
 
     virtual PHalChild* AllocPHalChild() MOZ_OVERRIDE;
     virtual bool DeallocPHalChild(PHalChild*) MOZ_OVERRIDE;
 
     virtual PIndexedDBChild* AllocPIndexedDBChild() MOZ_OVERRIDE;
     virtual bool DeallocPIndexedDBChild(PIndexedDBChild* aActor) MOZ_OVERRIDE;
 
     virtual PMemoryReportRequestChild*
-    AllocPMemoryReportRequestChild(const uint32_t& generation,
-                                   const bool &minimizeMemoryUsage,
-                                   const nsString &aDMDDumpIdent) MOZ_OVERRIDE;
+    AllocPMemoryReportRequestChild(const uint32_t& generation) MOZ_OVERRIDE;
+
     virtual bool
     DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) MOZ_OVERRIDE;
 
     virtual bool
     RecvPMemoryReportRequestConstructor(PMemoryReportRequestChild* child,
-                                        const uint32_t& generation,
-                                        const bool &minimizeMemoryUsage,
-                                        const nsString &aDMDDumpIdent) MOZ_OVERRIDE;
+                                        const uint32_t& generation) MOZ_OVERRIDE;
 
     virtual bool
     RecvAudioChannelNotify() MOZ_OVERRIDE;
 
     virtual bool
+    RecvDumpMemoryInfoToTempDir(const nsString& aIdentifier,
+                                const bool& aMinimizeMemoryUsage,
+                                const bool& aDumpChildProcesses) MOZ_OVERRIDE;
+    virtual bool
     RecvDumpGCAndCCLogsToFile(const nsString& aIdentifier,
                               const bool& aDumpAllTraces,
                               const bool& aDumpChildProcesses) MOZ_OVERRIDE;
 
     virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE;
     virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE;
     virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE;
     jsipc::JavaScriptChild *GetCPOWManager();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2035,38 +2035,20 @@ ContentParent::Observe(nsISupports* aSub
     else if (!strcmp(aTopic, "alertfinished") ||
              !strcmp(aTopic, "alertclickcallback") ||
              !strcmp(aTopic, "alertshow") ) {
         if (!SendNotifyAlertsObserver(nsDependentCString(aTopic),
                                       nsDependentString(aData)))
             return NS_ERROR_NOT_AVAILABLE;
     }
     else if (!strcmp(aTopic, "child-memory-reporter-request")) {
-        bool isNuwa = false;
 #ifdef MOZ_NUWA_PROCESS
-        isNuwa = IsNuwaProcess();
+        if (!IsNuwaProcess())
 #endif
-        if (!isNuwa) {
-            unsigned generation;
-            int minimize, identOffset = -1;
-            nsDependentString msg(aData);
-            NS_ConvertUTF16toUTF8 cmsg(msg);
-
-            if (sscanf(cmsg.get(),
-                       "generation=%x minimize=%d DMDident=%n",
-                       &generation, &minimize, &identOffset) < 2
-                || identOffset < 0) {
-                return NS_ERROR_INVALID_ARG;
-            }
-            // The pre-%n part of the string should be all ASCII, so the byte
-            // offset in identOffset should be correct as a char offset.
-            MOZ_ASSERT(cmsg[identOffset - 1] == '=');
-            unused << SendPMemoryReportRequestConstructor(
-              generation, minimize, nsString(Substring(msg, identOffset)));
-        }
+            unused << SendPMemoryReportRequestConstructor((uint32_t)(uintptr_t)aData);
     }
     else if (!strcmp(aTopic, "child-gc-request")){
         unused << SendGarbageCollect();
     }
     else if (!strcmp(aTopic, "child-cc-request")){
         unused << SendCycleCollect();
     }
     else if (!strcmp(aTopic, "child-mmu-request")){
@@ -2517,19 +2499,17 @@ ContentParent::RecvPIndexedDBConstructor
   IndexedDBParent* actor = static_cast<IndexedDBParent*>(aActor);
   actor->mFactory = factory;
   actor->mASCIIOrigin = factory->GetASCIIOrigin();
 
   return true;
 }
 
 PMemoryReportRequestParent*
-ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation,
-                                               const bool &minimizeMemoryUsage,
-                                               const nsString &aDMDDumpIdent)
+ContentParent::AllocPMemoryReportRequestParent(const uint32_t& generation)
 {
   MemoryReportRequestParent* parent = new MemoryReportRequestParent();
   return parent;
 }
 
 bool
 ContentParent::DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -354,19 +354,17 @@ private:
     virtual bool RecvGetRandomValues(const uint32_t& length,
                                      InfallibleTArray<uint8_t>* randomValues) MOZ_OVERRIDE;
 
     virtual bool DeallocPHalParent(PHalParent*) MOZ_OVERRIDE;
 
     virtual bool DeallocPIndexedDBParent(PIndexedDBParent* aActor) MOZ_OVERRIDE;
 
     virtual PMemoryReportRequestParent*
-    AllocPMemoryReportRequestParent(const uint32_t& generation,
-                                    const bool &minimizeMemoryUsage,
-                                    const nsString &aDMDDumpIdent) MOZ_OVERRIDE;
+    AllocPMemoryReportRequestParent(const uint32_t& generation) MOZ_OVERRIDE;
     virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) MOZ_OVERRIDE;
 
     virtual PTestShellParent* AllocPTestShellParent() MOZ_OVERRIDE;
     virtual bool DeallocPTestShellParent(PTestShellParent* shell) MOZ_OVERRIDE;
 
     virtual bool DeallocPNeckoParent(PNeckoParent* necko) MOZ_OVERRIDE;
 
     virtual PExternalHelperAppParent* AllocPExternalHelperAppParent(
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -268,30 +268,39 @@ both:
 child:
     /**
      * Update OS process privileges to |privs|.  Can usually only be
      * performed zero or one times.  The child will abnormally exit if
      * the privilege update fails.
      */
     async SetProcessPrivileges(ChildPrivileges privs);
 
-    PMemoryReportRequest(uint32_t generation, bool minimizeMemoryUsage, nsString DMDDumpIdent);
+    PMemoryReportRequest(uint32_t generation);
 
     /**
      * Notify the AudioChannelService in the child processes.
      */
     async AudioChannelNotify();
 
     async SpeakerManagerNotify();
 
     /**
+     * Do a memory info dump to a file in our temp directory.
+     *
+     * For documentation on the args, see
+     * MemoryInfoDumper::dumpMemoryInfoToTempDir.
+     */
+    async DumpMemoryInfoToTempDir(nsString identifier,
+                                  bool minimizeMemoryUsage,
+                                  bool dumpChildProcesses);
+    /**
      * Dump this process's GC and CC logs.
      *
-     * For documentation on the args, see dumpGCAndCCLogsToFile in
-     * nsIMemoryInfoDumper.idl
+     * For documentation on the args, see
+     * MemoryInfoDumper::dumpGCAndCCLogsToFile.
      */
     async DumpGCAndCCLogsToFile(nsString identifier,
                                 bool dumpAllTraces,
                                 bool dumpChildProcesses);
 
     PTestShell();
 
     RegisterChrome(ChromePackage[] packages, ResourceMapping[] resources,
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1407,17 +1407,18 @@ XPCJSRuntime::OutOfMemoryCallback(JSCont
     nsCOMPtr<nsIMemoryInfoDumper> dumper =
         do_GetService("@mozilla.org/memory-info-dumper;1");
     if (!dumper) {
         return;
     }
 
     // If this fails, it fails silently.
     dumper->DumpMemoryInfoToTempDir(NS_LITERAL_STRING("due-to-JS-OOM"),
-                                    /* minimizeMemoryUsage = */ false);
+                                    /* minimizeMemoryUsage = */ false,
+                                    /* dumpChildProcesses = */ false);
 }
 
 size_t
 XPCJSRuntime::SizeOfIncludingThis(MallocSizeOf mallocSizeOf)
 {
     size_t n = 0;
     n += mallocSizeOf(this);
     n += mWrappedJSMap->SizeOfIncludingThis(mallocSizeOf);
--- a/mobile/android/chrome/content/MemoryObserver.js
+++ b/mobile/android/chrome/content/MemoryObserver.js
@@ -55,11 +55,11 @@ var MemoryObserver = {
 
   gc: function() {
     window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).garbageCollect();
     Cu.forceGC();
   },
 
   dumpMemoryStats: function(aLabel) {
     let memDumper = Cc["@mozilla.org/memory-info-dumper;1"].getService(Ci.nsIMemoryInfoDumper);
-    memDumper.dumpMemoryInfoToTempDir(aLabel, /* minimize = */ false);
+    memDumper.dumpMemoryInfoToTempDir(aLabel, false, true);
   },
 };
--- a/xpcom/base/nsIMemoryInfoDumper.idl
+++ b/xpcom/base/nsIMemoryInfoDumper.idl
@@ -6,17 +6,17 @@
 #include "nsISupports.idl"
 
 [scriptable, function, uuid(2dea18fc-fbfa-4bf7-ad45-0efaf5495f5e)]
 interface nsIFinishDumpingCallback : nsISupports
 {
   void callback(in nsISupports data);
 };
 
-[scriptable, builtinclass, uuid(815bf31b-f5bd-425d-85c3-4657a7a91dad)]
+[scriptable, builtinclass, uuid(294df03b-e2ae-4fdd-b4fc-4c66a501e0ef)]
 interface nsIMemoryInfoDumper : nsISupports
 {
   /**
    * This dumps gzipped memory reports for this process and its child
    * processes.  If a file of the given name exists, it will be overwritten.
    *
    * @param aFilename The output file.
    *
@@ -89,40 +89,47 @@ interface nsIMemoryInfoDumper : nsISuppo
    * }
    */
   void dumpMemoryReportsToNamedFile(in AString aFilename,
                                     in nsIFinishDumpingCallback aFinishDumping,
                                     in nsISupports aFinishDumpingData);
 
   /**
    * Similar to dumpMemoryReportsToNamedFile, this method dumps gzipped memory
-   * reports for this process and its child processes to files in the tmp
-   * directory called memory-reports-<identifier>-<pid>.json.gz (or something
-   * similar, such as memory-reports-<identifier>-<pid>-1.json.gz; no existing
-   * file will be overwritten).
+   * reports for this process and possibly its child processes (and their
+   * children, recursively) to a file in the tmp directory called
+   * memory-reports-<identifier>-<pid>.json.gz (or something similar, such as
+   * memory-reports-<identifier>-<pid>-1.json.gz; no existing file will be
+   * overwritten).
    *
    * If DMD is enabled, this method also dumps gzipped DMD output to a file in
    * the tmp directory called dmd-<identifier>-<pid>.txt.gz (or something
    * similar; again, no existing file will be overwritten).
    *
    * @param aIdentifier this identifier will appear in the filename of our
-   *   about:memory dump and those of our children.
+   *   about:memory dump and those of our children (if aDumpChildProcesses is
+   *   true).
    *
    *   If the identifier is empty, the implementation may set it arbitrarily
    *   and use that new value for its own dump and the dumps of its child
    *   processes.  For example, the implementation may set |aIdentifier| to the
    *   number of seconds since the epoch.
    *
    * @param aMinimizeMemoryUsage indicates whether we should run a series of
    *   gc/cc's in an attempt to reduce our memory usage before collecting our
    *   memory report.
+   *
+   * @param aDumpChildProcesses indicates whether we should call
+   *   dumpMemoryInfoToTempDir in our child processes.  If
+   *   so, the child processes will also dump their children, and so on.
    */
   void dumpMemoryInfoToTempDir(
     in AString aIdentifier,
-    in bool aMinimizeMemoryUsage);
+    in bool aMinimizeMemoryUsage,
+    in bool aDumpChildProcesses);
 
   /**
    * Dump GC and CC logs to files in the OS's temp directory (or in
    * $MOZ_CC_LOG_DIRECTORY, if that environment variable is specified).
    *
    * @param aIdentifier If aIdentifier is non-empty, this string will appear in
    *   the filenames of the logs we create (both for this process and, if
    *   aDumpChildProcesses is true, for our child processes).
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -173,17 +173,17 @@ interface nsIMemoryReporter : nsISupport
 };
 
 [scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)]
 interface nsIFinishReportingCallback : nsISupports
 {
   void callback(in nsISupports data);
 };
 
-[scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)]
+[scriptable, builtinclass, uuid(12e08b1b-6590-4f78-996b-d9062c17e856)]
 interface nsIMemoryReporterManager : nsISupports
 {
   /*
    * Initialize.
    */
   void init();
 
   /*
@@ -238,48 +238,23 @@ interface nsIMemoryReporterManager : nsI
    * catch and ignore any error anyway.
    */
   void getReports(in nsIMemoryReporterCallback handleReport,
                   in nsISupports handleReportData,
                   in nsIFinishReportingCallback finishReporting,
                   in nsISupports finishReportingData);
 
   /*
-   * As above, but: If |minimizeMemoryUsage| is true, then each process will
-   * minimize its memory usage (see the |minimizeMemoryUsage| method) before
-   * gathering its report.  If DMD is enabled and |DMDDumpIdent| is non-empty
-   * then write a DMD report to a file in the usual temporary directory (see
-   * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
-   */
-  [noscript] void
-    getReportsExtended(in nsIMemoryReporterCallback handleReport,
-                       in nsISupports handleReportData,
-                       in nsIFinishReportingCallback finishReporting,
-                       in nsISupports finishReportingData,
-                       in boolean minimizeMemoryUsage,
-                       in AString DMDDumpIdent);
-
-  /*
    * Get memory reports in the current process only.  |handleReport| is called
    * for each report.
    */
   void getReportsForThisProcess(in nsIMemoryReporterCallback handleReport,
                                 in nsISupports handleReportData);
 
   /*
-   * As above, but if DMD is enabled and |DMDDumpIdent| is non-empty
-   * then write a DMD report to a file in the usual temporary directory (see
-   * |dumpMemoryInfoToTempDir| in |nsIMemoryInfoDumper|.)
-   */
-  [noscript] void
-    getReportsForThisProcessExtended(in nsIMemoryReporterCallback handleReport,
-                                     in nsISupports handleReportData,
-                                     in AString DMDDumpIdent);
-
-  /*
    * The memory reporter manager, for the most part, treats reporters
    * registered with it as a black box.  However, there are some
    * "distinguished" amounts (as could be reported by a memory reporter) that
    * the manager provides as attributes, because they are sufficiently
    * interesting that we want external code (e.g. telemetry) to be able to rely
    * on them.
    *
    * Note that these are not reporters and so getReports() and
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -55,31 +55,35 @@ using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace {
 
 class DumpMemoryInfoToTempDirRunnable : public nsRunnable
 {
 public:
   DumpMemoryInfoToTempDirRunnable(const nsAString& aIdentifier,
-                                  bool aMinimizeMemoryUsage)
+                                  bool aMinimizeMemoryUsage,
+                                  bool aDumpChildProcesses)
       : mIdentifier(aIdentifier)
       , mMinimizeMemoryUsage(aMinimizeMemoryUsage)
+      , mDumpChildProcesses(aDumpChildProcesses)
   {}
 
   NS_IMETHOD Run()
   {
     nsCOMPtr<nsIMemoryInfoDumper> dumper = do_GetService("@mozilla.org/memory-info-dumper;1");
-    dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage);
+    dumper->DumpMemoryInfoToTempDir(mIdentifier, mMinimizeMemoryUsage,
+                                    mDumpChildProcesses);
     return NS_OK;
   }
 
 private:
   const nsString mIdentifier;
   const bool mMinimizeMemoryUsage;
+  const bool mDumpChildProcesses;
 };
 
 class GCAndCCLogDumpRunnable : public nsRunnable
 {
 public:
   GCAndCCLogDumpRunnable(const nsAString& aIdentifier,
                          bool aDumpAllTraces,
                          bool aDumpChildProcesses)
@@ -348,17 +352,18 @@ public:
     }
 
     if (signum == sDumpAboutMemorySignum ||
         signum == sDumpAboutMemoryAfterMMUSignum) {
       // Dump our memory reports (but run this on the main thread!).
       bool doMMUFirst = signum == sDumpAboutMemoryAfterMMUSignum;
       nsRefPtr<DumpMemoryInfoToTempDirRunnable> runnable =
         new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(),
-                                            doMMUFirst);
+                                            doMMUFirst,
+                                            /* dumpChildProcesses = */ true);
       NS_DispatchToMainThread(runnable);
     }
     else if (signum == sGCAndCCDumpSignum) {
       // Dump GC and CC logs (from the main thread).
       nsRefPtr<GCAndCCLogDumpRunnable> runnable =
         new GCAndCCLogDumpRunnable(
             /* identifier = */ EmptyString(),
             /* allTraces = */ true,
@@ -510,17 +515,18 @@ public:
     bool doMMUMemoryReport = inputStr == NS_LITERAL_CSTRING("minimize memory report");
     bool doAllTracesGCCCDump = inputStr == NS_LITERAL_CSTRING("gc log");
     bool doSmallGCCCDump = inputStr == NS_LITERAL_CSTRING("abbreviated gc log");
 
     if (doMemoryReport || doMMUMemoryReport) {
       LOG("FifoWatcher dispatching memory report runnable.");
       nsRefPtr<DumpMemoryInfoToTempDirRunnable> runnable =
         new DumpMemoryInfoToTempDirRunnable(/* identifier = */ EmptyString(),
-                                            doMMUMemoryReport);
+                                            doMMUMemoryReport,
+                                            /* dumpChildProcesses = */ true);
       NS_DispatchToMainThread(runnable);
     } else if (doAllTracesGCCCDump || doSmallGCCCDump) {
       LOG("FifoWatcher dispatching GC/CC log runnable.");
       nsRefPtr<GCAndCCLogDumpRunnable> runnable =
         new GCAndCCLogDumpRunnable(
             /* identifier = */ EmptyString(),
             doAllTracesGCCCDump,
             /* dumpChildProcesses = */ true);
@@ -819,48 +825,35 @@ DumpHeader(nsIGZFileWriter* aWriter)
 static nsresult
 DumpFooter(nsIGZFileWriter* aWriter)
 {
   DUMP(aWriter, "\n  ]\n}\n");
 
   return NS_OK;
 }
 
-class TempDirMemoryFinishCallback MOZ_FINAL : public nsIFinishReportingCallback
+static nsresult
+DumpProcessMemoryReportsToGZFileWriter(nsGZFileWriter* aWriter)
 {
-public:
-  NS_DECL_ISUPPORTS
-
-  TempDirMemoryFinishCallback(nsGZFileWriter *aWriter,
-                              nsIFile *aTmpFile,
-                              const nsCString &aFilename,
-                              const nsString &aIdentifier)
-    : mrWriter(aWriter)
-    , mrTmpFile(aTmpFile)
-    , mrFilename(aFilename)
-    , mIdentifier(aIdentifier)
-  {}
+  nsresult rv = DumpHeader(aWriter);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  NS_IMETHOD Callback(nsISupports *aData);
-
-private:
-  nsRefPtr<nsGZFileWriter> mrWriter;
-  nsCOMPtr<nsIFile> mrTmpFile;
-  nsCString mrFilename;
-  nsString mIdentifier;
-};
+  // Process reporters.
+  nsCOMPtr<nsIMemoryReporterManager> mgr =
+    do_GetService("@mozilla.org/memory-reporter-manager;1");
+  nsRefPtr<DumpReportCallback> dumpReport = new DumpReportCallback(aWriter);
+  mgr->GetReportsForThisProcess(dumpReport, nullptr);
 
-NS_IMPL_ISUPPORTS1(TempDirMemoryFinishCallback, nsIFinishReportingCallback)
+  return DumpFooter(aWriter);
+}
 
-NS_IMETHODIMP
-nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier,
-                                            bool aMinimizeMemoryUsage)
+nsresult
+DumpProcessMemoryInfoToTempDir(const nsAString& aIdentifier)
 {
-  nsString identifier(aIdentifier);
-  EnsureNonEmptyIdentifier(identifier);
+  MOZ_ASSERT(!aIdentifier.IsEmpty());
 
 #ifdef MOZ_DMD
   // Clear DMD's reportedness state before running the memory reporters, to
   // avoid spurious twice-reported warnings.
   dmd::ClearReports();
 #endif
 
   // Open a new file named something like
@@ -872,60 +865,35 @@ nsMemoryInfoDumper::DumpMemoryInfoToTemp
   //
   // We do this because we don't want scripts which poll the filesystem
   // looking for memory report dumps to grab a file before we're finished
   // writing to it.
 
   // Note that |mrFilename| is missing the "incomplete-" prefix; we'll tack
   // that on in a moment.
   nsCString mrFilename;
-  // The "unified" indicates that we merge the memory reports from all
-  // processes and write out one file, rather than a separate file for
-  // each process as was the case before bug 946407.  This is so that
-  // the get_about_memory.py script in the B2G repository can
-  // determine when it's done waiting for files to appear.
-  MakeFilename("unified-memory-report", identifier, "json.gz", mrFilename);
+  MakeFilename("memory-report", aIdentifier, "json.gz", mrFilename);
 
   nsCOMPtr<nsIFile> mrTmpFile;
   nsresult rv;
   rv = nsMemoryInfoDumper::OpenTempFile(NS_LITERAL_CSTRING("incomplete-") +
                                         mrFilename,
                                         getter_AddRefs(mrTmpFile));
   if (NS_WARN_IF(NS_FAILED(rv)))
     return rv;
 
   nsRefPtr<nsGZFileWriter> mrWriter = new nsGZFileWriter();
   rv = mrWriter->Init(mrTmpFile);
   if (NS_WARN_IF(NS_FAILED(rv)))
     return rv;
 
   // Dump the memory reports to the file.
-  rv = DumpHeader(mrWriter);
-  if (NS_WARN_IF(NS_FAILED(rv)))
-    return rv;
-
-  // Process reporters.
-  nsCOMPtr<nsIMemoryReporterManager> mgr =
-    do_GetService("@mozilla.org/memory-reporter-manager;1");
-  nsRefPtr<DumpReportCallback> dumpReport = new DumpReportCallback(mrWriter);
-  nsRefPtr<nsIFinishReportingCallback> finishReport =
-    new TempDirMemoryFinishCallback(mrWriter, mrTmpFile, mrFilename, identifier);
-  rv = mgr->GetReportsExtended(dumpReport, nullptr,
-                               finishReport, nullptr,
-                               aMinimizeMemoryUsage,
-                               identifier);
-  return rv;
-}
+  DumpProcessMemoryReportsToGZFileWriter(mrWriter);
 
 #ifdef MOZ_DMD
-nsresult
-nsMemoryInfoDumper::DumpDMD(const nsAString &aIdentifier)
-{
-  nsresult rv;
-
   // Create a filename like dmd-<identifier>-<pid>.txt.gz, which will be used
   // if DMD is enabled.
   nsCString dmdFilename;
   MakeFilename("dmd", aIdentifier, "txt.gz", dmdFilename);
 
   // Open a new DMD file named |dmdFilename| in NS_OS_TEMP_DIR for writing,
   // and dump DMD output to it.  This must occur after the memory reporters
   // have been run (above), but before the memory-reports file has been
@@ -943,29 +911,19 @@ nsMemoryInfoDumper::DumpDMD(const nsAStr
 
   // Dump DMD output to the file.
 
   DMDWriteState state(dmdWriter);
   dmd::Writer w(DMDWrite, &state);
   dmd::Dump(w);
 
   rv = dmdWriter->Finish();
-  NS_WARN_IF(NS_FAILED(rv));
-  return rv;
-}
-#endif  // MOZ_DMD
-
-NS_IMETHODIMP
-TempDirMemoryFinishCallback::Callback(nsISupports *aData)
-{
-  nsresult rv;
-
-  rv = DumpFooter(mrWriter);
   if (NS_WARN_IF(NS_FAILED(rv)))
     return rv;
+#endif  // MOZ_DMD
 
   // The call to Finish() deallocates the memory allocated by mrWriter's first
   // DUMP() call (within DumpProcessMemoryReportsToGZFileWriter()).  Because
   // that memory was live while the memory reporters ran and thus measured by
   // them -- by "heap-allocated" if nothing else -- we want DMD to see it as
   // well.  So we deliberately don't call Finish() until after DMD finishes.
   rv = mrWriter->Finish();
   if (NS_WARN_IF(NS_FAILED(rv)))
@@ -1015,16 +973,54 @@ TempDirMemoryFinishCallback::Callback(ns
     return rv;
 
   nsString msg = NS_LITERAL_STRING(
     "nsIMemoryInfoDumper dumped reports to ");
   msg.Append(path);
   return cs->LogStringMessage(msg.get());
 }
 
+NS_IMETHODIMP
+nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier,
+                                            bool aMinimizeMemoryUsage,
+                                            bool aDumpChildProcesses)
+{
+  nsString identifier(aIdentifier);
+  EnsureNonEmptyIdentifier(identifier);
+
+  // Kick off memory report dumps in our child processes, if applicable.  We
+  // do this before doing our own report because writing a report may be I/O
+  // bound, in which case we want to busy the CPU with other reports while we
+  // work on our own.
+  if (aDumpChildProcesses) {
+    nsTArray<ContentParent*> children;
+    ContentParent::GetAll(children);
+    for (uint32_t i = 0; i < children.Length(); i++) {
+      unused << children[i]->SendDumpMemoryInfoToTempDir(
+          identifier, aMinimizeMemoryUsage, aDumpChildProcesses);
+    }
+  }
+
+  if (aMinimizeMemoryUsage) {
+    // Minimize memory usage, then run DumpMemoryInfoToTempDir again.
+    nsRefPtr<DumpMemoryInfoToTempDirRunnable> callback =
+      new DumpMemoryInfoToTempDirRunnable(identifier,
+                                          /* minimizeMemoryUsage = */ false,
+                                          /* dumpChildProcesses = */ false);
+    nsCOMPtr<nsIMemoryReporterManager> mgr =
+      do_GetService("@mozilla.org/memory-reporter-manager;1");
+    if (NS_WARN_IF(!mgr))
+      return NS_ERROR_FAILURE;
+    mgr->MinimizeMemoryUsage(callback);
+    return NS_OK;
+  }
+
+  return DumpProcessMemoryInfoToTempDir(identifier);
+}
+
 // This dumps the JSON footer and closes the file, and then calls the given
 // nsIFinishDumpingCallback.
 class FinishReportingCallback MOZ_FINAL : public nsIFinishReportingCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
   FinishReportingCallback(nsIFinishDumpingCallback* aFinishDumping,
--- a/xpcom/base/nsMemoryInfoDumper.h
+++ b/xpcom/base/nsMemoryInfoDumper.h
@@ -33,18 +33,15 @@ public:
   /**
    * This function creates a new unique file based on |aFilename| in a
    * world-readable temp directory. This is the system temp directory
    * or, in the case of Android, the downloads directory. If |aFile| is
    * non-null, it is assumed to point to a folder, and that folder is used
    * instead.
    */
   static nsresult OpenTempFile(const nsACString &aFilename, nsIFile* *aFile);
-#ifdef MOZ_DMD
-  static nsresult DumpDMD(const nsAString &aIdentifier);
-#endif
 };
 
 #define NS_MEMORY_INFO_DUMPER_CID \
 { 0x00bd71fb, 0x7f09, 0x4ec3, \
 { 0x96, 0xaf, 0xa0, 0xb5, 0x22, 0xb7, 0x79, 0x69 } }
 
 #endif
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -3,17 +3,16 @@
 /* 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 "nsAtomTable.h"
 #include "nsAutoPtr.h"
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
-#include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "nsMemoryReporterManager.h"
 #include "nsITimer.h"
 #include "nsThreadUtils.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIObserverService.h"
 #include "nsIGlobalObject.h"
@@ -948,33 +947,16 @@ nsMemoryReporterManager::DecrementNumChi
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetReports(
   nsIHandleReportCallback* aHandleReport,
   nsISupports* aHandleReportData,
   nsIFinishReportingCallback* aFinishReporting,
   nsISupports* aFinishReportingData)
 {
-  return GetReportsExtended(aHandleReport, aHandleReportData,
-                            aFinishReporting, aFinishReportingData,
-                            /* minimize = */ false,
-                            /* DMDident = */ nsString());
-}
-
-NS_IMETHODIMP
-nsMemoryReporterManager::GetReportsExtended(
-  nsIHandleReportCallback* aHandleReport,
-  nsISupports* aHandleReportData,
-  nsIFinishReportingCallback* aFinishReporting,
-  nsISupports* aFinishReportingData,
-  bool aMinimize,
-  const nsAString& aDMDDumpIdent)
-{
-  nsresult rv;
-
   // Memory reporters are not necessarily threadsafe, so this function must
   // be called from the main thread.
   if (!NS_IsMainThread()) {
     MOZ_CRASH();
   }
 
   uint32_t generation = mNextGeneration++;
 
@@ -992,71 +974,44 @@ nsMemoryReporterManager::GetReportsExten
   if (mNumChildProcesses > 0) {
     // Request memory reports from child processes.  We do this *before*
     // collecting reports for this process so each process can collect
     // reports in parallel.
     nsCOMPtr<nsIObserverService> obs =
       do_GetService("@mozilla.org/observer-service;1");
     NS_ENSURE_STATE(obs);
 
-    nsPrintfCString genStr("generation=%x minimize=%d DMDident=",
-                           generation, aMinimize ? 1 : 0);
-    nsAutoString msg = NS_ConvertUTF8toUTF16(genStr);
-    msg += aDMDDumpIdent;
-
+    // Casting the uint32_t generation to |const char16_t*| is a hack, but
+    // simpler than converting the number to an actual string.
     obs->NotifyObservers(nullptr, "child-memory-reporter-request",
-                         msg.get());
+                         (const char16_t*)(uintptr_t)generation);
 
     nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
     NS_ENSURE_TRUE(timer, NS_ERROR_FAILURE);
-    rv = timer->InitWithFuncCallback(TimeoutCallback,
-                                     this, kTimeoutLengthMS,
-                                     nsITimer::TYPE_ONE_SHOT);
+    nsresult rv = timer->InitWithFuncCallback(TimeoutCallback,
+                                              this, kTimeoutLengthMS,
+                                              nsITimer::TYPE_ONE_SHOT);
     NS_ENSURE_SUCCESS(rv, rv);
 
     mGetReportsState = new GetReportsState(generation,
                                            timer,
                                            mNumChildProcesses,
                                            aHandleReport,
                                            aHandleReportData,
                                            aFinishReporting,
-                                           aFinishReportingData,
-                                           aDMDDumpIdent);
-  } else {
-    mGetReportsState = new GetReportsState(generation,
-                                           nullptr,
-                                           /* mNumChildProcesses = */ 0,
-                                           aHandleReport,
-                                           aHandleReportData,
-                                           aFinishReporting,
-                                           aFinishReportingData,
-                                           aDMDDumpIdent);
+                                           aFinishReportingData);
   }
 
-  if (aMinimize) {
-    rv = MinimizeMemoryUsage(NS_NewRunnableMethod(this, &nsMemoryReporterManager::StartGettingReports));
-  } else {
-    rv = StartGettingReports();
-  }
-  return rv;
-}
-
-nsresult
-nsMemoryReporterManager::StartGettingReports()
-{
-  GetReportsState *s = mGetReportsState;
-
   // Get reports for this process.
-  GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData,
-                                   s->mDMDDumpIdent);
+  GetReportsForThisProcess(aHandleReport, aHandleReportData);
 
   // If there are no child processes, we can finish up immediately.
-  return (s->mNumChildProcesses == 0)
-    ? s->mFinishReporting->Callback(s->mFinishReportingData)
-    : NS_OK;
+  return (mNumChildProcesses == 0)
+       ? aFinishReporting->Callback(aFinishReportingData)
+       : NS_OK;
 }
 
 typedef nsCOMArray<nsIMemoryReporter> MemoryReporterArray;
 
 static PLDHashOperator
 StrongEnumerator(nsRefPtrHashKey<nsIMemoryReporter>* aElem, void* aData)
 {
   MemoryReporterArray *allReporters = static_cast<MemoryReporterArray*>(aData);
@@ -1072,57 +1027,32 @@ WeakEnumerator(nsPtrHashKey<nsIMemoryRep
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetReportsForThisProcess(
   nsIHandleReportCallback* aHandleReport,
   nsISupports* aHandleReportData)
 {
-  return GetReportsForThisProcessExtended(aHandleReport,
-                                          aHandleReportData,
-                                          nsString());
-}
-
-NS_IMETHODIMP
-nsMemoryReporterManager::GetReportsForThisProcessExtended(
-  nsIHandleReportCallback* aHandleReport,
-  nsISupports* aHandleReportData,
-  const nsAString& aDMDDumpIdent)
-{
   // Memory reporters are not necessarily threadsafe, so this function must
   // be called from the main thread.
   if (!NS_IsMainThread()) {
     MOZ_CRASH();
   }
 
-#ifdef MOZ_DMD
-  if (!aDMDDumpIdent.IsEmpty()) {
-    // Clear DMD's reportedness state before running the memory
-    // reporters, to avoid spurious twice-reported warnings.
-    dmd::ClearReports();
-  }
-#endif
-
   MemoryReporterArray allReporters;
   {
     mozilla::MutexAutoLock autoLock(mMutex);
     mStrongReporters->EnumerateEntries(StrongEnumerator, &allReporters);
     mWeakReporters->EnumerateEntries(WeakEnumerator, &allReporters);
   }
   for (uint32_t i = 0; i < allReporters.Length(); i++) {
     allReporters[i]->CollectReports(aHandleReport, aHandleReportData);
   }
 
-#ifdef MOZ_DMD
-  if (!aDMDDumpIdent.IsEmpty()) {
-    return nsMemoryInfoDumper::DumpDMD(aDMDDumpIdent);
-  }
-#endif
-
   return NS_OK;
 }
 
 // This function has no return value.  If something goes wrong, there's no
 // clear place to report the problem to, but that's ok -- we will end up
 // hitting the timeout and executing TimeoutCallback().
 void
 nsMemoryReporterManager::HandleChildReports(
--- a/xpcom/base/nsMemoryReporterManager.h
+++ b/xpcom/base/nsMemoryReporterManager.h
@@ -152,22 +152,19 @@ public:
       mozilla::PodZero(this);
     }
   };
   SizeOfTabFns mSizeOfTabFns;
 
 private:
   nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter,
                                   bool aForce, bool aStrongRef);
-  nsresult StartGettingReports();
 
   static void TimeoutCallback(nsITimer* aTimer, void* aData);
-  // Note: this timeout needs to be long enough to allow for the
-  // possibility of DMD reports and/or running on a low-end phone.
-  static const uint32_t kTimeoutLengthMS = 50000;
+  static const uint32_t kTimeoutLengthMS = 5000;
 
   mozilla::Mutex mMutex;
   bool mIsRegistrationBlocked;
 
   StrongReportersTable* mStrongReporters;
   WeakReportersTable* mWeakReporters;
 
   // These two are only used for testing purposes.
@@ -182,34 +179,31 @@ private:
     uint32_t                             mGeneration;
     nsCOMPtr<nsITimer>                   mTimer;
     uint32_t                             mNumChildProcesses;
     uint32_t                             mNumChildProcessesCompleted;
     nsCOMPtr<nsIHandleReportCallback>    mHandleReport;
     nsCOMPtr<nsISupports>                mHandleReportData;
     nsCOMPtr<nsIFinishReportingCallback> mFinishReporting;
     nsCOMPtr<nsISupports>                mFinishReportingData;
-    nsString                             mDMDDumpIdent;
 
     GetReportsState(uint32_t aGeneration, nsITimer* aTimer,
                     uint32_t aNumChildProcesses,
                     nsIHandleReportCallback* aHandleReport,
                     nsISupports* aHandleReportData,
                     nsIFinishReportingCallback* aFinishReporting,
-                    nsISupports* aFinishReportingData,
-                    const nsAString &aDMDDumpIdent)
+                    nsISupports* aFinishReportingData)
       : mGeneration(aGeneration)
       , mTimer(aTimer)
       , mNumChildProcesses(aNumChildProcesses)
       , mNumChildProcessesCompleted(0)
       , mHandleReport(aHandleReport)
       , mHandleReportData(aHandleReportData)
       , mFinishReporting(aFinishReporting)
       , mFinishReportingData(aFinishReportingData)
-      , mDMDDumpIdent(aDMDDumpIdent)
     {
     }
   };
 
   // When this is non-null, a request is in flight.  Note: We use manual
   // new/delete for this because its lifetime doesn't match block scope or
   // anything like that.
   GetReportsState* mGetReportsState;