903519 - Split out string nursery pointers from object nursery

903519 - Split out string nursery pointers from object nursery, this was not done before.
This commit is contained in:
win7-7 2026-01-05 19:32:28 +02:00 committed by wuggy
commit eb8b8e28d2
6 changed files with 90 additions and 3 deletions

View file

@ -1528,7 +1528,36 @@ class GCRuntime
* During incremental sweeping, this field temporarily holds the arenas of
* the current AllocKind being swept in order of increasing free space.
*/
SortedArenaList incrementalSweepList;
ActiveThreadData<SortedArenaList> incrementalSweepList;
private:
ActiveThreadData<Nursery> nursery_;
ActiveThreadData<gc::StoreBuffer> storeBuffer_;
public:
Nursery& nursery() { return nursery_.ref(); }
gc::StoreBuffer& storeBuffer() { return storeBuffer_.ref(); }
// Free LIFO blocks are transferred to this allocator before being freed
// after minor GC.
ActiveThreadData<LifoAlloc> blocksToFreeAfterMinorGC;
const void* addressOfNurseryPosition() {
return nursery_.refNoCheck().addressOfPosition();
}
const void* addressOfNurseryCurrentEnd() {
return nursery_.refNoCheck().addressOfCurrentEnd();
}
const void* addressOfStringNurseryCurrentEnd() {
return nursery_.refNoCheck().addressOfCurrentStringEnd();
}
void minorGC(JS::gcreason::Reason reason,
gcstats::Phase phase = gcstats::PHASE_MINOR_GC) JS_HAZ_GC_CALL;
void evictNursery(JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) {
minorGC(reason, gcstats::PHASE_EVICT_NURSERY);
}
void freeAllLifoBlocksAfterMinorGC(LifoAlloc* lifo);
friend class js::GCHelperState;
friend class MarkingValidator;

View file

@ -120,6 +120,7 @@ js::Nursery::Nursery(JSRuntime* rt)
, currentStartChunk_(0)
, currentStartPosition_(0)
, currentEnd_(0)
, currentStringEnd_(0)
, currentChunk_(0)
, maxChunkCount_(0)
, chunkCountLimit_(0)
@ -240,6 +241,8 @@ js::Nursery::disable()
currentEnd_ = 0;
position_ = 0;
currentStringEnd_ = 0;
runtime()->gc.storeBuffer().disable();
}
@ -248,6 +251,7 @@ js::Nursery::enableStrings()
{
MOZ_ASSERT(isEmpty());
canAllocateStrings_ = true;
currentStringEnd_ = currentEnd_;
}
void
@ -255,6 +259,7 @@ js::Nursery::disableStrings()
{
MOZ_ASSERT(isEmpty());
canAllocateStrings_ = false;
currentStringEnd_ = 0;
}
bool
@ -1002,6 +1007,8 @@ js::Nursery::setCurrentChunk(unsigned chunkno)
currentChunk_ = chunkno;
position_ = chunk(chunkno).start();
currentEnd_ = chunk(chunkno).end();
if (canAllocateStrings_)
currentStringEnd_ = currentEnd_;
chunk(chunkno).poisonAndInit(runtime(), JS_FRESH_NURSERY_PATTERN);
}

View file

@ -316,6 +316,7 @@ class Nursery
void* addressOfCurrentEnd() const { return (void*)&currentEnd_; }
void* addressOfPosition() const { return (void*)&position_; }
void* addressOfCurrentStringEnd() const { return (void*)&currentStringEnd_; }
void requestMinorGC(JS::gcreason::Reason reason) const;
@ -357,6 +358,12 @@ class Nursery
/* Pointer to the last byte of space in the current chunk. */
uintptr_t currentEnd_;
/*
* Pointer to the last byte of space in the current chunk, or nullptr if we
* are not allocating strings in the nursery.
*/
uintptr_t currentStringEnd_;
/* The index of the chunk that is currently being allocated from. */
unsigned currentChunk_;

View file

@ -217,6 +217,45 @@ CompileZone::addressOfFreeList(gc::AllocKind allocKind)
return zone()->arenas.addressOfFreeList(allocKind);
}
const void*
CompileZone::addressOfNurseryPosition()
{
return zone()->runtimeFromAnyThread()->gc.addressOfNurseryPosition();
}
const void*
CompileZone::addressOfStringNurseryPosition()
{
// Objects and strings share a nursery, for now at least.
return zone()->runtimeFromAnyThread()->gc.addressOfNurseryPosition();
}
const void*
CompileZone::addressOfNurseryCurrentEnd()
{
return zone()->runtimeFromAnyThread()->gc.addressOfNurseryCurrentEnd();
}
const void*
CompileZone::addressOfStringNurseryCurrentEnd()
{
return zone()->runtimeFromAnyThread()->gc.addressOfStringNurseryCurrentEnd();
}
bool
CompileZone::nurseryExists()
{
MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
return zone()->group()->nursery().exists();
}
void
CompileZone::setMinorGCShouldCancelIonCompilations()
{
MOZ_ASSERT(CurrentThreadCanAccessZone(zone()));
zone()->group()->storeBuffer().setShouldCancelIonCompilations();
}
JSCompartment*
CompileCompartment::compartment()
{

View file

@ -93,6 +93,11 @@ class CompileZone
static CompileZone* get(Zone* zone);
const void* addressOfNeedsIncrementalBarrier();
const void* addressOfFreeList(gc::AllocKind allocKind);
const void* addressOfNurseryPosition();
const void* addressOfStringNurseryPosition();
const void* addressOfNurseryCurrentEnd();
const void* addressOfStringNurseryCurrentEnd();
const void* addressOfFreeList(gc::AllocKind allocKind);
};

View file

@ -887,8 +887,8 @@ MOZ_ASSERT(IsNurseryAllocable(allocKind));
// very close to each other. In practice, the zone will probably be close
// (within 32 bits) as well. If so, use relative offsets between them, to
// avoid multiple 64-bit immediate loads.
auto nurseryPosAddr = intptr_t(zone->addressOfNurseryPosition());
auto nurseryEndAddr = intptr_t(zone->addressOfNurseryCurrentEnd());
auto nurseryPosAddr = intptr_t(zone->addressOfStringNurseryPosition());
auto nurseryEndAddr = intptr_t(zone->addressOfStringNurseryCurrentEnd());
auto zoneAddr = intptr_t(zone);
intptr_t maxOffset = std::max(std::abs(nurseryPosAddr - zoneAddr),