mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-07 00:08:39 +09:00
Bug 1369748 - Refactor GCRuntime::beginMarkPhase r=sfink
This commit is contained in:
parent
35e683a4fa
commit
f5541a3cc2
1 changed files with 106 additions and 75 deletions
181
js/src/jsgc.cpp
181
js/src/jsgc.cpp
|
|
@ -3421,6 +3421,8 @@ ArenaLists::checkEmptyArenaList(AllocKind kind)
|
|||
void
|
||||
GCRuntime::purgeRuntime(AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
gcstats::AutoPhase ap(stats(), gcstats::PhaseKind::PURGE);
|
||||
|
||||
for (GCCompartmentsIter comp(rt); !comp.done(); comp.next())
|
||||
comp->purge();
|
||||
|
||||
|
|
@ -3595,27 +3597,25 @@ ShouldCollectZone(Zone* zone, JS::gcreason::Reason reason)
|
|||
}
|
||||
|
||||
bool
|
||||
GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock)
|
||||
GCRuntime::prepareZonesForCollection(JS::gcreason::Reason reason, bool* isFullOut,
|
||||
AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
int64_t currentTime = PRMJ_Now();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (fullCompartmentChecks)
|
||||
checkForCompartmentMismatches();
|
||||
/* Assert that zone state is as we expect */
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
MOZ_ASSERT(!zone->isCollecting());
|
||||
MOZ_ASSERT(!zone->compartments().empty());
|
||||
for (auto i : AllAllocKinds())
|
||||
MOZ_ASSERT(!zone->arenas.arenaListsToSweep(i));
|
||||
}
|
||||
#endif
|
||||
|
||||
isFull = true;
|
||||
*isFullOut = true;
|
||||
bool any = false;
|
||||
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
/* Assert that zone state is as we expect */
|
||||
MOZ_ASSERT(!zone->isCollecting());
|
||||
MOZ_ASSERT(!zone->compartments.empty());
|
||||
#ifdef DEBUG
|
||||
for (auto i : AllAllocKinds())
|
||||
MOZ_ASSERT(!zone->arenas.arenaListsToSweep[i]);
|
||||
#endif
|
||||
int64_t currentTime = PRMJ_Now();
|
||||
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
/* Set up which zones will be collected. */
|
||||
if (ShouldCollectZone(zone, reason)) {
|
||||
if (!zone->isAtomsZone()) {
|
||||
|
|
@ -3623,7 +3623,7 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
|
|||
zone->setGCState(Zone::Mark);
|
||||
}
|
||||
} else {
|
||||
isFull = false;
|
||||
*isFullOut = false;
|
||||
}
|
||||
|
||||
zone->setPreservingCode(false);
|
||||
|
|
@ -3641,9 +3641,10 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
|
|||
c->zone()->setPreservingCode(true);
|
||||
}
|
||||
|
||||
if (!rt->gc.cleanUpEverything && canAllocateMoreCode) {
|
||||
if (JSCompartment* comp = jit::TopmostIonActivationCompartment(rt))
|
||||
comp->zone()->setPreservingCode(true);
|
||||
if (!cleanUpEverything && canAllocateMoreCode) {
|
||||
jit::JitActivationIterator activation(TlsContext.get());
|
||||
if (!activation.done())
|
||||
activation->compartment()->zone()->setPreservingCode(true);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -3667,7 +3668,68 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
|
|||
}
|
||||
|
||||
/* Check that at least one zone is scheduled for collection. */
|
||||
if (!any)
|
||||
return any;
|
||||
}
|
||||
|
||||
static void
|
||||
DiscardJITCodeForIncrementalGC(JSRuntime* rt)
|
||||
{
|
||||
js::CancelOffThreadIonCompile(rt, JS::Zone::Mark);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::MARK_DISCARD_CODE);
|
||||
zone->discardJitCode(rt->defaultFreeOp());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
RelazifyFunctionsForShrinkingGC(JSRuntime* rt)
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::RELAZIFY_FUNCTIONS);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (zone->isSelfHostingZone())
|
||||
continue;
|
||||
RelazifyFunctions(zone, AllocKind::FUNCTION);
|
||||
RelazifyFunctions(zone, AllocKind::FUNCTION_EXTENDED);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
PurgeShapeTablesForShrinkingGC(JSRuntime* rt)
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::PURGE_SHAPE_TABLES);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (zone->keepShapeTables() || zone->isSelfHostingZone())
|
||||
continue;
|
||||
for (auto baseShape = zone->cellIter<BaseShape>(); !baseShape.done(); baseShape.next())
|
||||
baseShape->maybePurgeTable();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
UnmarkCollectedZones(JSRuntime* rt)
|
||||
{
|
||||
gcstats::AutoPhase ap(rt->gc.stats(), gcstats::PhaseKind::UNMARK);
|
||||
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
/* Unmark everything in the zones being collected. */
|
||||
zone->arenas.unmarkAll();
|
||||
}
|
||||
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
/* Unmark all weak maps in the zones being collected. */
|
||||
WeakMapBase::unmarkZone(zone);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (fullCompartmentChecks)
|
||||
checkForCompartmentMismatches();
|
||||
#endif
|
||||
|
||||
if (!prepareZonesForCollection(reason, &isFull.ref(), lock))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
|
@ -3684,78 +3746,47 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
|
|||
GCMarker* gcmarker = ▮
|
||||
|
||||
/* For non-incremental GC the following sweep discards the jit code. */
|
||||
if (isIncremental) {
|
||||
js::CancelOffThreadIonCompile(rt, JS::Zone::Mark);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_MARK_DISCARD_CODE);
|
||||
zone->discardJitCode(rt->defaultFreeOp());
|
||||
}
|
||||
}
|
||||
if (isIncremental)
|
||||
DiscardJITCodeForIncrementalGC(rt);
|
||||
|
||||
/*
|
||||
* Relazify functions after discarding JIT code (we can't relazify
|
||||
* functions with JIT code) and before the actual mark phase, so that
|
||||
* the current GC can collect the JSScripts we're unlinking here.
|
||||
* We do this only when we're performing a shrinking GC, as too much
|
||||
* relazification can cause performance issues when we have to reparse
|
||||
* the same functions over and over.
|
||||
* Relazify functions after discarding JIT code (we can't relazify functions
|
||||
* with JIT code) and before the actual mark phase, so that the current GC
|
||||
* can collect the JSScripts we're unlinking here. We do this only when
|
||||
* we're performing a shrinking GC, as too much relazification can cause
|
||||
* performance issues when we have to reparse the same functions over and
|
||||
* over.
|
||||
*/
|
||||
if (invocationKind == GC_SHRINK) {
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_RELAZIFY_FUNCTIONS);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (zone->isSelfHostingZone())
|
||||
continue;
|
||||
RelazifyFunctions(zone, AllocKind::FUNCTION);
|
||||
RelazifyFunctions(zone, AllocKind::FUNCTION_EXTENDED);
|
||||
}
|
||||
}
|
||||
|
||||
/* Purge ShapeTables. */
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_PURGE_SHAPE_TABLES);
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
if (zone->keepShapeTables() || zone->isSelfHostingZone())
|
||||
continue;
|
||||
for (auto baseShape = zone->cellIter<BaseShape>(); !baseShape.done(); baseShape.next())
|
||||
baseShape->maybePurgeTable();
|
||||
}
|
||||
RelazifyFunctionsForShrinkingGC(rt);
|
||||
PurgeShapeTablesForShrinkingGC(rt);
|
||||
}
|
||||
|
||||
startNumber = number;
|
||||
updateMallocCountersOnGCStart();
|
||||
|
||||
/* Process any queued source compressions during the start of a major GC. */
|
||||
{
|
||||
AutoLockHelperThreadState helperLock;
|
||||
HelperThreadState().startHandlingCompressionTasks(helperLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* We must purge the runtime at the beginning of an incremental GC. The
|
||||
* danger if we purge later is that the snapshot invariant of incremental
|
||||
* GC will be broken, as follows. If some object is reachable only through
|
||||
* some cache (say the dtoaCache) then it will not be part of the snapshot.
|
||||
* If we purge after root marking, then the mutator could obtain a pointer
|
||||
* to the object and start using it. This object might never be marked, so
|
||||
* a GC hazard would exist.
|
||||
* danger if we purge later is that the snapshot invariant of incremental GC
|
||||
* will be broken, as follows. If some object is reachable only through some
|
||||
* cache (say the dtoaCache) then it will not be part of the snapshot. If
|
||||
* we purge after root marking, then the mutator could obtain a pointer to
|
||||
* the object and start using it. This object might never be marked, so a GC
|
||||
* hazard would exist.
|
||||
*/
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_PURGE);
|
||||
purgeRuntime(lock);
|
||||
}
|
||||
purgeRuntime(lock);
|
||||
|
||||
/*
|
||||
* Mark phase.
|
||||
*/
|
||||
gcstats::AutoPhase ap1(stats, gcstats::PHASE_MARK);
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_UNMARK);
|
||||
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
/* Unmark everything in the zones being collected. */
|
||||
zone->arenas.unmarkAll();
|
||||
}
|
||||
|
||||
for (GCZonesIter zone(rt); !zone.done(); zone.next()) {
|
||||
/* Unmark all weak maps in the zones being collected. */
|
||||
WeakMapBase::unmarkZone(zone);
|
||||
}
|
||||
}
|
||||
|
||||
UnmarkCollectedZones(rt);
|
||||
traceRuntimeForMajorGC(gcmarker, lock);
|
||||
|
||||
gcstats::AutoPhase ap2(stats, gcstats::PHASE_MARK_ROOTS);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue