Bug 1473213 (Part 4) - Add cells allocated statistics r=sfink

--HG--
extra : rebase_source : 667c5db83b674e28602fe38ca73bc6f250717c64
This commit is contained in:
Paul Bone 2018-08-08 12:54:50 +10:00
Родитель 3e4c1ee795
Коммит 0c73982d50
13 изменённых файлов: 113 добавлений и 0 удалений

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

@ -264,6 +264,7 @@ GCRuntime::tryNewTenuredThing(JSContext* cx, AllocKind kind, size_t thingSize)
checkIncrementalZoneState(cx, t); checkIncrementalZoneState(cx, t);
gcTracer.traceTenuredAlloc(t, kind); gcTracer.traceTenuredAlloc(t, kind);
cx->noteTenuredAlloc();
return t; return t;
} }

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

@ -7935,6 +7935,14 @@ GCRuntime::minorGC(JS::gcreason::Reason reason, gcstats::PhaseKind phase)
if (rt->mainContextFromOwnThread()->suppressGC) if (rt->mainContextFromOwnThread()->suppressGC)
return; return;
// Note that we aren't collecting the updated alloc counts from any helper
// threads. We should be but I'm not sure where to add that
// synchronisation.
uint32_t numAllocs = rt->mainContextFromOwnThread()->getAndResetAllocsThisZoneSinceMinorGC();
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next())
numAllocs += zone->getAndResetTenuredAllocsSinceMinorGC();
rt->gc.stats().setAllocsSinceMinorGCTenured(numAllocs);
gcstats::AutoPhase ap(rt->gc.stats(), phase); gcstats::AutoPhase ap(rt->gc.stats(), phase);
nursery().clearMinorGCRequest(); nursery().clearMinorGCRequest();
@ -8220,6 +8228,8 @@ GCRuntime::mergeRealms(Realm* source, Realm* target)
// Merge the allocator, stats and UIDs in source's zone into target's zone. // Merge the allocator, stats and UIDs in source's zone into target's zone.
target->zone()->arenas.adoptArenas(&source->zone()->arenas, targetZoneIsCollecting); target->zone()->arenas.adoptArenas(&source->zone()->arenas, targetZoneIsCollecting);
target->zone()->addTenuredAllocsSinceMinorGC(
source->zone()->getAndResetTenuredAllocsSinceMinorGC());
target->zone()->usage.adopt(source->zone()->usage); target->zone()->usage.adopt(source->zone()->usage);
target->zone()->adoptUniqueIds(source->zone()); target->zone()->adoptUniqueIds(source->zone());
target->zone()->adoptMallocBytes(source->zone()); target->zone()->adoptMallocBytes(source->zone());

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

@ -1023,6 +1023,9 @@ class GCRuntime
const void* addressOfStringNurseryCurrentEnd() { const void* addressOfStringNurseryCurrentEnd() {
return nursery_.refNoCheck().addressOfCurrentStringEnd(); return nursery_.refNoCheck().addressOfCurrentStringEnd();
} }
uint32_t* addressOfNurseryAllocCount() {
return stats().addressOfAllocsSinceMinorGCNursery();
}
void minorGC(JS::gcreason::Reason reason, void minorGC(JS::gcreason::Reason reason,
gcstats::PhaseKind phase = gcstats::PhaseKind::MINOR_GC) JS_HAZ_GC_CALL; gcstats::PhaseKind phase = gcstats::PhaseKind::MINOR_GC) JS_HAZ_GC_CALL;

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

@ -396,6 +396,7 @@ js::Nursery::allocate(size_t size)
void* thing = (void*)position(); void* thing = (void*)position();
position_ = position() + size; position_ = position() + size;
runtime()->gc.stats().noteNurseryAlloc();
JS_EXTRA_POISON(thing, JS_ALLOCATED_NURSERY_PATTERN, size, MemCheckKind::MakeUndefined); JS_EXTRA_POISON(thing, JS_ALLOCATED_NURSERY_PATTERN, size, MemCheckKind::MakeUndefined);
@ -620,6 +621,8 @@ js::Nursery::renderProfileJSON(JSONPrinter& json) const
json.property("lazy_capacity", previousGC.nurseryLazyCapacity); json.property("lazy_capacity", previousGC.nurseryLazyCapacity);
if (!timeInChunkAlloc_.IsZero()) if (!timeInChunkAlloc_.IsZero())
json.property("chunk_alloc_us", timeInChunkAlloc_, json.MICROSECONDS); json.property("chunk_alloc_us", timeInChunkAlloc_, json.MICROSECONDS);
json.property("cells_allocated_nursery", runtime()->gc.stats().allocsSinceMinorGCNursery());
json.property("cells_allocated_tenured", runtime()->gc.stats().allocsSinceMinorGCTenured());
json.beginObjectProperty("phase_times"); json.beginObjectProperty("phase_times");

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

