Bug 936964 (part 7, attempt 2) - Make lots of classes report their own memory consumption, instead of using a separate reporter class. r=mccr8,sr=bz.

* * *
Bug 936964 (part 7b) - Fix a use-after-free found by ASan.

--HG--
extra : rebase_source : d38ab6b63e9d576773baf8e55fa4f7182c33915e
This commit is contained in:
Nicholas Nethercote 2013-11-07 16:35:30 +11:00
parent 9245936f8b
commit 77419f6a47
68 changed files with 914 additions and 1067 deletions

View File

@ -417,7 +417,7 @@ nsContentUtils::Init()
return NS_ERROR_OUT_OF_MEMORY;
}
NS_RegisterMemoryReporter(new DOMEventListenerManagersHashReporter);
RegisterStrongMemoryReporter(new DOMEventListenerManagersHashReporter());
}
sBlockedScriptRunners = new nsTArray< nsCOMPtr<nsIRunnable> >;

View File

@ -733,9 +733,7 @@ nsDOMMemoryFile::DataOwner::EnsureMemoryReporterRegistered()
return;
}
nsRefPtr<nsDOMMemoryFileDataOwnerMemoryReporter> reporter = new
nsDOMMemoryFileDataOwnerMemoryReporter();
NS_RegisterMemoryReporter(reporter);
RegisterStrongMemoryReporter(new nsDOMMemoryFileDataOwnerMemoryReporter());
sMemoryReporterRegistered = true;
}

View File

@ -1300,7 +1300,7 @@ NS_NewGlobalMessageManager(nsIMessageBroadcaster** aResult)
nsFrameMessageManager* mm = new nsFrameMessageManager(nullptr,
nullptr,
MM_CHROME | MM_GLOBAL | MM_BROADCASTER);
NS_RegisterMemoryReporter(new MessageManagerReporter());
RegisterStrongMemoryReporter(new MessageManagerReporter());
return CallQueryInterface(mm, aResult);
}
@ -1835,7 +1835,7 @@ NS_NewChildProcessMessageManager(nsISyncMessageSender** aResult)
cb = new SameChildProcessMessageManagerCallback();
} else {
cb = new ChildProcessMessageManagerCallback();
NS_RegisterMemoryReporter(new MessageManagerReporter());
RegisterStrongMemoryReporter(new MessageManagerReporter());
}
nsFrameMessageManager* mm = new nsFrameMessageManager(cb,
nullptr,

View File

@ -53,7 +53,7 @@ nsHostObjectProtocolHandler::nsHostObjectProtocolHandler()
if (!initialized) {
initialized = true;
NS_RegisterMemoryReporter(new mozilla::HostObjectURLsReporter());
RegisterStrongMemoryReporter(new mozilla::HostObjectURLsReporter());
}
}

View File

@ -888,7 +888,7 @@ CanvasRenderingContext2D::EnsureTarget()
static bool registered = false;
if (!registered) {
registered = true;
NS_RegisterMemoryReporter(new Canvas2dPixelsReporter());
RegisterStrongMemoryReporter(new Canvas2dPixelsReporter());
}
gCanvasAzureMemoryUsed += mWidth * mHeight * 4;

View File

@ -5,39 +5,26 @@
#include "WebGLContext.h"
#include "WebGLMemoryTracker.h"
#include "nsIMemoryReporter.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS1(WebGLMemoryPressureObserver, nsIObserver)
class WebGLMemoryReporter MOZ_FINAL : public MemoryMultiReporter
{
public:
WebGLMemoryReporter()
: MemoryMultiReporter("webgl")
{}
NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb,
nsISupports* aClosure);
};
NS_IMETHODIMP
WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
nsISupports* aClosure)
WebGLMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
#define REPORT(_path, _kind, _units, _amount, _desc) \
do { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), _kind, \
_units, _amount, NS_LITERAL_CSTRING(_desc), \
aClosure); \
rv = aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
_kind, _units, _amount, \
NS_LITERAL_CSTRING(_desc), aData); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
REPORT("webgl-texture-memory",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
WebGLMemoryTracker::GetTextureMemoryUsed(),
KIND_OTHER, UNITS_BYTES, GetTextureMemoryUsed(),
"Memory used by WebGL textures.The OpenGL"
" implementation is free to store these textures in either video"
" memory or main memory. This measurement is only a lower bound,"
@ -45,13 +32,11 @@ WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
" is strided.");
REPORT("webgl-texture-count",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
WebGLMemoryTracker::GetTextureCount(),
KIND_OTHER, UNITS_COUNT, GetTextureCount(),
"Number of WebGL textures.");
REPORT("webgl-buffer-memory",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
WebGLMemoryTracker::GetBufferMemoryUsed(),
KIND_OTHER, UNITS_BYTES, GetBufferMemoryUsed(),
"Memory used by WebGL buffers. The OpenGL"
" implementation is free to store these buffers in either video"
" memory or main memory. This measurement is only a lower bound,"
@ -59,8 +44,7 @@ WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
" is strided.");
REPORT("explicit/webgl/buffer-cache-memory",
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
WebGLMemoryTracker::GetBufferCacheMemoryUsed(),
KIND_HEAP, UNITS_BYTES, GetBufferCacheMemoryUsed(),
"Memory used by WebGL buffer caches. The WebGL"
" implementation caches the contents of element array buffers"
" only.This adds up with the webgl-buffer-memory value, but"
@ -68,13 +52,11 @@ WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
" not managed by OpenGL.");
REPORT("webgl-buffer-count",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
WebGLMemoryTracker::GetBufferCount(),
KIND_OTHER, UNITS_COUNT, GetBufferCount(),
"Number of WebGL buffers.");
REPORT("webgl-renderbuffer-memory",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES,
WebGLMemoryTracker::GetRenderbufferMemoryUsed(),
KIND_OTHER, UNITS_BYTES, GetRenderbufferMemoryUsed(),
"Memory used by WebGL renderbuffers. The OpenGL"
" implementation is free to store these renderbuffers in either"
" video memory or main memory. This measurement is only a lower"
@ -82,24 +64,20 @@ WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
" storage is strided.");
REPORT("webgl-renderbuffer-count",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
WebGLMemoryTracker::GetRenderbufferCount(),
KIND_OTHER, UNITS_COUNT, GetRenderbufferCount(),
"Number of WebGL renderbuffers.");
REPORT("explicit/webgl/shader",
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
WebGLMemoryTracker::GetShaderSize(),
KIND_HEAP, UNITS_BYTES, GetShaderSize(),
"Combined size of WebGL shader ASCII sources and translation"
" logs cached on the heap.");
REPORT("webgl-shader-count",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
WebGLMemoryTracker::GetShaderCount(),
KIND_OTHER, UNITS_COUNT, GetShaderCount(),
"Number of WebGL shaders.");
REPORT("webgl-context-count",
nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT,
WebGLMemoryTracker::GetContextCount(),
KIND_OTHER, UNITS_COUNT, GetContextCount(),
"Number of WebGL contexts.");
#undef REPORT
@ -107,7 +85,7 @@ WebGLMemoryReporter::CollectReports(nsIMemoryReporterCallback* aCb,
return NS_OK;
}
NS_IMPL_ISUPPORTS1(WebGLMemoryTracker, nsISupports)
NS_IMPL_ISUPPORTS_INHERITED0(WebGLMemoryTracker, MemoryMultiReporter)
StaticRefPtr<WebGLMemoryTracker> WebGLMemoryTracker::sUniqueInstance;
@ -115,19 +93,25 @@ WebGLMemoryTracker* WebGLMemoryTracker::UniqueInstance()
{
if (!sUniqueInstance) {
sUniqueInstance = new WebGLMemoryTracker;
sUniqueInstance->InitMemoryReporter();
}
return sUniqueInstance;
}
WebGLMemoryTracker::WebGLMemoryTracker()
: MemoryMultiReporter("webgl")
{
mReporter = new WebGLMemoryReporter;
NS_RegisterMemoryReporter(mReporter);
}
void
WebGLMemoryTracker::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
WebGLMemoryTracker::~WebGLMemoryTracker()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(WebGLBufferMallocSizeOf)

View File

@ -15,10 +15,11 @@
#include "WebGLTexture.h"
#include "WebGLRenderbuffer.h"
#include "mozilla/StaticPtr.h"
#include "nsIMemoryReporter.h"
namespace mozilla {
class WebGLMemoryTracker : public nsISupports
class WebGLMemoryTracker : public MemoryMultiReporter
{
NS_DECL_ISUPPORTS
@ -26,13 +27,13 @@ class WebGLMemoryTracker : public nsISupports
virtual ~WebGLMemoryTracker();
static StaticRefPtr<WebGLMemoryTracker> sUniqueInstance;
// here we store plain pointers, not RefPtrs: we don't want the
// Here we store plain pointers, not RefPtrs: we don't want the
// WebGLMemoryTracker unique instance to keep alive all
// WebGLContexts ever created.
typedef nsTArray<const WebGLContext*> ContextsArrayType;
ContextsArrayType mContexts;
nsCOMPtr<nsIMemoryReporter> mReporter;
void InitMemoryReporter();
static WebGLMemoryTracker* UniqueInstance();
@ -54,6 +55,10 @@ class WebGLMemoryTracker : public nsISupports
}
}
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData);
private:
static int64_t GetTextureMemoryUsed() {
const ContextsArrayType & contexts = Contexts();
int64_t result = 0;

View File

@ -54,17 +54,20 @@ PRLogModuleInfo* gMediaDecoderLog;
#define DECODER_LOG(type, msg)
#endif
class MediaMemoryTracker : public nsISupports
class MediaMemoryTracker : public MemoryMultiReporter
{
NS_DECL_ISUPPORTS
MediaMemoryTracker();
virtual ~MediaMemoryTracker();
void InitMemoryReporter();
static StaticRefPtr<MediaMemoryTracker> sUniqueInstance;
static MediaMemoryTracker* UniqueInstance() {
if (!sUniqueInstance) {
sUniqueInstance = new MediaMemoryTracker();
sUniqueInstance->InitMemoryReporter();
}
return sUniqueInstance;
}
@ -76,8 +79,6 @@ class MediaMemoryTracker : public nsISupports
DecodersArray mDecoders;
nsCOMPtr<nsIMemoryReporter> mReporter;
public:
static void AddMediaDecoder(MediaDecoder* aDecoder)
{
@ -93,21 +94,13 @@ public:
}
}
static void GetAmounts(int64_t* aVideo, int64_t* aAudio)
{
*aVideo = 0;
*aAudio = 0;
DecodersArray& decoders = Decoders();
for (size_t i = 0; i < decoders.Length(); ++i) {
*aVideo += decoders[i]->VideoQueueMemoryInUse();
*aAudio += decoders[i]->AudioQueueMemoryInUse();
}
}
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData);
};
StaticRefPtr<MediaMemoryTracker> MediaMemoryTracker::sUniqueInstance;
NS_IMPL_ISUPPORTS1(MediaMemoryTracker, nsISupports)
NS_IMPL_ISUPPORTS_INHERITED0(MediaMemoryTracker, MemoryMultiReporter)
NS_IMPL_ISUPPORTS1(MediaDecoder, nsIObserver)
@ -1776,38 +1769,34 @@ MediaDecoder::IsAppleMP3Enabled()
}
#endif
class MediaReporter MOZ_FINAL : public MemoryMultiReporter
NS_IMETHODIMP
MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
public:
MediaReporter()
: MemoryMultiReporter("media")
{}
NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb,
nsISupports* aClosure)
{
int64_t video, audio;
MediaMemoryTracker::GetAmounts(&video, &audio);
#define REPORT(_path, _amount, _desc) \
do { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_HEAP, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
REPORT("explicit/media/decoded-video", video,
"Memory used by decoded video frames.");
REPORT("explicit/media/decoded-audio", audio,
"Memory used by decoded audio chunks.");
return NS_OK;
int64_t video = 0, audio = 0;
DecodersArray& decoders = Decoders();
for (size_t i = 0; i < decoders.Length(); ++i) {
video += decoders[i]->VideoQueueMemoryInUse();
audio += decoders[i]->AudioQueueMemoryInUse();
}
};
#define REPORT(_path, _amount, _desc) \
do { \
nsresult rv; \
rv = aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
KIND_HEAP, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aData); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
REPORT("explicit/media/decoded-video", video,
"Memory used by decoded video frames.");
REPORT("explicit/media/decoded-audio", audio,
"Memory used by decoded audio chunks.");
return NS_OK;
}
MediaDecoderOwner*
MediaDecoder::GetOwner()
@ -1817,14 +1806,19 @@ MediaDecoder::GetOwner()
}
MediaMemoryTracker::MediaMemoryTracker()
: mReporter(new MediaReporter())
: MemoryMultiReporter("media")
{
NS_RegisterMemoryReporter(mReporter);
}
void
MediaMemoryTracker::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
MediaMemoryTracker::~MediaMemoryTracker()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
} // namespace mozilla

View File

@ -191,7 +191,6 @@ destroying the MediaDecoder object.
#include "necko-config.h"
class nsIStreamListener;
class nsIMemoryReporter;
class nsIPrincipal;
class nsITimer;

View File

@ -9,7 +9,6 @@
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsICategoryManager.h"
#include "nsIMemoryReporter.h"
#include "nsIServiceManager.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
@ -117,30 +116,17 @@ GlobalNameHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
return true;
}
class ScriptNameSpaceManagerReporter MOZ_FINAL : public MemoryUniReporter
{
public:
ScriptNameSpaceManagerReporter(nsScriptNameSpaceManager* aManager)
: MemoryUniReporter(
"explicit/script-namespace-manager",
KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES,
"Memory used for the script namespace manager.")
, mManager(aManager)
{}
private:
int64_t Amount() { return mManager->SizeOfIncludingThis(MallocSizeOf); }
nsScriptNameSpaceManager* mManager;
};
NS_IMPL_ISUPPORTS2(nsScriptNameSpaceManager,
nsIObserver,
nsISupportsWeakReference)
NS_IMPL_ISUPPORTS_INHERITED2(
nsScriptNameSpaceManager,
MemoryUniReporter,
nsIObserver,
nsISupportsWeakReference)
nsScriptNameSpaceManager::nsScriptNameSpaceManager()
: mIsInitialized(false)
: MemoryUniReporter("explicit/script-namespace-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the script namespace manager.")
, mIsInitialized(false)
{
MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
}
@ -148,7 +134,7 @@ nsScriptNameSpaceManager::nsScriptNameSpaceManager()
nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
{
if (mIsInitialized) {
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
// Destroy the hash
PL_DHashTableFinish(&mGlobalNames);
PL_DHashTableFinish(&mNavigatorNames);
@ -363,8 +349,7 @@ nsScriptNameSpaceManager::Init()
return NS_ERROR_OUT_OF_MEMORY;
}
mReporter = new ScriptNameSpaceManagerReporter(this);
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
nsresult rv = NS_OK;
@ -882,8 +867,14 @@ SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, MallocSizeOf aMallocSizeOf,
return entry->SizeOfExcludingThis(aMallocSizeOf);
}
int64_t
nsScriptNameSpaceManager::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
nsScriptNameSpaceManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
nsScriptNameSpaceManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = 0;
n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,

View File

@ -22,6 +22,7 @@
#define nsScriptNameSpaceManager_h__
#include "mozilla/MemoryReporting.h"
#include "nsIMemoryReporter.h"
#include "nsIScriptNameSpaceManager.h"
#include "nsString.h"
#include "nsID.h"
@ -84,11 +85,11 @@ struct nsGlobalNameStruct
class nsIScriptContext;
class nsICategoryManager;
class nsIMemoryReporter;
class GlobalNameMapEntry;
class nsScriptNameSpaceManager : public nsIObserver,
class nsScriptNameSpaceManager : public mozilla::MemoryUniReporter,
public nsIObserver,
public nsSupportsWeakReference
{
public:
@ -162,6 +163,7 @@ public:
void EnumerateNavigatorNames(NameEnumerator aEnumerator,
void* aClosure);
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:
@ -224,8 +226,6 @@ private:
PLDHashTable mNavigatorNames;
bool mIsInitialized;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
#endif /* nsScriptNameSpaceManager_h__ */

View File

@ -94,7 +94,7 @@ nsWindowMemoryReporter::Init()
MOZ_ASSERT(!sWindowReporter);
sWindowReporter = new nsWindowMemoryReporter();
ClearOnShutdown(&sWindowReporter);
NS_RegisterMemoryReporter(sWindowReporter);
RegisterStrongMemoryReporter(sWindowReporter);
RegisterNonJSSizeOfTab(NonJSSizeOfTab);
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
@ -107,7 +107,7 @@ nsWindowMemoryReporter::Init()
/* weakRef = */ true);
}
NS_RegisterMemoryReporter(new GhostWindowsReporter());
RegisterStrongMemoryReporter(new GhostWindowsReporter());
RegisterGhostWindowsDistinguishedAmount(GhostWindowsReporter::DistinguishedAmount);
}

View File

@ -337,7 +337,8 @@ ContentParent::StartUp()
return;
}
NS_RegisterMemoryReporter(new ContentParentsMemoryReporter());
// Note: This reporter measures all ContentParents.
RegisterStrongMemoryReporter(new ContentParentsMemoryReporter());
sCanLaunchSubprocesses = true;

View File

@ -4023,7 +4023,7 @@ WorkerPrivate::EnableMemoryReporter()
// successfully registered the reporter.
mMemoryReporter = new MemoryReporter(this);
if (NS_FAILED(NS_RegisterMemoryReporter(mMemoryReporter))) {
if (NS_FAILED(RegisterWeakMemoryReporter(mMemoryReporter))) {
NS_WARNING("Failed to register memory reporter!");
// No need to lock here since a failed registration means our memory
// reporter can't start running. Just clean up.
@ -4078,7 +4078,7 @@ WorkerPrivate::DisableMemoryReporter()
}
// Finally unregister the memory reporter.
if (NS_FAILED(NS_UnregisterMemoryReporter(memoryReporter))) {
if (NS_FAILED(UnregisterWeakMemoryReporter(memoryReporter))) {
NS_WARNING("Failed to unregister memory reporter!");
}
}

View File

@ -74,7 +74,6 @@
#include "mozInlineSpellChecker.h"
#include "mozilla/Services.h"
#include <stdlib.h>
#include "nsIMemoryReporter.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
@ -84,6 +83,7 @@ NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
NS_INTERFACE_MAP_BEGIN(mozHunspell)
NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
@ -96,39 +96,28 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
mEncoder,
mDecoder)
class SpellCheckReporter MOZ_FINAL : public mozilla::MemoryUniReporter
{
public:
SpellCheckReporter()
: MemoryUniReporter("explicit/spell-check", KIND_HEAP, UNITS_BYTES,
"Memory used by the Hunspell spell checking engine's internal data structures.")
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
// being static.
static bool hasRun = false;
MOZ_ASSERT(!hasRun);
hasRun = true;
#endif
}
static void OnAlloc(void* ptr) { sAmount += MallocSizeOfOnAlloc(ptr); }
static void OnFree (void* ptr) { sAmount -= MallocSizeOfOnFree (ptr); }
private:
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
static int64_t sAmount;
};
int64_t SpellCheckReporter::sAmount = 0;
int64_t mozHunspell::sAmount = 0;
// WARNING: hunspell_alloc_hooks.h uses these two functions.
void HunspellReportMemoryAllocation(void* ptr) {
SpellCheckReporter::OnAlloc(ptr);
mozHunspell::OnAlloc(ptr);
}
void HunspellReportMemoryDeallocation(void* ptr) {
SpellCheckReporter::OnFree(ptr);
mozHunspell::OnFree(ptr);
}
mozHunspell::mozHunspell()
: MemoryUniReporter("explicit/spell-check", KIND_HEAP, UNITS_BYTES,
"Memory used by the spell-checking engine's internal data structures."),
mHunspell(nullptr)
{
#ifdef DEBUG
// There must be only one instance of this class, due to |sAmount|
// being static.
static bool hasRun = false;
MOZ_ASSERT(!hasRun);
hasRun = true;
#endif
}
nsresult
@ -142,15 +131,14 @@ mozHunspell::Init()
obs->AddObserver(this, "profile-after-change", true);
}
mReporter = new SpellCheckReporter();
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
return NS_OK;
}
mozHunspell::~mozHunspell()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
mPersonalDictionary = nullptr;
delete mHunspell;

View File

@ -66,6 +66,7 @@
#include "nsString.h"
#include "nsCOMPtr.h"
#include "nsCOMArray.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsIUnicodeEncoder.h"
#include "nsIUnicodeDecoder.h"
@ -79,11 +80,10 @@
{ 0x56c778e4, 0x1bee, 0x45f3, \
{ 0xa6, 0x89, 0x88, 0x66, 0x92, 0xa9, 0x7f, 0xe7 } }
class nsIMemoryReporter;
class mozHunspell : public mozISpellCheckingEngine,
public nsIObserver,
public nsSupportsWeakReference
class mozHunspell : public mozilla::MemoryUniReporter,
public mozISpellCheckingEngine,
public nsIObserver,
public nsSupportsWeakReference
{
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@ -91,7 +91,7 @@ public:
NS_DECL_NSIOBSERVER
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozHunspell, mozISpellCheckingEngine)
mozHunspell() : mHunspell(nullptr) { }
mozHunspell();
virtual ~mozHunspell();
nsresult Init();
@ -101,11 +101,16 @@ public:
// helper method for converting a word to the charset of the dictionary
nsresult ConvertCharset(const PRUnichar* aStr, char ** aDst);
static void OnAlloc(void* ptr) { sAmount += MallocSizeOfOnAlloc(ptr); }
static void OnFree (void* ptr) { sAmount -= MallocSizeOfOnFree (ptr); }
int64_t Amount() MOZ_OVERRIDE { return sAmount; }
protected:
nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
nsCOMPtr<nsIUnicodeEncoder> mEncoder;
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
nsCOMPtr<nsIUnicodeEncoder> mEncoder;
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
// Hashtable matches dictionary name to .aff file
nsInterfaceHashtable<nsStringHashKey, nsIFile> mDictionaries;
@ -118,7 +123,7 @@ protected:
Hunspell *mHunspell;
nsCOMPtr<nsIMemoryReporter> mReporter;
static int64_t sAmount;
};
#endif

View File

@ -1237,7 +1237,7 @@ void
GLContext::PlatformStartup()
{
CacheCanUploadNPOT();
NS_RegisterMemoryReporter(new GfxTexturesReporter());
RegisterStrongMemoryReporter(new GfxTexturesReporter());
}
void

View File

@ -225,7 +225,7 @@ GrallocBufferActor::GrallocBufferActor()
// the main thread.
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
NS_RegisterMemoryReporter(new GrallocReporter());
RegisterStrongMemoryReporter(new GrallocReporter());
registered = true;
}
}

View File

@ -676,7 +676,7 @@ gfxASurface::RecordMemoryUsedForSurfaceType(gfxSurfaceType aType,
static bool registered = false;
if (!registered) {
NS_RegisterMemoryReporter(new SurfaceMemoryReporter());
RegisterStrongMemoryReporter(new SurfaceMemoryReporter());
registered = true;
}

View File

@ -97,8 +97,7 @@ gfxAndroidPlatform::gfxAndroidPlatform()
FT_New_Library(&sFreetypeMemoryRecord, &gPlatformFTLibrary);
FT_Add_Default_Modules(gPlatformFTLibrary);
mFreetypeReporter = new FreetypeReporter();
NS_RegisterMemoryReporter(mFreetypeReporter);
RegisterStrongMemoryReporter(new FreetypeReporter());
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
nsCOMPtr<nsIScreen> screen;
@ -120,8 +119,6 @@ gfxAndroidPlatform::~gfxAndroidPlatform()
{
cairo_debug_reset_static_data();
NS_UnregisterMemoryReporter(mFreetypeReporter);
FT_Done_Library(gPlatformFTLibrary);
gPlatformFTLibrary = nullptr;
}

View File

@ -81,8 +81,6 @@ public:
private:
int mScreenDepth;
gfxImageFormat mOffscreenFormat;
nsCOMPtr<nsIMemoryReporter> mFreetypeReporter;
};
#endif /* GFX_PLATFORM_ANDROID_H */

View File

@ -1415,7 +1415,7 @@ gfxFontCache::Init()
if (!gGlobalCache) {
return NS_ERROR_OUT_OF_MEMORY;
}
NS_RegisterMemoryReporter(new MemoryReporter);
RegisterStrongMemoryReporter(new MemoryReporter());
return NS_OK;
}

View File

@ -502,7 +502,7 @@ gfxPlatform::Init()
obs->AddObserver(gPlatform->mMemoryPressureObserver, "memory-pressure", false);
}
NS_RegisterMemoryReporter(new GfxMemoryImageReporter());
RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
}
void

View File

@ -137,7 +137,7 @@ gfxPlatformFontList::gfxPlatformFontList(bool aNeedFullnamePostscriptNames)
NS_ADDREF(gFontListPrefObserver);
Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
NS_RegisterMemoryReporter(new MemoryReporter);
RegisterStrongMemoryReporter(new MemoryReporter());
}
gfxPlatformFontList::~gfxPlatformFontList()

View File

@ -366,26 +366,22 @@ gfxWindowsPlatform::gfxWindowsPlatform()
mScreenDC = GetDC(nullptr);
#ifdef CAIRO_HAS_D2D_SURFACE
NS_RegisterMemoryReporter(new GfxD2DSurfaceCacheReporter());
NS_RegisterMemoryReporter(new GfxD2DSurfaceVramReporter());
RegisterStrongMemoryReporter(new GfxD2DSurfaceCacheReporter());
RegisterStrongMemoryReporter(new GfxD2DSurfaceVramReporter());
mD2DDevice = nullptr;
#endif
NS_RegisterMemoryReporter(new GfxD2DVramDrawTargetReporter());
NS_RegisterMemoryReporter(new GfxD2DVramSourceSurfaceReporter());
RegisterStrongMemoryReporter(new GfxD2DVramDrawTargetReporter());
RegisterStrongMemoryReporter(new GfxD2DVramSourceSurfaceReporter());
UpdateRenderMode();
// This reporter is disabled because it frequently gives bogus values. See
// bug 917496.
//mGPUAdapterReporter = new GPUAdapterReporter();
//NS_RegisterMemoryReporter(mGPUAdapterReporter);
mGPUAdapterReporter = nullptr;
//RegisterStrongMemoryReporter(new GPUAdapterReporter());
}
gfxWindowsPlatform::~gfxWindowsPlatform()
{
//NS_UnregisterMemoryReporter(mGPUAdapterReporter);
mDeviceManager = nullptr;
::ReleaseDC(nullptr, mScreenDC);

View File

@ -301,8 +301,6 @@ private:
// TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
nsIMemoryReporter* mGPUAdapterReporter;
};
#endif /* GFX_WINDOWS_PLATFORM_H */

View File

@ -224,22 +224,22 @@ private:
* maintains high-level invariants and encapsulates the details of the surface
* cache's implementation.
*/
class SurfaceCacheImpl : public nsISupports
class SurfaceCacheImpl : public MemoryUniReporter
{
public:
NS_DECL_ISUPPORTS
SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
uint32_t aSurfaceCacheSize)
: mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
: MemoryUniReporter("imagelib-surface-cache",
KIND_OTHER, UNITS_BYTES,
"Memory used by the imagelib temporary surface cache.")
, mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
aSurfaceCacheExpirationTimeMS)
, mReporter(new SurfaceCacheReporter)
, mMemoryPressureObserver(new MemoryPressureObserver)
, mMaxCost(aSurfaceCacheSize)
, mAvailableCost(aSurfaceCacheSize)
{
NS_RegisterMemoryReporter(mReporter);
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
if (os)
os->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
@ -251,7 +251,11 @@ public:
if (os)
os->RemoveObserver(mMemoryPressureObserver, "memory-pressure");
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
void InitMemoryReporter() {
RegisterWeakMemoryReporter(this);
}
void Insert(DrawTarget* aTarget,
@ -385,9 +389,18 @@ public:
return PL_DHASH_NEXT;
}
int64_t SizeOfSurfacesEstimate() const
int64_t Amount() MOZ_OVERRIDE
{
return int64_t(mMaxCost - mAvailableCost);
return SizeOfSurfacesEstimate();
}
// XXX(seth): This is currently only an estimate and, since we don't know
// which surfaces are in GPU memory and which aren't, it's reported as
// KIND_OTHER and will also show up in heap-unclassified. Bug 923302 will
// make this nicer.
Cost SizeOfSurfacesEstimate() const
{
return mMaxCost - mAvailableCost;
}
private:
@ -417,25 +430,6 @@ private:
SurfaceCacheImpl* const mCache; // Weak pointer to owner.
};
// XXX(seth): This is currently only an estimate and, since we don't know which
// surfaces are in GPU memory and which aren't, it's reported as KIND_OTHER and
// will also show up in heap-unclassified. Bug 923302 will make this nicer.
struct SurfaceCacheReporter : public MemoryUniReporter
{
SurfaceCacheReporter()
: MemoryUniReporter("imagelib-surface-cache",
KIND_OTHER,
UNITS_BYTES,
"Memory used by the imagelib temporary surface cache.")
{ }
protected:
int64_t Amount() MOZ_OVERRIDE
{
return sInstance ? sInstance->SizeOfSurfacesEstimate() : 0;
}
};
struct MemoryPressureObserver : public nsIObserver
{
NS_DECL_ISUPPORTS
@ -455,13 +449,12 @@ private:
nsTArray<CostEntry> mCosts;
nsRefPtrHashtable<nsPtrHashKey<Image>, ImageSurfaceCache> mImageCaches;
SurfaceTracker mExpirationTracker;
nsRefPtr<SurfaceCacheReporter> mReporter;
nsRefPtr<MemoryPressureObserver> mMemoryPressureObserver;
const Cost mMaxCost;
Cost mAvailableCost;
};
NS_IMPL_ISUPPORTS1(SurfaceCacheImpl, nsISupports)
NS_IMPL_ISUPPORTS_INHERITED0(SurfaceCacheImpl, MemoryUniReporter)
NS_IMPL_ISUPPORTS1(SurfaceCacheImpl::MemoryPressureObserver, nsIObserver)
///////////////////////////////////////////////////////////////////////////////
@ -506,6 +499,7 @@ SurfaceCache::Initialize()
// we do not actually allocate any storage for surfaces at this time.
sInstance = new SurfaceCacheImpl(surfaceCacheExpirationTimeMS,
surfaceCacheSizeBytes);
sInstance->InitMemoryReporter();
}
/* static */ void

View File

@ -820,7 +820,7 @@ void imgLoader::GlobalInit()
sCacheMaxSize = 5 * 1024 * 1024;
sMemReporter = new imgMemoryReporter();
NS_RegisterMemoryReporter(sMemReporter);
RegisterStrongMemoryReporter(sMemReporter);
RegisterImagesContentUsedUncompressedDistinguishedAmount(imgMemoryReporter::ImagesContentUsedUncompressedDistinguishedAmount);
}

View File

@ -46,8 +46,8 @@ SharedMemory::SharedMemory()
{
static Atomic<uint32_t> registered;
if (registered.compareExchange(0, 1)) {
NS_RegisterMemoryReporter(new ShmemAllocatedReporter());
NS_RegisterMemoryReporter(new ShmemMappedReporter());
RegisterStrongMemoryReporter(new ShmemAllocatedReporter());
RegisterStrongMemoryReporter(new ShmemMappedReporter());
}
}

View File

