Back out e05936099653 (bug 1154053) on suspicion of causing the hellish frequency of Android 2.3 robocop-2 crashes that resulted in this CLOSED TREE, a=bustage

This commit is contained in:
Phil Ringnalda 2015-05-07 22:41:26 -07:00
parent 1a25d3754b
commit 3fc48280b7
5 changed files with 173 additions and 160 deletions

View File

@ -424,7 +424,7 @@ public:
private: private:
const uint32_t mGeneration; const uint32_t mGeneration;
// Non-null if we haven't yet called EndProcessReport() on it. // Non-null if we haven't yet called EndChildReport() on it.
nsRefPtr<nsMemoryReporterManager> mReporterManager; nsRefPtr<nsMemoryReporterManager> mReporterManager;
ContentParent* Owner() ContentParent* Owner()
@ -464,7 +464,7 @@ void
MemoryReportRequestParent::ActorDestroy(ActorDestroyReason aWhy) MemoryReportRequestParent::ActorDestroy(ActorDestroyReason aWhy)
{ {
if (mReporterManager) { if (mReporterManager) {
mReporterManager->EndProcessReport(mGeneration, aWhy == Deletion); mReporterManager->EndChildReport(mGeneration, aWhy == Deletion);
mReporterManager = nullptr; mReporterManager = nullptr;
} }
} }
@ -648,6 +648,7 @@ static const char* sObserverTopics[] = {
"profile-before-change", "profile-before-change",
NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC,
NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC, NS_IPC_IOSERVICE_SET_CONNECTIVITY_TOPIC,
"child-memory-reporter-request",
"memory-pressure", "memory-pressure",
"child-gc-request", "child-gc-request",
"child-cc-request", "child-cc-request",
@ -1975,6 +1976,18 @@ ContentParent::ActorDestroy(ActorDestroyReason why)
} }
} }
// Tell the memory reporter manager that this ContentParent is going away.
nsRefPtr<nsMemoryReporterManager> mgr =
nsMemoryReporterManager::GetOrCreate();
#ifdef MOZ_NUWA_PROCESS
bool isMemoryChild = !IsNuwaProcess();
#else
bool isMemoryChild = true;
#endif
if (mgr && isMemoryChild) {
mgr->DecrementNumChildProcesses();
}
// remove the global remote preferences observers // remove the global remote preferences observers
Preferences::RemoveObserver(this, ""); Preferences::RemoveObserver(this, "");
@ -2248,6 +2261,15 @@ ContentParent::ContentParent(mozIApplication* aApp,
IToplevelProtocol::SetTransport(mSubprocess->GetChannel()); IToplevelProtocol::SetTransport(mSubprocess->GetChannel());
if (!aIsNuwaProcess) {
// Tell the memory reporter manager that this ContentParent exists.
nsRefPtr<nsMemoryReporterManager> mgr =
nsMemoryReporterManager::GetOrCreate();
if (mgr) {
mgr->IncrementNumChildProcesses();
}
}
std::vector<std::string> extraArgs; std::vector<std::string> extraArgs;
if (aIsNuwaProcess) { if (aIsNuwaProcess) {
extraArgs.push_back("-nuwa"); extraArgs.push_back("-nuwa");
@ -2312,6 +2334,13 @@ ContentParent::ContentParent(ContentParent* aTemplate,
aPid, aPid,
*fd); *fd);
// Tell the memory reporter manager that this ContentParent exists.
nsRefPtr<nsMemoryReporterManager> mgr =
nsMemoryReporterManager::GetOrCreate();
if (mgr) {
mgr->IncrementNumChildProcesses();
}
mSubprocess->LaunchAndWaitForProcessHandle(); mSubprocess->LaunchAndWaitForProcessHandle();
// Clone actors routed by aTemplate for this instance. // Clone actors routed by aTemplate for this instance.
@ -3033,6 +3062,46 @@ ContentParent::Observe(nsISupports* aSubject,
nsDependentString(aData))) nsDependentString(aData)))
return NS_ERROR_NOT_AVAILABLE; return NS_ERROR_NOT_AVAILABLE;
} }
else if (!strcmp(aTopic, "child-memory-reporter-request")) {
bool isNuwa = false;
#ifdef MOZ_NUWA_PROCESS
isNuwa = IsNuwaProcess();
#endif
if (!isNuwa) {
unsigned generation;
int anonymize, minimize, identOffset = -1;
nsDependentString msg(aData);
NS_ConvertUTF16toUTF8 cmsg(msg);
if (sscanf(cmsg.get(),
"generation=%x anonymize=%d minimize=%d DMDident=%n",
&generation, &anonymize, &minimize, &identOffset) < 3
|| 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] == '=');
MaybeFileDesc dmdFileDesc = void_t();
#ifdef MOZ_DMD
nsAutoString dmdIdent(Substring(msg, identOffset));
if (!dmdIdent.IsEmpty()) {
FILE *dmdFile = nullptr;
nsresult rv = nsMemoryInfoDumper::OpenDMDFile(dmdIdent, Pid(), &dmdFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Proceed with the memory report as if DMD were disabled.
dmdFile = nullptr;
}
if (dmdFile) {
dmdFileDesc = FILEToFileDescriptor(dmdFile);
fclose(dmdFile);
}
}
#endif
unused << SendPMemoryReportRequestConstructor(
generation, anonymize, minimize, dmdFileDesc);
}
}
else if (!strcmp(aTopic, "child-gc-request")){ else if (!strcmp(aTopic, "child-gc-request")){
unused << SendGarbageCollect(); unused << SendGarbageCollect();
} }

