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);
gcTracer.traceTenuredAlloc(t, kind);
cx->noteTenuredAlloc();
return t;
}

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

@ -7935,6 +7935,14 @@ GCRuntime::minorGC(JS::gcreason::Reason reason, gcstats::PhaseKind phase)
if (rt->mainContextFromOwnThread()->suppressGC)
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);
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.
target->zone()->arenas.adoptArenas(&source->zone()->arenas, targetZoneIsCollecting);
target->zone()->addTenuredAllocsSinceMinorGC(
source->zone()->getAndResetTenuredAllocsSinceMinorGC());
target->zone()->usage.adopt(source->zone()->usage);
target->zone()->adoptUniqueIds(source->zone());
target->zone()->adoptMallocBytes(source->zone());

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

@ -1023,6 +1023,9 @@ class GCRuntime
const void* addressOfStringNurseryCurrentEnd() {
return nursery_.refNoCheck().addressOfCurrentStringEnd();
}
uint32_t* addressOfNurseryAllocCount() {
return stats().addressOfAllocsSinceMinorGCNursery();
}
void minorGC(JS::gcreason::Reason reason,
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();
position_ = position() + size;
runtime()->gc.stats().noteNurseryAlloc();
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);
if (!timeInChunkAlloc_.IsZero())
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");

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

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

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

@ -192,6 +192,27 @@ struct Statistics
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 endNurseryCollection(JS::gcreason::Reason reason);
@ -315,6 +336,15 @@ struct Statistics
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire,
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. */
size_t preBytes;

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

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

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

@ -340,6 +340,19 @@ class Zone : public JS::shadow::Zone,
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;
private:

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

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

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

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

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

@ -831,6 +831,12 @@ MacroAssembler::freeListAllocate(Register result, Register temp, gc::AllocKind a
Pop(result);
bind(&success);
if (GetJitContext()->cx) {
uint32_t* countAddress = GetJitContext()->cx->addressOfTenuredAllocCount();
movePtr(ImmPtr(countAddress), temp);
add32(Imm32(1), Address(temp, 0));
}
}
void
@ -993,6 +999,17 @@ MacroAssembler::bumpPointerAllocate(Register result, Register temp, Label* fail,
branchPtr(Assembler::Below, Address(temp, endOffset.value()), result, fail);
storePtr(result, Address(temp, 0));
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

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

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

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

@ -130,6 +130,11 @@ struct JSContext : public JS::RootingContext,
// Free lists for allocating in the current zone.
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.
js::ThreadData<js::gc::FreeLists*> atomsZoneFreeLists_;
@ -198,6 +203,20 @@ struct JSContext : public JS::RootingContext,
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.
JSAtomState& names() { return *runtime_->commonNames; }
js::StaticStrings& staticStrings() { return *runtime_->staticStrings; }