@ -3096,8 +3096,8 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
NS_RUNTIMEABORT("xpc_LocalizeRuntime failed.");
// Register memory reporters and distinguished amount functions.
NS_RegisterMemoryReporter(new JSMainRuntimeCompartmentsReporter);
NS_RegisterMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
RegisterStrongMemoryReporter(new JSMainRuntimeCompartmentsReporter());
RegisterStrongMemoryReporter(new JSMainRuntimeTemporaryPeakReporter());
RegisterJSMainRuntimeGCHeapDistinguishedAmount(JSMainRuntimeGCHeapDistinguishedAmount);
RegisterJSMainRuntimeTemporaryPeakDistinguishedAmount(JSMainRuntimeTemporaryPeakDistinguishedAmount);
RegisterJSMainRuntimeCompartmentsSystemDistinguishedAmount(JSMainRuntimeCompartmentsSystemDistinguishedAmount);

View File

@ -21,50 +21,32 @@
#include "nsNetUtil.h"
#include "nsIObserverService.h"
#include "nsLayoutStatics.h"
#include "nsIMemoryReporter.h"
using namespace mozilla;
class LayoutStyleSheetServiceReporter MOZ_FINAL
: public mozilla::MemoryUniReporter
{
public:
LayoutStyleSheetServiceReporter()
: MemoryUniReporter("explicit/layout/style-sheet-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for style sheets held by the style sheet service.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return nsStyleSheetService::gInstance
? nsStyleSheetService::gInstance->SizeOfIncludingThis(MallocSizeOf)
: 0;
}
};
nsStyleSheetService *nsStyleSheetService::gInstance = nullptr;
nsStyleSheetService::nsStyleSheetService()
: MemoryUniReporter("explicit/layout/style-sheet-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for style sheets held by the style sheet service.")
{
PR_STATIC_ASSERT(0 == AGENT_SHEET && 1 == USER_SHEET && 2 == AUTHOR_SHEET);
NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
gInstance = this;
nsLayoutStatics::AddRef();
mReporter = new LayoutStyleSheetServiceReporter();
NS_RegisterMemoryReporter(mReporter);
}
nsStyleSheetService::~nsStyleSheetService()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
gInstance = nullptr;
nsLayoutStatics::Release();
}
NS_IMPL_ISUPPORTS1(nsStyleSheetService, nsIStyleSheetService)
NS_IMPL_ISUPPORTS_INHERITED1(
nsStyleSheetService, MemoryUniReporter, nsIStyleSheetService)
void
nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager *aManager,
@ -141,6 +123,8 @@ nsStyleSheetService::Init()
catMan->EnumerateCategory("author-style-sheets", getter_AddRefs(sheets));
RegisterFromEnumerator(catMan, "author-style-sheets", sheets, AUTHOR_SHEET);
RegisterWeakMemoryReporter(this);
return NS_OK;
}
@ -301,8 +285,14 @@ SizeOfElementIncludingThis(nsIStyleSheet* aElement,
return aElement->SizeOfIncludingThis(aMallocSizeOf);
}
int64_t
nsStyleSheetService::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
nsStyleSheetService::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
nsStyleSheetService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
n += mSheets[AGENT_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,

View File

@ -11,6 +11,7 @@
#include "nsCOMArray.h"
#include "nsCOMPtr.h"
#include "nsIMemoryReporter.h"
#include "nsIStyleSheetService.h"
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
@ -26,7 +27,9 @@ class nsIStyleSheet;
#define NS_STYLESHEETSERVICE_CONTRACTID \
"@mozilla.org/content/style-sheet-service;1"
class nsStyleSheetService MOZ_FINAL : public nsIStyleSheetService
class nsStyleSheetService MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIStyleSheetService
{
public:
nsStyleSheetService() NS_HIDDEN;
@ -46,6 +49,8 @@ class nsStyleSheetService MOZ_FINAL : public nsIStyleSheetService
static nsStyleSheetService *GetInstance();
static nsStyleSheetService *gInstance;
int64_t Amount() MOZ_OVERRIDE;
private:
NS_HIDDEN_(void) RegisterFromEnumerator(nsICategoryManager *aManager,
@ -62,8 +67,6 @@ class nsStyleSheetService MOZ_FINAL : public nsIStyleSheetService
uint32_t aSheetType);
nsCOMArray<nsIStyleSheet> mSheets[3];
nsCOMPtr<nsIMemoryReporter> mReporter;
};
#endif

View File

@ -10,30 +10,14 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/css/Loader.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsNetUtil.h"
#include "nsIObserverService.h"
#include "nsServiceManagerUtils.h"
#include "nsIXULRuntime.h"
#include "nsCSSStyleSheet.h"
class LayoutStyleSheetCacheReporter MOZ_FINAL
: public mozilla::MemoryUniReporter
{
public:
LayoutStyleSheetCacheReporter()
: MemoryUniReporter("explicit/layout/style-sheet-cache",
KIND_HEAP, UNITS_BYTES,
"Memory used for some built-in style sheets.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return nsLayoutStylesheetCache::SizeOfIncludingThis(MallocSizeOf);
}
};
NS_IMPL_ISUPPORTS1(nsLayoutStylesheetCache, nsIObserver)
NS_IMPL_ISUPPORTS_INHERITED1(
nsLayoutStylesheetCache, MemoryUniReporter, nsIObserver)
nsresult
nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
@ -158,17 +142,14 @@ nsLayoutStylesheetCache::Shutdown()
NS_IF_RELEASE(gStyleCache);
}
size_t
nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
int64_t
nsLayoutStylesheetCache::Amount()
{
return nsLayoutStylesheetCache::gStyleCache
? nsLayoutStylesheetCache::gStyleCache->
SizeOfIncludingThisHelper(aMallocSizeOf)
: 0;
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
nsLayoutStylesheetCache::SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf) const
nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
{
size_t n = aMallocSizeOf(this);
@ -190,6 +171,9 @@ nsLayoutStylesheetCache::SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMalloc
}
nsLayoutStylesheetCache::nsLayoutStylesheetCache()
: MemoryUniReporter("explicit/layout/style-sheet-cache",
KIND_HEAP, UNITS_BYTES,
"Memory used for some built-in style sheets.")
{
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();
@ -224,17 +208,20 @@ nsLayoutStylesheetCache::nsLayoutStylesheetCache()
LoadSheet(uri, mFullScreenOverrideSheet, true);
}
NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
mReporter = new LayoutStyleSheetCacheReporter();
NS_RegisterMemoryReporter(mReporter);
}
nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
gStyleCache = nullptr;
}
void
nsLayoutStylesheetCache::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
void
nsLayoutStylesheetCache::EnsureGlobal()
{
@ -244,6 +231,8 @@ nsLayoutStylesheetCache::EnsureGlobal()
if (!gStyleCache) return;
NS_ADDREF(gStyleCache);
gStyleCache->InitMemoryReporter();
}
void

View File

@ -7,6 +7,7 @@
#ifndef nsLayoutStylesheetCache_h__
#define nsLayoutStylesheetCache_h__
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsAutoPtr.h"
#include "mozilla/Attributes.h"
@ -14,7 +15,6 @@
class nsCSSStyleSheet;
class nsIFile;
class nsIMemoryReporter;
class nsIURI;
namespace mozilla {
@ -24,7 +24,8 @@ class Loader;
}
class nsLayoutStylesheetCache MOZ_FINAL
: public nsIObserver
: public mozilla::MemoryUniReporter
, public nsIObserver
{
NS_DECL_ISUPPORTS
NS_DECL_NSIOBSERVER
@ -39,7 +40,8 @@ class nsLayoutStylesheetCache MOZ_FINAL
static void Shutdown();
static size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
private:
nsLayoutStylesheetCache();
@ -47,12 +49,11 @@ private:
static void EnsureGlobal();
void InitFromProfile();
void InitMemoryReporter();
static void LoadSheetFile(nsIFile* aFile, nsRefPtr<nsCSSStyleSheet> &aSheet);
static void LoadSheet(nsIURI* aURI, nsRefPtr<nsCSSStyleSheet> &aSheet,
bool aEnableUnsafeRules);
size_t SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf) const;
static nsLayoutStylesheetCache* gStyleCache;
static mozilla::css::Loader* gCSSLoader;
nsRefPtr<nsCSSStyleSheet> mScrollbarsSheet;
@ -62,8 +63,6 @@ private:
nsRefPtr<nsCSSStyleSheet> mUASheet;
nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
#endif

View File

@ -341,7 +341,7 @@ class AddPreferencesMemoryReporterRunnable : public nsRunnable
{
NS_IMETHOD Run()
{
return NS_RegisterMemoryReporter(new PreferenceServiceReporter());
return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
}
};
} // anonymous namespace
@ -376,9 +376,9 @@ Preferences::GetInstanceForService()
gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
// Preferences::GetInstanceForService() can be called from GetService(), and
// NS_RegisterMemoryReporter calls GetService(nsIMemoryReporter). To avoid a
// potential recursive GetService() call, we can't register the memory
// reporter here; instead, do it off a runnable.
// RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter). To
// avoid a potential recursive GetService() call, we can't register the
// memory reporter here; instead, do it off a runnable.
nsRefPtr<AddPreferencesMemoryReporterRunnable> runnable =
new AddPreferencesMemoryReporterRunnable();
NS_DispatchToMainThread(runnable);

View File

@ -399,12 +399,12 @@ nsDiskCacheDevice::nsDiskCacheDevice()
, mReporter(nullptr)
{
mReporter = new NetworkDiskCacheReporter(this);
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(mReporter);
}
nsDiskCacheDevice::~nsDiskCacheDevice()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(mReporter);
Shutdown();
}

View File

@ -64,13 +64,13 @@ nsMemoryCacheDevice::nsMemoryCacheDevice()
PR_INIT_CLIST(&mEvictionList[i]);
mReporter = new NetworkMemoryCacheReporter(this);
NS_RegisterMemoryReporter(mReporter);
mozilla::RegisterWeakMemoryReporter(mReporter);
}
nsMemoryCacheDevice::~nsMemoryCacheDevice()
{
NS_UnregisterMemoryReporter(mReporter);
mozilla::UnregisterWeakMemoryReporter(mReporter);
Shutdown();
}

View File

@ -7,7 +7,6 @@
#include "nsIDNSRecord.h"
#include "nsIDNSListener.h"
#include "nsICancelable.h"
#include "nsIMemoryReporter.h"
#include "nsIPrefService.h"
#include "nsIPrefBranch.h"
#include "nsIServiceManager.h"
@ -394,26 +393,11 @@ nsDNSSyncRequest::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
//-----------------------------------------------------------------------------
class NetworkDNSServiceReporter MOZ_FINAL : public MemoryUniReporter
{
public:
NetworkDNSServiceReporter(nsDNSService* aService)
: MemoryUniReporter("explicit/network/dns-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for the DNS service.")
, mService(aService)
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return mService->SizeOfIncludingThis(MallocSizeOf);
}
nsDNSService *mService;
};
nsDNSService::nsDNSService()
: mLock("nsDNSServer.mLock")
: MemoryUniReporter("explicit/network/dns-service",
KIND_HEAP, UNITS_BYTES,
"Memory used for the DNS service.")
, mLock("nsDNSServer.mLock")
, mFirstTime(true)
, mOffline(false)
{
@ -423,7 +407,8 @@ nsDNSService::~nsDNSService()
{
}
NS_IMPL_ISUPPORTS3(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver)
NS_IMPL_ISUPPORTS_INHERITED3(nsDNSService, MemoryUniReporter, nsIDNSService,
nsPIDNSService, nsIObserver)
NS_IMETHODIMP
nsDNSService::Init()
@ -529,8 +514,7 @@ nsDNSService::Init()
}
}
mReporter = new NetworkDNSServiceReporter(this);
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
return rv;
}
@ -538,7 +522,7 @@ nsDNSService::Init()
NS_IMETHODIMP
nsDNSService::Shutdown()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
nsRefPtr<nsHostResolver> res;
{
@ -937,7 +921,7 @@ SizeOfLocalDomainsEntryExcludingThis(nsCStringHashKey* entry,
}
size_t
nsDNSService::SizeOfIncludingThis(MallocSizeOf mallocSizeOf) const
nsDNSService::SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const
{
// Measurement of the following members may be added later if DMD finds it
// is worthwhile:

View File

@ -7,6 +7,7 @@
#include "nsPIDNSService.h"
#include "nsIIDNService.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsHostResolver.h"
#include "nsAutoPtr.h"
@ -16,9 +17,8 @@
#include "mozilla/Mutex.h"
#include "mozilla/Attributes.h"
class nsIMemoryReporter;
class nsDNSService MOZ_FINAL : public nsPIDNSService
class nsDNSService MOZ_FINAL : public mozilla::MemoryUniReporter
, public nsPIDNSService
, public nsIObserver
{
public:
@ -30,6 +30,10 @@ public:
nsDNSService();
~nsDNSService();
int64_t Amount() MOZ_OVERRIDE
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
private:
@ -50,8 +54,6 @@ private:
bool mFirstTime;
bool mOffline;
nsTHashtable<nsCStringHashKey> mLocalDomains;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
#endif //nsDNSService2_h__

View File

@ -13,13 +13,13 @@
#include "nsEffectiveTLDService.h"
#include "nsIIDNService.h"
#include "nsIMemoryReporter.h"
#include "nsNetUtil.h"
#include "prnetdb.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS1(nsEffectiveTLDService, nsIEffectiveTLDService)
NS_IMPL_ISUPPORTS_INHERITED1(nsEffectiveTLDService, MemoryUniReporter,
nsIEffectiveTLDService)
// ----------------------------------------------------------------------
@ -61,28 +61,15 @@ nsDomainEntry::FuncForStaticAsserts(void)
static nsEffectiveTLDService *gService = nullptr;
class EffectiveTLDServiceReporter MOZ_FINAL : public MemoryUniReporter
{
public:
EffectiveTLDServiceReporter()
: MemoryUniReporter("explicit/xpcom/effective-TLD-service",
KIND_HEAP, UNITS_BYTES,
"Memory used by the effective TLD service.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return gService ? gService->SizeOfIncludingThis(MallocSizeOf) : 0;
}
};
nsEffectiveTLDService::nsEffectiveTLDService()
// We'll probably have to rehash at least once, since nsTHashtable doesn't
// use a perfect hash, but at least we'll save a few rehashes along the way.
// Next optimization here is to precompute the hash using something like
// gperf, but one step at a time. :-)
: mHash(ArrayLength(nsDomainEntry::entries))
: MemoryUniReporter("explicit/xpcom/effective-TLD-service",
KIND_HEAP, UNITS_BYTES,
"Memory used by the effective TLD service.")
, mHash(ArrayLength(nsDomainEntry::entries))
{
}
@ -112,27 +99,31 @@ nsEffectiveTLDService::Init()
MOZ_ASSERT(!gService);
gService = this;
mReporter = new EffectiveTLDServiceReporter();
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
return NS_OK;
}
nsEffectiveTLDService::~nsEffectiveTLDService()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
gService = nullptr;
}
int64_t
nsEffectiveTLDService::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
nsEffectiveTLDService::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
nsEffectiveTLDService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
n += mHash.SizeOfExcludingThis(nullptr, aMallocSizeOf);
// Measurement of the following members may be added later if DMD finds it is
// worthwhile:
// - mReporter
// - mIDNService
return n;

View File

@ -102,7 +102,9 @@ private:
#undef ETLD_STR_NUM1
};
class nsEffectiveTLDService MOZ_FINAL : public nsIEffectiveTLDService
class nsEffectiveTLDService MOZ_FINAL
: public mozilla::MemoryUniReporter
, public nsIEffectiveTLDService
{
public:
NS_DECL_ISUPPORTS
@ -111,6 +113,7 @@ public:
nsEffectiveTLDService();
nsresult Init();
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:
@ -118,7 +121,6 @@ private:
nsresult NormalizeHostname(nsCString &aHostname);
~nsEffectiveTLDService();
nsCOMPtr<nsIMemoryReporter> mReporter;
nsTHashtable<nsDomainEntry> mHash;
nsCOMPtr<nsIIDNService> mIDNService;
};

View File

@ -16,7 +16,6 @@
#include "nsDirectoryServiceUtils.h"
#include "nsIClassInfo.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsIObserverService.h"
#include "nsIOutputStream.h"
@ -52,38 +51,31 @@
namespace mozilla {
namespace scache {
class StartupCacheMappingReporter MOZ_FINAL : public MemoryUniReporter
NS_IMETHODIMP
StartupCache::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
public:
StartupCacheMappingReporter()
: MemoryUniReporter("explicit/startup-cache/mapping",
KIND_NONHEAP, UNITS_BYTES,
"Memory used to hold the mapping of the startup cache from file. This memory "
"is likely to be swapped out shortly after start-up.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
mozilla::scache::StartupCache* sc =
mozilla::scache::StartupCache::GetSingleton();
return sc ? sc->SizeOfMapping() : 0;
}
};
#define REPORT(_path, _kind, _amount, _desc) \
do { \
nsresult rv = \
aHandleReport->Callback(EmptyCString(), \
NS_LITERAL_CSTRING(_path), \
_kind, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aData); \
NS_ENSURE_SUCCESS(rv, rv); \
} while (0)
class StartupCacheDataReporter MOZ_FINAL : public MemoryUniReporter
{
public:
StartupCacheDataReporter()
: MemoryUniReporter("explicit/startup-cache/data", KIND_HEAP, UNITS_BYTES,
"Memory used by the startup cache for things other than the file mapping.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
mozilla::scache::StartupCache* sc =
mozilla::scache::StartupCache::GetSingleton();
return sc ? sc->HeapSizeOfIncludingThis(MallocSizeOf) : 0;
}
REPORT("explicit/startup-cache/mapping", KIND_NONHEAP,
SizeOfMapping(),
"Memory used to hold the mapping of the startup cache from file. "
"This memory is likely to be swapped out shortly after start-up.");
REPORT("explicit/startup-cache/data", KIND_HEAP,
HeapSizeOfIncludingThis(MallocSizeOf),
"Memory used by the startup cache for things other than the file "
"mapping.");
return NS_OK;
};
static const char sStartupCacheName[] = "startupCache." SC_WORDSIZE "." SC_ENDIAN;
@ -131,10 +123,11 @@ bool StartupCache::gShutdownInitiated;
bool StartupCache::gIgnoreDiskCache;
enum StartupCache::TelemetrifyAge StartupCache::gPostFlushAgeAction = StartupCache::IGNORE_AGE;
NS_IMPL_ISUPPORTS1(StartupCache, nsISupports)
NS_IMPL_ISUPPORTS_INHERITED0(StartupCache, MemoryMultiReporter)
StartupCache::StartupCache()
: mArchive(nullptr), mStartupWriteInitiated(false), mWriteThread(nullptr)
: MemoryMultiReporter("startup-cache"),
mArchive(nullptr), mStartupWriteInitiated(false), mWriteThread(nullptr)
{ }
StartupCache::~StartupCache()
@ -156,8 +149,7 @@ StartupCache::~StartupCache()
WriteToDisk();
}
NS_UnregisterMemoryReporter(mMappingReporter);
NS_UnregisterMemoryReporter(mDataReporter);
UnregisterWeakMemoryReporter(this);
}
nsresult
@ -244,10 +236,7 @@ StartupCache::Init()
InvalidateCache();
}
mMappingReporter = new StartupCacheMappingReporter();
mDataReporter = new StartupCacheDataReporter();
NS_RegisterMemoryReporter(mMappingReporter);
NS_RegisterMemoryReporter(mDataReporter);
RegisterWeakMemoryReporter(this);
return NS_OK;
}
@ -385,7 +374,7 @@ StartupCache::PutBuffer(const char* id, const char* inbuf, uint32_t len)
}
size_t
StartupCache::SizeOfMapping()
StartupCache::SizeOfMapping()
{
return mArchive ? mArchive->SizeOfMapping() : 0;
}

View File

