Bug 721628 (part 4) - Use better names for various JS memory reporting things. r=Ms2ger.

--HG--
extra : rebase_source : 4edc916c571906329075b6be68c245267f9b61d0
This commit is contained in:
Nicholas Nethercote 2012-01-29 14:11:32 -08:00
Родитель 6ee279d5ec
Коммит 881438bc8e
5 изменённых файлов: 207 добавлений и 211 удалений

Просмотреть файл

@ -232,16 +232,16 @@ public:
{
AssertIsOnMainThread();
JS::IterateData data(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
nsresult rv = CollectForRuntime(/* isQuick = */false, &data);
JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
nsresult rv = CollectForRuntime(/* isQuick = */false, &rtStats);
if (NS_FAILED(rv)) {
return rv;
}
// Always report, even if we're disabled, so that we at least get an entry
// in about::memory.
ReportJSRuntimeStats(data, mPathPrefix, aCallback, aClosure);
ReportJSRuntimeStats(rtStats, mPathPrefix, aCallback, aClosure);
return NS_OK;
}
@ -1524,7 +1524,7 @@ public:
*mSucceeded = mIsQuick
? JS::GetExplicitNonHeapForRuntime(JS_GetRuntime(aCx), static_cast<int64_t*>(mData), xpc::JsMallocSizeOf)
: JS::CollectCompartmentStatsForRuntime(JS_GetRuntime(aCx), static_cast<JS::IterateData*>(mData));
: JS::CollectRuntimeStats(JS_GetRuntime(aCx), static_cast<JS::RuntimeStats*>(mData));
{
MutexAutoLock lock(mMutex);

Просмотреть файл

@ -116,10 +116,10 @@ struct CompartmentStats
TypeInferenceSizes typeInferenceSizes;
};
struct IterateData
struct RuntimeStats
{
IterateData(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
DestroyNameCallback destroyNameCb)
RuntimeStats(JSMallocSizeOfFun mallocSizeOf, GetNameCallback getNameCb,
DestroyNameCallback destroyNameCb)
: runtimeObject(0)
, runtimeAtomsTable(0)
, runtimeContexts(0)
@ -187,7 +187,7 @@ struct IterateData
#ifdef JS_THREADSAFE
extern JS_PUBLIC_API(bool)
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data);
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
extern JS_PUBLIC_API(bool)
GetExplicitNonHeapForRuntime(JSRuntime *rt, int64_t *amount,

Просмотреть файл

@ -55,23 +55,23 @@ namespace JS {
using namespace js;
static void
CompartmentMemoryCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
CompartmentStatsCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
IterateData *data = static_cast<IterateData *>(vdata);
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
// CollectCompartmentStatsForRuntime reserves enough space.
MOZ_ALWAYS_TRUE(data->compartmentStatsVector.growBy(1));
CompartmentStats &curr = data->compartmentStatsVector.back();
curr.init(data->getNameCb(cx, compartment), data->destroyNameCb);
data->currCompartmentStats = &curr;
// CollectRuntimeStats reserves enough space.
MOZ_ALWAYS_TRUE(rtStats->compartmentStatsVector.growBy(1));
CompartmentStats &cStats = rtStats->compartmentStatsVector.back();
cStats.init(rtStats->getNameCb(cx, compartment), rtStats->destroyNameCb);
rtStats->currCompartmentStats = &cStats;
// Get the compartment-level numbers.
#ifdef JS_METHODJIT
curr.mjitCode = compartment->sizeOfMjitCode();
cStats.mjitCode = compartment->sizeOfMjitCode();
#endif
compartment->sizeOfTypeInferenceData(cx, &curr.typeInferenceSizes, data->mallocSizeOf);
curr.shapesCompartmentTables = compartment->sizeOfShapeTable(data->mallocSizeOf);
compartment->sizeOfTypeInferenceData(cx, &cStats.typeInferenceSizes, rtStats->mallocSizeOf);
cStats.shapesCompartmentTables = compartment->sizeOfShapeTable(rtStats->mallocSizeOf);
}
static void
@ -88,108 +88,107 @@ ChunkCallback(JSContext *cx, void *vdata, gc::Chunk *chunk)
{
// Nb: This function is only called for dirty chunks, which is why we
// increment gcHeapChunkDirtyDecommitted.
IterateData *data = static_cast<IterateData *>(vdata);
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
if (chunk->decommittedArenas.get(i))
data->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
rtStats->gcHeapChunkDirtyDecommitted += gc::ArenaSize;
}
static void
ArenaCallback(JSContext *cx, void *vdata, gc::Arena *arena,
JSGCTraceKind traceKind, size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
data->currCompartmentStats->gcHeapArenaHeaders +=
sizeof(gc::ArenaHeader);
rtStats->currCompartmentStats->gcHeapArenaHeaders += sizeof(gc::ArenaHeader);
size_t allocationSpace = arena->thingsSpan(thingSize);
data->currCompartmentStats->gcHeapArenaPadding +=
rtStats->currCompartmentStats->gcHeapArenaPadding +=
gc::ArenaSize - allocationSpace - sizeof(gc::ArenaHeader);
// We don't call the callback on unused things. So we compute the
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
// We do this by setting arenaUnused to maxArenaUnused here, and then
// subtracting thingSize for every used cell, in CellCallback().
data->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
rtStats->currCompartmentStats->gcHeapArenaUnused += allocationSpace;
}
static void
CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats *curr = data->currCompartmentStats;
RuntimeStats *rtStats = static_cast<RuntimeStats *>(vdata);
CompartmentStats *cStats = rtStats->currCompartmentStats;
switch (traceKind) {
case JSTRACE_OBJECT:
{
JSObject *obj = static_cast<JSObject *>(thing);
if (obj->isFunction()) {
curr->gcHeapObjectsFunction += thingSize;
cStats->gcHeapObjectsFunction += thingSize;
} else {
curr->gcHeapObjectsNonFunction += thingSize;
cStats->gcHeapObjectsNonFunction += thingSize;
}
size_t slotsSize, elementsSize;
obj->sizeOfExcludingThis(data->mallocSizeOf, &slotsSize, &elementsSize);
curr->objectSlots += slotsSize;
curr->objectElements += elementsSize;
obj->sizeOfExcludingThis(rtStats->mallocSizeOf, &slotsSize, &elementsSize);
cStats->objectSlots += slotsSize;
cStats->objectElements += elementsSize;
break;
}
case JSTRACE_STRING:
{
JSString *str = static_cast<JSString *>(thing);
curr->gcHeapStrings += thingSize;
curr->stringChars += str->sizeOfExcludingThis(data->mallocSizeOf);
cStats->gcHeapStrings += thingSize;
cStats->stringChars += str->sizeOfExcludingThis(rtStats->mallocSizeOf);
break;
}
case JSTRACE_SHAPE:
{
Shape *shape = static_cast<Shape*>(thing);
size_t propTableSize, kidsSize;
shape->sizeOfExcludingThis(data->mallocSizeOf, &propTableSize, &kidsSize);
shape->sizeOfExcludingThis(rtStats->mallocSizeOf, &propTableSize, &kidsSize);
if (shape->inDictionary()) {
curr->gcHeapShapesDict += thingSize;
curr->shapesExtraDictTables += propTableSize;
cStats->gcHeapShapesDict += thingSize;
cStats->shapesExtraDictTables += propTableSize;
JS_ASSERT(kidsSize == 0);
} else {
curr->gcHeapShapesTree += thingSize;
curr->shapesExtraTreeTables += propTableSize;
curr->shapesExtraTreeShapeKids += kidsSize;
cStats->gcHeapShapesTree += thingSize;
cStats->shapesExtraTreeTables += propTableSize;
cStats->shapesExtraTreeShapeKids += kidsSize;
}
break;
}
case JSTRACE_BASE_SHAPE:
{
curr->gcHeapShapesBase += thingSize;
cStats->gcHeapShapesBase += thingSize;
break;
}
case JSTRACE_SCRIPT:
{
JSScript *script = static_cast<JSScript *>(thing);
curr->gcHeapScripts += thingSize;
curr->scriptData += script->sizeOfData(data->mallocSizeOf);
cStats->gcHeapScripts += thingSize;
cStats->scriptData += script->sizeOfData(rtStats->mallocSizeOf);
#ifdef JS_METHODJIT
curr->mjitData += script->sizeOfJitScripts(data->mallocSizeOf);
cStats->mjitData += script->sizeOfJitScripts(rtStats->mallocSizeOf);
#endif
break;
}
case JSTRACE_TYPE_OBJECT:
{
types::TypeObject *obj = static_cast<types::TypeObject *>(thing);
curr->gcHeapTypeObjects += thingSize;
obj->sizeOfExcludingThis(&curr->typeInferenceSizes, data->mallocSizeOf);
cStats->gcHeapTypeObjects += thingSize;
obj->sizeOfExcludingThis(&cStats->typeInferenceSizes, rtStats->mallocSizeOf);
break;
}
case JSTRACE_XML:
{
curr->gcHeapXML += thingSize;
cStats->gcHeapXML += thingSize;
break;
}
}
// Yes, this is a subtraction: see ArenaCallback() for details.
curr->gcHeapArenaUnused -= thingSize;
cStats->gcHeapArenaUnused -= thingSize;
}
JS_PUBLIC_API(bool)
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
{
JSContext *cx = JS_NewContext(rt, 0);
if (!cx)
@ -198,119 +197,116 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
{
JSAutoRequest ar(cx);
if (!data->compartmentStatsVector.reserve(rt->compartments.length()))
if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length()))
return false;
data->gcHeapChunkCleanDecommitted =
rt->gcChunkPool.countCleanDecommittedArenas(rt) *
gc::ArenaSize;
data->gcHeapChunkCleanUnused =
int64_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) *
gc::ChunkSize -
data->gcHeapChunkCleanDecommitted;
data->gcHeapChunkTotal =
int64_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) *
gc::ChunkSize;
rtStats->gcHeapChunkCleanDecommitted =
rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize;
rtStats->gcHeapChunkCleanUnused =
int64_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize -
rtStats->gcHeapChunkCleanDecommitted;
rtStats->gcHeapChunkTotal =
int64_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
IterateCompartmentsArenasCells(cx, data, CompartmentMemoryCallback,
IterateCompartmentsArenasCells(cx, rtStats, CompartmentStatsCallback,
ArenaCallback, CellCallback);
IterateChunks(cx, data, ChunkCallback);
IterateChunks(cx, rtStats, ChunkCallback);
data->runtimeObject = data->mallocSizeOf(rt);
rtStats->runtimeObject = rtStats->mallocSizeOf(rt);
size_t normal, temporary, regexpCode, stackCommitted;
rt->sizeOfExcludingThis(data->mallocSizeOf,
rt->sizeOfExcludingThis(rtStats->mallocSizeOf,
&normal,
&temporary,
&regexpCode,
&stackCommitted);
data->runtimeNormal = normal;
data->runtimeTemporary = temporary;
data->runtimeRegexpCode = regexpCode;
data->runtimeStackCommitted = stackCommitted;
rtStats->runtimeNormal = normal;
rtStats->runtimeTemporary = temporary;
rtStats->runtimeRegexpCode = regexpCode;
rtStats->runtimeStackCommitted = stackCommitted;
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
// JSRuntime, and so counted when JSRuntime is counted.
data->runtimeAtomsTable =
rt->atomState.atoms.sizeOfExcludingThis(data->mallocSizeOf);
rtStats->runtimeAtomsTable =
rt->atomState.atoms.sizeOfExcludingThis(rtStats->mallocSizeOf);
JSContext *acx, *iter = NULL;
while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL)
data->runtimeContexts += acx->sizeOfIncludingThis(data->mallocSizeOf);
rtStats->runtimeContexts += acx->sizeOfIncludingThis(rtStats->mallocSizeOf);
}
JS_DestroyContextNoGC(cx);
// This is initialized to all bytes stored in used chunks, and then we
// subtract used space from it each time around the loop.
data->gcHeapChunkDirtyUnused = data->gcHeapChunkTotal -
data->gcHeapChunkCleanUnused -
data->gcHeapChunkCleanDecommitted -
data->gcHeapChunkDirtyDecommitted;
rtStats->gcHeapChunkDirtyUnused = rtStats->gcHeapChunkTotal -
rtStats->gcHeapChunkCleanUnused -
rtStats->gcHeapChunkCleanDecommitted -
rtStats->gcHeapChunkDirtyDecommitted;
for (size_t index = 0;
index < data->compartmentStatsVector.length();
index < rtStats->compartmentStatsVector.length();
index++) {
CompartmentStats &stats = data->compartmentStatsVector[index];
CompartmentStats &cStats = rtStats->compartmentStatsVector[index];
int64_t used = stats.gcHeapArenaHeaders +
stats.gcHeapArenaPadding +
stats.gcHeapArenaUnused +
stats.gcHeapObjectsNonFunction +
stats.gcHeapObjectsFunction +
stats.gcHeapStrings +
stats.gcHeapShapesTree +
stats.gcHeapShapesDict +
stats.gcHeapShapesBase +
stats.gcHeapScripts +
stats.gcHeapTypeObjects +
stats.gcHeapXML;
int64_t used = cStats.gcHeapArenaHeaders +
cStats.gcHeapArenaPadding +
cStats.gcHeapArenaUnused +
cStats.gcHeapObjectsNonFunction +
cStats.gcHeapObjectsFunction +
cStats.gcHeapStrings +
cStats.gcHeapShapesTree +
cStats.gcHeapShapesDict +
cStats.gcHeapShapesBase +
cStats.gcHeapScripts +
cStats.gcHeapTypeObjects +
cStats.gcHeapXML;
data->gcHeapChunkDirtyUnused -= used;
data->gcHeapArenaUnused += stats.gcHeapArenaUnused;
data->totalObjects += stats.gcHeapObjectsNonFunction +
stats.gcHeapObjectsFunction +
stats.objectSlots +
stats.objectElements;
data->totalShapes += stats.gcHeapShapesTree +
stats.gcHeapShapesDict +
stats.gcHeapShapesBase +
stats.shapesExtraTreeTables +
stats.shapesExtraDictTables +
stats.shapesCompartmentTables;
data->totalScripts += stats.gcHeapScripts +
stats.scriptData;
data->totalStrings += stats.gcHeapStrings +
stats.stringChars;
rtStats->gcHeapChunkDirtyUnused -= used;
rtStats->gcHeapArenaUnused += cStats.gcHeapArenaUnused;
rtStats->totalObjects += cStats.gcHeapObjectsNonFunction +
cStats.gcHeapObjectsFunction +
cStats.objectSlots +
cStats.objectElements;
rtStats->totalShapes += cStats.gcHeapShapesTree +
cStats.gcHeapShapesDict +
cStats.gcHeapShapesBase +
cStats.shapesExtraTreeTables +
cStats.shapesExtraDictTables +
cStats.shapesCompartmentTables;
rtStats->totalScripts += cStats.gcHeapScripts +
cStats.scriptData;
rtStats->totalStrings += cStats.gcHeapStrings +
cStats.stringChars;
#ifdef JS_METHODJIT
data->totalMjit += stats.mjitCode +
stats.mjitData;
rtStats->totalMjit += cStats.mjitCode +
cStats.mjitData;
#endif
data->totalTypeInference += stats.gcHeapTypeObjects +
stats.typeInferenceSizes.objects +
stats.typeInferenceSizes.scripts +
stats.typeInferenceSizes.tables;
data->totalAnalysisTemp += stats.typeInferenceSizes.temporary;
rtStats->totalTypeInference += cStats.gcHeapTypeObjects +
cStats.typeInferenceSizes.objects +
cStats.typeInferenceSizes.scripts +
cStats.typeInferenceSizes.tables;
rtStats->totalAnalysisTemp += cStats.typeInferenceSizes.temporary;
}
size_t numDirtyChunks = (data->gcHeapChunkTotal -
data->gcHeapChunkCleanUnused) /
size_t numDirtyChunks = (rtStats->gcHeapChunkTotal -
rtStats->gcHeapChunkCleanUnused) /
gc::ChunkSize;
int64_t perChunkAdmin =
sizeof(gc::Chunk) - (sizeof(gc::Arena) * gc::ArenasPerChunk);
data->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
data->gcHeapChunkDirtyUnused -= data->gcHeapChunkAdmin;
rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
rtStats->gcHeapChunkDirtyUnused -= rtStats->gcHeapChunkAdmin;
// Why 10000x? 100x because it's a percentage, and another 100x
// because nsIMemoryReporter requires that for percentage amounts so
// they can be fractional.
data->gcHeapUnusedPercentage = (data->gcHeapChunkCleanUnused +
data->gcHeapChunkDirtyUnused +
data->gcHeapChunkCleanDecommitted +
data->gcHeapChunkDirtyDecommitted +
data->gcHeapArenaUnused) * 10000 /
data->gcHeapChunkTotal;
rtStats->gcHeapUnusedPercentage = (rtStats->gcHeapChunkCleanUnused +
rtStats->gcHeapChunkDirtyUnused +
rtStats->gcHeapChunkCleanDecommitted +
rtStats->gcHeapChunkDirtyDecommitted +
rtStats->gcHeapArenaUnused) * 10000 /
rtStats->gcHeapChunkTotal;
return true;
}

Просмотреть файл

@ -1350,11 +1350,11 @@ ReportMemoryPercentage(const nsACString &path, PRInt32 kind, PRInt64 amount,
template <int N>
inline const nsCString
MakeMemoryReporterPath(const nsACString &pathPrefix,
const JS::CompartmentStats &compartmentStats,
const JS::CompartmentStats &cStats,
const char (&reporterName)[N])
{
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
*static_cast<nsCString*>(compartmentStats.name) +
*static_cast<nsCString*>(cStats.name) +
NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
}
@ -1422,52 +1422,52 @@ namespace xpconnect {
namespace memory {
static PRInt64
ReportCompartmentStats(const JS::CompartmentStats &stats,
ReportCompartmentStats(const JS::CompartmentStats &cStats,
const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
PRInt64 gcTotal = 0;
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/arena/headers"),
&gcTotal, stats.gcHeapArenaHeaders,
&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);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/arena/padding"),
&gcTotal, stats.gcHeapArenaPadding,
&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);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/arena/unused"),
&gcTotal, stats.gcHeapArenaUnused,
&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);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/objects/non-function"),
&gcTotal, stats.gcHeapObjectsNonFunction,
&gcTotal, cStats.gcHeapObjectsNonFunction,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"non-function objects.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/objects/function"),
&gcTotal, stats.gcHeapObjectsFunction,
&gcTotal, cStats.gcHeapObjectsFunction,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"function objects.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/strings"),
&gcTotal, stats.gcHeapStrings,
&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 "
@ -1475,52 +1475,52 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
"under 'gc-heap/string-chars' instead.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/scripts"),
&gcTotal, stats.gcHeapScripts,
&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);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/shapes/tree"),
&gcTotal, stats.gcHeapShapesTree,
&gcTotal, cStats.gcHeapShapesTree,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes that are in a property tree.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/shapes/dict"),
&gcTotal, stats.gcHeapShapesDict,
&gcTotal, cStats.gcHeapShapesDict,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes that are in dictionary mode.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/shapes/base"),
&gcTotal, stats.gcHeapShapesBase,
&gcTotal, cStats.gcHeapShapesBase,
"Memory on the compartment's garbage-collected JavaScript heap that collates "
"data common to many shapes.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/type-objects"),
&gcTotal, stats.gcHeapTypeObjects,
&gcTotal, cStats.gcHeapTypeObjects,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"type inference information.",
callback, closure);
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportGCHeapBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"gc-heap/xml"),
&gcTotal, stats.gcHeapXML,
&gcTotal, cStats.gcHeapXML,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"E4X XML objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"object-slots"),
nsIMemoryReporter::KIND_HEAP, stats.objectSlots,
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 "
@ -1528,16 +1528,16 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
"'gc-heap/objects' instead.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"object-elements"),
nsIMemoryReporter::KIND_HEAP, stats.objectElements,
nsIMemoryReporter::KIND_HEAP, cStats.objectElements,
"Memory allocated for the compartment's object element arrays, "
"which are used to represent indexed object properties.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"string-chars"),
nsIMemoryReporter::KIND_HEAP, stats.stringChars,
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 "
@ -1545,83 +1545,83 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
"'gc-heap/strings' instead.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"shapes-extra/tree-tables"),
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeTables,
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);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"shapes-extra/dict-tables"),
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraDictTables,
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables,
"Memory allocated for the compartment's property tables that belong to "
"shapes that are in dictionary mode.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"shapes-extra/tree-shape-kids"),
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeShapeKids,
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);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"shapes-extra/compartment-tables"),
nsIMemoryReporter::KIND_HEAP, stats.shapesCompartmentTables,
nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables,
"Memory used by compartment wide tables storing shape information "
"for use during object construction.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"script-data"),
nsIMemoryReporter::KIND_HEAP, stats.scriptData,
nsIMemoryReporter::KIND_HEAP, cStats.scriptData,
"Memory allocated for JSScript bytecode and various variable-length "
"tables.",
callback, closure);
#ifdef JS_METHODJIT
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"mjit-code"),
nsIMemoryReporter::KIND_NONHEAP, stats.mjitCode,
nsIMemoryReporter::KIND_NONHEAP, cStats.mjitCode,
"Memory used by the method JIT to hold the compartment's generated code.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"mjit-data"),
nsIMemoryReporter::KIND_HEAP, stats.mjitData,
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);
#endif
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"type-inference/script-main"),
nsIMemoryReporter::KIND_HEAP,
stats.typeInferenceSizes.scripts,
cStats.typeInferenceSizes.scripts,
"Memory used during type inference to store type sets of variables "
"and dynamically observed types.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"type-inference/object-main"),
nsIMemoryReporter::KIND_HEAP,
stats.typeInferenceSizes.objects,
cStats.typeInferenceSizes.objects,
"Memory used during type inference to store types and possible "
"property types of JS objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"type-inference/tables"),
nsIMemoryReporter::KIND_HEAP,
stats.typeInferenceSizes.tables,
cStats.typeInferenceSizes.tables,
"Memory used during type inference for compartment-wide tables.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, cStats,
"analysis-temporary"),
nsIMemoryReporter::KIND_HEAP,
stats.typeInferenceSizes.temporary,
cStats.typeInferenceSizes.temporary,
"Memory used during type inference and compilation to hold transient "
"analysis information. Cleared on GC.",
callback, closure);
@ -1630,54 +1630,54 @@ ReportCompartmentStats(const JS::CompartmentStats &stats,
}
void
ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
ReportJSRuntimeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
PRInt64 gcTotal = 0;
for (size_t index = 0;
index < data.compartmentStatsVector.length();
index < rtStats.compartmentStatsVector.length();
index++) {
gcTotal += ReportCompartmentStats(data.compartmentStatsVector[index], pathPrefix,
gcTotal += ReportCompartmentStats(rtStats.compartmentStatsVector[index], pathPrefix,
callback, closure);
}
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"),
nsIMemoryReporter::KIND_HEAP, data.runtimeObject,
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeObject,
"Memory used by the JSRuntime object.",
callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"),
nsIMemoryReporter::KIND_HEAP, data.runtimeAtomsTable,
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeAtomsTable,
"Memory used by the atoms table.",
callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"),
nsIMemoryReporter::KIND_HEAP, data.runtimeContexts,
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeContexts,
"Memory used by JSContext objects and certain structures "
"hanging off them." ,
callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/normal"),
nsIMemoryReporter::KIND_HEAP, data.runtimeNormal,
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeNormal,
"Memory used by a JSRuntime, "
"excluding memory that is reported by "
"other reporters under 'explicit/js/runtime/'.",
callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"),
nsIMemoryReporter::KIND_HEAP, data.runtimeTemporary,
nsIMemoryReporter::KIND_HEAP, rtStats.runtimeTemporary,
"Memory held transiently in JSRuntime and used during "
"compilation. It mostly holds parse nodes.",
callback, closure);
ReportMemoryBytes0(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"),
nsIMemoryReporter::KIND_NONHEAP, data.runtimeRegexpCode,
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtimeRegexpCode,
"Memory used by the regexp JIT to hold generated code.",
callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"),
nsIMemoryReporter::KIND_NONHEAP, data.runtimeStackCommitted,
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.",
@ -1685,7 +1685,7 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
ReportGCHeapBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-chunk-dirty-unused"),
&gcTotal, data.gcHeapChunkDirtyUnused,
&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"
@ -1694,7 +1694,7 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
ReportGCHeapBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-chunk-clean-unused"),
&gcTotal, data.gcHeapChunkCleanUnused,
&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 "
@ -1704,21 +1704,21 @@ ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
ReportGCHeapBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-decommitted"),
&gcTotal,
data.gcHeapChunkCleanDecommitted + data.gcHeapChunkDirtyDecommitted,
rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
"Memory in the address space of the garbage-collected JavaScript heap that "
"is currently returned to the OS.",
callback, closure);
ReportGCHeapBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-chunk-admin"),
&gcTotal, data.gcHeapChunkAdmin,
&gcTotal, rtStats.gcHeapChunkAdmin,
"Memory on the garbage-collected JavaScript heap, within chunks, that is "
"used to hold internal book-keeping information.",
callback, closure);
// gcTotal is the sum of everything we've reported for the GC heap. It
// should equal data.gcHeapChunkTotal.
JS_ASSERT(gcTotal == data.gcHeapChunkTotal);
// should equal rtStats.gcHeapChunkTotal.
JS_ASSERT(gcTotal == rtStats.gcHeapChunkTotal);
}
} // namespace memory
@ -1740,9 +1740,9 @@ public:
// the callback. Separating these steps is important because the
// callback may be a JS function, and executing JS while getting these
// stats seems like a bad idea.
JS::IterateData data(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
if (!JS::CollectCompartmentStatsForRuntime(xpcrt->GetJSRuntime(), &data))
JS::RuntimeStats rtStats(xpc::JsMallocSizeOf, xpc::GetCompartmentName,
xpc::DestroyCompartmentName);
if (!JS::CollectRuntimeStats(xpcrt->GetJSRuntime(), &rtStats))
return NS_ERROR_FAILURE;
uint64_t xpconnect;
@ -1755,7 +1755,7 @@ public:
NS_NAMED_LITERAL_CSTRING(pathPrefix, "explicit/js/");
// This is the second step (see above).
ReportJSRuntimeStats(data, pathPrefix, callback, closure);
ReportJSRuntimeStats(rtStats, pathPrefix, callback, closure);
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("xpconnect"),
nsIMemoryReporter::KIND_HEAP, xpconnect,
@ -1764,28 +1764,28 @@ public:
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-chunk-dirty-unused"),
nsIMemoryReporter::KIND_OTHER,
data.gcHeapChunkDirtyUnused,
rtStats.gcHeapChunkDirtyUnused,
"The same as 'explicit/js/gc-heap-chunk-dirty-unused'. Shown here for "
"easy comparison with other 'js-gc' reporters.",
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-chunk-clean-unused"),
nsIMemoryReporter::KIND_OTHER,
data.gcHeapChunkCleanUnused,
rtStats.gcHeapChunkCleanUnused,
"The same as 'explicit/js/gc-heap-chunk-clean-unused'. Shown here for "
"easy comparison with other 'js-gc' reporters.",
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-decommitted"),
nsIMemoryReporter::KIND_OTHER,
data.gcHeapChunkCleanDecommitted + data.gcHeapChunkDirtyDecommitted,
rtStats.gcHeapChunkCleanDecommitted + rtStats.gcHeapChunkDirtyDecommitted,
"The same as 'explicit/js/gc-heap-decommitted'. Shown here for "
"easy comparison with other 'js-gc' reporters.",
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-arena-unused"),
nsIMemoryReporter::KIND_OTHER,
data.gcHeapArenaUnused,
rtStats.gcHeapArenaUnused,
"Memory on the 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.",
@ -1793,7 +1793,7 @@ public:
ReportMemoryPercentage(NS_LITERAL_CSTRING("js-gc-heap-unused-fraction"),
nsIMemoryReporter::KIND_OTHER,
data.gcHeapUnusedPercentage,
rtStats.gcHeapUnusedPercentage,
"Fraction of the 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' + "
@ -1801,14 +1801,14 @@ public:
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-objects"),
nsIMemoryReporter::KIND_OTHER, data.totalObjects,
nsIMemoryReporter::KIND_OTHER, rtStats.totalObjects,
"Memory used for all object-related data. This is the sum of all "
"compartments' 'gc-heap/objects-non-function', "
"'gc-heap/objects-function' and 'object-slots' numbers.",
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-shapes"),
nsIMemoryReporter::KIND_OTHER, data.totalShapes,
nsIMemoryReporter::KIND_OTHER, rtStats.totalShapes,
"Memory used for all shape-related data. This is the sum of all "
"compartments' 'gc-heap/shapes/tree', 'gc-heap/shapes/dict', "
"'gc-heap/shapes/base', "
@ -1817,32 +1817,32 @@ public:
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-scripts"),
nsIMemoryReporter::KIND_OTHER, data.totalScripts,
nsIMemoryReporter::KIND_OTHER, rtStats.totalScripts,
"Memory used for all script-related data. This is the sum of all "
"compartments' 'gc-heap/scripts' and 'script-data' numbers.",
callback, closure);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-strings"),
nsIMemoryReporter::KIND_OTHER, data.totalStrings,
nsIMemoryReporter::KIND_OTHER, rtStats.totalStrings,
"Memory used for all string-related data. This is the sum of all "
"compartments' 'gc-heap/strings' and 'string-chars' numbers.",
callback, closure);
#ifdef JS_METHODJIT
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-mjit"),
nsIMemoryReporter::KIND_OTHER, data.totalMjit,
nsIMemoryReporter::KIND_OTHER, rtStats.totalMjit,
"Memory used by the method JIT. This is the sum of all compartments' "
"'mjit-code', and 'mjit-data' numbers.",
callback, closure);
#endif
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-type-inference"),
nsIMemoryReporter::KIND_OTHER, data.totalTypeInference,
nsIMemoryReporter::KIND_OTHER, rtStats.totalTypeInference,
"Non-transient memory used by type inference. 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);
ReportMemoryBytes(NS_LITERAL_CSTRING("js-total-analysis-temporary"),
nsIMemoryReporter::KIND_OTHER, data.totalAnalysisTemp,
nsIMemoryReporter::KIND_OTHER, rtStats.totalAnalysisTemp,
"Memory used transiently during type inference and compilation. "
"This is the sum of all compartments' 'analysis-temporary' numbers.",
callback, closure);

Просмотреть файл

@ -230,7 +230,7 @@ namespace xpconnect {
namespace memory {
void
ReportJSRuntimeStats(const JS::IterateData &data, const nsACString &pathPrefix,
ReportJSRuntimeStats(const JS::RuntimeStats &rtStats, const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure);