mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 711130 (part 5) - Overhaul the "other measurements" measurements for JS memory consumption. r=terrence.
--HG-- extra : rebase_source : 492af75618c40eb2a92be2756f67db93834729cf
This commit is contained in:
parent
647a888256
commit
26f000b52d
@ -30,6 +30,13 @@ struct TypeInferenceSizes
|
||||
size_t objects;
|
||||
size_t tables;
|
||||
size_t temporary;
|
||||
|
||||
void add(TypeInferenceSizes &sizes) {
|
||||
this->scripts += sizes.scripts;
|
||||
this->objects += sizes.objects;
|
||||
this->tables += sizes.tables;
|
||||
this->temporary += sizes.temporary;
|
||||
}
|
||||
};
|
||||
|
||||
// These measurements relate directly to the JSRuntime, and not to
|
||||
@ -79,6 +86,9 @@ struct CompartmentStats
|
||||
}
|
||||
|
||||
void *extra;
|
||||
|
||||
// If you add a new number, remember to update add() and maybe
|
||||
// gcHeapThingsSize()!
|
||||
size_t gcHeapArenaAdmin;
|
||||
size_t gcHeapUnusedGcThings;
|
||||
|
||||
@ -107,6 +117,45 @@ struct CompartmentStats
|
||||
size_t crossCompartmentWrappers;
|
||||
|
||||
TypeInferenceSizes typeInferenceSizes;
|
||||
|
||||
// Add cStats's numbers to this object's numbers.
|
||||
void add(CompartmentStats &cStats) {
|
||||
#define ADD(x) this->x += cStats.x
|
||||
|
||||
ADD(gcHeapArenaAdmin);
|
||||
ADD(gcHeapUnusedGcThings);
|
||||
|
||||
ADD(gcHeapObjectsNonFunction);
|
||||
ADD(gcHeapObjectsFunction);
|
||||
ADD(gcHeapStrings);
|
||||
ADD(gcHeapShapesTree);
|
||||
ADD(gcHeapShapesDict);
|
||||
ADD(gcHeapShapesBase);
|
||||
ADD(gcHeapScripts);
|
||||
ADD(gcHeapTypeObjects);
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
ADD(gcHeapXML);
|
||||
#endif
|
||||
|
||||
ADD(objectSlots);
|
||||
ADD(objectElements);
|
||||
ADD(objectMisc);
|
||||
ADD(stringChars);
|
||||
ADD(shapesExtraTreeTables);
|
||||
ADD(shapesExtraDictTables);
|
||||
ADD(shapesExtraTreeShapeKids);
|
||||
ADD(shapesCompartmentTables);
|
||||
ADD(scriptData);
|
||||
ADD(mjitData);
|
||||
ADD(crossCompartmentWrappers);
|
||||
|
||||
#undef ADD
|
||||
|
||||
typeInferenceSizes.add(cStats.typeInferenceSizes);
|
||||
}
|
||||
|
||||
// The size of all the live things in the GC heap.
|
||||
size_t gcHeapThingsSize();
|
||||
};
|
||||
|
||||
struct RuntimeStats
|
||||
@ -114,21 +163,14 @@ struct RuntimeStats
|
||||
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
|
||||
: runtime()
|
||||
, gcHeapChunkTotal(0)
|
||||
, gcHeapCommitted(0)
|
||||
, gcHeapUnused(0)
|
||||
, gcHeapUnusedChunks(0)
|
||||
, gcHeapUnusedArenas(0)
|
||||
, gcHeapChunkCleanDecommitted(0)
|
||||
, gcHeapChunkDirtyDecommitted(0)
|
||||
, gcHeapUnusedChunks(0)
|
||||
, gcHeapUnusedArenas(0)
|
||||
, gcHeapUnusedGcThings(0)
|
||||
, gcHeapChunkAdmin(0)
|
||||
, totalObjects(0)
|
||||
, totalShapes(0)
|
||||
, totalScripts(0)
|
||||
, totalStrings(0)
|
||||
, totalMjit(0)
|
||||
, totalTypeInference(0)
|
||||
, totalAnalysisTemp(0)
|
||||
, gcHeapGcThings(0)
|
||||
, totals()
|
||||
, compartmentStatsVector()
|
||||
, currCompartmentStats(NULL)
|
||||
, mallocSizeOf(mallocSizeOf)
|
||||
@ -136,23 +178,35 @@ struct RuntimeStats
|
||||
|
||||
RuntimeSizes runtime;
|
||||
|
||||
// If you add a new number, remember to update the constructor!
|
||||
|
||||
// Here's a useful breakdown of the GC heap.
|
||||
//
|
||||
// - rtStats.gcHeapChunkTotal
|
||||
// - decommitted bytes
|
||||
// - rtStats.gcHeapChunkCleanDecommitted (decommitted arenas in empty chunks)
|
||||
// - rtStats.gcHeapChunkDirtyDecommitted (decommitted arenas in non-empty chunks)
|
||||
// - unused bytes
|
||||
// - rtStats.gcHeapUnusedChunks (empty chunks)
|
||||
// - rtStats.gcHeapUnusedArenas (empty arenas within non-empty chunks)
|
||||
// - rtStats.total.gcHeapUnusedGcThings (empty GC thing slots within non-empty arenas)
|
||||
// - used bytes
|
||||
// - rtStats.gcHeapChunkAdmin
|
||||
// - rtStats.total.gcHeapArenaAdmin
|
||||
// - rtStats.gcHeapGcThings (in-use GC things)
|
||||
|
||||
size_t gcHeapChunkTotal;
|
||||
size_t gcHeapCommitted;
|
||||
size_t gcHeapUnused;
|
||||
size_t gcHeapUnusedChunks;
|
||||
size_t gcHeapUnusedArenas;
|
||||
size_t gcHeapChunkCleanDecommitted;
|
||||
size_t gcHeapChunkDirtyDecommitted;
|
||||
size_t gcHeapUnusedChunks;
|
||||
size_t gcHeapUnusedArenas;
|
||||
size_t gcHeapUnusedGcThings;
|
||||
size_t gcHeapChunkAdmin;
|
||||
size_t totalObjects;
|
||||
size_t totalShapes;
|
||||
size_t totalScripts;
|
||||
size_t totalStrings;
|
||||
size_t totalMjit;
|
||||
size_t totalTypeInference;
|
||||
size_t totalAnalysisTemp;
|
||||
size_t gcHeapGcThings;
|
||||
|
||||
// The sum of all compartment's measurements.
|
||||
CompartmentStats totals;
|
||||
|
||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||
CompartmentStats *currCompartmentStats;
|
||||
|
||||
|
@ -22,6 +22,34 @@ namespace JS {
|
||||
|
||||
using namespace js;
|
||||
|
||||
size_t
|
||||
CompartmentStats::gcHeapThingsSize()
|
||||
{
|
||||
// These are just the GC-thing measurements.
|
||||
size_t n = 0;
|
||||
n += gcHeapObjectsNonFunction;
|
||||
n += gcHeapObjectsFunction;
|
||||
n += gcHeapStrings;
|
||||
n += gcHeapShapesTree;
|
||||
n += gcHeapShapesDict;
|
||||
n += gcHeapShapesBase;
|
||||
n += gcHeapScripts;
|
||||
n += gcHeapTypeObjects;
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
n += gcHeapXML;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
size_t n2 = n;
|
||||
n2 += gcHeapArenaAdmin;
|
||||
n2 += gcHeapUnusedGcThings;
|
||||
// These numbers should sum to a multiple of the arena size.
|
||||
JS_ASSERT(n2 % gc::ArenaSize == 0);
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
|
||||
{
|
||||
@ -157,71 +185,32 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||
if (!rtStats->compartmentStatsVector.reserve(rt->compartments.length()))
|
||||
return false;
|
||||
|
||||
rtStats->gcHeapChunkCleanDecommitted =
|
||||
rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize;
|
||||
rtStats->gcHeapUnusedChunks =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize -
|
||||
rtStats->gcHeapChunkCleanDecommitted;
|
||||
rtStats->gcHeapChunkTotal =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
|
||||
|
||||
IterateCompartmentsArenasCells(rt, rtStats, StatsCompartmentCallback,
|
||||
StatsArenaCallback, StatsCellCallback);
|
||||
rtStats->gcHeapChunkCleanDecommitted =
|
||||
rt->gcChunkPool.countCleanDecommittedArenas(rt) * gc::ArenaSize;
|
||||
|
||||
rtStats->gcHeapUnusedChunks =
|
||||
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize -
|
||||
rtStats->gcHeapChunkCleanDecommitted;
|
||||
|
||||
// This just computes rtStats->gcHeapChunkDirtyDecommitted.
|
||||
IterateChunks(rt, rtStats, StatsChunkCallback);
|
||||
|
||||
// Take the per-compartment measurements.
|
||||
IterateCompartmentsArenasCells(rt, rtStats, StatsCompartmentCallback,
|
||||
StatsArenaCallback, StatsCellCallback);
|
||||
|
||||
// Take the "explcit/js/runtime/" measurements.
|
||||
rt->sizeOfIncludingThis(rtStats->mallocSizeOf, &rtStats->runtime);
|
||||
|
||||
// This is initialized to all bytes stored in used chunks, and then we
|
||||
// subtract used space from it each time around the loop.
|
||||
rtStats->gcHeapUnusedArenas = rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapUnusedChunks -
|
||||
rtStats->gcHeapChunkCleanDecommitted -
|
||||
rtStats->gcHeapChunkDirtyDecommitted;
|
||||
rtStats->gcHeapGcThings = 0;
|
||||
for (size_t i = 0; i < rtStats->compartmentStatsVector.length(); i++) {
|
||||
CompartmentStats &cStats = rtStats->compartmentStatsVector[i];
|
||||
|
||||
rtStats->totalMjit = rtStats->runtime.mjitCode;
|
||||
|
||||
for (size_t index = 0;
|
||||
index < rtStats->compartmentStatsVector.length();
|
||||
index++) {
|
||||
CompartmentStats &cStats = rtStats->compartmentStatsVector[index];
|
||||
|
||||
size_t used = cStats.gcHeapArenaAdmin +
|
||||
cStats.gcHeapUnusedGcThings +
|
||||
cStats.gcHeapObjectsNonFunction +
|
||||
cStats.gcHeapObjectsFunction +
|
||||
cStats.gcHeapStrings +
|
||||
cStats.gcHeapShapesTree +
|
||||
cStats.gcHeapShapesDict +
|
||||
cStats.gcHeapShapesBase +
|
||||
cStats.gcHeapScripts +
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
cStats.gcHeapXML +
|
||||
#endif
|
||||
cStats.gcHeapTypeObjects;
|
||||
|
||||
rtStats->gcHeapUnusedArenas -= used;
|
||||
rtStats->gcHeapUnusedGcThings += cStats.gcHeapUnusedGcThings;
|
||||
rtStats->totalObjects += cStats.gcHeapObjectsNonFunction +
|
||||
cStats.gcHeapObjectsFunction +
|
||||
cStats.objectSlots +
|
||||
cStats.objectElements +
|
||||
cStats.objectMisc;
|
||||
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;
|
||||
rtStats->totalMjit += cStats.mjitData;
|
||||
rtStats->totalTypeInference += cStats.gcHeapTypeObjects +
|
||||
cStats.typeInferenceSizes.objects +
|
||||
cStats.typeInferenceSizes.scripts +
|
||||
cStats.typeInferenceSizes.tables;
|
||||
rtStats->totalAnalysisTemp += cStats.typeInferenceSizes.temporary;
|
||||
rtStats->totals.add(cStats);
|
||||
rtStats->gcHeapGcThings += cStats.gcHeapThingsSize();
|
||||
}
|
||||
|
||||
size_t numDirtyChunks =
|
||||
@ -231,14 +220,16 @@ CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats)
|
||||
rtStats->gcHeapChunkAdmin = numDirtyChunks * perChunkAdmin;
|
||||
rtStats->gcHeapUnusedArenas -= rtStats->gcHeapChunkAdmin;
|
||||
|
||||
rtStats->gcHeapUnused = rtStats->gcHeapUnusedArenas +
|
||||
rtStats->gcHeapUnusedChunks +
|
||||
rtStats->gcHeapUnusedGcThings;
|
||||
|
||||
rtStats->gcHeapCommitted = rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapChunkCleanDecommitted -
|
||||
rtStats->gcHeapChunkDirtyDecommitted;
|
||||
|
||||
// |gcHeapUnusedArenas| is the only thing left. Compute it in terms of
|
||||
// all the others. See the comment in RuntimeStats for explanation.
|
||||
rtStats->gcHeapUnusedArenas = rtStats->gcHeapChunkTotal -
|
||||
rtStats->gcHeapChunkCleanDecommitted -
|
||||
rtStats->gcHeapChunkDirtyDecommitted -
|
||||
rtStats->gcHeapUnusedChunks -
|
||||
rtStats->totals.gcHeapUnusedGcThings -
|
||||
rtStats->gcHeapChunkAdmin -
|
||||
rtStats->totals.gcHeapArenaAdmin -
|
||||
rtStats->gcHeapGcThings;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1227,25 +1227,9 @@ static const size_t SUNDRIES_THRESHOLD = 8192;
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} while (0)
|
||||
|
||||
#define CREPORT(_path, _kind, _units, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
if (amount >= SUNDRIES_THRESHOLD) { \
|
||||
nsresult rv; \
|
||||
rv = cb->Callback(EmptyCString(), _path, _kind, _units, amount, \
|
||||
NS_LITERAL_CSTRING(_desc), closure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} else { \
|
||||
otherSundries += amount; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define REPORT_BYTES(_path, _kind, _amount, _desc) \
|
||||
REPORT(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc);
|
||||
|
||||
#define CREPORT_BYTES(_path, _kind, _amount, _desc) \
|
||||
CREPORT(_path, _kind, nsIMemoryReporter::UNITS_BYTES, _amount, _desc);
|
||||
|
||||
#define REPORT_GC_BYTES(_path, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
@ -1258,6 +1242,23 @@ static const size_t SUNDRIES_THRESHOLD = 8192;
|
||||
gcTotal += amount; \
|
||||
} while (0)
|
||||
|
||||
// Nb: all non-GC compartment reports are currently KIND_HEAP, and this macro
|
||||
// relies on that.
|
||||
#define CREPORT_BYTES(_path, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
if (amount >= SUNDRIES_THRESHOLD) { \
|
||||
nsresult rv; \
|
||||
rv = cb->Callback(EmptyCString(), _path, \
|
||||
nsIMemoryReporter::KIND_HEAP, \
|
||||
nsIMemoryReporter::UNITS_BYTES, amount, \
|
||||
NS_LITERAL_CSTRING(_desc), closure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
} else { \
|
||||
otherSundries += amount; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CREPORT_GC_BYTES(_path, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
@ -1274,18 +1275,16 @@ static const size_t SUNDRIES_THRESHOLD = 8192;
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
template <int N>
|
||||
inline const nsCString
|
||||
MakePath(const nsACString &pathPrefix, const JS::CompartmentStats &cStats,
|
||||
const char (&reporterName)[N])
|
||||
{
|
||||
const char *name = static_cast<char *>(cStats.extra);
|
||||
if (!name)
|
||||
name = "error while initializing compartment name";
|
||||
return pathPrefix + NS_LITERAL_CSTRING("compartment(") +
|
||||
nsDependentCString(name) + NS_LITERAL_CSTRING(")/") +
|
||||
nsDependentCString(reporterName);
|
||||
}
|
||||
#define RREPORT_BYTES(_path, _kind, _amount, _desc) \
|
||||
do { \
|
||||
size_t amount = _amount; /* evaluate _amount only once */ \
|
||||
nsresult rv; \
|
||||
rv = cb->Callback(EmptyCString(), _path, _kind, \
|
||||
nsIMemoryReporter::UNITS_BYTES, amount, \
|
||||
NS_LITERAL_CSTRING(_desc), closure); \
|
||||
NS_ENSURE_SUCCESS(rv, rv); \
|
||||
rtTotal += amount; \
|
||||
} while (0)
|
||||
|
||||
namespace xpc {
|
||||
|
||||
@ -1293,182 +1292,180 @@ static nsresult
|
||||
ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *cb,
|
||||
nsISupports *closure, size_t *gcTotalOut)
|
||||
nsISupports *closure, size_t *gcTotalOut = NULL)
|
||||
{
|
||||
size_t gcTotal = 0, gcHeapSundries = 0, otherSundries = 0;
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/arena-admin"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/arena-admin"),
|
||||
cStats.gcHeapArenaAdmin,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap, within arenas, that is used (a) to hold internal "
|
||||
"bookkeeping information, and (b) to provide padding to "
|
||||
"align GC things.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/unused-gc-things"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/unused-gc-things"),
|
||||
cStats.gcHeapUnusedGcThings,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap taken by empty GC thing slots within non-empty "
|
||||
"arenas.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/objects/non-function"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/objects/non-function"),
|
||||
cStats.gcHeapObjectsNonFunction,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds non-function objects.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/objects/function"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/objects/function"),
|
||||
cStats.gcHeapObjectsFunction,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds function objects.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/strings"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/strings"),
|
||||
cStats.gcHeapStrings,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the 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.");
|
||||
"counted under 'gc-heap/string-chars' instead.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/scripts"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/scripts"),
|
||||
cStats.gcHeapScripts,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the 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.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/shapes/tree"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/shapes/tree"),
|
||||
cStats.gcHeapShapesTree,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds shapes that are in a property tree.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/shapes/dict"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/shapes/dict"),
|
||||
cStats.gcHeapShapesDict,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds shapes that are in dictionary mode.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/shapes/base"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/shapes/base"),
|
||||
cStats.gcHeapShapesBase,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that collates data common to many shapes.");
|
||||
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/type-objects"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/type-objects"),
|
||||
cStats.gcHeapTypeObjects,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds type inference information.");
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
CREPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/xml"),
|
||||
CREPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/xml"),
|
||||
cStats.gcHeapXML,
|
||||
"Memory on the compartment's garbage-collected JavaScript "
|
||||
"Memory on the garbage-collected JavaScript "
|
||||
"heap that holds E4X XML objects.");
|
||||
#endif
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "objects/slots"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectSlots,
|
||||
"Memory allocated for the compartment's non-fixed object "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("objects/slots"),
|
||||
cStats.objectSlots,
|
||||
"Memory allocated for the 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 "
|
||||
"stored on the JavaScript heap; those slots "
|
||||
"are not counted here, but in 'gc-heap/objects' instead.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "objects/elements"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectElements,
|
||||
"Memory allocated for the compartment's object element "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("objects/elements"),
|
||||
cStats.objectElements,
|
||||
"Memory allocated for object element "
|
||||
"arrays, which are used to represent indexed object "
|
||||
"properties.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "objects/misc"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.objectMisc,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("objects/misc"),
|
||||
cStats.objectMisc,
|
||||
"Memory allocated for various small, miscellaneous "
|
||||
"structures that hang off certain kinds of objects.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "string-chars"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.stringChars,
|
||||
"Memory allocated to hold the compartment's string "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("string-chars"),
|
||||
cStats.stringChars,
|
||||
"Memory allocated to hold 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.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "shapes-extra/tree-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeTables,
|
||||
"Memory allocated for the compartment's property tables "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("shapes-extra/tree-tables"),
|
||||
cStats.shapesExtraTreeTables,
|
||||
"Memory allocated for the property tables "
|
||||
"that belong to shapes that are in a property tree.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "shapes-extra/dict-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraDictTables,
|
||||
"Memory allocated for the compartment's property tables "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("shapes-extra/dict-tables"),
|
||||
cStats.shapesExtraDictTables,
|
||||
"Memory allocated for the property tables "
|
||||
"that belong to shapes that are in dictionary mode.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "shapes-extra/tree-shape-kids"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesExtraTreeShapeKids,
|
||||
"Memory allocated for the compartment's kid hashes that "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("shapes-extra/tree-shape-kids"),
|
||||
cStats.shapesExtraTreeShapeKids,
|
||||
"Memory allocated for the kid hashes that "
|
||||
"belong to shapes that are in a property tree.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "shapes-extra/compartment-tables"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.shapesCompartmentTables,
|
||||
"Memory used by compartment wide tables storing shape "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("shapes-extra/compartment-tables"),
|
||||
cStats.shapesCompartmentTables,
|
||||
"Memory used by compartment-wide tables storing shape "
|
||||
"information for use during object construction.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "script-data"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.scriptData,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("script-data"),
|
||||
cStats.scriptData,
|
||||
"Memory allocated for JSScript bytecode and various "
|
||||
"variable-length tables.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "mjit-data"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.mjitData,
|
||||
"Memory used by the method JIT for the compartment's "
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("mjit-data"),
|
||||
cStats.mjitData,
|
||||
"Memory used by the method JIT for "
|
||||
"compilation data: JITScripts, native maps, and inline "
|
||||
"cache structs.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "cross-compartment-wrappers"),
|
||||
nsIMemoryReporter::KIND_HEAP, cStats.crossCompartmentWrappers,
|
||||
"Memory used by the compartment's cross-compartment "
|
||||
"wrappers.");
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("cross-compartment-wrappers"),
|
||||
cStats.crossCompartmentWrappers,
|
||||
"Memory used by cross-compartment wrappers.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "type-inference/script-main"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("type-inference/script-main"),
|
||||
cStats.typeInferenceSizes.scripts,
|
||||
"Memory used during type inference to store type sets of "
|
||||
"variables and dynamically observed types.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "type-inference/object-main"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("type-inference/object-main"),
|
||||
cStats.typeInferenceSizes.objects,
|
||||
"Memory used during type inference to store types and "
|
||||
"possible property types of JS objects.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "type-inference/tables"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("type-inference/tables"),
|
||||
cStats.typeInferenceSizes.tables,
|
||||
"Memory used during type inference for compartment-wide "
|
||||
"tables.");
|
||||
|
||||
CREPORT_BYTES(MakePath(pathPrefix, cStats, "analysis-temporary"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
CREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("analysis-temporary"),
|
||||
cStats.typeInferenceSizes.temporary,
|
||||
"Memory used during type inference and compilation to hold "
|
||||
"transient analysis information. Cleared on GC.");
|
||||
|
||||
if (gcHeapSundries > 0) {
|
||||
REPORT_GC_BYTES(MakePath(pathPrefix, cStats, "gc-heap/sundries"),
|
||||
// We deliberately don't use CREPORT_GC_BYTES here.
|
||||
REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/sundries"),
|
||||
gcHeapSundries,
|
||||
"The sum of all this compartment's gc-heap "
|
||||
"The sum of all the gc-heap "
|
||||
"measurements that are too small to be worth showing "
|
||||
"individually.");
|
||||
}
|
||||
|
||||
if (otherSundries > 0) {
|
||||
REPORT_BYTES(MakePath(pathPrefix, cStats, "other-sundries"),
|
||||
nsIMemoryReporter::KIND_HEAP,
|
||||
otherSundries,
|
||||
"The sum of all this compartment's non-gc-heap "
|
||||
// We deliberately don't use CREPORT_BYTES here.
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("other-sundries"),
|
||||
nsIMemoryReporter::KIND_HEAP, otherSundries,
|
||||
"The sum of all the non-gc-heap "
|
||||
"measurements that are too small to be worth showing "
|
||||
"individually.");
|
||||
}
|
||||
|
||||
*gcTotalOut += gcTotal;
|
||||
if (gcTotalOut) {
|
||||
*gcTotalOut += gcTotal;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1477,78 +1474,94 @@ nsresult
|
||||
ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
|
||||
const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *cb,
|
||||
nsISupports *closure)
|
||||
nsISupports *closure, size_t *rtTotalOut)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Report each compartment's numbers.
|
||||
|
||||
size_t gcTotal = 0;
|
||||
for (size_t index = 0;
|
||||
index < rtStats.compartmentStatsVector.length();
|
||||
index++) {
|
||||
rv = ReportCompartmentStats(rtStats.compartmentStatsVector[index],
|
||||
pathPrefix, cb, closure, &gcTotal);
|
||||
for (size_t i = 0; i < rtStats.compartmentStatsVector.length(); i++) {
|
||||
JS::CompartmentStats cStats = rtStats.compartmentStatsVector[i];
|
||||
const char *name = static_cast<char *>(cStats.extra);
|
||||
nsCString pathPrefix2 = pathPrefix + NS_LITERAL_CSTRING("compartment(") +
|
||||
nsDependentCString(name) + NS_LITERAL_CSTRING(")/");
|
||||
|
||||
rv = ReportCompartmentStats(cStats, pathPrefix2, cb, closure, &gcTotal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.object,
|
||||
"Memory used by the JSRuntime object.");
|
||||
// Report the rtStats.runtime numbers under "runtime/", and compute their
|
||||
// total for later.
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.atomsTable,
|
||||
"Memory used by the atoms table.");
|
||||
size_t rtTotal = 0;
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.contexts,
|
||||
"Memory used by JSContext objects and certain structures "
|
||||
"hanging off them.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/runtime-object"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.object,
|
||||
"Memory used by the JSRuntime object.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/dtoa"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.dtoa,
|
||||
"Memory used by DtoaState, which is used for converting "
|
||||
"strings to numbers and vice versa.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/atoms-table"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.atomsTable,
|
||||
"Memory used by the atoms table.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.temporary,
|
||||
"Memory held transiently in JSRuntime and used during "
|
||||
"compilation. It mostly holds parse nodes.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/contexts"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.contexts,
|
||||
"Memory used by JSContext objects and certain structures "
|
||||
"hanging off them.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/mjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.mjitCode,
|
||||
"Memory used by the method JIT to hold the runtime's "
|
||||
"generated code.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/dtoa"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.dtoa,
|
||||
"Memory used by DtoaState, which is used for converting "
|
||||
"strings to numbers and vice versa.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.regexpCode,
|
||||
"Memory used by the regexp JIT to hold generated code.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/temporary"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.temporary,
|
||||
"Memory held transiently in JSRuntime and used during "
|
||||
"compilation. It mostly holds parse nodes.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/unused-code-memory"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.unusedCodeMemory,
|
||||
"Memory allocated by the method and/or regexp JIT to hold the "
|
||||
"runtime's code, but which is currently unused.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/mjit-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.mjitCode,
|
||||
"Memory used by the method JIT to hold the runtime's "
|
||||
"generated code.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.stackCommitted,
|
||||
"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.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/regexp-code"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.regexpCode,
|
||||
"Memory used by the regexp JIT to hold generated code.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.gcMarker,
|
||||
"Memory used for the GC mark stack and gray roots.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/unused-code-memory"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.unusedCodeMemory,
|
||||
"Memory allocated by the method and/or regexp JIT to hold the "
|
||||
"runtime's code, but which is currently unused.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/math-cache"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.mathCache,
|
||||
"Memory used for the math cache.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/stack-committed"),
|
||||
nsIMemoryReporter::KIND_NONHEAP, rtStats.runtime.stackCommitted,
|
||||
"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.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/script-filenames"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.scriptFilenames,
|
||||
"Memory used for the table holding script filenames.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/gc-marker"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.gcMarker,
|
||||
"Memory used for the GC mark stack and gray roots.");
|
||||
|
||||
REPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/compartment-objects"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.compartmentObjects,
|
||||
"Memory used for JSCompartment objects. These are fairly "
|
||||
"small and all the same size, so they're not worth reporting "
|
||||
"on a per-compartment basis.");
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/math-cache"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.mathCache,
|
||||
"Memory used for the math cache.");
|
||||
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/script-filenames"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.scriptFilenames,
|
||||
"Memory used for the table holding script filenames.");
|
||||
|
||||
RREPORT_BYTES(pathPrefix + NS_LITERAL_CSTRING("runtime/compartment-objects"),
|
||||
nsIMemoryReporter::KIND_HEAP, rtStats.runtime.compartmentObjects,
|
||||
"Memory used for JSCompartment objects. These are fairly "
|
||||
"small and all the same size, so they're not worth reporting "
|
||||
"on a per-compartment basis.");
|
||||
|
||||
if (rtTotalOut) {
|
||||
*rtTotalOut = rtTotal;
|
||||
}
|
||||
|
||||
// Report GC numbers that don't belong to a compartment.
|
||||
|
||||
REPORT_GC_BYTES(pathPrefix + NS_LITERAL_CSTRING("gc-heap/unused-arenas"),
|
||||
rtStats.gcHeapUnusedArenas,
|
||||
@ -1697,125 +1710,83 @@ public:
|
||||
// This is the second step (see above). First we report stuff in the
|
||||
// "explicit" tree, then we report other stuff.
|
||||
|
||||
size_t rtTotal = 0;
|
||||
nsresult rv =
|
||||
xpc::ReportJSRuntimeExplicitTreeStats(rtStats, explicitJs, cb,
|
||||
closure);
|
||||
closure, &rtTotal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
REPORT_BYTES(explicitJs + NS_LITERAL_CSTRING("xpconnect"),
|
||||
nsIMemoryReporter::KIND_HEAP, xpconnect,
|
||||
"Memory used by XPConnect.");
|
||||
// Report the sums of the compartment numbers.
|
||||
rv = ReportCompartmentStats(rtStats.totals,
|
||||
NS_LITERAL_CSTRING("js-main-runtime/compartments/"),
|
||||
cb, closure);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-arenas"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedArenas,
|
||||
"The same as 'explicit/js/gc-heap/unused-arenas'. "
|
||||
"Shown here for easy comparison with other 'js-gc' "
|
||||
"reporters.");
|
||||
// Report the sum of the runtime/ numbers.
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/runtime"),
|
||||
nsIMemoryReporter::KIND_OTHER, rtTotal,
|
||||
"The sum of all measurements under 'explicit/js/runtime/'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-chunks"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedChunks,
|
||||
"The same as 'explicit/js/gc-heap/unused-chunks'. "
|
||||
"Shown here for easy comparison with other 'js-gc' "
|
||||
"reporters.");
|
||||
// Report the numbers for memory outside of compartments.
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-unused-gc-things"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedGcThings,
|
||||
"Memory on the main JSRuntime's garbage-collected "
|
||||
"JavaScript heap taken by empty GC thing slots within "
|
||||
"non-empty arenas. This is the sum of all compartments' "
|
||||
"'gc-heap/unused-gc-things' numbers.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed-unused"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnused,
|
||||
"Amount of the GC heap that's committed, but that is "
|
||||
"neither part of an active allocation nor being used for "
|
||||
"bookkeeping. Equal to 'gc-heap-unused-chunks' + "
|
||||
"'gc-heap-unused-arenas' + 'gc-heap-unused-gc-things'.");
|
||||
|
||||
// Why 10000x? 100x because it's a percentage, and another 100x
|
||||
// because nsIMemoryReporter requires that for UNITS_PERCENTAGE
|
||||
// reporters so we can get two decimal places out of the integer value.
|
||||
REPORT(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed-unused-ratio"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
nsIMemoryReporter::UNITS_PERCENTAGE,
|
||||
(PRInt64) 10000 * rtStats.gcHeapUnused /
|
||||
((double) rtStats.gcHeapCommitted - rtStats.gcHeapUnused),
|
||||
"Ratio of committed, unused bytes to allocated bytes; i.e. "
|
||||
"'gc-heap-committed-unused' / 'gc-heap-allocated'. This "
|
||||
"measures the overhead of the GC heap allocator relative to the "
|
||||
"amount of memory allocated.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapCommitted,
|
||||
"Committed memory (i.e., in physical memory or swap) "
|
||||
"used by the garbage-collected JavaScript heap.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-allocated"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
(rtStats.gcHeapCommitted - rtStats.gcHeapUnused),
|
||||
"Amount of the GC heap used for active allocations and "
|
||||
"bookkeeping. This is calculated as 'gc-heap-committed' "
|
||||
"- 'gc-heap-unused'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-decommitted"),
|
||||
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.");
|
||||
"The same as 'explicit/js/gc-heap/decommitted'.");
|
||||
|
||||
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.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/unused-chunks"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedChunks,
|
||||
"The same as 'explicit/js/gc-heap/unused-chunks'.");
|
||||
|
||||
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'.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/unused-arenas"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedArenas,
|
||||
"The same as 'explicit/js/gc-heap/unused-arenas'.");
|
||||
|
||||
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/gc-heap/chunk-admin"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapChunkAdmin,
|
||||
"The same as 'explicit/js/gc-heap/chunk-admin'.");
|
||||
|
||||
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.");
|
||||
// Report a breakdown of the committed GC space.
|
||||
|
||||
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.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/chunks"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedChunks,
|
||||
"The same as 'explicit/js/gc-heap/unused-chunks'.");
|
||||
|
||||
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.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/arenas"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapUnusedArenas,
|
||||
"The same as 'explicit/js/gc-heap/unused-arenas'.");
|
||||
|
||||
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.");
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/unused/gc-things"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.totals.gcHeapUnusedGcThings,
|
||||
"The same as 'js-main-runtime/compartments/gc-heap/unused-gc-things'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/chunk-admin"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapChunkAdmin,
|
||||
"The same as 'explicit/js/gc-heap/chunk-admin'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/arena-admin"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.totals.gcHeapArenaAdmin,
|
||||
"The same as 'js-main-runtime/compartments/gc-heap/arena-admin'.");
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime-gc-heap-committed/used/gc-things"),
|
||||
nsIMemoryReporter::KIND_OTHER,
|
||||
rtStats.gcHeapGcThings,
|
||||
"Memory on the garbage-collected JavaScript heap that holds GC things such "
|
||||
"as objects, strings, scripts, etc.")
|
||||
|
||||
// Report xpconnect.
|
||||
|
||||
REPORT_BYTES(NS_LITERAL_CSTRING("explicit/xpconnect"),
|
||||
nsIMemoryReporter::KIND_HEAP, xpconnect,
|
||||
"Memory used by XPConnect.");
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -268,7 +268,7 @@ nsresult
|
||||
ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
|
||||
const nsACString &pathPrefix,
|
||||
nsIMemoryMultiReporterCallback *cb,
|
||||
nsISupports *closure);
|
||||
nsISupports *closure, size_t *rtTotal = NULL);
|
||||
|
||||
/**
|
||||
* Convert a jsval to PRInt64. Return true on success.
|
||||
|
@ -511,7 +511,6 @@ function getTreesByProcess(aMgr, aTreesByProcess, aDegeneratesByProcess,
|
||||
assert(aDescription !== "", "empty smaps description");
|
||||
|
||||
} else {
|
||||
assert(aKind === KIND_OTHER, "bad other kind");
|
||||
assert(gSentenceRegExp.test(aDescription),
|
||||
"non-sentence other description");
|
||||
}
|
||||
|
@ -63,7 +63,7 @@
|
||||
vsizeAmounts.push(aAmount);
|
||||
} else if (aPath === "resident") {
|
||||
residentAmounts.push(aAmount);
|
||||
} else if (aPath === "js-main-runtime-gc-heap-committed") {
|
||||
} else if (aPath === "js-main-runtime-gc-heap-committed/used/gc-things") {
|
||||
jsGcHeapAmounts.push(aAmount);
|
||||
} else if (aPath === "heap-allocated") {
|
||||
heapAllocatedAmounts.push(aAmount);
|
||||
@ -141,7 +141,7 @@
|
||||
}
|
||||
checkSpecialReport("vsize", vsizeAmounts);
|
||||
checkSpecialReport("resident", residentAmounts);
|
||||
checkSpecialReport("js-main-runtime-gc-heap-committed", jsGcHeapAmounts);
|
||||
checkSpecialReport("js-main-runtime-gc-heap-committed/used/gc-things", jsGcHeapAmounts);
|
||||
checkSpecialReport("storage-sqlite", storageSqliteAmounts);
|
||||
|
||||
ok(areJsCompartmentsPresent, "js compartments are present");
|
||||
|
@ -45,8 +45,8 @@ interface nsISimpleEnumerator;
|
||||
* OTHER, units COUNT, an amount of 1, and a description that's an empty
|
||||
* string.
|
||||
*
|
||||
* - All other reports must have kind OTHER, and a description that is a
|
||||
* sentence.
|
||||
* - All other reports are unconstrained except that they must have a
|
||||
* description that is a sentence.
|
||||
*/
|
||||
[scriptable, uuid(b2c39f65-1799-4b92-a806-ab3cf6af3cfa)]
|
||||
interface nsIMemoryReporter : nsISupports
|
||||
@ -114,6 +114,9 @@ interface nsIMemoryReporter : nsISupports
|
||||
*
|
||||
* - OTHER: reporters which don't fit into either of these categories.
|
||||
* They can have any units.
|
||||
*
|
||||
* The kind only matters for reporters in the "explicit" tree;
|
||||
* aboutMemory.js uses it to calculate "heap-unclassified".
|
||||
*/
|
||||
const PRInt32 KIND_NONHEAP = 0;
|
||||
const PRInt32 KIND_HEAP = 1;
|
||||
|
Loading…
Reference in New Issue
Block a user