Bug 1194555 - Part 5: Add option for async memory reporters. r=njn

This commit is contained in:
Eric Rahm 2015-10-06 11:23:35 -07:00
parent 7440eba788
commit f2b2a50da6
3 changed files with 87 additions and 66 deletions

View File

@ -205,7 +205,7 @@ interface nsIFinishReportingCallback : nsISupports
void callback(in nsISupports data);
};
[scriptable, builtinclass, uuid(6cc4aa56-e18c-4b61-9290-6297172d6978)]
[scriptable, builtinclass, uuid(babbadb0-b22d-4b05-9ca9-01e617828ec1)]
interface nsIMemoryReporterManager : nsISupports
{
/*
@ -220,6 +220,7 @@ interface nsIMemoryReporterManager : nsISupports
* unregisterStrongReporter() at any point.
*/
void registerStrongReporter(in nsIMemoryReporter reporter);
void registerStrongAsyncReporter(in nsIMemoryReporter reporter);
/*
* Like registerReporter, but the Manager service will hold a weak reference
@ -229,6 +230,7 @@ interface nsIMemoryReporterManager : nsISupports
* register your JavaScript components with registerStrongReporter().
*/
void registerWeakReporter(in nsIMemoryReporter reporter);
void registerWeakAsyncReporter(in nsIMemoryReporter reporter);
/*
* Unregister the given memory reporter, which must have been registered with
@ -444,10 +446,12 @@ namespace mozilla {
// Register a memory reporter. The manager service will hold a strong
// reference to this reporter.
XPCOM_API(nsresult) RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter);
XPCOM_API(nsresult) RegisterStrongAsyncMemoryReporter(nsIMemoryReporter* aReporter);
// Register a memory reporter. The manager service will hold a weak reference
// to this reporter.
XPCOM_API(nsresult) RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
XPCOM_API(nsresult) RegisterWeakAsyncMemoryReporter(nsIMemoryReporter* aReporter);
// Unregister a strong memory reporter.
XPCOM_API(nsresult) UnregisterStrongMemoryReporter(nsIMemoryReporter* aReporter);

View File

@ -1530,12 +1530,10 @@ nsMemoryReporterManager::GetReportsForThisProcessExtended(
{
mozilla::MutexAutoLock autoLock(mMutex);
for (auto iter = mStrongReporters->Iter(); !iter.Done(); iter.Next()) {
nsRefPtrHashKey<nsIMemoryReporter>* entry = iter.Get();
allReporters.AppendElement(entry->GetKey());
allReporters.AppendElement(iter.Key());
}
for (auto iter = mWeakReporters->Iter(); !iter.Done(); iter.Next()) {
nsPtrHashKey<nsIMemoryReporter>* entry = iter.Get();
allReporters.AppendElement(entry->GetKey());
allReporters.AppendElement(iter.Key());
}
}
for (uint32_t i = 0; i < allReporters.Length(); i++) {
@ -1775,7 +1773,7 @@ CrashIfRefcountIsZero(nsISupports* aObj)
nsresult
nsMemoryReporterManager::RegisterReporterHelper(
nsIMemoryReporter* aReporter, bool aForce, bool aStrong)
nsIMemoryReporter* aReporter, bool aForce, bool aStrong, bool aIsAsync)
{
// This method is thread-safe.
mozilla::MutexAutoLock autoLock(mMutex);
@ -1802,7 +1800,7 @@ nsMemoryReporterManager::RegisterReporterHelper(
//
if (aStrong) {
nsCOMPtr<nsIMemoryReporter> kungFuDeathGrip = aReporter;
mStrongReporters->PutEntry(aReporter);
mStrongReporters->Put(aReporter, aIsAsync);
CrashIfRefcountIsZero(aReporter);
} else {
CrashIfRefcountIsZero(aReporter);
@ -1815,7 +1813,7 @@ nsMemoryReporterManager::RegisterReporterHelper(
// CollectReports().
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
mWeakReporters->PutEntry(aReporter);
mWeakReporters->Put(aReporter, aIsAsync);
}
return NS_OK;
@ -1825,14 +1823,32 @@ NS_IMETHODIMP
nsMemoryReporterManager::RegisterStrongReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ true);
/* strong = */ true,
/* async = */ false);
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterStrongAsyncReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ true,
/* async = */ true);
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterWeakReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ false);
/* strong = */ false,
/* async = */ false);
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterWeakAsyncReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ false,
/* async = */ true);
}
NS_IMETHODIMP
@ -1840,7 +1856,8 @@ nsMemoryReporterManager::RegisterStrongReporterEvenIfBlocked(
nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ true,
/* strong = */ true);
/* strong = */ true,
/* async = */ false);
}
NS_IMETHODIMP
@ -1852,7 +1869,7 @@ nsMemoryReporterManager::UnregisterStrongReporter(nsIMemoryReporter* aReporter)
MOZ_ASSERT(!mWeakReporters->Contains(aReporter));
if (mStrongReporters->Contains(aReporter)) {
mStrongReporters->RemoveEntry(aReporter);
mStrongReporters->Remove(aReporter);
return NS_OK;
}
@ -1861,7 +1878,7 @@ nsMemoryReporterManager::UnregisterStrongReporter(nsIMemoryReporter* aReporter)
// references that these reporters aren't expecting (which can keep them
// alive longer than intended).
if (mSavedStrongReporters && mSavedStrongReporters->Contains(aReporter)) {
mSavedStrongReporters->RemoveEntry(aReporter);
mSavedStrongReporters->Remove(aReporter);
return NS_OK;
}
@ -1877,7 +1894,7 @@ nsMemoryReporterManager::UnregisterWeakReporter(nsIMemoryReporter* aReporter)
MOZ_ASSERT(!mStrongReporters->Contains(aReporter));
if (mWeakReporters->Contains(aReporter)) {
mWeakReporters->RemoveEntry(aReporter);
mWeakReporters->Remove(aReporter);
return NS_OK;
}
@ -1886,7 +1903,7 @@ nsMemoryReporterManager::UnregisterWeakReporter(nsIMemoryReporter* aReporter)
// references that the old reporters aren't expecting (which can end up as
// dangling pointers that lead to use-after-frees).
if (mSavedWeakReporters && mSavedWeakReporters->Contains(aReporter)) {
mSavedWeakReporters->RemoveEntry(aReporter);
mSavedWeakReporters->Remove(aReporter);
return NS_OK;
}
@ -2303,54 +2320,6 @@ nsMemoryReporterManager::SizeOfTab(nsIDOMWindow* aTopWindow,
namespace mozilla {
nsresult
RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
{
// Hold a strong reference to the argument to make sure it gets released if
// we return early below.
nsCOMPtr<nsIMemoryReporter> reporter = aReporter;
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->RegisterStrongReporter(reporter);
}
nsresult
RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->RegisterWeakReporter(aReporter);
}
nsresult
UnregisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->UnregisterStrongReporter(aReporter);
}
nsresult
UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->UnregisterWeakReporter(aReporter);
}
#define GET_MEMORY_REPORTER_MANAGER(mgr) \
nsRefPtr<nsMemoryReporterManager> mgr = \
nsMemoryReporterManager::GetOrCreate(); \
@ -2358,6 +2327,54 @@ UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter)
return NS_ERROR_FAILURE; \
}
nsresult
RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
{
// Hold a strong reference to the argument to make sure it gets released if
// we return early below.
nsCOMPtr<nsIMemoryReporter> reporter = aReporter;
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->RegisterStrongReporter(reporter);
}
nsresult
RegisterStrongAsyncMemoryReporter(nsIMemoryReporter* aReporter)
{
// Hold a strong reference to the argument to make sure it gets released if
// we return early below.
nsCOMPtr<nsIMemoryReporter> reporter = aReporter;
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->RegisterStrongAsyncReporter(reporter);
}
nsresult
RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter)
{
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->RegisterWeakReporter(aReporter);
}
nsresult
RegisterWeakAsyncMemoryReporter(nsIMemoryReporter* aReporter)
{
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->RegisterWeakAsyncReporter(aReporter);
}
nsresult
UnregisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
{
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->UnregisterStrongReporter(aReporter);
}
nsresult
UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter)
{
GET_MEMORY_REPORTER_MANAGER(mgr)
return mgr->UnregisterWeakReporter(aReporter);
}
// Macro for generating functions that register distinguished amount functions
// with the memory reporter manager.
#define DEFINE_REGISTER_DISTINGUISHED_AMOUNT(kind, name) \

View File

@ -41,8 +41,8 @@ public:
return static_cast<nsMemoryReporterManager*>(imgr.get());
}
typedef nsTHashtable<nsRefPtrHashKey<nsIMemoryReporter>> StrongReportersTable;
typedef nsTHashtable<nsPtrHashKey<nsIMemoryReporter>> WeakReportersTable;
typedef nsDataHashtable<nsRefPtrHashKey<nsIMemoryReporter>, bool> StrongReportersTable;
typedef nsDataHashtable<nsPtrHashKey<nsIMemoryReporter>, bool> WeakReportersTable;
// Inter-process memory reporting proceeds as follows.
//
@ -184,7 +184,7 @@ public:
private:
nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter,
bool aForce, bool aStrongRef);
bool aForce, bool aStrongRef, bool aIsAsync);
nsresult StartGettingReports();
nsresult FinishReporting();