View File

@ -4749,13 +4749,3 @@ pref("dom.secureelement.enabled", false);
// both composition string and data attribute of compositionupdate // both composition string and data attribute of compositionupdate
// and compositionend events. // and compositionend events.
pref("dom.compositionevent.allow_control_characters", false); pref("dom.compositionevent.allow_control_characters", false);
#ifdef MOZ_WIDGET_GONK
// Bug 1154053: Serialize B2G memory reports; smaller devices are
// usually overcommitted on memory by using zRAM, so memory reporting
// causes memory pressure from uncompressing cold heap memory.
pref("memory.report_concurrency", 1);
#else
// Desktop probably doesn't have swapped-out children like that.
pref("memory.report_concurrency", 10);
#endif

View File

@ -35,7 +35,6 @@
let prefs = [ let prefs = [
["dom.ipc.processCount", 3], // Allow up to 3 child processes ["dom.ipc.processCount", 3], // Allow up to 3 child processes
["memory.report_concurrency", 2], // Cover more child handling cases
["memory.system_memory_reporter", true] // Test SystemMemoryReporter ["memory.system_memory_reporter", true] // Test SystemMemoryReporter
]; ];

View File

@ -23,12 +23,9 @@
#endif #endif
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/PodOperations.h" #include "mozilla/PodOperations.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "mozilla/dom/PMemoryReportRequestParent.h" // for dom::MemoryReport #include "mozilla/dom/PMemoryReportRequestParent.h" // for dom::MemoryReport
#include "mozilla/dom/ContentParent.h"
#include "mozilla/ipc/FileDescriptorUtils.h"
#ifdef XP_WIN #ifdef XP_WIN
#include <process.h> #include <process.h>
@ -1249,6 +1246,7 @@ nsMemoryReporterManager::nsMemoryReporterManager()
, mWeakReporters(new WeakReportersTable()) , mWeakReporters(new WeakReportersTable())
, mSavedStrongReporters(nullptr) , mSavedStrongReporters(nullptr)
, mSavedWeakReporters(nullptr) , mSavedWeakReporters(nullptr)
, mNumChildProcesses(0)
, mNextGeneration(1) , mNextGeneration(1)
, mGetReportsState(nullptr) , mGetReportsState(nullptr)
{ {
@ -1273,6 +1271,29 @@ nsMemoryReporterManager::~nsMemoryReporterManager()
#define MEMORY_REPORTING_LOG(...) #define MEMORY_REPORTING_LOG(...)
#endif #endif
void
nsMemoryReporterManager::IncrementNumChildProcesses()
{
if (!NS_IsMainThread()) {
MOZ_CRASH();
}
mNumChildProcesses++;
MEMORY_REPORTING_LOG("IncrementNumChildProcesses --> %d\n",
mNumChildProcesses);
}
void
nsMemoryReporterManager::DecrementNumChildProcesses()
{
if (!NS_IsMainThread()) {
MOZ_CRASH();
}
MOZ_ASSERT(mNumChildProcesses > 0);
mNumChildProcesses--;
MEMORY_REPORTING_LOG("DecrementNumChildProcesses --> %d\n",
mNumChildProcesses);
}
NS_IMETHODIMP NS_IMETHODIMP
nsMemoryReporterManager::GetReports( nsMemoryReporterManager::GetReports(
nsIHandleReportCallback* aHandleReport, nsIHandleReportCallback* aHandleReport,
@ -1316,23 +1337,18 @@ nsMemoryReporterManager::GetReportsExtended(
return NS_OK; return NS_OK;
} }
MEMORY_REPORTING_LOG("GetReports (gen=%u)\n", generation); MEMORY_REPORTING_LOG("GetReports (gen=%u, %d child(ren) present)\n",
generation, mNumChildProcesses);
uint32_t concurrency = Preferences::GetUint("memory.report_concurrency", 1);
MOZ_ASSERT(concurrency >= 1);
if (concurrency < 1) {
concurrency = 1;
}
mGetReportsState = new GetReportsState(generation, mGetReportsState = new GetReportsState(generation,
aAnonymize, aAnonymize,
aMinimize, aMinimize,
concurrency, mNumChildProcesses,
aHandleReport, aHandleReport,
aHandleReportData, aHandleReportData,
aFinishReporting, aFinishReporting,
aFinishReportingData, aFinishReportingData,
aDMDDumpIdent); aDMDDumpIdent);
mGetReportsState->mChildrenPending = new nsTArray<nsRefPtr<mozilla::dom::ContentParent>>();
if (aMinimize) { if (aMinimize) {
rv = MinimizeMemoryUsage(NS_NewRunnableMethod( rv = MinimizeMemoryUsage(NS_NewRunnableMethod(
@ -1364,18 +1380,12 @@ nsMemoryReporterManager::StartGettingReports()
GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData, GetReportsForThisProcessExtended(s->mHandleReport, s->mHandleReportData,
s->mAnonymize, parentDMDFile); s->mAnonymize, parentDMDFile);
nsTArray<ContentParent*> childWeakRefs; MOZ_ASSERT(s->mNumChildProcessesCompleted == 0);
ContentParent::GetAll(childWeakRefs); if (s->mNumChildProcesses > 0) {
if (!childWeakRefs.IsEmpty()) {
// Request memory reports from child processes. This happens // Request memory reports from child processes. This happens
// after the parent report so that the parent's main thread will // after the parent report so that the parent's main thread will
// be free to process the child reports, instead of causing them // be free to process the child reports, instead of causing them
// to be buffered and consume (possibly scarce) memory. // to be buffered and consume (possibly scarce) memory.
for (size_t i = 0; i < childWeakRefs.Length(); ++i) {
s->mChildrenPending->AppendElement(childWeakRefs[i]);
}
nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID); nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
// Don't use NS_ENSURE_* here; can't return until the report is finished. // Don't use NS_ENSURE_* here; can't return until the report is finished.
if (NS_WARN_IF(!timer)) { if (NS_WARN_IF(!timer)) {
@ -1392,12 +1402,27 @@ nsMemoryReporterManager::StartGettingReports()
MOZ_ASSERT(!s->mTimer); MOZ_ASSERT(!s->mTimer);
s->mTimer.swap(timer); s->mTimer.swap(timer);
}
// The parent's report is done; make note of that, and start nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
// launching child process reports (if any). if (NS_WARN_IF(!obs)) {
EndProcessReport(s->mGeneration, true); FinishReporting();
return NS_OK; return NS_ERROR_UNEXPECTED;
}
nsPrintfCString genStr("generation=%x anonymize=%d minimize=%d DMDident=",
s->mGeneration, s->mAnonymize ? 1 : 0,
s->mMinimize ? 1 : 0);
nsAutoString msg = NS_ConvertUTF8toUTF16(genStr);
msg += s->mDMDDumpIdent;
obs->NotifyObservers(nullptr, "child-memory-reporter-request",
msg.get());
return NS_OK;
} else {
// If there are no child processes, we can finish up immediately.
return FinishReporting();
}
} }
typedef nsCOMArray<nsIMemoryReporter> MemoryReporterArray; typedef nsCOMArray<nsIMemoryReporter> MemoryReporterArray;
@ -1477,12 +1502,17 @@ nsMemoryReporterManager::GetStateForGeneration(uint32_t aGeneration)
GetReportsState* s = mGetReportsState; GetReportsState* s = mGetReportsState;
if (!s) { if (!s) {
// If we reach here, then: // If we reach here, either:
// //
// - A child process reported back too late, and no subsequent request // - A child process reported back too late, and no subsequent request
// is in flight. // is in flight.
// //
// So there's nothing to be done. Just ignore it. // - (Unlikely) A "child-memory-reporter-request" notification was
// triggered from somewhere other than GetReports(), causing child
// processes to report back when the nsMemoryReporterManager wasn't
// expecting it.
//
// Either way, there's nothing to be done. Just ignore it.
MEMORY_REPORTING_LOG( MEMORY_REPORTING_LOG(
"HandleChildReports: no request in flight (aGen=%u)\n", "HandleChildReports: no request in flight (aGen=%u)\n",
aGeneration); aGeneration);
@ -1529,85 +1559,31 @@ nsMemoryReporterManager::HandleChildReport(
s->mHandleReportData); s->mHandleReportData);
} }
/* static */ bool
nsMemoryReporterManager::StartChildReport(mozilla::dom::ContentParent* aChild,
const GetReportsState* aState)
{
#ifdef MOZ_NUWA_PROCESS
if (aChild->IsNuwaProcess()) {
return false;
}
#endif
if (!aChild->IsAlive()) {
MEMORY_REPORTING_LOG("StartChildReports (gen=%u): child exited before"
" its report was started\n",
aState->mGeneration);
return false;
}
mozilla::dom::MaybeFileDesc dmdFileDesc = void_t();
#ifdef MOZ_DMD
if (!aState->mDMDDumpIdent.IsEmpty()) {
FILE *dmdFile = nullptr;
nsresult rv = nsMemoryInfoDumper::OpenDMDFile(aState->mDMDDumpIdent,
aChild->Pid(), &dmdFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Proceed with the memory report as if DMD were disabled.
dmdFile = nullptr;
}
if (dmdFile) {
dmdFileDesc = mozilla::ipc::FILEToFileDescriptor(dmdFile);
fclose(dmdFile);
}
}
#endif
return aChild->SendPMemoryReportRequestConstructor(
aState->mGeneration, aState->mAnonymize, aState->mMinimize, dmdFileDesc);
}
void void
nsMemoryReporterManager::EndProcessReport(uint32_t aGeneration, bool aSuccess) nsMemoryReporterManager::EndChildReport(uint32_t aGeneration, bool aSuccess)
{ {
GetReportsState* s = GetStateForGeneration(aGeneration); GetReportsState* s = GetStateForGeneration(aGeneration);
if (!s) { if (!s) {
return; return;
} }
MOZ_ASSERT(s->mNumProcessesRunning > 0); s->mNumChildProcessesCompleted++;
s->mNumProcessesRunning--;
s->mNumProcessesCompleted++;
MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): process %u %s"
" (%u running, %u pending)\n",
aGeneration, s->mNumProcessesCompleted,
aSuccess ? "completed" : "exited during report",
s->mNumProcessesRunning,
static_cast<unsigned>(s->mChildrenPending->Length()));
// Start pending children up to the concurrency limit. if (aSuccess) {
while (s->mNumProcessesRunning < s->mConcurrencyLimit && MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): completed child %d\n",
!s->mChildrenPending->IsEmpty()) { aGeneration, s->mNumChildProcessesCompleted);
// Pop last element from s->mChildrenPending } else {
nsRefPtr<ContentParent> nextChild; // Unfortunately, there's no way to indicate this in the report yet.
nextChild.swap(s->mChildrenPending->LastElement()); // (Also, we don't have the child's identifier at this point.)
s->mChildrenPending->TruncateLength(s->mChildrenPending->Length() - 1); MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): child %d exited"
// Start report (if the child is still alive and not Nuwa). " during report\n",
if (StartChildReport(nextChild, s)) { aGeneration, s->mNumChildProcessesCompleted);
++s->mNumProcessesRunning;
MEMORY_REPORTING_LOG("HandleChildReports (aGen=%u): started child report"
" (%u running, %u pending)\n",
aGeneration, s->mNumProcessesRunning,
static_cast<unsigned>(s->mChildrenPending->Length()));
}
} }
// If all the child processes (if any) have reported, we can cancel // If all the child processes have reported, we can cancel the timer and
// the timer (if started) and finish up. Otherwise, just return. // finish up. Otherwise, just return.
if (s->mNumProcessesRunning == 0) { if (s->mNumChildProcessesCompleted >= s->mNumChildProcesses) {
MOZ_ASSERT(s->mChildrenPending->IsEmpty()); s->mTimer->Cancel();
if (s->mTimer) {
s->mTimer->Cancel();
}
FinishReporting(); FinishReporting();
} }
} }
@ -1622,9 +1598,8 @@ nsMemoryReporterManager::TimeoutCallback(nsITimer* aTimer, void* aData)
// crash regardless of DEBUG, and this way the compiler doesn't // crash regardless of DEBUG, and this way the compiler doesn't
// complain about unused variables. // complain about unused variables.
MOZ_RELEASE_ASSERT(s, "mgr->mGetReportsState"); MOZ_RELEASE_ASSERT(s, "mgr->mGetReportsState");
MEMORY_REPORTING_LOG("TimeoutCallback (s->gen=%u; %u running, %u pending)\n", MEMORY_REPORTING_LOG("TimeoutCallback (s->gen=%u)\n",
s->mGeneration, s->mNumProcessesRunning, s->mGeneration);
static_cast<unsigned>(s->mChildrenPending->Length()));
// We don't bother sending any kind of cancellation message to the child // We don't bother sending any kind of cancellation message to the child
// processes that haven't reported back. // processes that haven't reported back.
@ -1640,9 +1615,8 @@ nsMemoryReporterManager::FinishReporting()
} }
MOZ_ASSERT(mGetReportsState); MOZ_ASSERT(mGetReportsState);
MEMORY_REPORTING_LOG("FinishReporting (s->gen=%u; %u processes reported)\n", MEMORY_REPORTING_LOG("FinishReporting (s->gen=%u)\n",
mGetReportsState->mGeneration, mGetReportsState->mGeneration);
mGetReportsState->mNumProcessesCompleted);
// Call this before deleting |mGetReportsState|. That way, if // Call this before deleting |mGetReportsState|. That way, if
// |mFinishReportData| calls GetReports(), it will silently abort, as // |mFinishReportData| calls GetReports(), it will silently abort, as
@ -1655,11 +1629,6 @@ nsMemoryReporterManager::FinishReporting()
return rv; return rv;
} }
nsMemoryReporterManager::GetReportsState::~GetReportsState()
{
delete mChildrenPending;
}
static void static void
CrashIfRefcountIsZero(nsISupports* aObj) CrashIfRefcountIsZero(nsISupports* aObj)
{ {

View File

@ -7,22 +7,21 @@
#ifndef nsMemoryReporterManager_h__ #ifndef nsMemoryReporterManager_h__
#define nsMemoryReporterManager_h__ #define nsMemoryReporterManager_h__
#include "mozilla/Mutex.h"
#include "nsHashKeys.h"
#include "nsIMemoryReporter.h" #include "nsIMemoryReporter.h"
#include "nsITimer.h" #include "nsITimer.h"
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "mozilla/Mutex.h"
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include "nsHashKeys.h"
class nsITimer;
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {
class ContentParent;
class MemoryReport; class MemoryReport;
} }
} }
class nsITimer;
class nsMemoryReporterManager final : public nsIMemoryReporterManager class nsMemoryReporterManager final : public nsIMemoryReporterManager
{ {
virtual ~nsMemoryReporterManager(); virtual ~nsMemoryReporterManager();
@ -44,27 +43,24 @@ public:
typedef nsTHashtable<nsRefPtrHashKey<nsIMemoryReporter>> StrongReportersTable; typedef nsTHashtable<nsRefPtrHashKey<nsIMemoryReporter>> StrongReportersTable;
typedef nsTHashtable<nsPtrHashKey<nsIMemoryReporter>> WeakReportersTable; typedef nsTHashtable<nsPtrHashKey<nsIMemoryReporter>> WeakReportersTable;
void IncrementNumChildProcesses();
void DecrementNumChildProcesses();
// Inter-process memory reporting proceeds as follows. // Inter-process memory reporting proceeds as follows.
// //
// - GetReports() (declared within NS_DECL_NSIMEMORYREPORTERMANAGER) // - GetReports() (declared within NS_DECL_NSIMEMORYREPORTERMANAGER)
// synchronously gets memory reports for the current process, sets up some // synchronously gets memory reports for the current process, tells all
// state (mGetReportsState) for when child processes report back -- // child processes to get memory reports, and sets up some state
// including a timer -- and starts telling child processes to get memory // (mGetReportsState) for when the child processes report back, including a
// reports. Control then returns to the main event loop. // timer. Control then returns to the main event loop.
//
// The number of concurrent child process reports is limited by the pref
// "memory.report_concurrency" in order to prevent the memory overhead of
// memory reporting from causing problems, especially on B2G when swapping
// to compressed RAM; see bug 1154053.
// //
// - HandleChildReport() is called (asynchronously) once per child process // - HandleChildReport() is called (asynchronously) once per child process
// reporter callback. // reporter callback.
// //
// - EndProcessReport() is called (asynchronously) once per process that // - EndChildReport() is called (asynchronously) once per child process that
// finishes reporting back, including the parent. If all processes do so // finishes reporting back. If all child processes do so before time-out,
// before time-out, the timer is cancelled. If there are child processes // the timer is cancelled. (The number of child processes is part of the
// whose requests have not yet been sent, they will be started until the // saved request state.)
// concurrency limit is (again) reached.
// //
// - TimeoutCallback() is called (asynchronously) if all the child processes // - TimeoutCallback() is called (asynchronously) if all the child processes
// don't respond within the time threshold. // don't respond within the time threshold.
@ -108,12 +104,12 @@ public:
// is incomplete. // is incomplete.
// //
// Now, what what happens if a child process is created/destroyed in the // Now, what what happens if a child process is created/destroyed in the
// middle of a request? Well, GetReportsState is initialized with an array // middle of a request? Well, GetReportsState contains a copy of
// of child process actors as of when the report started. So... // mNumChildProcesses which it uses to determine finished-ness. So...
// //
// - If a process is created after reporting starts, it won't be sent a // - If a process is created, it won't have received the request for reports,
// request for reports. So the reported data will reflect how things were // and the GetReportsState's mNumChildProcesses won't account for it. So
// when the request began. // the reported data will reflect how things were when the request began.
// //
// - If a process is destroyed before it starts reporting back, the reported // - If a process is destroyed before it starts reporting back, the reported
// data will reflect how things are when the request ends. // data will reflect how things are when the request ends.
@ -131,7 +127,7 @@ public:
// //
void HandleChildReport(uint32_t aGeneration, void HandleChildReport(uint32_t aGeneration,
const mozilla::dom::MemoryReport& aChildReport); const mozilla::dom::MemoryReport& aChildReport);
void EndProcessReport(uint32_t aGeneration, bool aSuccess); void EndChildReport(uint32_t aGeneration, bool aSuccess);
// Functions that (a) implement distinguished amounts, and (b) are outside of // Functions that (a) implement distinguished amounts, and (b) are outside of
// this module. // this module.
@ -203,6 +199,7 @@ private:
StrongReportersTable* mSavedStrongReporters; StrongReportersTable* mSavedStrongReporters;
WeakReportersTable* mSavedWeakReporters; WeakReportersTable* mSavedWeakReporters;
uint32_t mNumChildProcesses;
uint32_t mNextGeneration; uint32_t mNextGeneration;
struct GetReportsState struct GetReportsState
@ -211,13 +208,8 @@ private:
bool mAnonymize; bool mAnonymize;
bool mMinimize; bool mMinimize;
nsCOMPtr<nsITimer> mTimer; nsCOMPtr<nsITimer> mTimer;
// This is a pointer to an nsTArray because otherwise C++ is uint32_t mNumChildProcesses;
// unhappy unless this header includes ContentParent.h, which not uint32_t mNumChildProcessesCompleted;
// everything that includes this header knows how to find.
nsTArray<nsRefPtr<mozilla::dom::ContentParent>>* mChildrenPending;
uint32_t mNumProcessesRunning;
uint32_t mNumProcessesCompleted;
uint32_t mConcurrencyLimit;
nsCOMPtr<nsIHandleReportCallback> mHandleReport; nsCOMPtr<nsIHandleReportCallback> mHandleReport;
nsCOMPtr<nsISupports> mHandleReportData; nsCOMPtr<nsISupports> mHandleReportData;
nsCOMPtr<nsIFinishReportingCallback> mFinishReporting; nsCOMPtr<nsIFinishReportingCallback> mFinishReporting;
@ -225,7 +217,7 @@ private:
nsString mDMDDumpIdent; nsString mDMDDumpIdent;
GetReportsState(uint32_t aGeneration, bool aAnonymize, bool aMinimize, GetReportsState(uint32_t aGeneration, bool aAnonymize, bool aMinimize,
uint32_t aConcurrencyLimit, uint32_t aNumChildProcesses,
nsIHandleReportCallback* aHandleReport, nsIHandleReportCallback* aHandleReport,
nsISupports* aHandleReportData, nsISupports* aHandleReportData,
nsIFinishReportingCallback* aFinishReporting, nsIFinishReportingCallback* aFinishReporting,
@ -234,10 +226,8 @@ private:
: mGeneration(aGeneration) : mGeneration(aGeneration)
, mAnonymize(aAnonymize) , mAnonymize(aAnonymize)
, mMinimize(aMinimize) , mMinimize(aMinimize)
, mChildrenPending(nullptr) , mNumChildProcesses(aNumChildProcesses)
, mNumProcessesRunning(1) // reporting starts with the parent , mNumChildProcessesCompleted(0)
, mNumProcessesCompleted(0)
, mConcurrencyLimit(aConcurrencyLimit)
, mHandleReport(aHandleReport) , mHandleReport(aHandleReport)
, mHandleReportData(aHandleReportData) , mHandleReportData(aHandleReportData)
, mFinishReporting(aFinishReporting) , mFinishReporting(aFinishReporting)
@ -245,8 +235,6 @@ private:
, mDMDDumpIdent(aDMDDumpIdent) , mDMDDumpIdent(aDMDDumpIdent)
{ {
} }
~GetReportsState();
}; };
// When this is non-null, a request is in flight. Note: We use manual // When this is non-null, a request is in flight. Note: We use manual
@ -255,8 +243,6 @@ private:
GetReportsState* mGetReportsState; GetReportsState* mGetReportsState;
GetReportsState* GetStateForGeneration(uint32_t aGeneration); GetReportsState* GetStateForGeneration(uint32_t aGeneration);
static bool StartChildReport(mozilla::dom::ContentParent* aChild,
const GetReportsState* aState);
}; };
#define NS_MEMORY_REPORTER_MANAGER_CID \ #define NS_MEMORY_REPORTER_MANAGER_CID \