@ -11,6 +11,7 @@
#include "nsZipArchive.h"
#include "nsIStartupCache.h"
#include "nsITimer.h"
#include "nsIMemoryReporter.h"
#include "nsIObserverService.h"
#include "nsIObserver.h"
#include "nsIOutputStream.h"
@ -19,8 +20,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/StaticPtr.h"
class nsIMemoryReporter;
/**
* The StartupCache is a persistent cache of simple key-value pairs,
* where the keys are null-terminated c-strings and the values are
@ -98,7 +97,7 @@ class StartupCacheListener MOZ_FINAL : public nsIObserver
NS_DECL_NSIOBSERVER
};
class StartupCache : public nsISupports
class StartupCache : public mozilla::MemoryMultiReporter
{
friend class StartupCacheListener;
@ -131,6 +130,9 @@ public:
static StartupCache* GetSingleton();
static void DeleteSingleton();
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData);
// This measures all the heap memory used by the StartupCache, i.e. it
// excludes the mapping.
size_t HeapSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
@ -179,9 +181,6 @@ private:
#ifdef DEBUG
nsTHashtable<nsISupportsHashKey> mWriteObjectMap;
#endif
nsCOMPtr<nsIMemoryReporter> mMappingReporter;
nsCOMPtr<nsIMemoryReporter> mDataReporter;
};
// This debug outputstream attempts to detect if clients are writing multiple

View File

@ -33,7 +33,6 @@
#endif
#include "nsIPromptService.h"
#include "nsIMemoryReporter.h"
#ifdef MOZ_STORAGE_MEMORY
# include "mozmemory.h"
@ -70,156 +69,140 @@ StorageSQLiteDistinguishedAmount()
return ::sqlite3_memory_used();
}
class StorageSQLiteReporter MOZ_FINAL : public MemoryMultiReporter
/**
* Passes a single SQLite memory statistic to a memory reporter callback.
*
* @param aHandleReport
* The callback.
* @param aData
* The data for the callback.
* @param aConn
* The SQLite connection.
* @param aPathHead
* Head of the path for the memory report.
* @param aKind
* The memory report statistic kind, one of "stmt", "cache" or
* "schema".
* @param aDesc
* The memory report description.
* @param aOption
* The SQLite constant for getting the measurement.
* @param aTotal
* The accumulator for the measurement.
*/
nsresult
ReportConn(nsIHandleReportCallback *aHandleReport,
nsISupports *aData,
sqlite3 *aConn,
const nsACString &aPathHead,
const nsACString &aKind,
const nsACString &aDesc,
int aOption,
size_t *aTotal)
{
private:
Service *mService; // a weakref because Service contains a strongref to this
nsCString mStmtDesc;
nsCString mCacheDesc;
nsCString mSchemaDesc;
nsCString path(aPathHead);
path.Append(aKind);
path.AppendLiteral("-used");
public:
StorageSQLiteReporter(Service *aService)
: MemoryMultiReporter("storage-sqlite")
, mService(aService)
int curr = 0, max = 0;
int rc = ::sqlite3_db_status(aConn, aOption, &curr, &max, 0);
nsresult rv = convertResultCode(rc);
NS_ENSURE_SUCCESS(rv, rv);
rv = aHandleReport->Callback(EmptyCString(), path,
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, int64_t(curr),
aDesc, aData);
NS_ENSURE_SUCCESS(rv, rv);
*aTotal += curr;
return NS_OK;
}
// Warning: To get a Connection's measurements requires holding its lock.
// There may be a delay getting the lock if another thread is accessing the
// Connection. This isn't very nice if CollectReports is called from the main
// thread! But at the time of writing this function is only called when
// about:memory is loaded (not, for example, when telemetry pings occur) and
// any delays in that case aren't so bad.
NS_IMETHODIMP
Service::CollectReports(nsIHandleReportCallback *aHandleReport,
nsISupports *aData)
{
nsresult rv;
size_t totalConnSize = 0;
{
mStmtDesc = NS_LITERAL_CSTRING(
"Memory (approximate) used by all prepared statements used by "
"connections to this database.");
nsTArray<nsRefPtr<Connection> > connections;
getConnections(connections);
mCacheDesc = NS_LITERAL_CSTRING(
"Memory (approximate) used by all pager caches used by connections "
"to this database.");
for (uint32_t i = 0; i < connections.Length(); i++) {
nsRefPtr<Connection> &conn = connections[i];
mSchemaDesc = NS_LITERAL_CSTRING(
"Memory (approximate) used to store the schema for all databases "
"associated with connections to this database.");
}
// Warning: To get a Connection's measurements requires holding its lock.
// There may be a delay getting the lock if another thread is accessing the
// Connection. This isn't very nice if CollectReports is called from the
// main thread! But at the time of writing this function is only called when
// about:memory is loaded (not, for example, when telemetry pings occur) and
// any delays in that case aren't so bad.
NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb,
nsISupports *aClosure)
{
nsresult rv;
size_t totalConnSize = 0;
{
nsTArray<nsRefPtr<Connection> > connections;
mService->getConnections(connections);
for (uint32_t i = 0; i < connections.Length(); i++) {
nsRefPtr<Connection> &conn = connections[i];
// Someone may have closed the Connection, in which case we skip it.
bool isReady;
(void)conn->GetConnectionReady(&isReady);
if (!isReady) {
continue;
}
nsCString pathHead("explicit/storage/sqlite/");
pathHead.Append(conn->getFilename());
pathHead.AppendLiteral("/");
SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex);
rv = reportConn(aCb, aClosure, *conn.get(), pathHead,
NS_LITERAL_CSTRING("stmt"), mStmtDesc,
SQLITE_DBSTATUS_STMT_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = reportConn(aCb, aClosure, *conn.get(), pathHead,
NS_LITERAL_CSTRING("cache"), mCacheDesc,
SQLITE_DBSTATUS_CACHE_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
rv = reportConn(aCb, aClosure, *conn.get(), pathHead,
NS_LITERAL_CSTRING("schema"), mSchemaDesc,
SQLITE_DBSTATUS_SCHEMA_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
// Someone may have closed the Connection, in which case we skip it.
bool isReady;
(void)conn->GetConnectionReady(&isReady);
if (!isReady) {
continue;
}
#ifdef MOZ_DMD
if (::sqlite3_memory_used() != int64_t(gSqliteMemoryUsed)) {
NS_WARNING("memory consumption reported by SQLite doesn't match "
"our measurements");
}
#endif
nsCString pathHead("explicit/storage/sqlite/");
pathHead.Append(conn->getFilename());
pathHead.AppendLiteral("/");
SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex);
NS_NAMED_LITERAL_CSTRING(stmtDesc,
"Memory (approximate) used by all prepared statements used by "
"connections to this database.");
rv = ReportConn(aHandleReport, aData, *conn.get(), pathHead,
NS_LITERAL_CSTRING("stmt"), stmtDesc,
SQLITE_DBSTATUS_STMT_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_CSTRING(cacheDesc,
"Memory (approximate) used by all pager caches used by connections "
"to this database.");
rv = ReportConn(aHandleReport, aData, *conn.get(), pathHead,
NS_LITERAL_CSTRING("cache"), cacheDesc,
SQLITE_DBSTATUS_CACHE_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
NS_NAMED_LITERAL_CSTRING(schemaDesc,
"Memory (approximate) used to store the schema for all databases "
"associated with connections to this database.");
rv = ReportConn(aHandleReport, aData, *conn.get(), pathHead,
NS_LITERAL_CSTRING("schema"), schemaDesc,
SQLITE_DBSTATUS_SCHEMA_USED, &totalConnSize);
NS_ENSURE_SUCCESS(rv, rv);
}
int64_t other = ::sqlite3_memory_used() - totalConnSize;
rv = aCb->Callback(NS_LITERAL_CSTRING(""),
NS_LITERAL_CSTRING("explicit/storage/sqlite/other"),
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, other,
NS_LITERAL_CSTRING("All unclassified sqlite memory."),
aClosure);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
#ifdef MOZ_DMD
if (::sqlite3_memory_used() != int64_t(gSqliteMemoryUsed)) {
NS_WARNING("memory consumption reported by SQLite doesn't match "
"our measurements");
}
#endif
}
private:
/**
* Passes a single SQLite memory statistic to a memory reporter callback.
*
* @param aCallback
* The callback.
* @param aClosure
* The closure for the callback.
* @param aConn
* The SQLite connection.
* @param aPathHead
* Head of the path for the memory report.
* @param aKind
* The memory report statistic kind, one of "stmt", "cache" or
* "schema".
* @param aDesc
* The memory report description.
* @param aOption
* The SQLite constant for getting the measurement.
* @param aTotal
* The accumulator for the measurement.
*/
nsresult reportConn(nsIMemoryReporterCallback *aCb,
nsISupports *aClosure,
sqlite3 *aConn,
const nsACString &aPathHead,
const nsACString &aKind,
const nsACString &aDesc,
int aOption,
size_t *aTotal)
{
nsCString path(aPathHead);
path.Append(aKind);
path.AppendLiteral("-used");
int64_t other = ::sqlite3_memory_used() - totalConnSize;
int curr = 0, max = 0;
int rc = ::sqlite3_db_status(aConn, aOption, &curr, &max, 0);
nsresult rv = convertResultCode(rc);
NS_ENSURE_SUCCESS(rv, rv);
rv = aHandleReport->Callback(
EmptyCString(),
NS_LITERAL_CSTRING("explicit/storage/sqlite/other"),
KIND_HEAP, UNITS_BYTES, other,
NS_LITERAL_CSTRING("All unclassified sqlite memory."),
aData);
NS_ENSURE_SUCCESS(rv, rv);
rv = aCb->Callback(NS_LITERAL_CSTRING(""), path,
nsIMemoryReporter::KIND_HEAP,
nsIMemoryReporter::UNITS_BYTES, int64_t(curr),
aDesc, aClosure);
NS_ENSURE_SUCCESS(rv, rv);
*aTotal += curr;
return NS_OK;
}
};
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// Service
NS_IMPL_ISUPPORTS2(
NS_IMPL_ISUPPORTS_INHERITED2(
Service,
MemoryMultiReporter,
mozIStorageService,
nsIObserver
)
@ -295,7 +278,8 @@ Service::getSynchronousPref()
int32_t Service::sDefaultPageSize = PREF_TS_PAGESIZE_DEFAULT;
Service::Service()
: mMutex("Service::mMutex")
: MemoryMultiReporter("storage-sqlite")
, mMutex("Service::mMutex")
, mSqliteVFS(nullptr)
, mRegistrationMutex("Service::mRegistrationMutex")
, mConnections()
@ -304,7 +288,7 @@ Service::Service()
Service::~Service()
{
(void)::NS_UnregisterMemoryReporter(mStorageSQLiteReporter);
mozilla::UnregisterWeakMemoryReporter(this);
mozilla::UnregisterStorageSQLiteDistinguishedAmount();
int rc = sqlite3_vfs_unregister(mSqliteVFS);
@ -535,11 +519,7 @@ Service::initialize()
sDefaultPageSize =
Preferences::GetInt(PREF_TS_PAGESIZE, PREF_TS_PAGESIZE_DEFAULT);
// Create and register our SQLite memory reporter and distinguished amount
// function. Registration can only happen on the main thread (otherwise
// you'll get cryptic crashes).
mStorageSQLiteReporter = new StorageSQLiteReporter(this);
(void)::NS_RegisterMemoryReporter(mStorageSQLiteReporter);
mozilla::RegisterWeakMemoryReporter(this);
mozilla::RegisterStorageSQLiteDistinguishedAmount(StorageSQLiteDistinguishedAmount);
return NS_OK;

View File

@ -10,6 +10,7 @@
#include "nsCOMPtr.h"
#include "nsICollation.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsTArray.h"
#include "mozilla/Mutex.h"
@ -24,7 +25,8 @@ namespace mozilla {
namespace storage {
class Connection;
class Service : public mozIStorageService
class Service : public MemoryMultiReporter
, public mozIStorageService
, public nsIObserver
{
public:
@ -56,6 +58,9 @@ public:
NS_DECL_MOZISTORAGESERVICE
NS_DECL_NSIOBSERVER
NS_IMETHOD CollectReports(nsIHandleReportCallback *aHandleReport,
nsISupports *aData);
/**
* Obtains an already AddRefed pointer to XPConnect. This is used by
* language helpers.

View File

@ -6,7 +6,7 @@
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<!-- This file uses fake memory reporters to test the presentation of memory
<!-- This file uses fake memory reporters to test the presentation of memory
reports in about:memory. test_memoryReporters.xul uses the real
memory reporters to test whether the memory reporters are producing
sensible results. -->
@ -27,15 +27,8 @@
let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
getService(Ci.nsIMemoryReporterManager);
// Remove all the real reporters; save them to restore at the end.
mgr.blockRegistration();
let e = mgr.enumerateReporters();
let realReporters = [];
while (e.hasMoreElements()) {
let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
mgr.unregisterReporter(r);
realReporters.push(r);
}
// Hide all the real reporters; we'll restore them at the end.
mgr.blockRegistrationAndHideExistingReporters();
// Setup various fake-but-deterministic reporters.
const KB = 1024;
@ -123,7 +116,7 @@
}
];
for (let i = 0; i < fakeReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(fakeReporters[i]);
mgr.registerStrongReporterEvenIfBlocked(fakeReporters[i]);
}
// mgr.explicit sums "heap-allocated" and all the appropriate NONHEAP ones:
@ -140,7 +133,7 @@
} catch (ex) {
is(ex.result, Cr.NS_ERROR_NOT_AVAILABLE, "mgr.explicit exception");
}
// The main process always comes first when we display about:memory. The
// remaining processes are sorted by their |resident| values (starting with
// the largest). Processes without a |resident| memory reporter are saved
@ -200,7 +193,7 @@
}
];
for (let i = 0; i < fakeReporters2.length; i++) {
mgr.registerReporterEvenIfBlocked(fakeReporters2[i]);
mgr.registerStrongReporterEvenIfBlocked(fakeReporters2[i]);
}
fakeReporters = fakeReporters.concat(fakeReporters2);
]]>
@ -550,16 +543,7 @@ End of 5th\n\
function finish()
{
// Unregister fake reporters and re-register the real reporters, just in
// case subsequent tests rely on them.
for (let i = 0; i < fakeReporters.length; i++) {
mgr.unregisterReporter(fakeReporters[i]);
}
for (let i = 0; i < realReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(realReporters[i]);
}
mgr.unblockRegistration();
mgr.unblockRegistrationAndRestoreOriginalReporters();
SimpleTest.finish();
}

View File

@ -22,15 +22,8 @@
let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
getService(Ci.nsIMemoryReporterManager);
// Remove all the real reporters; save them to restore at the end.
mgr.blockRegistration();
let e = mgr.enumerateReporters();
let realReporters = [];
while (e.hasMoreElements()) {
let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
mgr.unregisterReporter(r);
realReporters.push(r);
}
// Hide all the real reporters; we'll restore them at the end.
mgr.blockRegistrationAndHideExistingReporters();
// Setup various fake-but-deterministic reporters.
const KB = 1024;
@ -66,7 +59,7 @@
];
for (let i = 0; i < fakeReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(fakeReporters[i]);
mgr.registerStrongReporterEvenIfBlocked(fakeReporters[i]);
}
]]>
@ -78,16 +71,7 @@
<![CDATA[
function finish()
{
// Unregister fake reporters and re-register the real reporters, just in
// case subsequent tests rely on them.
for (let i = 0; i < fakeReporters.length; i++) {
mgr.unregisterReporter(fakeReporters[i]);
}
for (let i = 0; i < realReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(realReporters[i]);
}
mgr.unblockRegistration();
mgr.unblockRegistrationAndRestoreOriginalReporters();
SimpleTest.finish();
}

View File

@ -22,15 +22,8 @@
let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
getService(Ci.nsIMemoryReporterManager);
// Remove all the real reporters; save them to restore at the end.
mgr.blockRegistration();
let e = mgr.enumerateReporters();
let realReporters = [];
while (e.hasMoreElements()) {
let r = e.getNext().QueryInterface(Ci.nsIMemoryReporter);
mgr.unregisterReporter(r);
realReporters.push(r);
}
// Hide all the real reporters; we'll restore them at the end.
mgr.blockRegistrationAndHideExistingReporters();
// Setup a minimal number of fake reporters.
const KB = 1024;
@ -53,7 +46,7 @@
];
for (let i = 0; i < fakeReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(fakeReporters[i]);
mgr.registerStrongReporterEvenIfBlocked(fakeReporters[i]);
}
]]>
@ -65,16 +58,7 @@
<![CDATA[
function finish()
{
// Unregister fake reporters and re-register the real reporters, just in
// case subsequent tests rely on them.
for (let i = 0; i < fakeReporters.length; i++) {
mgr.unregisterReporter(fakeReporters[i]);
}
for (let i = 0; i < realReporters.length; i++) {
mgr.registerReporterEvenIfBlocked(realReporters[i]);
}
mgr.unblockRegistration();
mgr.unblockRegistrationAndRestoreOriginalReporters();
SimpleTest.finish();
}

View File

@ -31,7 +31,6 @@
#include "nsIXPConnect.h"
#include "mozilla/unused.h"
#include "nsContentUtils.h" // for nsAutoScriptBlocker
#include "nsIMemoryReporter.h"
#include "mozilla/ipc/URIUtils.h"
#include "nsPrintfCString.h"
#include "nsTHashtable.h"
@ -1908,23 +1907,6 @@ StoreAndNotifyEmbedVisit(VisitData& aPlace,
(void)NS_DispatchToMainThread(event);
}
class HistoryLinksHashtableReporter MOZ_FINAL : public MemoryUniReporter
{
public:
HistoryLinksHashtableReporter()
: MemoryUniReporter("explicit/history-links-hashtable",
KIND_HEAP, UNITS_BYTES,
"Memory used by the hashtable that records changes to the visited state of "
"links.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
History* history = History::GetService();
return history ? history->SizeOfIncludingThis(MallocSizeOf) : 0;
}
};
} // anonymous namespace
////////////////////////////////////////////////////////////////////////////////
@ -1933,7 +1915,11 @@ private:
History* History::gService = nullptr;
History::History()
: mShuttingDown(false)
: MemoryUniReporter("explicit/history-links-hashtable",
KIND_HEAP, UNITS_BYTES,
"Memory used by the hashtable that records changes to the visited state of "
"links.")
, mShuttingDown(false)
, mShutdownMutex("History::mShutdownMutex")
, mObservers(VISIT_OBSERVERS_INITIAL_CACHE_SIZE)
, mRecentlyVisitedURIsNextIndex(0)
@ -1946,14 +1932,11 @@ History::History()
if (os) {
(void)os->AddObserver(this, TOPIC_PLACES_SHUTDOWN, false);
}
mReporter = new HistoryLinksHashtableReporter();
NS_RegisterMemoryReporter(mReporter);
}
History::~History()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
gService = nullptr;
@ -1961,6 +1944,12 @@ History::~History()
"Not all Links were removed before we disappear!");
}
void
History::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
NS_IMETHODIMP
History::NotifyVisited(nsIURI* aURI)
{
@ -2232,6 +2221,12 @@ History::SizeOfEntryExcludingThis(KeyClass* aEntry, mozilla::MallocSizeOf aMallo
return aEntry->array.SizeOfExcludingThis(aMallocSizeOf);
}
int64_t
History::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
History::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOfThis)
{
@ -2261,6 +2256,7 @@ History::GetSingleton()
if (!gService) {
gService = new History();
NS_ENSURE_TRUE(gService, nullptr);
gService->InitMemoryReporter();
}
NS_ADDREF(gService);
@ -2918,8 +2914,9 @@ History::Observe(nsISupports* aSubject, const char* aTopic,
////////////////////////////////////////////////////////////////////////////////
//// nsISupports
NS_IMPL_ISUPPORTS4(
NS_IMPL_ISUPPORTS_INHERITED4(
History
, MemoryUniReporter
, IHistory
, nsIDownloadHistory
, mozIAsyncHistory

View File

@ -20,11 +20,10 @@
#include "nsURIHashKey.h"
#include "nsTObserverArray.h"
#include "nsDeque.h"
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "mozIStorageConnection.h"
class nsIMemoryReporter;
namespace mozilla {
namespace places {
@ -36,7 +35,8 @@ struct VisitData;
// Max size of History::mRecentlyVisitedURIs
#define RECENTLY_VISITED_URI_SIZE 8
class History : public IHistory
class History : mozilla::MemoryUniReporter
, public IHistory
, public nsIDownloadHistory
, public mozIAsyncHistory
, public nsIObserver
@ -85,6 +85,7 @@ public:
* Get the number of bytes of memory this History object is using,
* including sizeof(*this))
*/
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
/**
@ -131,6 +132,8 @@ public:
private:
virtual ~History();
void InitMemoryReporter();
/**
* Obtains a read-write database connection.
*/
@ -210,8 +213,6 @@ private:
RecentlyVisitedArray::index_type mRecentlyVisitedURIsNextIndex;
bool IsRecentlyVisitedURI(nsIURI* aURI);
nsCOMPtr<nsIMemoryReporter> mReporter;
};
} // namespace places

View File

@ -232,15 +232,18 @@ HangReports::GetDuration(unsigned aIndex) const {
return mDurations[aIndex];
}
class TelemetryImpl MOZ_FINAL : public nsITelemetry
class TelemetryImpl MOZ_FINAL
: public MemoryUniReporter
, public nsITelemetry
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITELEMETRY
public:
TelemetryImpl();
~TelemetryImpl();
void InitMemoryReporter();
static bool CanRecord();
static already_AddRefed<nsITelemetry> CreateTelemetryInstance();
static void ShutdownTelemetry();
@ -252,7 +255,8 @@ public:
#endif
static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
static int64_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
struct Stat {
uint32_t hitCount;
uint32_t totalTime;
@ -264,7 +268,7 @@ public:
typedef nsBaseHashtableET<nsCStringHashKey, StmtStats> SlowSQLEntryType;
private:
size_t SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf);
TelemetryImpl();
static nsCString SanitizeSQL(const nsACString& sql);
@ -326,7 +330,6 @@ private:
// mThreadHangStats stores recorded, inactive thread hang stats
Vector<Telemetry::ThreadHangStats> mThreadHangStats;
Mutex mThreadHangStatsMutex;
nsCOMPtr<nsIMemoryReporter> mReporter;
CombinedStacks mLateWritesStacks; // This is collected out of the main thread.
bool mCachedTelemetryData;
@ -338,8 +341,14 @@ private:
TelemetryImpl* TelemetryImpl::sTelemetry = nullptr;
int64_t
TelemetryImpl::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
TelemetryImpl::SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf)
TelemetryImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
// Ignore the hashtables in mAddonMap; they are not significant.
@ -350,41 +359,19 @@ TelemetryImpl::SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf)
n += mTrackedDBs.SizeOfExcludingThis(nullptr, aMallocSizeOf);
n += mHangReports.SizeOfExcludingThis();
n += mThreadHangStats.sizeOfExcludingThis(aMallocSizeOf);
return n;
}
int64_t
TelemetryImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
int64_t n = 0;
if (sTelemetry) {
n += sTelemetry->SizeOfIncludingThisHelper(aMallocSizeOf);
}
// It's a bit gross that we measure this other stuff that lives outside of
// TelemetryImpl... oh well.
StatisticsRecorder::Histograms hs;
StatisticsRecorder::GetHistograms(&hs);
for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) {
Histogram *h = *it;
n += h->SizeOfIncludingThis(aMallocSizeOf);
}
return n;
}
class TelemetryReporter MOZ_FINAL : public MemoryUniReporter
{
public:
TelemetryReporter()
: MemoryUniReporter("explicit/telemetry", KIND_HEAP, UNITS_BYTES,
"Memory used by the telemetry system.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return TelemetryImpl::SizeOfIncludingThis(MallocSizeOf);
}
};
// A initializer to initialize histogram collection
StatisticsRecorder gStatisticsRecorder;
@ -764,7 +751,7 @@ public:
private:
const char* mShutdownTimeFilename;
nsCOMPtr<nsIFile> mFailedProfileLockFile;
nsCOMPtr<TelemetryImpl> mTelemetry;
nsRefPtr<TelemetryImpl> mTelemetry;
nsCOMPtr<nsIFile> mProfileDir;
public:
@ -944,6 +931,8 @@ TelemetryImpl::AsyncFetchTelemetryData(nsIFetchTelemetryDataCallback *aCallback)
}
TelemetryImpl::TelemetryImpl():
MemoryUniReporter("explicit/telemetry", KIND_HEAP, UNITS_BYTES,
"Memory used by the telemetry system."),
mHistogramMap(Telemetry::HistogramCount),
mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
mHashMutex("Telemetry::mHashMutex"),
@ -969,12 +958,15 @@ mFailedLockCount(0)
// Mark immutable to prevent asserts on simultaneous access from multiple threads
mTrackedDBs.MarkImmutable();
#endif
mReporter = new TelemetryReporter();
NS_RegisterMemoryReporter(mReporter);
}
TelemetryImpl::~TelemetryImpl() {
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
void
TelemetryImpl::InitMemoryReporter() {
RegisterWeakMemoryReporter(this);
}
NS_IMETHODIMP
@ -2028,6 +2020,9 @@ TelemetryImpl::CreateTelemetryInstance()
NS_ADDREF(sTelemetry);
// AddRef for the caller
nsCOMPtr<nsITelemetry> ret = sTelemetry;
sTelemetry->InitMemoryReporter();
return ret.forget();
}
@ -2252,7 +2247,7 @@ TelemetryImpl::RecordThreadHangStats(Telemetry::ThreadHangStats& aStats)
sTelemetry->mThreadHangStats.append(Move(aStats));
}
NS_IMPL_ISUPPORTS1(TelemetryImpl, nsITelemetry)
NS_IMPL_ISUPPORTS_INHERITED1(TelemetryImpl, MemoryUniReporter, nsITelemetry)
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance)
#define NS_TELEMETRY_CID \

View File

@ -14,7 +14,6 @@
#include "nsIUrlClassifierPrefixSet.h"
#include "nsIRandomGenerator.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsToolkitCompsCID.h"
#include "nsTArray.h"
#include "nsThreadUtils.h"
@ -36,34 +35,12 @@ static const PRLogModuleInfo *gUrlClassifierPrefixSetLog = nullptr;
#define LOG_ENABLED() (false)
#endif
class PrefixSetReporter MOZ_FINAL : public MemoryUniReporter
{
public:
PrefixSetReporter(nsUrlClassifierPrefixSet* aPrefixSet,
const nsACString& aName)
: MemoryUniReporter(
nsPrintfCString(
"explicit/storage/prefix-set/%s",
(!aName.IsEmpty() ? PromiseFlatCString(aName).get() : "?!")
).get(),
KIND_HEAP, UNITS_BYTES,
"Memory used by the prefix set for a URL classifier.")
, mPrefixSet(aPrefixSet)
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return mPrefixSet->SizeOfIncludingThis(MallocSizeOf);
}
nsUrlClassifierPrefixSet* mPrefixSet;
};
NS_IMPL_ISUPPORTS1(nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet)
NS_IMPL_ISUPPORTS2(
nsUrlClassifierPrefixSet, nsIUrlClassifierPrefixSet, nsIMemoryReporter)
nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
: mHasPrefixes(false)
, mMemoryReportPath()
{
#if defined(PR_LOGGING)
if (!gUrlClassifierPrefixSetLog)
@ -74,15 +51,20 @@ nsUrlClassifierPrefixSet::nsUrlClassifierPrefixSet()
NS_IMETHODIMP
nsUrlClassifierPrefixSet::Init(const nsACString& aName)
{
mReporter = new PrefixSetReporter(this, aName);
NS_RegisterMemoryReporter(mReporter);
mMemoryReportPath =
nsPrintfCString(
"explicit/storage/prefix-set/%s",
(!aName.IsEmpty() ? PromiseFlatCString(aName).get() : "?!")
);
RegisterWeakMemoryReporter(this);
return NS_OK;
}
nsUrlClassifierPrefixSet::~nsUrlClassifierPrefixSet()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
NS_IMETHODIMP
@ -268,8 +250,21 @@ nsUrlClassifierPrefixSet::Contains(uint32_t aPrefix, bool* aFound)
return NS_OK;
}
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(UrlClassifierMallocSizeOf)
NS_IMETHODIMP
nsUrlClassifierPrefixSet::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
return aHandleReport->Callback(
EmptyCString(), mMemoryReportPath, KIND_HEAP, UNITS_BYTES,
SizeOfIncludingThis(UrlClassifierMallocSizeOf),
NS_LITERAL_CSTRING("Memory used by the prefix set for a URL classifier."),
aData);
}
size_t
nsUrlClassifierPrefixSet::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
nsUrlClassifierPrefixSet::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = 0;
n += aMallocSizeOf(this);

