diff --git a/content/canvas/src/WebGLContextReporter.cpp b/content/canvas/src/WebGLContextReporter.cpp index 8584643770ae..d3bb7098dd65 100644 --- a/content/canvas/src/WebGLContextReporter.cpp +++ b/content/canvas/src/WebGLContextReporter.cpp @@ -70,101 +70,83 @@ NS_IMETHODIMP WebGLMemoryMultiReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, nsISupports* aClosure) { - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-texture-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetTextureMemoryUsed(), - NS_LITERAL_CSTRING("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," - " actual memory usage may be higher for example if the storage" - " is strided."), - aClosure); - - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-texture-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetTextureCount(), - NS_LITERAL_CSTRING("Number of WebGL textures."), - aClosure); +#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); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-buffer-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferMemoryUsed(), - NS_LITERAL_CSTRING("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," - " actual memory usage may be higher for example if the storage" - " is strided."), - aClosure); - - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("explicit/webgl/buffer-cache-memory"), - nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetBufferCacheMemoryUsed(), - NS_LITERAL_CSTRING("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" - " contrary to it, this one represents bytes on the heap," - " not managed by OpenGL."), - aClosure); - - aCb->Callback( - EmptyCString(), NS_LITERAL_CSTRING("webgl-buffer-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetBufferCount(), - NS_LITERAL_CSTRING("Number of WebGL buffers."), - aClosure); + REPORT("webgl-texture-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::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," + " actual memory usage may be higher for example if the storage" + " is strided."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-renderbuffer-memory"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetRenderbufferMemoryUsed(), - NS_LITERAL_CSTRING("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" - " bound, actual memory usage may be higher for example if the" - " storage is strided."), - aClosure); + REPORT("webgl-texture-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetTextureCount(), + "Number of WebGL textures."); + + REPORT("webgl-buffer-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::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," + " actual memory usage may be higher for example if the storage" + " is strided."); + + REPORT("explicit/webgl/buffer-cache-memory", + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::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" + " contrary to it, this one represents bytes on the heap," + " not managed by OpenGL."); + + REPORT("webgl-buffer-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetBufferCount(), + "Number of WebGL buffers."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-renderbuffer-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(), - NS_LITERAL_CSTRING("Number of WebGL renderbuffers."), - aClosure); + REPORT("webgl-renderbuffer-memory", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::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" + " bound, actual memory usage may be higher for example if the" + " storage is strided."); + + REPORT("webgl-renderbuffer-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetRenderbufferCount(), + "Number of WebGL renderbuffers."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("explicit/webgl/shader"), - nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, - WebGLMemoryMultiReporterWrapper::GetShaderSize(), - NS_LITERAL_CSTRING("Combined size of WebGL shader ASCII sources and" - " translation logs cached on the heap."), - aClosure); + REPORT("explicit/webgl/shader", + nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES, + WebGLMemoryMultiReporterWrapper::GetShaderSize(), + "Combined size of WebGL shader ASCII sources and translation" + " logs cached on the heap."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-shader-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetShaderCount(), - NS_LITERAL_CSTRING("Number of WebGL shaders."), - aClosure); + REPORT("webgl-shader-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetShaderCount(), + "Number of WebGL shaders."); - aCb->Callback( - EmptyCString(), - NS_LITERAL_CSTRING("webgl-context-count"), - nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, - WebGLMemoryMultiReporterWrapper::GetContextCount(), - NS_LITERAL_CSTRING("Number of WebGL contexts."), - aClosure); + REPORT("webgl-context-count", + nsIMemoryReporter::KIND_OTHER, nsIMemoryReporter::UNITS_COUNT, + WebGLMemoryMultiReporterWrapper::GetContextCount(), + "Number of WebGL contexts."); + +#undef REPORT return NS_OK; } diff --git a/dom/base/nsWindowMemoryReporter.cpp b/dom/base/nsWindowMemoryReporter.cpp index 8d8bd1bdddfb..b94e7afe6834 100644 --- a/dom/base/nsWindowMemoryReporter.cpp +++ b/dom/base/nsWindowMemoryReporter.cpp @@ -90,7 +90,7 @@ AppendWindowURI(nsGlobalWindow *aWindow, nsACString& aStr) NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMStyleMallocSizeOf, "windows") -static void +static nsresult CollectWindowReports(nsGlobalWindow *aWindow, nsWindowSizes *aWindowTotalSizes, nsIMemoryMultiReporterCallback *aCb, @@ -197,9 +197,11 @@ CollectWindowReports(nsGlobalWindow *aWindow, if (_amount > 0) { \ nsCAutoString path(_path1); \ path += _path2; \ - aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP, \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), path, nsIMemoryReporter::KIND_HEAP,\ nsIMemoryReporter::UNITS_BYTES, _amount, \ NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ } \ } while (0) @@ -226,6 +228,8 @@ CollectWindowReports(nsGlobalWindow *aWindow, aWindowTotalSizes->mLayoutTextRuns += windowSizes.mLayoutTextRuns; #undef REPORT + + return NS_OK; } typedef nsTArray< nsRefPtr > WindowArray; @@ -264,15 +268,18 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb, nsRefPtr *end = w + windows.Length(); nsWindowSizes windowTotalSizes(NULL); for (; w != end; ++w) { - CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure); + nsresult rv = CollectWindowReports(*w, &windowTotalSizes, aCb, aClosure); + NS_ENSURE_SUCCESS(rv, rv); } #define REPORT(_path, _amount, _desc) \ do { \ - aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ - nsIMemoryReporter::KIND_OTHER, \ - nsIMemoryReporter::UNITS_BYTES, _amount, \ - NS_LITERAL_CSTRING(_desc), aClosure); \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_OTHER, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ } while (0) REPORT("window-objects-dom", windowTotalSizes.mDOM, diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index e827aab9886b..059b05cb79fe 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -249,7 +249,10 @@ public: // Always report, even if we're disabled, so that we at least get an entry // in about::memory. - ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix, aCallback, aClosure); + rv = ReportJSRuntimeExplicitTreeStats(rtStats, mPathPrefix, aCallback, aClosure); + if (NS_FAILED(rv)) { + return rv; + } return NS_OK; } diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index a500897eb08b..e8b04770d371 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -293,29 +293,28 @@ public: FreeLibrary(gdi32Handle); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-committed"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - committedBytesUsed, - NS_LITERAL_CSTRING("Memory committed by the Windows graphics system."), - aClosure); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-dedicated"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - dedicatedBytesUsed, - NS_LITERAL_CSTRING("Out-of-process memory allocated for this process in a " - "physical GPU adapter's memory."), - aClosure); - aCb->Callback(EmptyCString(), - NS_LITERAL_CSTRING("gpu-shared"), - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_BYTES, - sharedBytesUsed, - NS_LITERAL_CSTRING("In-process memory that is shared with the GPU."), - aClosure); +#define REPORT(_path, _amount, _desc) \ + do { \ + nsresult rv; \ + rv = aCb->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path), \ + nsIMemoryReporter::KIND_OTHER, \ + nsIMemoryReporter::UNITS_BYTES, _amount, \ + NS_LITERAL_CSTRING(_desc), aClosure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) + + REPORT("gpu-committed", committedBytesUsed, + "Memory committed by the Windows graphics system."); + + REPORT("gpu-dedicated", dedicatedBytesUsed, + "Out-of-process memory allocated for this process in a " + "physical GPU adapter's memory."); + + REPORT("gpu-shared", sharedBytesUsed, + "In-process memory that is shared with the GPU."); +#undef REPORT + return NS_OK; } diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index 15cdcc970ecd..1ef4c20c3a09 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -1286,87 +1286,6 @@ DestroyCompartmentName(void *string) } // namespace xpc -namespace { - -template -inline void -ReportMemory(const nsACString &path, PRInt32 kind, PRInt32 units, - PRInt64 amount, const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, nsISupports *closure) -{ - callback->Callback(NS_LITERAL_CSTRING(""), path, kind, units, amount, - NS_LITERAL_CSTRING(desc), closure); -} - -template -inline void -ReportMemoryBytes(const nsACString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, kind, nsIMemoryReporter::UNITS_BYTES, amount, desc, - callback, closure); -} - -template -inline void -ReportMemoryBytes0(const nsCString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - if (amount) - ReportMemoryBytes(path, kind, amount, desc, callback, closure); -} - -template -inline void -ReportGCHeapBytes(const nsACString &path, PRInt64 *total, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, nsIMemoryReporter::KIND_NONHEAP, nsIMemoryReporter::UNITS_BYTES, amount, - desc, callback, closure); - *total += amount; -} - -template -inline void -ReportGCHeapBytes0(const nsCString &path, PRInt64 *total, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - if (amount) - return ReportGCHeapBytes(path, total, amount, desc, callback, closure); -} - -template -inline void -ReportMemoryPercentage(const nsACString &path, PRInt32 kind, PRInt64 amount, - const char (&desc)[N], - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) -{ - ReportMemory(path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, amount, desc, - callback, closure); -} - -template -inline const nsCString -MakeMemoryReporterPath(const nsACString &pathPrefix, - const JS::CompartmentStats &cStats, - const char (&reporterName)[N]) -{ - return pathPrefix + NS_LITERAL_CSTRING("compartment(") + - *static_cast(cStats.name) + - NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName); -} - -} // anonymous namespace - // We have per-compartment GC heap totals, so we can't put the total GC heap // size in the explicit allocations tree. But it's a useful figure, so put it // in the "others" list. @@ -1404,340 +1323,354 @@ GetJSUserCompartmentCount() // XPConnectJSCompartmentCount to avoid that problem, but then we couldn't // easily report them via telemetry, so we live with the small risk of // inconsistencies. -NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSSystemCompartmentCount, - "js-compartments-system", - KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - GetJSSystemCompartmentCount, - "The number of JavaScript compartments for system code. The sum of this " - "and 'js-compartments-user' might not match the number of " - "compartments listed under 'js' if a garbage collection occurs at an " - "inopportune time, but such cases should be rare.") +NS_MEMORY_REPORTER_IMPLEMENT( + XPConnectJSSystemCompartmentCount, + "js-compartments-system", + KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + GetJSSystemCompartmentCount, + "The number of JavaScript compartments for system code. The sum of this " + "and 'js-compartments-user' might not match the number of compartments " + "listed under 'js' if a garbage collection occurs at an inopportune time, " + "but such cases should be rare.") -NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSUserCompartmentCount, - "js-compartments-user", - KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - GetJSUserCompartmentCount, - "The number of JavaScript compartments for user code. The sum of this " - "and 'js-compartments-system' might not match the number of " - "compartments listed under 'js' if a garbage collection occurs at an " - "inopportune time, but such cases should be rare.") +NS_MEMORY_REPORTER_IMPLEMENT( + XPConnectJSUserCompartmentCount, + "js-compartments-user", + KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + GetJSUserCompartmentCount, + "The number of JavaScript compartments for user code. The sum of this " + "and 'js-compartments-system' might not match the number of compartments " + "listed under 'js' if a garbage collection occurs at an inopportune time, " + "but such cases should be rare.") + +// The REPORT* macros do an unconditional report. The REPORT*0 macros only +// report if the value is non-zero. + +#define REPORT(_path, _kind, _units, _amount, _desc) \ + do { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, _kind, _units, _amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } while (0) + +#define REPORT0(_path, _kind, _units, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + if (amount > 0) { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, _kind, _units, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + } \ + } while (0) + +#define REPORT_BYTES(_path, _kind, _amount, _desc) \ + REPORT(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc); + +#define REPORT_BYTES0(_path, _kind, _amount, _desc) \ + REPORT0(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc); + +#define REPORT_GC_BYTES(_path, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, \ + nsIMemoryReporter::KIND_NONHEAP, \ + nsIMemoryReporter::UNITS_BYTES, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + gcTotal += amount; \ + } while (0) + +#define REPORT_GC_BYTES0(_path, _amount, _desc) \ + do { \ + size_t amount = _amount; /* evaluate _amount only once */ \ + if (amount > 0) { \ + nsresult rv; \ + rv = cb->Callback(EmptyCString(), _path, \ + nsIMemoryReporter::KIND_NONHEAP, \ + nsIMemoryReporter::UNITS_BYTES, amount, \ + NS_LITERAL_CSTRING(_desc), closure); \ + NS_ENSURE_SUCCESS(rv, rv); \ + gcTotal += amount; \ + } \ + } while (0) + +template +inline const nsCString +MakePath(const nsACString &pathPrefix, const JS::CompartmentStats &cStats, + const char (&reporterName)[N]) +{ + return pathPrefix + NS_LITERAL_CSTRING("compartment(") + + *static_cast(cStats.name) + + NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName); +} namespace mozilla { namespace xpconnect { namespace memory { -static PRInt64 +static nsresult ReportCompartmentStats(const JS::CompartmentStats &cStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, - nsISupports *closure) + nsIMemoryMultiReporterCallback *cb, + nsISupports *closure, size_t *gcTotalOut) { - PRInt64 gcTotal = 0; + size_t gcTotal = 0; - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/headers"), - &gcTotal, cStats.gcHeapArenaHeaders, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that is used to hold internal book-keeping information.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/headers"), + cStats.gcHeapArenaHeaders, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that is used to hold internal " + "book-keeping information."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/padding"), - &gcTotal, cStats.gcHeapArenaPadding, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that is unused and present only so that other data is aligned. " - "This constitutes internal fragmentation.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/padding"), + cStats.gcHeapArenaPadding, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that is unused and present only so " + "that other data is aligned. This constitutes internal " + "fragmentation."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/arena/unused"), - &gcTotal, cStats.gcHeapArenaUnused, - "Memory on the compartment's garbage-collected JavaScript heap, within " - "arenas, that could be holding useful data but currently isn't.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/arena/unused"), + cStats.gcHeapArenaUnused, + "Memory on the compartment's garbage-collected JavaScript " + "heap, within arenas, that could be holding useful data " + "but currently isn't."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/objects/non-function"), - &gcTotal, cStats.gcHeapObjectsNonFunction, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "non-function objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/objects/non-function"), + cStats.gcHeapObjectsNonFunction, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds non-function objects."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/objects/function"), - &gcTotal, cStats.gcHeapObjectsFunction, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "function objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/objects/function"), + cStats.gcHeapObjectsFunction, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds function objects."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/strings"), - &gcTotal, cStats.gcHeapStrings, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "string headers. String headers contain various pieces of information " - "about a string, but do not contain (except in the case of very short " - "strings) the string characters; characters in longer strings are counted " - "under 'gc-heap/string-chars' instead.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/strings"), + cStats.gcHeapStrings, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds string headers. String headers contain " + "various pieces of information about a string, but do not " + "contain (except in the case of very short strings) the " + "string characters; characters in longer strings are " + "counted " "under 'gc-heap/string-chars' instead."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/scripts"), - &gcTotal, cStats.gcHeapScripts, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "JSScript instances. A JSScript is created for each user-defined function " - "in a script. One is also created for the top-level code in a script.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/scripts"), + cStats.gcHeapScripts, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds JSScript instances. A JSScript is " + "created for each user-defined function in a script. One " + "is also created for the top-level code in a script."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/tree"), - &gcTotal, cStats.gcHeapShapesTree, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "shapes that are in a property tree.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/tree"), + cStats.gcHeapShapesTree, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds shapes that are in a property tree."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/dict"), - &gcTotal, cStats.gcHeapShapesDict, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "shapes that are in dictionary mode.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/dict"), + cStats.gcHeapShapesDict, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds shapes that are in dictionary mode."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/shapes/base"), - &gcTotal, cStats.gcHeapShapesBase, - "Memory on the compartment's garbage-collected JavaScript heap that collates " - "data common to many shapes.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/shapes/base"), + cStats.gcHeapShapesBase, + "Memory on the compartment's garbage-collected JavaScript " + "heap that collates data common to many shapes."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/type-objects"), - &gcTotal, cStats.gcHeapTypeObjects, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "type inference information.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/type-objects"), + cStats.gcHeapTypeObjects, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds type inference information."); - ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "gc-heap/xml"), - &gcTotal, cStats.gcHeapXML, - "Memory on the compartment's garbage-collected JavaScript heap that holds " - "E4X XML objects.", - callback, closure); + REPORT_GC_BYTES0(MakePath(pathPrefix, cStats, "gc-heap/xml"), + cStats.gcHeapXML, + "Memory on the compartment's garbage-collected JavaScript " + "heap that holds E4X XML objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/slots"), - nsIMemoryReporter::KIND_HEAP, cStats.objectSlots, - "Memory allocated for the compartment's non-fixed object slot arrays, " - "which are used to represent object properties. Some objects also " - "contain a fixed number of slots which are stored on the compartment's " - "JavaScript heap; those slots are not counted here, but in " - "'gc-heap/objects' instead.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/slots"), + nsIMemoryReporter::KIND_HEAP, cStats.objectSlots, + "Memory allocated for the compartment's non-fixed object " + "slot arrays, which are used to represent object properties. " + "Some objects also contain a fixed number of slots which are " + "stored on the compartment's JavaScript heap; those slots " + "are not counted here, but in 'gc-heap/objects' instead."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/elements"), - nsIMemoryReporter::KIND_HEAP, cStats.objectElements, - "Memory allocated for the compartment's object element arrays, " - "which are used to represent indexed object properties.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/elements"), + nsIMemoryReporter::KIND_HEAP, cStats.objectElements, + "Memory allocated for the compartment's object element " + "arrays, which are used to represent indexed object " + "properties."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "objects/misc"), - nsIMemoryReporter::KIND_HEAP, cStats.objectMisc, - "Memory allocated for various small, miscellaneous " - "structures that hang off certain kinds of objects.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "objects/misc"), + nsIMemoryReporter::KIND_HEAP, cStats.objectMisc, + "Memory allocated for various small, miscellaneous " + "structures that hang off certain kinds of objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "string-chars"), - nsIMemoryReporter::KIND_HEAP, cStats.stringChars, - "Memory allocated to hold the compartment's string characters. Sometimes " - "more memory is allocated than necessary, to simplify string " - "concatenation. Each string also includes a header which is stored on the " - "compartment's JavaScript heap; that header is not counted here, but in " - "'gc-heap/strings' instead.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "string-chars"), + nsIMemoryReporter::KIND_HEAP, cStats.stringChars, + "Memory allocated to hold the compartment's string " + "characters. Sometimes more memory is allocated than " + "necessary, to simplify string concatenation. Each string " + "also includes a header which is stored on the " + "compartment's JavaScript heap; that header is not counted " + "here, but in 'gc-heap/strings' instead."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/tree-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables, - "Memory allocated for the compartment's property tables that belong to " - "shapes that are in a property tree.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/tree-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables, + "Memory allocated for the compartment's property tables " + "that belong to shapes that are in a property tree."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/dict-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables, - "Memory allocated for the compartment's property tables that belong to " - "shapes that are in dictionary mode.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/dict-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables, + "Memory allocated for the compartment's property tables " + "that belong to shapes that are in dictionary mode."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/tree-shape-kids"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids, - "Memory allocated for the compartment's kid hashes that belong to shapes " - "that are in a property tree.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/tree-shape-kids"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids, + "Memory allocated for the compartment's kid hashes that " + "belong to shapes that are in a property tree."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "shapes-extra/compartment-tables"), - nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables, - "Memory used by compartment wide tables storing shape information " - "for use during object construction.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "shapes-extra/compartment-tables"), + nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables, + "Memory used by compartment wide tables storing shape " + "information for use during object construction."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "script-data"), - nsIMemoryReporter::KIND_HEAP, cStats.scriptData, - "Memory allocated for JSScript bytecode and various variable-length " - "tables.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "script-data"), + nsIMemoryReporter::KIND_HEAP, cStats.scriptData, + "Memory allocated for JSScript bytecode and various " + "variable-length tables."); #ifdef JS_METHODJIT - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "mjit/code"), - nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode, - "Memory used by the method JIT to hold the compartment's generated code.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "mjit/code"), + nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode, + "Memory used by the method JIT to hold the compartment's " + "generated code."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "mjit/data"), - nsIMemoryReporter::KIND_HEAP, cStats.mjitData, - "Memory used by the method JIT for the compartment's compilation data: " - "JITScripts, native maps, and inline cache structs.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "mjit/data"), + nsIMemoryReporter::KIND_HEAP, cStats.mjitData, + "Memory used by the method JIT for the compartment's " + "compilation data: JITScripts, native maps, and inline " + "cache structs."); #endif - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/script-main"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.scripts, - "Memory used during type inference to store type sets of variables " - "and dynamically observed types.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/script-main"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.scripts, + "Memory used during type inference to store type sets of " + "variables and dynamically observed types."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/object-main"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.objects, - "Memory used during type inference to store types and possible " - "property types of JS objects.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/object-main"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.objects, + "Memory used during type inference to store types and " + "possible property types of JS objects."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "type-inference/tables"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.tables, - "Memory used during type inference for compartment-wide tables.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "type-inference/tables"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.tables, + "Memory used during type inference for compartment-wide " + "tables."); - ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats, - "analysis-temporary"), - nsIMemoryReporter::KIND_HEAP, - cStats.typeInferenceSizes.temporary, - "Memory used during type inference and compilation to hold transient " - "analysis information. Cleared on GC.", - callback, closure); + REPORT_BYTES0(MakePath(pathPrefix, cStats, "analysis-temporary"), + nsIMemoryReporter::KIND_HEAP, + cStats.typeInferenceSizes.temporary, + "Memory used during type inference and compilation to hold " + "transient analysis information. Cleared on GC."); - return gcTotal; + *gcTotalOut += gcTotal; + + return NS_OK; } -void -ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, +nsresult +ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, + const nsACString &pathPrefix, + nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { - PRInt64 gcTotal = 0; + nsresult rv; + size_t gcTotal = 0; for (size_t index = 0; index < rtStats.compartmentStatsVector.length(); index++) { - gcTotal += ReportCompartmentStats(rtStats.compartmentStatsVector[index], pathPrefix, - callback, closure); + rv = ReportCompartmentStats(rtStats.compartmentStatsVector[index], + pathPrefix, cb, closure, &gcTotal); + NS_ENSURE_SUCCESS(rv, rv); } - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject, - "Memory used by the JSRuntime object.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject, + "Memory used by the JSRuntime object."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable, - "Memory used by the atoms table.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable, + "Memory used by the atoms table."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts, - "Memory used by JSContext objects and certain structures " - "hanging off them." , - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts, + "Memory used by JSContext objects and certain structures " + "hanging off them."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal, - "Memory used by a JSRuntime, " - "excluding memory that is reported by " - "other reporters under 'explicit/js/runtime/'.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal, + "Memory used by a JSRuntime, excluding memory that is " + "reported by other reporters under 'explicit/js/runtime/'."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary, - "Memory held transiently in JSRuntime and used during " - "compilation. It mostly holds parse nodes.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary, + "Memory held transiently in JSRuntime and used during " + "compilation. It mostly holds parse nodes."); - ReportMemoryBytes0(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"), - nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode, - "Memory used by the regexp JIT to hold generated code.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"), + nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode, + "Memory used by the regexp JIT to hold generated code."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"), - nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted, - "Memory used for the JS call stack. This is the committed portion " - "of the stack; the uncommitted portion is not measured because it " - "hardly costs anything.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"), + nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeStackCommitted, + "Memory used for the JS call stack. This is the committed " + "portion of the stack; the uncommitted portion is not " + "measured because it hardly costs anything."); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"), - nsIMemoryReporter::KIND_HEAP, rtStats.runtimeGCMarker, - "Memory used for the GC mark stack and gray roots.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"), + nsIMemoryReporter::KIND_HEAP, rtStats.runtimeGCMarker, + "Memory used for the GC mark stack and gray roots."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"), - &gcTotal, rtStats.gcHeapChunkDirtyUnused, - "Memory on the garbage-collected JavaScript heap, within chunks with at " - "least one allocated GC thing, that could be holding useful data but " - "currently isn't. Memory here is mutually exclusive with memory reported" - "under 'explicit/js/gc-heap-decommitted'.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"), + rtStats.gcHeapChunkDirtyUnused, + "Memory on the garbage-collected JavaScript heap, within " + "chunks with at least one allocated GC thing, that could " + "be holding useful data but currently isn't. Memory here " + "is mutually exclusive with memory reported under " + "'explicit/js/gc-heap-decommitted'."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"), - &gcTotal, rtStats.gcHeapChunkCleanUnused, - "Memory on the garbage-collected JavaScript heap taken by completely empty " - "chunks, that soon will be released unless claimed for new allocations. " - "Memory here is mutually exclusive with memory reported under " - "'explicit/js/gc-heap-decommitted'.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"), + rtStats.gcHeapChunkCleanUnused, + "Memory on the garbage-collected JavaScript heap taken by " + "completely empty chunks, that soon will be released " + "unless claimed for new allocations. Memory here is " + "mutually exclusive with memory reported under " + "'explicit/js/gc-heap-decommitted'."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-decommitted"), - &gcTotal, - rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, - "Memory in the address space of the garbage-collected JavaScript heap that " - "is currently returned to the OS.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-decommitted"), + rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, + "Memory in the address space of the garbage-collected " + "JavaScript heap that is currently returned to the OS."); - ReportGCHeapBytes(pathPrefix + - NS_LITERAL_CSTRING("gc-heap-chunk-admin"), - &gcTotal, rtStats.gcHeapChunkAdmin, - "Memory on the garbage-collected JavaScript heap, within chunks, that is " - "used to hold internal book-keeping information.", - callback, closure); + REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap-chunk-admin"), + rtStats.gcHeapChunkAdmin, + "Memory on the garbage-collected JavaScript heap, within " + "chunks, that is used to hold internal book-keeping " + "information."); // gcTotal is the sum of everything we've reported for the GC heap. It // should equal rtStats.gcHeapChunkTotal. - JS_ASSERT(size_t(gcTotal) == rtStats.gcHeapChunkTotal); + JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal); + + return NS_OK; } } // namespace memory @@ -1775,11 +1708,11 @@ class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter xpc::DestroyCompartmentName(name); } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { // First we collect the compartment paths. Then we report them. Doing - // the two steps interleaved is a bad idea, because calling |callback| + // the two steps interleaved is a bad idea, because calling |cb| // from within CompartmentCallback() leads to all manner of assertions. // Collect. @@ -1791,10 +1724,10 @@ class JSCompartmentsMultiReporter : public nsIMemoryMultiReporter // Report. for (size_t i = 0; i < paths.length(); i++) // These ones don't need a description, hence the "". - ReportMemory(paths[i], - nsIMemoryReporter::KIND_OTHER, - nsIMemoryReporter::UNITS_COUNT, - 1, "", callback, closure); + REPORT(nsCString(paths[i]), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_COUNT, + 1, ""); return NS_OK; } @@ -1823,7 +1756,7 @@ public: return NS_OK; } - NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *cb, nsISupports *closure) { XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance(); @@ -1847,102 +1780,101 @@ public: // This is the second step (see above). First we report stuff in the // "explicit" tree, then we report other stuff. - ReportJSRuntimeExplicitTreeStats(rtStats, pathPrefix, callback, closure); + nsresult rv = + ReportJSRuntimeExplicitTreeStats(rtStats, pathPrefix, cb, closure); + NS_ENSURE_SUCCESS(rv, rv); - ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("xpconnect"), - nsIMemoryReporter::KIND_HEAP, xpconnect, - "Memory used by XPConnect.", - callback, closure); + REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("xpconnect"), + nsIMemoryReporter::KIND_HEAP, xpconnect, + "Memory used by XPConnect."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-dirty-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkDirtyUnused, - "The same as 'explicit/js/gc-heap-chunk-dirty-unused'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-dirty-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkDirtyUnused, + "The same as 'explicit/js/gc-heap-chunk-dirty-unused'. " + "Shown here for easy comparison with other 'js-gc' " + "reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-clean-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkCleanUnused, - "The same as 'explicit/js/gc-heap-chunk-clean-unused'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-chunk-clean-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkCleanUnused, + "The same as 'explicit/js/gc-heap-chunk-clean-unused'. " + "Shown here for easy comparison with other 'js-gc' " + "reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, - "The same as 'explicit/js/gc-heap-decommitted'. Shown here for " - "easy comparison with other 'js-gc' reporters.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted, + "The same as 'explicit/js/gc-heap-decommitted'. Shown " + "here for easy comparison with other 'js-gc' reporters."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-arena-unused"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapArenaUnused, - "Memory on the main JSRuntime's garbage-collected JavaScript heap, " - "within arenas, that could be holding useful data but currently isn't. " - "This is the sum of all compartments' 'gc-heap/arena-unused' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-arena-unused"), + nsIMemoryReporter::KIND_OTHER, + rtStats.gcHeapArenaUnused, + "Memory on the main JSRuntime's garbage-collected " + "JavaScript heap, within arenas, that could be holding " + "useful data but currently isn't. This is the sum of all " + "compartments' 'gc-heap/arena-unused' numbers."); - ReportMemoryPercentage(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-fraction"), - nsIMemoryReporter::KIND_OTHER, - rtStats.gcHeapUnusedPercentage, - "Fraction of the main JSRuntime's garbage-collected JavaScript " - "heap that is unused. Computed as ('js-gc-heap-chunk-clean-unused' " - "+ 'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + " - "'js-gc-heap-arena-unused') / 'js-gc-heap'.", - callback, closure); + REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-fraction"), + nsIMemoryReporter::KIND_OTHER, + nsIMemoryReporter::UNITS_PERCENTAGE, + rtStats.gcHeapUnusedPercentage, + "Fraction of the main JSRuntime's garbage-collected JavaScript " + "heap that is unused. Computed as " + "('js-gc-heap-chunk-clean-unused' + " + "'js-gc-heap-chunk-dirty-unused' + 'js-gc-heap-decommitted' + " + "'js-gc-heap-arena-unused') / 'js-gc-heap'."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-objects"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects, - "Memory used for all object-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/objects-non-function', " - "'gc-heap/objects-function' and 'object-slots' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-objects"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects, + "Memory used for all object-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/objects-non-function', " + "'gc-heap/objects-function' and 'object-slots' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-shapes"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes, - "Memory used for all shape-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/shapes/tree', " - "'gc-heap/shapes/dict', 'gc-heap/shapes/base', " - "'shapes-extra/tree-tables', 'shapes-extra/dict-tables', " - "'shapes-extra/tree-shape-kids' and 'shapes-extra/empty-shape-arrays'.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-shapes"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes, + "Memory used for all shape-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/shapes/tree', 'gc-heap/shapes/dict', " + "'gc-heap/shapes/base', 'shapes-extra/tree-tables', " + "'shapes-extra/dict-tables', " + "'shapes-extra/tree-shape-kids' and " + "'shapes-extra/empty-shape-arrays'."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-scripts"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts, - "Memory used for all script-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/scripts' and " - "'script-data' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-scripts"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts, + "Memory used for all script-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/scripts' and 'script-data' numbers."); + + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-strings"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings, + "Memory used for all string-related data in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/strings' and 'string-chars' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-strings"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings, - "Memory used for all string-related data in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/strings' and " - "'string-chars' numbers.", - callback, closure); #ifdef JS_METHODJIT - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-mjit"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit, - "Memory used by the method JIT in the main JSRuntime. " - "This is the sum of all compartments' 'mjit/code', and 'mjit/data' " - "numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-mjit"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit, + "Memory used by the method JIT in the main JSRuntime. " + "This is the sum of all compartments' 'mjit/code', and " + "'mjit/data' numbers."); #endif - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-type-inference"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference, - "Non-transient memory used by type inference in the main JSRuntime. " - "This is the sum of all compartments' 'gc-heap/type-objects', " - "'type-inference/script-main', 'type-inference/object-main' and " - "'type-inference/tables' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-type-inference"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference, + "Non-transient memory used by type inference in the main " + "JSRuntime. This is the sum of all compartments' " + "'gc-heap/type-objects', 'type-inference/script-main', " + "'type-inference/object-main' and " + "'type-inference/tables' numbers."); - ReportMemoryBytes(NS_LITERAL_CSTRING("js-main-runtime-analysis-temporary"), - nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp, - "Memory used transiently during type inference and compilation in the " - "main JSRuntime. This is the sum of all compartments' " - "'analysis-temporary' numbers.", - callback, closure); + REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-analysis-temporary"), + nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp, + "Memory used transiently during type inference and " + "compilation in the main JSRuntime. This is the sum of " + "all compartments' 'analysis-temporary' numbers."); return NS_OK; } diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 46830c44d298..9191ca0f68a8 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -238,9 +238,10 @@ namespace memory { // This reports all the stats in |rtStats| that belong in the "explicit" tree, // (which isn't all of them). -void -ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix, - nsIMemoryMultiReporterCallback *callback, +nsresult +ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats, + const nsACString &pathPrefix, + nsIMemoryMultiReporterCallback *cb, nsISupports *closure); } // namespace memory diff --git a/storage/src/mozStorageService.cpp b/storage/src/mozStorageService.cpp index 4988ede95de8..0999d7faa033 100644 --- a/storage/src/mozStorageService.cpp +++ b/storage/src/mozStorageService.cpp @@ -194,9 +194,10 @@ public: // 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(nsIMemoryMultiReporterCallback *aCallback, + NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure) { + nsresult rv; size_t totalConnSize = 0; { nsTArray > connections; @@ -218,29 +219,32 @@ public: SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("stmt"), mStmtDesc, - SQLITE_DBSTATUS_STMT_USED); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("cache"), mCacheDesc, - SQLITE_DBSTATUS_CACHE_USED); - totalConnSize += - doConnMeasurement(aCallback, aClosure, *conn.get(), pathHead, - NS_LITERAL_CSTRING("schema"), mSchemaDesc, - SQLITE_DBSTATUS_SCHEMA_USED); + 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); } } PRInt64 other = ::sqlite3_memory_used() - totalConnSize; - aCallback->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); + 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; } @@ -272,14 +276,17 @@ private: * The memory report description. * @param aOption * The SQLite constant for getting the measurement. + * @param aTotal + * The accumulator for the measurement. */ - size_t doConnMeasurement(nsIMemoryMultiReporterCallback *aCallback, - nsISupports *aClosure, - sqlite3 *aConn, - const nsACString &aPathHead, - const nsACString &aKind, - const nsACString &aDesc, - int aOption) + nsresult reportConn(nsIMemoryMultiReporterCallback *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); @@ -290,11 +297,14 @@ private: nsresult rv = convertResultCode(rc); NS_ENSURE_SUCCESS(rv, rv); - aCallback->Callback(NS_LITERAL_CSTRING(""), path, - nsIMemoryReporter::KIND_HEAP, - nsIMemoryReporter::UNITS_BYTES, PRInt64(curr), - aDesc, aClosure); - return curr; + rv = aCb->Callback(NS_LITERAL_CSTRING(""), path, + nsIMemoryReporter::KIND_HEAP, + nsIMemoryReporter::UNITS_BYTES, PRInt64(curr), + aDesc, aClosure); + NS_ENSURE_SUCCESS(rv, rv); + *aTotal += curr; + + return NS_OK; } }; diff --git a/xpcom/base/MapsMemoryReporter.cpp b/xpcom/base/MapsMemoryReporter.cpp index 923dc4dad17f..ab2142f880c6 100644 --- a/xpcom/base/MapsMemoryReporter.cpp +++ b/xpcom/base/MapsMemoryReporter.cpp @@ -157,7 +157,7 @@ public: } NS_IMETHOD - CollectReports(nsIMemoryMultiReporterCallback *aCallback, + CollectReports(nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure); NS_IMETHOD @@ -174,7 +174,7 @@ private: nsresult ParseMapping(FILE *aFile, - nsIMemoryMultiReporterCallback *aCallback, + nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen); @@ -188,7 +188,7 @@ private: ParseMapBody(FILE *aFile, const nsACString &aName, const nsACString &aDescription, - nsIMemoryMultiReporterCallback *aCallback, + nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen); @@ -212,7 +212,7 @@ MapsReporter::MapsReporter() } NS_IMETHODIMP -MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCallback, +MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure) { CategoriesSeen categoriesSeen; @@ -222,7 +222,7 @@ MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCallback, return NS_ERROR_FAILURE; while (true) { - nsresult rv = ParseMapping(f, aCallback, aClosure, &categoriesSeen); + nsresult rv = ParseMapping(f, aCb, aClosure, &categoriesSeen); if (NS_FAILED(rv)) break; } @@ -237,13 +237,15 @@ MapsReporter::CollectReports(nsIMemoryMultiReporterCallback *aCallback, NS_ASSERTION(categoriesSeen.mSeenVsize, "Didn't create a vsize node?"); NS_ASSERTION(categoriesSeen.mSeenVsize, "Didn't create a resident node?"); if (!categoriesSeen.mSeenSwap) { - aCallback->Callback(NS_LITERAL_CSTRING(""), - NS_LITERAL_CSTRING("smaps/swap/total"), - nsIMemoryReporter::KIND_NONHEAP, - nsIMemoryReporter::UNITS_BYTES, - 0, - NS_LITERAL_CSTRING("This process uses no swap space."), - aClosure); + nsresult rv; + rv = aCb->Callback(NS_LITERAL_CSTRING(""), + NS_LITERAL_CSTRING("smaps/swap/total"), + nsIMemoryReporter::KIND_NONHEAP, + nsIMemoryReporter::UNITS_BYTES, + 0, + NS_LITERAL_CSTRING("This process uses no swap space."), + aClosure); + NS_ENSURE_SUCCESS(rv, rv); } return NS_OK; @@ -293,7 +295,7 @@ MapsReporter::FindLibxul() nsresult MapsReporter::ParseMapping( FILE *aFile, - nsIMemoryMultiReporterCallback *aCallback, + nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen) { @@ -347,7 +349,7 @@ MapsReporter::ParseMapping( GetReporterNameAndDescription(path, perms, name, description); while (true) { - nsresult rv = ParseMapBody(aFile, name, description, aCallback, + nsresult rv = ParseMapBody(aFile, name, description, aCb, aClosure, aCategoriesSeen); if (NS_FAILED(rv)) break; @@ -476,7 +478,7 @@ MapsReporter::ParseMapBody( FILE *aFile, const nsACString &aName, const nsACString &aDescription, - nsIMemoryMultiReporterCallback *aCallback, + nsIMemoryMultiReporterCallback *aCb, nsISupports *aClosure, CategoriesSeen *aCategoriesSeen) { @@ -523,12 +525,14 @@ MapsReporter::ParseMapBody( path.Append("/"); path.Append(aName); - aCallback->Callback(NS_LITERAL_CSTRING(""), - path, - nsIMemoryReporter::KIND_NONHEAP, - nsIMemoryReporter::UNITS_BYTES, - PRInt64(size) * 1024, // convert from kB to bytes - aDescription, aClosure); + nsresult rv; + rv = aCb->Callback(NS_LITERAL_CSTRING(""), + path, + nsIMemoryReporter::KIND_NONHEAP, + nsIMemoryReporter::UNITS_BYTES, + PRInt64(size) * 1024, // convert from kB to bytes + aDescription, aClosure); + NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }