зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1473213 (Part 4) - Add cells allocated statistics r=sfink
--HG-- extra : rebase_source : 667c5db83b674e28602fe38ca73bc6f250717c64
This commit is contained in:
Родитель
3e4c1ee795
Коммит
0c73982d50
|
@ -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; }
|
||||||
|
|
Загрузка…
Ссылка в новой задаче