View File

@ -10,6 +10,7 @@
#include "nsISupportsUtils.h"
#include "nsID.h"
#include "nsIFile.h"
#include "nsIMemoryReporter.h"
#include "nsIMutableArray.h"
#include "nsIUrlClassifierPrefixSet.h"
#include "nsTArray.h"
@ -19,9 +20,9 @@
#include "mozilla/CondVar.h"
#include "mozilla/FileUtils.h"
class nsIMemoryReporter;
class nsUrlClassifierPrefixSet : public nsIUrlClassifierPrefixSet
class nsUrlClassifierPrefixSet
: public nsIUrlClassifierPrefixSet
, public nsIMemoryReporter
{
public:
nsUrlClassifierPrefixSet();
@ -35,10 +36,10 @@ public:
NS_IMETHOD LoadFromFile(nsIFile* aFile);
NS_IMETHOD StoreToFile(nsIFile* aFile);
NS_DECL_ISUPPORTS
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIMEMORYREPORTER
// Return the estimated size of the set on disk and in memory,
// in bytes
// Return the estimated size of the set on disk and in memory, in bytes.
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
protected:
@ -46,8 +47,6 @@ protected:
static const uint32_t MAX_INDEX_DIFF = (1 << 16);
static const uint32_t PREFIXSET_VERSION_MAGIC = 1;
nsCOMPtr<nsIMemoryReporter> mReporter;
nsresult MakePrefixSet(const uint32_t* aArray, uint32_t aLength);
uint32_t BinSearch(uint32_t start, uint32_t end, uint32_t target);
nsresult LoadFromFd(mozilla::AutoFDClose& fileFd);
@ -63,6 +62,8 @@ protected:
FallibleTArray<uint32_t> mIndexStarts;
// array containing deltas from indices.
FallibleTArray<uint16_t> mDeltas;
nsCString mMemoryReportPath;
};
#endif

View File

@ -510,10 +510,10 @@ void Activate()
Preferences::AddUintVarCache(&sLowMemoryNotificationIntervalMS,
"memory.low_memory_notification_interval_ms", 10000);
NS_RegisterMemoryReporter(new LowCommitSpaceEventsReporter());
NS_RegisterMemoryReporter(new LowMemoryEventsPhysicalReporter());
RegisterStrongMemoryReporter(new LowCommitSpaceEventsReporter());
RegisterStrongMemoryReporter(new LowMemoryEventsPhysicalReporter());
if (sizeof(void*) == 4) {
NS_RegisterMemoryReporter(new LowMemoryEventsVirtualReporter());
RegisterStrongMemoryReporter(new LowMemoryEventsVirtualReporter());
}
RegisterLowMemoryEventsVirtualDistinguishedAmount(LowMemoryEventsVirtualDistinguishedAmount);
RegisterLowMemoryEventsPhysicalDistinguishedAmount(LowMemoryEventsPhysicalDistinguishedAmount);

View File

@ -995,7 +995,7 @@ enum ccType {
// Top level structure for the cycle collector.
////////////////////////////////////////////////////////////////////////
class nsCycleCollector : public nsISupports
class nsCycleCollector : public MemoryMultiReporter
{
NS_DECL_ISUPPORTS
@ -1020,8 +1020,6 @@ class nsCycleCollector : public nsISupports
CC_BeforeUnlinkCallback mBeforeUnlinkCB;
CC_ForgetSkippableCallback mForgetSkippableCB;
nsCOMPtr<nsIMemoryReporter> mReporter;
nsPurpleBuffer mPurpleBuf;
uint32_t mUnmergedNeeded;
@ -1056,7 +1054,10 @@ public:
nsICycleCollectorListener *aManualListener);
void Shutdown();
void SizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData);
void SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
size_t *aObjectSize,
size_t *aGraphNodesSize,
size_t *aGraphEdgesSize,
@ -1081,7 +1082,7 @@ private:
void CleanupAfterCollection();
};
NS_IMPL_ISUPPORTS1(nsCycleCollector, nsISupports)
NS_IMPL_ISUPPORTS_INHERITED0(nsCycleCollector, MemoryMultiReporter)
/**
* GraphWalker is templatized over a Visitor class that must provide
@ -2475,70 +2476,58 @@ nsCycleCollector::CollectWhite()
////////////////////////
// Memory reporter
// Memory reporting
////////////////////////
class CycleCollectorReporter MOZ_FINAL : public MemoryMultiReporter
NS_IMETHODIMP
nsCycleCollector::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
public:
CycleCollectorReporter(nsCycleCollector* aCollector)
: MemoryMultiReporter("cycle-collector"),
mCollector(aCollector)
{}
size_t objectSize, graphNodesSize, graphEdgesSize, weakMapsSize,
purpleBufferSize;
SizeOfIncludingThis(MallocSizeOf,
&objectSize,
&graphNodesSize, &graphEdgesSize,
&weakMapsSize,
&purpleBufferSize);
NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCb,
nsISupports* aClosure)
{
size_t objectSize, graphNodesSize, graphEdgesSize, weakMapsSize,
purpleBufferSize;
mCollector->SizeOfIncludingThis(MallocSizeOf,
&objectSize,
&graphNodesSize, &graphEdgesSize,
&weakMapsSize,
&purpleBufferSize);
#define REPORT(_path, _amount, _desc) \
do { \
size_t amount = _amount; /* evaluate |_amount| only once */ \
if (amount > 0) { \
nsresult rv; \
rv = aHandleReport->Callback(EmptyCString(), \
NS_LITERAL_CSTRING(_path), \
KIND_HEAP, UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), \
aData); \
if (NS_WARN_IF(NS_FAILED(rv))) \
return rv; \
} \
} while (0)
#define REPORT(_path, _amount, _desc) \
do { \
size_t amount = _amount; /* evaluate |_amount| only once */ \
if (amount > 0) { \
nsresult rv; \
rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \
nsIMemoryReporter::KIND_HEAP, \
nsIMemoryReporter::UNITS_BYTES, _amount, \
NS_LITERAL_CSTRING(_desc), aClosure); \
if (NS_WARN_IF(NS_FAILED(rv))) \
return rv; \
} \
} while (0)
REPORT("explicit/cycle-collector/collector-object", objectSize,
"Memory used for the cycle collector object itself.");
REPORT("explicit/cycle-collector/collector-object", objectSize,
"Memory used for the cycle collector object itself.");
REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize,
"Memory used for the nodes of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/graph-nodes", graphNodesSize,
"Memory used for the nodes of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize,
"Memory used for the edges of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/graph-edges", graphEdgesSize,
"Memory used for the edges of the cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/weak-maps", weakMapsSize,
"Memory used for the representation of weak maps in the "
"cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/weak-maps", weakMapsSize,
"Memory used for the representation of weak maps in the "
"cycle collector's graph. "
"This should be zero when the collector is idle.");
REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize,
"Memory used for the cycle collector's purple buffer.");
REPORT("explicit/cycle-collector/purple-buffer", purpleBufferSize,
"Memory used for the cycle collector's purple buffer.");
#undef REPORT
#undef REPORT
return NS_OK;
}
private:
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf)
nsCycleCollector* mCollector;
return NS_OK;
};
@ -2547,6 +2536,7 @@ class CycleCollectorReporter MOZ_FINAL : public MemoryMultiReporter
////////////////////////////////////////////////////////////////////////
nsCycleCollector::nsCycleCollector() :
MemoryMultiReporter("cycle-collector"),
mCollectionInProgress(false),
mScanInProgress(false),
mJSRuntime(nullptr),
@ -2554,7 +2544,6 @@ nsCycleCollector::nsCycleCollector() :
mWhiteNodeCount(0),
mBeforeUnlinkCB(nullptr),
mForgetSkippableCB(nullptr),
mReporter(nullptr),
mUnmergedNeeded(0),
mMergedInARow(0)
{
@ -2562,7 +2551,7 @@ nsCycleCollector::nsCycleCollector() :
nsCycleCollector::~nsCycleCollector()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
}
void
@ -2573,12 +2562,12 @@ nsCycleCollector::RegisterJSRuntime(CycleCollectedJSRuntime *aJSRuntime)
mJSRuntime = aJSRuntime;
// We can't register the reporter in nsCycleCollector() because that runs
// We can't register as a reporter in nsCycleCollector() because that runs
// before the memory reporter manager is initialized. So we do it here
// instead.
static bool registered = false;
if (!registered) {
NS_RegisterMemoryReporter(new CycleCollectorReporter(this));
RegisterWeakMemoryReporter(this);
registered = true;
}
}
@ -2859,7 +2848,7 @@ nsCycleCollector::Shutdown()
}
void
nsCycleCollector::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf,
nsCycleCollector::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
size_t *aObjectSize,
size_t *aGraphNodesSize,
size_t *aGraphEdgesSize,

View File

@ -178,7 +178,7 @@ interface nsIFinishReportingCallback : nsISupports
void callback(in nsISupports data);
};
[scriptable, builtinclass, uuid(41c667f4-16b3-424f-95d9-a6f903f72eb2)]
[scriptable, builtinclass, uuid(9245d89e-6523-45f9-bc15-a69789e33cbb)]
interface nsIMemoryReporterManager : nsISupports
{
/*
@ -189,21 +189,30 @@ interface nsIMemoryReporterManager : nsISupports
/*
* Register the given nsIMemoryReporter. After a reporter is registered,
* it will be available via enumerateReporters(). The Manager service
* will hold a strong reference to the given reporter.
* will hold a strong reference to the given reporter, and will be
* responsible for freeing the reporter at shutdown.
*/
void registerReporter(in nsIMemoryReporter reporter);
void registerStrongReporter(in nsIMemoryReporter reporter);
/*
* Unregister the given memory reporter.
* Like registerReporter, but the Manager service will hold a weak reference
* to the given reporter. The reporter should be unregistered before
* shutdown.
*/
void unregisterReporter(in nsIMemoryReporter reporter);
void registerWeakReporter(in nsIMemoryReporter reporter);
/*
* Unregister the given memory reporter, which must have been registered with
* registerWeakReporter().
*/
void unregisterWeakReporter(in nsIMemoryReporter reporter);
/*
* These functions should only be used for testing purposes.
*/
void blockRegistration();
void unblockRegistration();
void registerReporterEvenIfBlocked(in nsIMemoryReporter aReporter);
void blockRegistrationAndHideExistingReporters();
void unblockRegistrationAndRestoreOriginalReporters();
void registerStrongReporterEvenIfBlocked(in nsIMemoryReporter aReporter);
/*
* Return an enumerator of nsIMemoryReporters that are currently registered
@ -364,15 +373,19 @@ class nsPIDOMWindow;
// around for backwards compatibility.
typedef nsIMemoryReporterCallback nsIHandleReportCallback;
// Note that the memory reporters are held in an nsCOMArray, which means
// that individual reporters should be referenced with |nsIMemoryReporter *|
// instead of nsCOMPtr<nsIMemoryReporter>.
XPCOM_API(nsresult) NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter);
XPCOM_API(nsresult) NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter);
namespace mozilla {
// Register a memory reporter. The manager service will hold a strong
// reference to this reporter.
XPCOM_API(nsresult) RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter);
// Register a memory reporter. The manager service will hold a weak reference
// to this reporter.
XPCOM_API(nsresult) RegisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
// Unregister a weak memory reporter.
XPCOM_API(nsresult) UnregisterWeakMemoryReporter(nsIMemoryReporter* aReporter);
// The memory reporter manager provides access to several distinguished
// amounts via attributes. Some of these amounts are provided by Gecko
// components that cannot be accessed directly from XPCOM code. So we provide

View File

@ -713,7 +713,7 @@ private:
// registered with nsMemoryReporterManager entirely within nsAtomTable.cpp.
// However, the obvious time to register it is when the table is initialized,
// and that happens before XPCOM components are initialized, which means the
// NS_RegisterMemoryReporter call fails. So instead we do it here.
// RegisterStrongMemoryReporter call fails. So instead we do it here.
class AtomTablesReporter MOZ_FINAL : public MemoryUniReporter
{
public:
@ -801,40 +801,40 @@ nsMemoryReporterManager::Init()
#endif
#ifdef HAVE_JEMALLOC_STATS
RegisterReporter(new HeapAllocatedReporter);
RegisterReporter(new HeapOverheadWasteReporter);
RegisterReporter(new HeapOverheadBookkeepingReporter);
RegisterReporter(new HeapOverheadPageCacheReporter);
RegisterReporter(new HeapCommittedReporter);
RegisterReporter(new HeapOverheadRatioReporter);
RegisterStrongReporter(new HeapAllocatedReporter());
RegisterStrongReporter(new HeapOverheadWasteReporter());
RegisterStrongReporter(new HeapOverheadBookkeepingReporter());
RegisterStrongReporter(new HeapOverheadPageCacheReporter());
RegisterStrongReporter(new HeapCommittedReporter());
RegisterStrongReporter(new HeapOverheadRatioReporter());
#endif
#ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
RegisterReporter(new VsizeReporter);
RegisterReporter(new ResidentReporter);
RegisterStrongReporter(new VsizeReporter());
RegisterStrongReporter(new ResidentReporter());
#endif
#ifdef HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER
RegisterReporter(new VsizeMaxContiguousReporter);
RegisterStrongReporter(new VsizeMaxContiguousReporter());
#endif
#ifdef HAVE_RESIDENT_UNIQUE_REPORTER
RegisterReporter(new ResidentUniqueReporter);
RegisterStrongReporter(new ResidentUniqueReporter());
#endif
#ifdef HAVE_PAGE_FAULT_REPORTERS
RegisterReporter(new PageFaultsSoftReporter);
RegisterReporter(new PageFaultsHardReporter);
RegisterStrongReporter(new PageFaultsSoftReporter());
RegisterStrongReporter(new PageFaultsHardReporter());
#endif
#ifdef HAVE_PRIVATE_REPORTER
RegisterReporter(new PrivateReporter);
RegisterStrongReporter(new PrivateReporter());
#endif
RegisterReporter(new AtomTablesReporter);
RegisterStrongReporter(new AtomTablesReporter());
#ifdef MOZ_DMD
RegisterReporter(new mozilla::dmd::DMDReporter);
RegisterStrongReporter(new mozilla::dmd::DMDReporter());
#endif
#if defined(XP_LINUX)
@ -846,21 +846,23 @@ nsMemoryReporterManager::Init()
namespace {
/**
* HastableEnumerator takes an nsTHashtable<nsISupportsHashKey>& in its
* constructor and creates an nsISimpleEnumerator from its contents.
*
* The resultant enumerator works over a copy of the hashtable, so it's safe to
* mutate or destroy the hashtable after the enumerator is created.
*/
class HashtableEnumerator MOZ_FINAL : public nsISimpleEnumerator
// ReporterEnumerator takes the two hashtables of reporters in its constructor
// and creates an nsISimpleEnumerator from its contents.
//
// The resultant enumerator works over a copy of the hashtable elements, so
// it's safe to mutate or destroy the hashtables after the enumerator is
// created.
//
class ReporterEnumerator MOZ_FINAL : public nsISimpleEnumerator
{
public:
HashtableEnumerator(nsTHashtable<nsISupportsHashKey>& aHashtable)
: mIndex(0)
ReporterEnumerator(
nsMemoryReporterManager::StrongReportersTable* aStrongReporters,
nsMemoryReporterManager::WeakReportersTable* aWeakReporters)
: mIndex(0)
{
aHashtable.EnumerateEntries(EnumeratorFunc, this);
aStrongReporters->EnumerateEntries(StrongEnumerator, this);
aWeakReporters->EnumerateEntries(WeakEnumerator, this);
}
NS_DECL_ISUPPORTS
@ -868,31 +870,43 @@ public:
private:
static PLDHashOperator
EnumeratorFunc(nsISupportsHashKey* aEntry, void* aData);
StrongEnumerator(nsISupportsHashKey* aEntry, void* aData);
static PLDHashOperator
WeakEnumerator(nsPtrHashKey<nsISupports>* aEntry, void* aData);
uint32_t mIndex;
nsCOMArray<nsISupports> mArray;
};
NS_IMPL_ISUPPORTS1(HashtableEnumerator, nsISimpleEnumerator)
NS_IMPL_ISUPPORTS1(ReporterEnumerator, nsISimpleEnumerator)
/* static */ PLDHashOperator
HashtableEnumerator::EnumeratorFunc(nsISupportsHashKey* aElem, void* aData)
ReporterEnumerator::StrongEnumerator(nsISupportsHashKey* aElem, void* aData)
{
HashtableEnumerator* enumerator = static_cast<HashtableEnumerator*>(aData);
ReporterEnumerator* enumerator = static_cast<ReporterEnumerator*>(aData);
enumerator->mArray.AppendObject(aElem->GetKey());
return PL_DHASH_NEXT;
}
/* static */ PLDHashOperator
ReporterEnumerator::WeakEnumerator(nsPtrHashKey<nsISupports>* aElem,
void* aData)
{
ReporterEnumerator* enumerator = static_cast<ReporterEnumerator*>(aData);
enumerator->mArray.AppendObject(aElem->GetKey());
return PL_DHASH_NEXT;
}
NS_IMETHODIMP
HashtableEnumerator::HasMoreElements(bool* aResult)
ReporterEnumerator::HasMoreElements(bool* aResult)
{
*aResult = mIndex < mArray.Length();
return NS_OK;
}
NS_IMETHODIMP
HashtableEnumerator::GetNext(nsISupports** aNext)
ReporterEnumerator::GetNext(nsISupports** aNext)
{
if (mIndex < mArray.Length()) {
nsCOMPtr<nsISupports> next = mArray.ObjectAt(mIndex);
@ -910,6 +924,10 @@ HashtableEnumerator::GetNext(nsISupports** aNext)
nsMemoryReporterManager::nsMemoryReporterManager()
: mMutex("nsMemoryReporterManager::mMutex"),
mIsRegistrationBlocked(false),
mStrongReporters(new StrongReportersTable()),
mWeakReporters(new WeakReportersTable()),
mSavedStrongReporters(nullptr),
mSavedWeakReporters(nullptr),
mNumChildProcesses(0),
mNextGeneration(1),
mGetReportsState(nullptr)
@ -918,6 +936,10 @@ nsMemoryReporterManager::nsMemoryReporterManager()
nsMemoryReporterManager::~nsMemoryReporterManager()
{
delete mStrongReporters;
delete mWeakReporters;
NS_ASSERTION(!mSavedStrongReporters, "failed to restore strong reporters");
NS_ASSERTION(!mSavedWeakReporters, "failed to restore weak reporters");
}
NS_IMETHODIMP
@ -931,8 +953,8 @@ nsMemoryReporterManager::EnumerateReporters(nsISimpleEnumerator** aResult)
mozilla::MutexAutoLock autoLock(mMutex);
nsRefPtr<HashtableEnumerator> enumerator =
new HashtableEnumerator(mReporters);
nsRefPtr<ReporterEnumerator> enumerator =
new ReporterEnumerator(mStrongReporters, mWeakReporters);
enumerator.forget(aResult);
return NS_OK;
}
@ -1025,12 +1047,9 @@ nsMemoryReporterManager::GetReports(
}
// Get reports for this process.
nsRefPtr<HashtableEnumerator> e;
{
mozilla::MutexAutoLock autoLock(mMutex);
e = new HashtableEnumerator(mReporters);
}
bool more;
nsCOMPtr<nsISimpleEnumerator> e;
EnumerateReporters(getter_AddRefs(e));
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
nsCOMPtr<nsIMemoryReporter> r;
e->GetNext(getter_AddRefs(r));
@ -1152,76 +1171,96 @@ nsMemoryReporterManager::FinishReporting()
}
static void
DebugAssertRefcountIsNonZero(nsISupports* aObj)
CrashIfRefcountIsZero(nsISupports* aObj)
{
#ifdef DEBUG
// This will probably crash if the object's refcount is 0.
uint32_t refcnt = NS_ADDREF(aObj);
MOZ_ASSERT(refcnt >= 2);
if (refcnt <= 1) {
MOZ_CRASH("CrashIfRefcountIsZero: refcount is zero");
}
NS_RELEASE(aObj);
#endif
}
nsresult
nsMemoryReporterManager::RegisterReporterHelper(
nsIMemoryReporter* aReporter, bool aForce)
nsIMemoryReporter* aReporter, bool aForce, bool aStrong)
{
// This method is thread-safe.
mozilla::MutexAutoLock autoLock(mMutex);
if ((mIsRegistrationBlocked && !aForce) || mReporters.Contains(aReporter)) {
if (mIsRegistrationBlocked && !aForce) {
return NS_ERROR_FAILURE;
}
// This method needs to be safe even if |aReporter| has a refcnt of 0, so
// we take a kung fu death grip before calling PutEntry. Otherwise, if
// PutEntry addref'ed and released |aReporter| before finally addref'ing it
// for good, it would free aReporter!
//
// The kung fu death grip could itself be problematic if PutEntry didn't
// addref |aReporter| (because then when the death grip goes out of scope,
// we would delete the reporter). In debug mode, we check that this
// doesn't happen.
if (mStrongReporters->Contains(aReporter) ||
mWeakReporters->Contains(aReporter))
{
nsCOMPtr<nsIMemoryReporter> kungFuDeathGrip = aReporter;
mReporters.PutEntry(aReporter);
return NS_ERROR_FAILURE;
}
DebugAssertRefcountIsNonZero(aReporter);
// If |aStrong| is true, |aReporter| may have a refcnt of 0, so we take
// a kung fu death grip before calling PutEntry. Otherwise, if PutEntry
// addref'ed and released |aReporter| before finally addref'ing it for
// good, it would free aReporter! The kung fu death grip could itself be
// problematic if PutEntry didn't addref |aReporter| (because then when the
// death grip goes out of scope, we would delete the reporter). In debug
// mode, we check that this doesn't happen.
//
// If |aStrong| is false, we require that |aReporter| have a non-zero
// refcnt.
//
if (aStrong) {
nsCOMPtr<nsIMemoryReporter> kungFuDeathGrip = aReporter;
mStrongReporters->PutEntry(aReporter);
CrashIfRefcountIsZero(aReporter);
} else {
CrashIfRefcountIsZero(aReporter);
mWeakReporters->PutEntry(aReporter);
}
return NS_OK;
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter* aReporter)
nsMemoryReporterManager::RegisterStrongReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false);
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ true);
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterReporterEvenIfBlocked(
nsMemoryReporterManager::RegisterWeakReporter(nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ false,
/* strong = */ false);
}
NS_IMETHODIMP
nsMemoryReporterManager::RegisterStrongReporterEvenIfBlocked(
nsIMemoryReporter* aReporter)
{
return RegisterReporterHelper(aReporter, /* force = */ true);
return RegisterReporterHelper(aReporter, /* force = */ true,
/* strong = */ true);
}
NS_IMETHODIMP
nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter* aReporter)
nsMemoryReporterManager::UnregisterWeakReporter(nsIMemoryReporter* aReporter)
{
// This method is thread-safe.
mozilla::MutexAutoLock autoLock(mMutex);
if (!mReporters.Contains(aReporter)) {
return NS_ERROR_FAILURE;
MOZ_ASSERT(!mStrongReporters->Contains(aReporter));
if (mWeakReporters->Contains(aReporter)) {
mWeakReporters->RemoveEntry(aReporter);
return NS_OK;
}
mReporters.RemoveEntry(aReporter);
return NS_OK;
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsMemoryReporterManager::BlockRegistration()
nsMemoryReporterManager::BlockRegistrationAndHideExistingReporters()
{
// This method is thread-safe.
mozilla::MutexAutoLock autoLock(mMutex);
@ -1229,17 +1268,35 @@ nsMemoryReporterManager::BlockRegistration()
return NS_ERROR_FAILURE;
}
mIsRegistrationBlocked = true;
// Hide the existing reporters, saving them for later restoration.
MOZ_ASSERT(!mSavedStrongReporters);
MOZ_ASSERT(!mSavedWeakReporters);
mSavedStrongReporters = mStrongReporters;
mSavedWeakReporters = mWeakReporters;
mStrongReporters = new StrongReportersTable();
mWeakReporters = new WeakReportersTable();
return NS_OK;
}
NS_IMETHODIMP
nsMemoryReporterManager::UnblockRegistration()
nsMemoryReporterManager::UnblockRegistrationAndRestoreOriginalReporters()
{
// This method is thread-safe.
mozilla::MutexAutoLock autoLock(mMutex);
if (!mIsRegistrationBlocked) {
return NS_ERROR_FAILURE;
}
// Banish the current reporters, and restore the hidden ones.
delete mStrongReporters;
delete mWeakReporters;
mStrongReporters = mSavedStrongReporters;
mWeakReporters = mSavedWeakReporters;
mSavedStrongReporters = nullptr;
mSavedWeakReporters = nullptr;
mIsRegistrationBlocked = false;
return NS_OK;
}
@ -1621,28 +1678,38 @@ nsMemoryReporterManager::SizeOfTab(nsIDOMWindow* aTopWindow,
NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter)
NS_IMPL_ISUPPORTS1(MemoryMultiReporter, nsIMemoryReporter)
nsresult
NS_RegisterMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->RegisterReporter(aReporter);
}
nsresult
NS_UnregisterMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->UnregisterReporter(aReporter);
}
namespace mozilla {
nsresult
RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
{
nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
if (!mgr) {
return NS_ERROR_FAILURE;
}
return mgr->RegisterStrongReporter(aReporter);
}
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
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(); \

View File

@ -36,6 +36,9 @@ public:
return static_cast<nsMemoryReporterManager*>(imgr.get());
}
typedef nsTHashtable<nsISupportsHashKey> StrongReportersTable;
typedef nsTHashtable<nsPtrHashKey<nsISupports> > WeakReportersTable;
void IncrementNumChildProcesses();
void DecrementNumChildProcesses();
@ -146,15 +149,22 @@ public:
SizeOfTabFns mSizeOfTabFns;
private:
nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter, bool aForce);
nsresult RegisterReporterHelper(nsIMemoryReporter* aReporter,
bool aForce, bool aStrongRef);
static void TimeoutCallback(nsITimer* aTimer, void* aData);
static const uint32_t kTimeoutLengthMS = 5000;
nsTHashtable<nsISupportsHashKey> mReporters;
Mutex mMutex;
bool mIsRegistrationBlocked;
StrongReportersTable* mStrongReporters;
WeakReportersTable* mWeakReporters;
// These two are only used for testing purposes.
StrongReportersTable* mSavedStrongReporters;
WeakReportersTable* mSavedWeakReporters;
uint32_t mNumChildProcesses;
uint32_t mNextGeneration;

View File

@ -583,7 +583,7 @@ NS_InitXPCOM2(nsIServiceManager* *result,
// The memory reporter manager is up and running -- register a reporter for
// ICU's memory usage.
NS_RegisterMemoryReporter(new ICUReporter());
RegisterStrongMemoryReporter(new ICUReporter());
mozilla::Telemetry::Init();

View File

@ -17,7 +17,6 @@
#include "nsClassHashtable.h"
#include "nsIFactory.h"
#include "nsIStringEnumerator.h"
#include "nsIMemoryReporter.h"
#include "nsSupportsPrimitives.h"
#include "nsComponentManagerUtils.h"
#include "nsServiceManagerUtils.h"
@ -401,22 +400,7 @@ CategoryEnumerator::enumfunc_createenumerator(const char* aStr, CategoryNode* aN
// nsCategoryManager implementations
//
NS_IMPL_QUERY_INTERFACE1(nsCategoryManager, nsICategoryManager)
class XPCOMCategoryManagerReporter MOZ_FINAL : public MemoryUniReporter
{
public:
XPCOMCategoryManagerReporter()
: MemoryUniReporter("explicit/xpcom/category-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM category manager.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return nsCategoryManager::SizeOfIncludingThis(MallocSizeOf);
}
};
NS_IMPL_QUERY_INTERFACE_INHERITED1(nsCategoryManager, MemoryUniReporter, nsICategoryManager)
NS_IMETHODIMP_(nsrefcnt)
nsCategoryManager::AddRef()
@ -457,9 +441,11 @@ nsCategoryManager::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
}
nsCategoryManager::nsCategoryManager()
: mLock("nsCategoryManager")
: MemoryUniReporter("explicit/xpcom/category-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM category manager.")
, mLock("nsCategoryManager")
, mSuppressNotifications(false)
, mReporter(nullptr)
{
PL_INIT_ARENA_POOL(&mArena, "CategoryManagerArena",
NS_CATEGORYMANAGER_ARENA_SIZE);
@ -468,13 +454,12 @@ nsCategoryManager::nsCategoryManager()
void
nsCategoryManager::InitMemoryReporter()
{
mReporter = new XPCOMCategoryManagerReporter();
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
}
nsCategoryManager::~nsCategoryManager()
{
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
// the hashtable contains entries that must be deleted before the arena is
// destroyed, or else you will have PRLocks undestroyed and other Really
@ -493,13 +478,10 @@ nsCategoryManager::get_category(const char* aName) {
return node;
}
/* static */ int64_t
nsCategoryManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
int64_t
nsCategoryManager::Amount()
{
return nsCategoryManager::gCategoryManager
? nsCategoryManager::gCategoryManager->SizeOfIncludingThisHelper(
aMallocSizeOf)
: 0;
return SizeOfIncludingThis(MallocSizeOf);
}
static size_t
@ -514,7 +496,7 @@ SizeOfCategoryManagerTableEntryExcludingThis(nsDepCharHashKey::KeyType aKey,
}
size_t
nsCategoryManager::SizeOfIncludingThisHelper(MallocSizeOf aMallocSizeOf)
nsCategoryManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
@ -583,7 +565,9 @@ nsCategoryManager::NotifyObservers( const char *aTopic,
r = new CategoryNotificationRunnable(entry, aTopic, aCategoryName);
} else {
r = new CategoryNotificationRunnable(this, aTopic, aCategoryName);
r = new CategoryNotificationRunnable(
NS_ISUPPORTS_CAST(nsICategoryManager*, this),
aTopic, aCategoryName);
}
NS_DispatchToMainThread(r);

View File

@ -11,6 +11,7 @@
#include "plarena.h"
#include "nsClassHashtable.h"
#include "nsICategoryManager.h"
#include "nsIMemoryReporter.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
#include "mozilla/Attributes.h"
@ -97,7 +98,8 @@ private:
* This implementation is thread-safe.
*/
class nsCategoryManager MOZ_FINAL
: public nsICategoryManager
: public mozilla::MemoryUniReporter
, public nsICategoryManager
{
public:
NS_DECL_ISUPPORTS
@ -122,7 +124,7 @@ public:
static nsCategoryManager* GetSingleton();
static void Destroy();
static int64_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
int64_t Amount() MOZ_OVERRIDE;
private:
static nsCategoryManager* gCategoryManager;
@ -130,7 +132,7 @@ private:
nsCategoryManager();
~nsCategoryManager();
size_t SizeOfIncludingThisHelper(mozilla::MallocSizeOf aMallocSizeOf);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
CategoryNode* get_category(const char* aName);
void NotifyObservers(const char* aTopic,
@ -141,8 +143,6 @@ private:
nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable;
mozilla::Mutex mLock;
bool mSuppressNotifications;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
#endif

View File

@ -40,7 +40,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "nsIConsoleService.h"
#include "nsIMemoryReporter.h"
#include "nsIObserverService.h"
#include "nsISimpleEnumerator.h"
#include "nsIStringEnumerator.h"
@ -283,24 +282,6 @@ CloneAndAppend(nsIFile* aBase, const nsACString& append)
// nsComponentManagerImpl
////////////////////////////////////////////////////////////////////////////////
class XPCOMComponentManagerReporter MOZ_FINAL : public MemoryUniReporter
{
public:
XPCOMComponentManagerReporter()
: MemoryUniReporter("explicit/xpcom/component-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM component manager.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
return nsComponentManagerImpl::gComponentManager
? nsComponentManagerImpl::gComponentManager->SizeOfIncludingThis(
MallocSizeOf)
: 0;
}
};
nsresult
nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
{
@ -316,7 +297,10 @@ nsComponentManagerImpl::Create(nsISupports* aOuter, REFNSIID aIID, void** aResul
static const int CONTRACTID_HASHTABLE_INITIAL_SIZE = 2048;
nsComponentManagerImpl::nsComponentManagerImpl()
: mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
: MemoryUniReporter("explicit/xpcom/component-manager",
KIND_HEAP, UNITS_BYTES,
"Memory used for the XPCOM component manager.")
, mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
, mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE)
, mLock("nsComponentManagerImpl.mLock")
, mStatus(NOT_INITIALIZED)
@ -414,8 +398,7 @@ nsresult nsComponentManagerImpl::Init()
nsCategoryManager::GetSingleton()->SuppressNotifications(false);
mReporter = new XPCOMComponentManagerReporter();
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
// Unfortunately, we can't register the nsCategoryManager memory reporter
// in its constructor (which is triggered by the GetSingleton() call
@ -800,8 +783,7 @@ nsresult nsComponentManagerImpl::Shutdown(void)
// Shutdown the component manager
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning Shutdown."));
NS_UnregisterMemoryReporter(mReporter);
mReporter = nullptr;
UnregisterWeakMemoryReporter(this);
// Release all cached factories
mContractIDs.Clear();
@ -836,13 +818,14 @@ nsComponentManagerImpl::~nsComponentManagerImpl()
PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
}
NS_IMPL_ISUPPORTS5(nsComponentManagerImpl,
nsIComponentManager,
nsIServiceManager,
nsIComponentRegistrar,
nsISupportsWeakReference,
nsIInterfaceRequestor)
NS_IMPL_ISUPPORTS_INHERITED5(
nsComponentManagerImpl,
MemoryUniReporter,
nsIComponentManager,
nsIServiceManager,
nsIComponentRegistrar,
nsISupportsWeakReference,
nsIInterfaceRequestor)
nsresult
nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
@ -1707,8 +1690,14 @@ SizeOfContractIDsEntryExcludingThis(nsCStringHashKey::KeyType aKey,
return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
}
int64_t
nsComponentManagerImpl::Amount()
{
return SizeOfIncludingThis(MallocSizeOf);
}
size_t
nsComponentManagerImpl::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
n += mLoaderMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);

View File

@ -11,6 +11,7 @@
#include "xpcom-private.h"
#include "nsIComponentManager.h"
#include "nsIComponentRegistrar.h"
#include "nsIMemoryReporter.h"
#include "nsIServiceManager.h"
#include "nsIFile.h"
#include "mozilla/MemoryReporting.h"
@ -38,7 +39,6 @@
#include "mozilla/Attributes.h"
struct nsFactoryEntry;
class nsIMemoryReporter;
class nsIServiceManager;
struct PRThread;
@ -119,7 +119,8 @@ typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock;
typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock;
class nsComponentManagerImpl MOZ_FINAL
: public nsIComponentManager
: public mozilla::MemoryUniReporter
, public nsIComponentManager
, public nsIServiceManager
, public nsSupportsWeakReference
, public nsIComponentRegistrar
@ -312,12 +313,11 @@ public:
nsTArray<PendingServiceInfo> mPendingServices;
int64_t Amount() MOZ_OVERRIDE;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
private:
~nsComponentManagerImpl();
nsCOMPtr<nsIMemoryReporter> mReporter;
};

View File

@ -46,7 +46,7 @@ struct ObserverRef
class nsObserverList : public nsCharPtrHashKey
{
friend class mozilla::ObserverServiceReporter;
friend class nsObserverService;
public:
nsObserverList(const char *key) : nsCharPtrHashKey(key)

View File

@ -11,7 +11,6 @@
#include "nsObserverList.h"
#include "nsThreadUtils.h"
#include "nsEnumeratorUtils.h"
#include "nsIMemoryReporter.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/Services.h"
@ -42,22 +41,6 @@ GetObserverServiceLog()
namespace mozilla {
class ObserverServiceReporter MOZ_FINAL : public MemoryMultiReporter
{
public:
ObserverServiceReporter()
: MemoryMultiReporter("observer-service")
{}
NS_IMETHOD CollectReports(nsIMemoryReporterCallback *aCb,
nsISupports *aClosure);
protected:
static const size_t kSuspectReferentCount = 100;
static PLDHashOperator CountReferents(nsObserverList* aObserverList,
void* aClosure);
};
struct SuspectObserver {
SuspectObserver(const char* aTopic, size_t aReferentCount)
: topic(aTopic), referentCount(aReferentCount) {}
@ -74,9 +57,13 @@ struct ObserverServiceReferentCount {
nsTArray<SuspectObserver> suspectObservers;
};
} // namespace mozilla
using namespace mozilla;
PLDHashOperator
ObserverServiceReporter::CountReferents(nsObserverList* aObserverList,
void* aClosure)
nsObserverService::CountReferents(nsObserverList* aObserverList,
void* aClosure)
{
if (!aObserverList) {
return PL_DHASH_NEXT;
@ -120,18 +107,11 @@ ObserverServiceReporter::CountReferents(nsObserverList* aObserverList,
}
NS_IMETHODIMP
ObserverServiceReporter::CollectReports(nsIMemoryReporterCallback* cb,
nsISupports* aClosure)
nsObserverService::CollectReports(nsIHandleReportCallback* aHandleReport,
nsISupports* aData)
{
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
nsObserverService* service = static_cast<nsObserverService*>(os.get());
if (!service) {
return NS_OK;
}
ObserverServiceReferentCount referentCount;
service->mObserverTopicTable.EnumerateEntries(CountReferents,
&referentCount);
mObserverTopicTable.EnumerateEntries(CountReferents, &referentCount);
nsresult rv;
for (uint32_t i = 0; i < referentCount.suspectObservers.Length(); i++) {
@ -139,53 +119,44 @@ ObserverServiceReporter::CollectReports(nsIMemoryReporterCallback* cb,
nsPrintfCString suspectPath("observer-service-suspect/"
"referent(topic=%s)",
suspect.topic);
rv = cb->Callback(/* process */ EmptyCString(),
suspectPath,
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
suspect.referentCount,
rv = aHandleReport->Callback(/* process */ EmptyCString(),
suspectPath, KIND_OTHER, UNITS_COUNT, suspect.referentCount,
NS_LITERAL_CSTRING("A topic with a suspiciously large number of "
"referents. This may be symptomatic of a leak "
"if the number of referents is high with "
"respect to the number of windows."),
aClosure);
aData);
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
}
rv = cb->Callback(/* process */ EmptyCString(),
rv = aHandleReport->Callback(/* process */ EmptyCString(),
NS_LITERAL_CSTRING("observer-service/referent/strong"),
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
referentCount.numStrong,
KIND_OTHER, UNITS_COUNT, referentCount.numStrong,
NS_LITERAL_CSTRING("The number of strong references held by the "
"observer service."),
aClosure);
aData);
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
rv = cb->Callback(/* process */ EmptyCString(),
rv = aHandleReport->Callback(/* process */ EmptyCString(),
NS_LITERAL_CSTRING("observer-service/referent/weak/alive"),
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
referentCount.numWeakAlive,
KIND_OTHER, UNITS_COUNT, referentCount.numWeakAlive,
NS_LITERAL_CSTRING("The number of weak references held by the "
"observer service that are still alive."),
aClosure);
aData);
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
rv = cb->Callback(/* process */ EmptyCString(),
rv = aHandleReport->Callback(/* process */ EmptyCString(),
NS_LITERAL_CSTRING("observer-service/referent/weak/dead"),
nsIMemoryReporter::KIND_OTHER,
nsIMemoryReporter::UNITS_COUNT,
referentCount.numWeakDead,
KIND_OTHER, UNITS_COUNT, referentCount.numWeakDead,
NS_LITERAL_CSTRING("The number of weak references held by the "
"observer service that are dead."),
aClosure);
aData);
if (NS_WARN_IF(NS_FAILED(rv)))
return rv;
@ -193,18 +164,19 @@ ObserverServiceReporter::CollectReports(nsIMemoryReporterCallback* cb,
return NS_OK;
}
} // namespace mozilla
using namespace mozilla;
////////////////////////////////////////////////////////////////////////////////
// nsObserverService Implementation
NS_IMPL_ISUPPORTS2(nsObserverService, nsIObserverService, nsObserverService)
NS_IMPL_ISUPPORTS_INHERITED2(
nsObserverService,
MemoryMultiReporter,
nsIObserverService,
nsObserverService)
nsObserverService::nsObserverService() :
mShuttingDown(false), mReporter(nullptr)
MemoryMultiReporter("observer-service"),
mShuttingDown(false)
{
}
@ -216,16 +188,13 @@ nsObserverService::~nsObserverService(void)
void
nsObserverService::RegisterReporter()
{
mReporter = new ObserverServiceReporter();
NS_RegisterMemoryReporter(mReporter);
RegisterWeakMemoryReporter(this);
}
void
nsObserverService::Shutdown()
{
if (mReporter) {
NS_UnregisterMemoryReporter(mReporter);
}
UnregisterWeakMemoryReporter(this);
mShuttingDown = true;

View File

@ -8,6 +8,7 @@
#include "nsIObserverService.h"
#include "nsObserverList.h"
#include "nsIMemoryReporter.h"
#include "nsTHashtable.h"
#include "mozilla/Attributes.h"
@ -17,13 +18,10 @@
class nsIMemoryReporter;
namespace mozilla {
class ObserverServiceReporter;
} // namespace mozilla
class nsObserverService MOZ_FINAL : public nsIObserverService {
friend class mozilla::ObserverServiceReporter;
class nsObserverService MOZ_FINAL
: public mozilla::MemoryMultiReporter
, public nsIObserverService
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_OBSERVERSERVICE_CID)
@ -41,13 +39,18 @@ public:
// collector will not traverse them.
NS_IMETHOD UnmarkGrayStrongObservers();
NS_IMETHOD CollectReports(nsIHandleReportCallback *aHandleReport,
nsISupports *aData);
private:
~nsObserverService(void);
void RegisterReporter();
static const size_t kSuspectReferentCount = 100;
static PLDHashOperator CountReferents(nsObserverList* aObserverList,
void* aClosure);
bool mShuttingDown;
nsTHashtable<nsObserverList> mObserverTopicTable;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsObserverService, NS_OBSERVERSERVICE_CID)

View File

@ -8,6 +8,7 @@
#define mozilla_XPTInterfaceInfoManager_h_
#include "nsIInterfaceInfoManager.h"
#include "nsIMemoryReporter.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/Mutex.h"
@ -25,7 +26,8 @@ class xptiTypelibGuts;
namespace mozilla {
class XPTInterfaceInfoManager MOZ_FINAL
: public nsIInterfaceInfoManager
: public mozilla::MemoryUniReporter
, public nsIInterfaceInfoManager
{
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIINTERFACEINFOMANAGER
@ -47,15 +49,16 @@ public:
xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
static int64_t GetXPTIWorkingSetSize();
int64_t Amount() MOZ_OVERRIDE;
private:
XPTInterfaceInfoManager();
~XPTInterfaceInfoManager();
void InitMemoryReporter();
void RegisterXPTHeader(XPTHeader* aHeader);
// idx is the index of this interface in the XPTHeader
void VerifyAndAddEntryIfNew(XPTInterfaceDirectoryEntry* iface,
uint16_t idx,
@ -109,8 +112,6 @@ private:
xptiWorkingSet mWorkingSet;
Mutex mResolveLock;
nsCOMPtr<nsIMemoryReporter> mReporter;
};
}

View File

@ -6,22 +6,25 @@
/* Implementation of xptiInterfaceInfoManager. */
#include "mozilla/MemoryReporting.h"
#include "mozilla/XPTInterfaceInfoManager.h"
#include "mozilla/FileUtils.h"
#include "mozilla/MemoryReporting.h"
#include "xptiprivate.h"
#include "nsDependentString.h"
#include "nsString.h"
#include "nsISupportsArray.h"
#include "nsArrayEnumerator.h"
#include "nsDirectoryService.h"
#include "mozilla/FileUtils.h"
#include "nsIMemoryReporter.h"
using namespace mozilla;
NS_IMPL_ISUPPORTS1(XPTInterfaceInfoManager,
nsIInterfaceInfoManager)
NS_IMPL_ISUPPORTS_INHERITED1(
XPTInterfaceInfoManager,
MemoryUniReporter,
nsIInterfaceInfoManager)
static XPTInterfaceInfoManager* gInterfaceInfoManager = nullptr;
#ifdef DEBUG
@ -29,7 +32,7 @@ static int gCallCount = 0;
#endif
size_t
XPTInterfaceInfoManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
{
size_t n = aMallocSizeOf(this);
ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
@ -40,28 +43,18 @@ XPTInterfaceInfoManager::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf)
return n;
}
class XPTIWorkingSetReporter MOZ_FINAL : public MemoryUniReporter
int64_t
XPTInterfaceInfoManager::Amount()
{
public:
XPTIWorkingSetReporter()
: MemoryUniReporter("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES,
"Memory used by the XPCOM typelib system.")
{}
private:
int64_t Amount() MOZ_OVERRIDE
{
size_t n = gInterfaceInfoManager
? gInterfaceInfoManager->SizeOfIncludingThis(MallocSizeOf)
: 0;
size_t n = SizeOfIncludingThis(MallocSizeOf);
// Measure gXPTIStructArena here, too. This is a bit grotty because it
// doesn't belong to the xptiInterfaceInfoManager, but there's no
// obviously better place to measure it.
n += XPT_SizeOfArena(gXPTIStructArena, MallocSizeOf);
// Measure gXPTIStructArena here, too. This is a bit grotty because it
// doesn't belong to the XPTIInterfaceInfoManager, but there's no
// obviously better place to measure it.
n += XPT_SizeOfArena(gXPTIStructArena, MallocSizeOf);
return n;
}
};
return n;
}
// static
XPTInterfaceInfoManager*
@ -70,6 +63,7 @@ XPTInterfaceInfoManager::GetSingleton()
if (!gInterfaceInfoManager) {
gInterfaceInfoManager = new XPTInterfaceInfoManager();
NS_ADDREF(gInterfaceInfoManager);
gInterfaceInfoManager->InitMemoryReporter();
}
return gInterfaceInfoManager;
}
@ -81,11 +75,11 @@ XPTInterfaceInfoManager::FreeInterfaceInfoManager()
}
XPTInterfaceInfoManager::XPTInterfaceInfoManager()
: mWorkingSet(),
: MemoryUniReporter("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES,
"Memory used by the XPCOM typelib system."),
mWorkingSet(),
mResolveLock("XPTInterfaceInfoManager.mResolveLock")
{
mReporter = new XPTIWorkingSetReporter();
NS_RegisterMemoryReporter(mReporter);
}
XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
@ -93,7 +87,7 @@ XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
// We only do this on shutdown of the service.
mWorkingSet.InvalidateInterfaceInfos();
NS_UnregisterMemoryReporter(mReporter);
UnregisterWeakMemoryReporter(this);
gInterfaceInfoManager = nullptr;
#ifdef DEBUG
@ -101,6 +95,12 @@ XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
#endif
}
void
XPTInterfaceInfoManager::InitMemoryReporter()
{
RegisterWeakMemoryReporter(this);
}
void
XPTInterfaceInfoManager::RegisterBuffer(char *buf, uint32_t length)
{