Bug 831588 - Don't measure decommitted GC arenas in the "explicit" tree. r=terrence,jlebar.

--HG--
extra : rebase_source : a35d978b8884e25169cca8ffc93f96e532e82320
This commit is contained in:
Nicholas Nethercote 2013-03-26 15:07:33 -07:00
parent 0cd79bb341
commit f229655d31
4 changed files with 52 additions and 33 deletions

View File

@ -17,14 +17,13 @@ namespace js {
template <size_t nbits>
class BitArray {
private:
uintptr_t map[nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1)];
static const size_t numSlots =
nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1);
uintptr_t map[numSlots];
public:
void clear(bool value) {
if (value)
memset(map, 0xFF, sizeof(map));
else
memset(map, 0, sizeof(map));
memset(map, value ? 0xFF : 0, sizeof(map));
}
inline bool get(size_t offset) const {
@ -45,6 +44,14 @@ class BitArray {
map[index] &= ~mask;
}
bool isAllClear() const {
for (size_t i = 0; i < numSlots; i++) {
if (map[i])
return false;
}
return true;
}
private:
inline void getMarkWordAndMask(size_t offset,
uintptr_t *indexp, uintptr_t *maskp) const {

View File

@ -83,6 +83,22 @@ CompartmentStats::GCHeapThingsSize()
return n;
}
static void
DecommittedArenasChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
{
// This case is common and fast to check. Do it first.
if (chunk->decommittedArenas.isAllClear())
return;
size_t n = 0;
for (size_t i = 0; i < gc::ArenasPerChunk; i++) {
if (chunk->decommittedArenas.get(i))
n += gc::ArenaSize;
}
JS_ASSERT(n > 0);
*static_cast<size_t *>(data) += n;
}
static void
StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
{
@ -122,15 +138,6 @@ StatsZoneCallback(JSRuntime *rt, void *data, Zone *zone)
&zStats.typePool);
}
static void
StatsChunkCallback(JSRuntime *rt, void *data, gc::Chunk *chunk)
{
RuntimeStats *rtStats = static_cast<RuntimeStats *>(data);
for (size_t i = 0; i < gc::ArenasPerChunk; i++)
if (chunk->decommittedArenas.get(i))
rtStats->gcHeapDecommittedArenas += gc::ArenaSize;
}
static void
StatsArenaCallback(JSRuntime *rt, void *data, gc::Arena *arena,
JSGCTraceKind traceKind, size_t thingSize)
@ -300,8 +307,8 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
rtStats->gcHeapUnusedChunks =
size_t(JS_GetGCParameter(rt, JSGC_UNUSED_CHUNKS)) * gc::ChunkSize;
// This just computes rtStats->gcHeapDecommittedArenas.
IterateChunks(rt, rtStats, StatsChunkCallback);
IterateChunks(rt, &rtStats->gcHeapDecommittedArenas,
DecommittedArenasChunkCallback);
// Take the per-compartment measurements.
IteratorClosure closure(rtStats, opv);
@ -364,9 +371,14 @@ JS::CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats, ObjectPrivateVisit
JS_PUBLIC_API(int64_t)
JS::GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf)
{
// explicit/<compartment>/gc-heap/*
// explicit/*/gc-heap/*
size_t n = size_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * gc::ChunkSize;
// Subtract decommitted arenas, which aren't included in "explicit".
size_t decommittedArenas = 0;
IterateChunks(rt, &decommittedArenas, DecommittedArenasChunkCallback);
n -= decommittedArenas;
// explicit/runtime/mjit-code
// explicit/runtime/regexp-code
// explicit/runtime/stack-committed

View File

@ -2045,10 +2045,16 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
// Report GC numbers that don't belong to a compartment.
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-arenas"),
rtStats.gcHeapUnusedArenas,
"Memory on the garbage-collected JavaScript heap taken by "
"empty arenas within non-empty chunks.");
// We don't want to report decommitted memory in "explicit", so we just
// change the leading "explicit/" to "decommitted/".
nsCString rtPath2(rtPath);
rtPath2.Replace(0, strlen("explicit"), NS_LITERAL_CSTRING("decommitted"));
REPORT_GC_BYTES(rtPath2 + NS_LITERAL_CSTRING("gc-heap/decommitted-arenas"),
rtStats.gcHeapDecommittedArenas,
"Memory on the garbage-collected JavaScript heap, in "
"arenas in non-empty chunks, that is returned to the OS. "
"This means it takes up address space but no physical "
"memory or swap space.");
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-chunks"),
rtStats.gcHeapUnusedChunks,
@ -2056,12 +2062,10 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
"empty chunks, which will soon be released unless claimed "
"for new allocations.");
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/decommitted-arenas"),
rtStats.gcHeapDecommittedArenas,
"Memory on the garbage-collected JavaScript heap, "
"in arenas in non-empty chunks, that is returned to the OS. "
"This means it takes up address space but no physical "
"memory or swap space.");
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-arenas"),
rtStats.gcHeapUnusedArenas,
"Memory on the garbage-collected JavaScript heap taken by "
"empty arenas within non-empty chunks.");
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/chunk-admin"),
rtStats.gcHeapChunkAdmin,
@ -2339,11 +2343,6 @@ JSMemoryMultiReporter::CollectReports(WindowPaths *windowPaths,
// Report the numbers for memory outside of compartments.
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/decommitted-arenas"),
nsIMemoryReporter::KIND_OTHER,
rtStats.gcHeapDecommittedArenas,
"The same as 'explicit/js-non-window/gc-heap/decommitted-arenas'.");
REPORT_BYTES(NS_LITERAL_CSTRING("js-main-runtime/gc-heap/unused-chunks"),
nsIMemoryReporter::KIND_OTHER,
rtStats.gcHeapUnusedChunks,

View File

@ -289,7 +289,8 @@ const kTreeDescriptions = {
"This tree covers explicit memory allocations by the application, both at the \
operating system level (via calls to functions such as VirtualAlloc, \
vm_allocate, and mmap), and at the heap allocation level (via functions such \
as malloc, calloc, realloc, memalign, operator new, and operator new[]).\
as malloc, calloc, realloc, memalign, operator new, and operator new[]) that \
have not been explicitly decommitted (i.e. evicted from memory and swap). \
\n\n\
It excludes memory that is mapped implicitly such as code and data segments, \
and thread stacks. It also excludes heap memory that has been freed by the \