@ -752,6 +752,7 @@ Statistics::Statistics(JSRuntime* rt)
gcTimerFile(nullptr), gcTimerFile(nullptr),
gcDebugFile(nullptr), gcDebugFile(nullptr),
nonincrementalReason_(gc::AbortReason::None), nonincrementalReason_(gc::AbortReason::None),
allocsSinceMinorGC({0, 0}),
preBytes(0), preBytes(0),
thresholdTriggered(false), thresholdTriggered(false),
triggerAmount(0.0), triggerAmount(0.0),
@ -1046,6 +1047,8 @@ Statistics::endNurseryCollection(JS::gcreason::Reason reason)
JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END, JS::GCNurseryProgress::GC_NURSERY_COLLECTION_END,
reason); reason);
} }
allocsSinceMinorGC = {0, 0};
} }
void void

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

@ -192,6 +192,27 @@ struct Statistics
thresholdTriggered = true; thresholdTriggered = true;
} }
void noteNurseryAlloc() {
allocsSinceMinorGC.nursery++;
}
// tenured allocs don't include nursery evictions.
void setAllocsSinceMinorGCTenured(uint32_t allocs) {
allocsSinceMinorGC.tenured = allocs;
}
uint32_t allocsSinceMinorGCNursery() {
return allocsSinceMinorGC.nursery;
}
uint32_t allocsSinceMinorGCTenured() {
return allocsSinceMinorGC.tenured;
}
uint32_t* addressOfAllocsSinceMinorGCNursery() {
return &allocsSinceMinorGC.nursery;
}
void beginNurseryCollection(JS::gcreason::Reason reason); void beginNurseryCollection(JS::gcreason::Reason reason);
void endNurseryCollection(JS::gcreason::Reason reason); void endNurseryCollection(JS::gcreason::Reason reason);
@ -315,6 +336,15 @@ struct Statistics
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire, mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
mozilla::recordreplay::Behavior::DontPreserve>> counts; mozilla::recordreplay::Behavior::DontPreserve>> counts;
/*
* These events cannot be kept in the above array, we need to take their
* address.
*/
struct {
uint32_t nursery;
uint32_t tenured;
} allocsSinceMinorGC;
/* Allocated space before the GC started. */ /* Allocated space before the GC started. */
size_t preBytes; size_t preBytes;

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

@ -34,6 +34,7 @@ JS::Zone::Zone(JSRuntime* rt)
uniqueIds_(this), uniqueIds_(this),
suppressAllocationMetadataBuilder(this, false), suppressAllocationMetadataBuilder(this, false),
arenas(this), arenas(this),
tenuredAllocsSinceMinorGC_(0),
types(this), types(this),
gcWeakMapList_(this), gcWeakMapList_(this),
compartments_(), compartments_(),

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

@ -340,6 +340,19 @@ class Zone : public JS::shadow::Zone,
js::gc::ArenaLists arenas; js::gc::ArenaLists arenas;
private:
// Number of allocations since the most recent minor GC for this thread.
mozilla::Atomic<uint32_t, mozilla::Relaxed> tenuredAllocsSinceMinorGC_;
public:
void addTenuredAllocsSinceMinorGC(uint32_t allocs) {
tenuredAllocsSinceMinorGC_ += allocs;
}
uint32_t getAndResetTenuredAllocsSinceMinorGC() {
return tenuredAllocsSinceMinorGC_.exchange(0);
}
js::TypeZone types; js::TypeZone types;
private: private:

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

