Bug 697016 - Refine per-compartment JS reporters. r=bhackett.

This commit is contained in:
Nicholas Nethercote 2011-10-27 22:19:57 -07:00
parent 66dc6a8e8f
commit 71761b057d
3 changed files with 86 additions and 38 deletions

View File

@ -454,7 +454,8 @@ struct Shape : public js::gc::Cell
size_t sizeOfKids(JSUsableSizeFun usf) const {
/* Nb: |countMe| is true because the kids HashTable is on the heap. */
return (!inDictionary() && kids.isHash())
JS_ASSERT(!inDictionary());
return kids.isHash()
? kids.toHash()->sizeOf(usf, /* countMe */true)
: 0;
}
@ -522,7 +523,7 @@ struct Shape : public js::gc::Cell
/* Used by sharedNonNative. */
explicit Shape(uint32 shape);
bool inDictionary() const { return (flags & IN_DICTIONARY) != 0; }
protected:
bool frozen() const { return (flags & FROZEN) != 0; }
void setFrozen() { flags |= FROZEN; }
@ -536,6 +537,7 @@ struct Shape : public js::gc::Cell
PUBLIC_FLAGS = HAS_SHORTID | METHOD
};
bool inDictionary() const { return (flags & IN_DICTIONARY) != 0; }
uintN getFlags() const { return flags & PUBLIC_FLAGS; }
bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
bool isMethod() const { return (flags & METHOD) != 0; }

View File

@ -1306,30 +1306,42 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
{
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats *curr = data->currCompartmentStats;
curr->gcHeapKinds[traceKind] += thingSize;
switch (traceKind) {
case JSTRACE_OBJECT:
{
JSObject *obj = static_cast<JSObject *>(thing);
if (obj->isFunction()) {
curr->gcHeapObjectsFunction += thingSize;
} else {
curr->gcHeapObjectsNonFunction += thingSize;
}
curr->objectSlots += obj->sizeOfSlotsArray(moz_malloc_usable_size);
break;
}
case JSTRACE_STRING:
{
JSString *str = static_cast<JSString *>(thing);
curr->gcHeapStrings += thingSize;
curr->stringChars += str->charsHeapSize(moz_malloc_usable_size);
break;
}
case JSTRACE_SHAPE:
{
js::Shape *shape = static_cast<js::Shape *>(thing);
curr->propertyTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
curr->shapeKids += shape->sizeOfKids(moz_malloc_usable_size);
if (shape->inDictionary()) {
curr->gcHeapShapesDict += thingSize;
curr->shapesExtraDictTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
} else {
curr->gcHeapShapesTree += thingSize;
curr->shapesExtraTreeTables += shape->sizeOfPropertyTable(moz_malloc_usable_size);
curr->shapesExtraTreeShapeKids += shape->sizeOfKids(moz_malloc_usable_size);
}
break;
}
case JSTRACE_SCRIPT:
{
JSScript *script = static_cast<JSScript *>(thing);
curr->gcHeapScripts += thingSize;
curr->scriptData += script->dataSize(moz_malloc_usable_size);
#ifdef JS_METHODJIT
curr->mjitData += script->jitDataSize(moz_malloc_usable_size);
@ -1339,11 +1351,13 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
case JSTRACE_TYPE_OBJECT:
{
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
curr->gcHeapTypeObjects += thingSize;
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory);
break;
}
case JSTRACE_XML:
{
curr->gcHeapXML += thingSize;
break;
}
}
@ -1572,9 +1586,15 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
PRInt64 used = stats.gcHeapArenaHeaders +
stats.gcHeapArenaPadding +
stats.gcHeapArenaUnused;
for (size_t i = 0; i < ArrayLength(stats.gcHeapKinds); ++i)
used += stats.gcHeapKinds[i];
stats.gcHeapArenaUnused +
stats.gcHeapObjectsNonFunction +
stats.gcHeapObjectsFunction +
stats.gcHeapStrings +
stats.gcHeapShapesTree +
stats.gcHeapShapesDict +
stats.gcHeapScripts +
stats.gcHeapTypeObjects +
stats.gcHeapXML;
data->gcHeapChunkDirtyUnused -= used;
data->gcHeapArenaUnused += stats.gcHeapArenaUnused;
@ -1609,14 +1629,14 @@ ReportCompartmentStats(const CompartmentStats &stats,
nsISupports *closure)
{
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-headers"),
"gc-heap/arena/headers"),
JS_GC_HEAP_KIND, stats.gcHeapArenaHeaders,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is used to hold internal book-keeping information.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-padding"),
"gc-heap/arena/padding"),
JS_GC_HEAP_KIND, stats.gcHeapArenaPadding,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is unused and present only so that other data is aligned. "
@ -1624,22 +1644,29 @@ ReportCompartmentStats(const CompartmentStats &stats,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-unused"),
"gc-heap/arena/unused"),
JS_GC_HEAP_KIND, stats.gcHeapArenaUnused,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that could be holding useful data but currently isn't.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/objects"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_OBJECT],
"gc-heap/objects/non-function"),
JS_GC_HEAP_KIND, stats.gcHeapObjectsNonFunction,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"objects.",
"non-function objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/objects/function"),
JS_GC_HEAP_KIND, stats.gcHeapObjectsFunction,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"function objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/strings"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_STRING],
JS_GC_HEAP_KIND, stats.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 "
@ -1649,30 +1676,36 @@ ReportCompartmentStats(const CompartmentStats &stats,
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/scripts"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_SCRIPT],
JS_GC_HEAP_KIND, stats.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);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/shapes"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_SHAPE],
"gc-heap/shapes/tree"),
JS_GC_HEAP_KIND, stats.gcHeapShapesTree,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes. A shape is an internal data structure that makes JavaScript "
"property accesses fast.",
"shapes that are in a property tree.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/shapes/dict"),
JS_GC_HEAP_KIND, stats.gcHeapShapesDict,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes that are in dictionary mode.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/type-objects"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_TYPE_OBJECT],
JS_GC_HEAP_KIND, stats.gcHeapTypeObjects,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"type inference information.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/xml"),
JS_GC_HEAP_KIND, stats.gcHeapKinds[JSTRACE_XML],
JS_GC_HEAP_KIND, stats.gcHeapXML,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"E4X XML objects.",
callback, closure);
@ -1698,11 +1731,24 @@ ReportCompartmentStats(const CompartmentStats &stats,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"property-tables"),
nsIMemoryReporter::KIND_HEAP, stats.propertyTables,
"Memory allocated for the compartment's property tables. A property "
"table is an internal data structure that makes JavaScript property "
"accesses fast." SLOP_BYTES_STRING,
"shapes-extra/tree-tables"),
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraTreeTables,
"Memory allocated for the compartment's property tables that belong to "
"shapes that are in a property tree." SLOP_BYTES_STRING,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"shapes-extra/dict-tables"),
nsIMemoryReporter::KIND_HEAP, stats.shapesExtraDictTables,
"Memory allocated for the compartment's property tables that belong to "
"shapes that are in dictionary mode." SLOP_BYTES_STRING,
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"shapes-extra/tree-shape-kids"),
nsIMemoryReporter::KIND_HEAP, stats.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.name,
@ -1712,14 +1758,6 @@ ReportCompartmentStats(const CompartmentStats &stats,
"Arrays attached to prototype JS objects managing shape information.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"shape-kids"),
nsIMemoryReporter::KIND_HEAP, stats.shapeKids,
"Memory allocated for the compartment's shape kids. A shape kid "
"is an internal data structure that makes JavaScript property accesses "
"fast.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"script-data"),
nsIMemoryReporter::KIND_HEAP, stats.scriptData,

View File

@ -197,12 +197,20 @@ struct CompartmentStats
PRInt64 gcHeapArenaPadding;
PRInt64 gcHeapArenaUnused;
PRInt64 gcHeapKinds[JSTRACE_LAST + 1];
PRInt64 gcHeapObjectsNonFunction;
PRInt64 gcHeapObjectsFunction;
PRInt64 gcHeapStrings;
PRInt64 gcHeapShapesTree;
PRInt64 gcHeapShapesDict;
PRInt64 gcHeapScripts;
PRInt64 gcHeapTypeObjects;
PRInt64 gcHeapXML;
PRInt64 objectSlots;
PRInt64 stringChars;
PRInt64 propertyTables;
PRInt64 shapeKids;
PRInt64 shapesExtraTreeTables;
PRInt64 shapesExtraDictTables;
PRInt64 shapesExtraTreeShapeKids;
PRInt64 scriptData;
#ifdef JS_METHODJIT