зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1669669 - Don't mark or sweep permanent atoms r=sfink
Differential Revision: https://phabricator.services.mozilla.com/D121392
This commit is contained in:
Родитель
ab4d1a3f8c
Коммит
37016a9847
|
@ -1646,6 +1646,49 @@ void GCRuntime::finish() {
|
|||
stats().printTotalProfileTimes();
|
||||
}
|
||||
|
||||
void GCRuntime::freezePermanentAtoms() {
|
||||
// This is called just after the permanent atoms have been created. At this
|
||||
// point all existing atoms are permanent. Move the arenas containing atoms
|
||||
// out of atoms zone arena lists until shutdown. Since we won't sweep them, we
|
||||
// don't need to mark them at the start of every GC.
|
||||
|
||||
MOZ_ASSERT(atomsZone);
|
||||
MOZ_ASSERT(zones().empty());
|
||||
|
||||
atomsZone->arenas.clearFreeLists();
|
||||
freezePermanentAtomsOfKind(AllocKind::ATOM, permanentAtoms.ref());
|
||||
freezePermanentAtomsOfKind(AllocKind::FAT_INLINE_ATOM,
|
||||
permanentFatInlineAtoms.ref());
|
||||
}
|
||||
|
||||
void GCRuntime::freezePermanentAtomsOfKind(AllocKind kind,
|
||||
ArenaList& arenaList) {
|
||||
for (auto atom = atomsZone->cellIterUnsafe<JSAtom>(kind); !atom.done();
|
||||
atom.next()) {
|
||||
MOZ_ASSERT(atom->isPermanentAtom());
|
||||
atom->asTenured().markBlack();
|
||||
}
|
||||
|
||||
arenaList = std::move(atomsZone->arenas.arenaList(kind));
|
||||
}
|
||||
|
||||
void GCRuntime::restorePermanentAtoms() {
|
||||
// Move the arenas containing permanent atoms that were removed by
|
||||
// freezePermanentAtoms() back to the atoms zone arena lists so we can collect
|
||||
// them.
|
||||
|
||||
MOZ_ASSERT(heapState() == JS::HeapState::MajorCollecting);
|
||||
|
||||
restorePermanentAtomsOfKind(AllocKind::ATOM, permanentAtoms.ref());
|
||||
restorePermanentAtomsOfKind(AllocKind::FAT_INLINE_ATOM,
|
||||
permanentFatInlineAtoms.ref());
|
||||
}
|
||||
|
||||
void GCRuntime::restorePermanentAtomsOfKind(AllocKind kind,
|
||||
ArenaList& arenaList) {
|
||||
atomsZone->arenas.arenaList(kind).insertListWithCursorAtEnd(arenaList);
|
||||
}
|
||||
|
||||
bool GCRuntime::setParameter(JSGCParamKey key, uint32_t value) {
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||
waitBackgroundSweepEnd();
|
||||
|
@ -4414,6 +4457,10 @@ bool GCRuntime::beginPreparePhase(JS::GCReason reason, AutoGCSession& session) {
|
|||
session.maybeCheckAtomsAccess.emplace(rt);
|
||||
}
|
||||
|
||||
if (reason == JS::GCReason::DESTROY_RUNTIME) {
|
||||
restorePermanentAtoms();
|
||||
}
|
||||
|
||||
/*
|
||||
* Start a parallel task to clear all mark state for the zones we are
|
||||
* collecting. This is linear in the size of the heap we are collecting and so
|
||||
|
|
|
@ -288,6 +288,11 @@ class GCRuntime {
|
|||
void finishRoots();
|
||||
void finish();
|
||||
|
||||
void freezePermanentAtoms();
|
||||
void freezePermanentAtomsOfKind(AllocKind kind, ArenaList& arenaList);
|
||||
void restorePermanentAtoms();
|
||||
void restorePermanentAtomsOfKind(AllocKind kind, ArenaList& arenaList);
|
||||
|
||||
JS::HeapState heapState() const { return heapState_; }
|
||||
|
||||
inline bool hasZealMode(ZealMode mode);
|
||||
|
@ -934,6 +939,10 @@ class GCRuntime {
|
|||
AtomMarkingRuntime atomMarking;
|
||||
|
||||
private:
|
||||
// Arenas used for permanent atoms and static strings created at startup.
|
||||
MainThreadData<ArenaList> permanentAtoms;
|
||||
MainThreadData<ArenaList> permanentFatInlineAtoms;
|
||||
|
||||
// When chunks are empty, they reside in the emptyChunks pool and are
|
||||
// re-used as needed or eventually expired if not re-used. The emptyChunks
|
||||
// pool gets refilled from the background allocation task heuristically so
|
||||
|
|
|
@ -311,7 +311,7 @@ void js::gc::GCRuntime::traceRuntime(JSTracer* trc, AutoTraceSession& session) {
|
|||
void js::gc::GCRuntime::traceRuntimeAtoms(JSTracer* trc,
|
||||
const AutoAccessAtomsZone& access) {
|
||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::MARK_RUNTIME_DATA);
|
||||
rt->tracePermanentAtoms(trc);
|
||||
rt->tracePermanentAtomsDuringInit(trc);
|
||||
TraceAtoms(trc, access);
|
||||
TraceWellKnownSymbols(trc);
|
||||
jit::JitRuntime::TraceAtomZoneRoots(trc, access);
|
||||
|
|
|
@ -446,24 +446,15 @@ static void TracePermanentAtoms(JSTracer* trc, AtomSet::Range atoms) {
|
|||
}
|
||||
}
|
||||
|
||||
void JSRuntime::tracePermanentAtoms(JSTracer* trc) {
|
||||
void JSRuntime::tracePermanentAtomsDuringInit(JSTracer* trc) {
|
||||
// Permanent atoms only need to be traced in the runtime which owns them.
|
||||
if (parentRuntime) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Static strings are not included in the permanent atoms table.
|
||||
if (staticStrings) {
|
||||
staticStrings->trace(trc);
|
||||
}
|
||||
|
||||
if (permanentAtomsDuringInit_) {
|
||||
TracePermanentAtoms(trc, permanentAtomsDuringInit_->all());
|
||||
}
|
||||
|
||||
if (permanentAtoms_) {
|
||||
TracePermanentAtoms(trc, permanentAtoms_->all());
|
||||
}
|
||||
}
|
||||
|
||||
void js::TraceWellKnownSymbols(JSTracer* trc) {
|
||||
|
@ -636,6 +627,8 @@ bool JSRuntime::initMainAtomsTables(JSContext* cx) {
|
|||
MOZ_ASSERT(!parentRuntime);
|
||||
MOZ_ASSERT(!permanentAtomsPopulated());
|
||||
|
||||
gc.freezePermanentAtoms();
|
||||
|
||||
// The permanent atoms table has now been populated.
|
||||
permanentAtoms_ =
|
||||
js_new<FrozenAtomSet>(permanentAtomsDuringInit_); // Takes ownership.
|
||||
|
|
|
@ -860,7 +860,7 @@ struct JSRuntime {
|
|||
}
|
||||
|
||||
bool initMainAtomsTables(JSContext* cx);
|
||||
void tracePermanentAtoms(JSTracer* trc);
|
||||
void tracePermanentAtomsDuringInit(JSTracer* trc);
|
||||
|
||||
// Cached well-known symbols (ES6 rev 24 6.1.5.1). Like permanent atoms,
|
||||
// these are shared with the parentRuntime, if any.
|
||||
|
|
Загрузка…
Ссылка в новой задаче