@ -214,6 +214,12 @@ CompileZone::addressOfStringNurseryCurrentEnd()
return zone()->runtimeFromAnyThread()->gc.addressOfStringNurseryCurrentEnd(); return zone()->runtimeFromAnyThread()->gc.addressOfStringNurseryCurrentEnd();
} }
uint32_t*
CompileZone::addressOfNurseryAllocCount()
{
return zone()->runtimeFromAnyThread()->gc.addressOfNurseryAllocCount();
}
bool bool
CompileZone::canNurseryAllocateStrings() CompileZone::canNurseryAllocateStrings()
{ {

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

@ -82,6 +82,8 @@ class CompileZone
const void* addressOfNurseryCurrentEnd(); const void* addressOfNurseryCurrentEnd();
const void* addressOfStringNurseryCurrentEnd(); const void* addressOfStringNurseryCurrentEnd();
uint32_t* addressOfNurseryAllocCount();
bool nurseryExists(); bool nurseryExists();
bool canNurseryAllocateStrings(); bool canNurseryAllocateStrings();
void setMinorGCShouldCancelIonCompilations(); void setMinorGCShouldCancelIonCompilations();

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

@ -831,6 +831,12 @@ MacroAssembler::freeListAllocate(Register result, Register temp, gc::AllocKind a
Pop(result); Pop(result);
bind(&success); bind(&success);
if (GetJitContext()->cx) {
uint32_t* countAddress = GetJitContext()->cx->addressOfTenuredAllocCount();
movePtr(ImmPtr(countAddress), temp);
add32(Imm32(1), Address(temp, 0));
}
} }
void void
@ -993,6 +999,17 @@ MacroAssembler::bumpPointerAllocate(Register result, Register temp, Label* fail,
branchPtr(Assembler::Below, Address(temp, endOffset.value()), result, fail); branchPtr(Assembler::Below, Address(temp, endOffset.value()), result, fail);
storePtr(result, Address(temp, 0)); storePtr(result, Address(temp, 0));
subPtr(Imm32(size), result); subPtr(Imm32(size), result);
CompileZone* zone = GetJitContext()->realm->zone();
uint32_t* countAddress = zone->addressOfNurseryAllocCount();
CheckedInt<int32_t> counterOffset = (CheckedInt<uintptr_t>(uintptr_t(countAddress)) -
CheckedInt<uintptr_t>(uintptr_t(posAddr))).toChecked<int32_t>();
if (counterOffset.isValid()) {
add32(Imm32(1), Address(temp, counterOffset.value()));
} else {
movePtr(ImmPtr(countAddress), temp);
add32(Imm32(1), Address(temp, 0));
}
} }
// Inlined equivalent of gc::AllocateString, jumping to fail if nursery // Inlined equivalent of gc::AllocateString, jumping to fail if nursery

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

@ -422,6 +422,11 @@ JSContext::enterAtomsZone()
inline void inline void
JSContext::setZone(js::Zone *zone, JSContext::IsAtomsZone isAtomsZone) JSContext::setZone(js::Zone *zone, JSContext::IsAtomsZone isAtomsZone)
{ {
if (zone_)
zone_->addTenuredAllocsSinceMinorGC(allocsThisZoneSinceMinorGC_);
allocsThisZoneSinceMinorGC_ = 0;
zone_ = zone; zone_ = zone;
if (zone == nullptr) { if (zone == nullptr) {
freeLists_ = nullptr; freeLists_ = nullptr;

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

@ -130,6 +130,11 @@ struct JSContext : public JS::RootingContext,
// Free lists for allocating in the current zone. // Free lists for allocating in the current zone.
js::ThreadData<js::gc::FreeLists*> freeLists_; js::ThreadData<js::gc::FreeLists*> freeLists_;
// This is reset each time we switch zone, then added to the variable in the
// zone when we switch away from it. This would be a js::ThreadData but we
// need to take its address.
uint32_t allocsThisZoneSinceMinorGC_;
// Free lists for parallel allocation in the atoms zone on helper threads. // Free lists for parallel allocation in the atoms zone on helper threads.
js::ThreadData<js::gc::FreeLists*> atomsZoneFreeLists_; js::ThreadData<js::gc::FreeLists*> atomsZoneFreeLists_;
@ -198,6 +203,20 @@ struct JSContext : public JS::RootingContext,
js::ReportAllocationOverflow(this); js::ReportAllocationOverflow(this);
} }
void noteTenuredAlloc() {
allocsThisZoneSinceMinorGC_++;
}
uint32_t* addressOfTenuredAllocCount() {
return &allocsThisZoneSinceMinorGC_;
}
uint32_t getAndResetAllocsThisZoneSinceMinorGC() {
uint32_t allocs = allocsThisZoneSinceMinorGC_;
allocsThisZoneSinceMinorGC_ = 0;
return allocs;
}
// Accessors for immutable runtime data. // Accessors for immutable runtime data.
JSAtomState& names() { return *runtime_->commonNames; } JSAtomState& names() { return *runtime_->commonNames; }
js::StaticStrings& staticStrings() { return *runtime_->staticStrings; } js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }