mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-16 22:04:36 +00:00
Bug 732843 - Handle Callback() failures in memory multi-reporters. r=jlebar.
--HG-- extra : rebase_source : 54af85a1ef839922d5443cdc36f601611258944a
This commit is contained in:
parent
00c7e687b5
commit
a4e916975c
@ -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;
|
||||
}
|
||||
|
@ -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<nsGlobalWindow> > WindowArray;
|
||||
@ -264,15 +268,18 @@ nsWindowMemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsRefPtr<nsGlobalWindow> *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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -1286,87 +1286,6 @@ DestroyCompartmentName(void *string)
|
||||
|
||||
} // namespace xpc
|
||||
|
||||
namespace {
|
||||
|
||||
template <int N>
|
||||
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 <int N>
|
||||
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 <int N>
|
||||
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 <int N>
|
||||
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 <int N>
|
||||
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 <int N>
|
||||
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 <int N>
|
||||
inline const nsCString
|
||||
MakeMemoryReporterPath(const nsACString &pathPrefix,
|
||||
const JS::CompartmentStats &cStats,
|
||||
const char (&reporterName)[N])
|
||||
{
|
||||
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
|
||||
*static_cast<nsCString*>(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 <int N>
|
||||
inline const nsCString
|
||||
MakePath(const nsACString &pathPrefix, const JS::CompartmentStats &cStats,
|
||||
const char (&reporterName)[N])
|
||||
{
|
||||
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
|
||||
*static_cast<nsCString*>(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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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<nsRefPtr<Connection> > 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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user