mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Bug 1288793 - Part 1: Convert js::gc::State to an enum class; r=jonco
* * * Bug _ - Add a test to ensure that abort works during decommit slices; NOT_REVIEWED --HG-- extra : rebase_source : b606dd26b62301f16079aae0e0085d86be502169
This commit is contained in:
parent
5c68ffe2b9
commit
baaf9059ef
@ -864,23 +864,7 @@ GCState(JSContext* cx, unsigned argc, Value* vp)
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* state;
|
||||
gc::State globalState = cx->runtime()->gc.state();
|
||||
if (globalState == gc::NO_INCREMENTAL)
|
||||
state = "none";
|
||||
else if (globalState == gc::MARK)
|
||||
state = "mark";
|
||||
else if (globalState == gc::SWEEP)
|
||||
state = "sweep";
|
||||
else if (globalState == gc::FINALIZE)
|
||||
state = "finalize";
|
||||
else if (globalState == gc::COMPACT)
|
||||
state = "compact";
|
||||
else if (globalState == gc::DECOMMIT)
|
||||
state = "decommit";
|
||||
else
|
||||
MOZ_CRASH("Unobserveable global GC state");
|
||||
|
||||
const char* state = StateName(cx->runtime()->gc.state());
|
||||
JSString* str = JS_NewStringCopyZ(cx, state);
|
||||
if (!str)
|
||||
return false;
|
||||
|
@ -689,8 +689,8 @@ class GCRuntime
|
||||
public:
|
||||
// Internal public interface
|
||||
State state() const { return incrementalState; }
|
||||
bool isHeapCompacting() const { return state() == COMPACT; }
|
||||
bool isForegroundSweeping() const { return state() == SWEEP; }
|
||||
bool isHeapCompacting() const { return state() == State::Compact; }
|
||||
bool isForegroundSweeping() const { return state() == State::Sweep; }
|
||||
bool isBackgroundSweeping() { return helperState.isBackgroundSweeping(); }
|
||||
void waitBackgroundSweepEnd() { helperState.waitBackgroundSweepEnd(); }
|
||||
void waitBackgroundSweepOrAllocEnd() {
|
||||
@ -766,7 +766,7 @@ class GCRuntime
|
||||
void disallowIncrementalGC() { incrementalAllowed = false; }
|
||||
|
||||
bool isIncrementalGCEnabled() const { return mode == JSGC_MODE_INCREMENTAL && incrementalAllowed; }
|
||||
bool isIncrementalGCInProgress() const { return state() != NO_INCREMENTAL; }
|
||||
bool isIncrementalGCInProgress() const { return state() != State::NotActive; }
|
||||
|
||||
bool isGenerationalGCEnabled() const { return generationalDisabled == 0; }
|
||||
void disableGenerationalGC();
|
||||
|
@ -346,8 +346,8 @@ static void
|
||||
AssertRootMarkingPhase(JSTracer* trc)
|
||||
{
|
||||
MOZ_ASSERT_IF(trc->isMarkingTracer(),
|
||||
trc->runtime()->gc.state() == NO_INCREMENTAL ||
|
||||
trc->runtime()->gc.state() == MARK_ROOTS);
|
||||
trc->runtime()->gc.state() == State::NotActive ||
|
||||
trc->runtime()->gc.state() == State::MarkRoots);
|
||||
}
|
||||
|
||||
|
||||
@ -1945,7 +1945,7 @@ bool
|
||||
GCMarker::markDelayedChildren(SliceBudget& budget)
|
||||
{
|
||||
GCRuntime& gc = runtime()->gc;
|
||||
gcstats::AutoPhase ap(gc.stats, gc.state() == MARK, gcstats::PHASE_MARK_DELAYED);
|
||||
gcstats::AutoPhase ap(gc.stats, gc.state() == State::Mark, gcstats::PHASE_MARK_DELAYED);
|
||||
|
||||
MOZ_ASSERT(unmarkedArenaStackTop);
|
||||
do {
|
||||
@ -2439,7 +2439,7 @@ CheckIsMarkedThing(T* thingp)
|
||||
JSRuntime* rt = (*thingp)->runtimeFromAnyThread();
|
||||
MOZ_ASSERT_IF(!ThingIsPermanentAtomOrWellKnownSymbol(*thingp),
|
||||
CurrentThreadCanAccessRuntime(rt) ||
|
||||
(rt->isHeapCollecting() && rt->gc.state() == SWEEP));
|
||||
(rt->isHeapCollecting() && rt->gc.state() == State::Sweep));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ struct Statistics
|
||||
double startTimestamp, size_t startFaults, gc::State initialState)
|
||||
: budget(budget), reason(reason),
|
||||
initialState(initialState),
|
||||
finalState(gc::NO_INCREMENTAL),
|
||||
finalState(gc::State::NotActive),
|
||||
resetReason(nullptr),
|
||||
start(start), startTimestamp(startTimestamp),
|
||||
startFaults(startFaults)
|
||||
|
@ -203,7 +203,7 @@ gc::GCRuntime::startVerifyPreBarriers()
|
||||
/* Create the root node. */
|
||||
trc->curnode = MakeNode(trc, nullptr, JS::TraceKind(0));
|
||||
|
||||
incrementalState = MARK_ROOTS;
|
||||
incrementalState = State::MarkRoots;
|
||||
|
||||
/* Make all the roots be edges emanating from the root node. */
|
||||
markRuntime(trc, TraceRuntime, prep.session().lock);
|
||||
@ -230,7 +230,7 @@ gc::GCRuntime::startVerifyPreBarriers()
|
||||
}
|
||||
|
||||
verifyPreData = trc;
|
||||
incrementalState = MARK;
|
||||
incrementalState = State::Mark;
|
||||
marker.start();
|
||||
|
||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||
@ -244,7 +244,7 @@ gc::GCRuntime::startVerifyPreBarriers()
|
||||
return;
|
||||
|
||||
oom:
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
incrementalState = State::NotActive;
|
||||
js_delete(trc);
|
||||
verifyPreData = nullptr;
|
||||
}
|
||||
@ -342,7 +342,7 @@ gc::GCRuntime::endVerifyPreBarriers()
|
||||
number++;
|
||||
|
||||
verifyPreData = nullptr;
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
incrementalState = State::NotActive;
|
||||
|
||||
if (!compartmentCreated && IsIncrementalGCSafe(rt)) {
|
||||
CheckEdgeTracer cetrc(rt);
|
||||
|
@ -17,12 +17,12 @@ var g = newGlobal();
|
||||
|
||||
// Start an off thread compilation that will not run until GC has finished
|
||||
if ("gcstate" in this)
|
||||
assertEq(gcstate(), "mark");
|
||||
assertEq(gcstate(), "Mark");
|
||||
g.offThreadCompileScript('23;', {});
|
||||
|
||||
// Wait for the compilation to finish, which must finish the GC first
|
||||
assertEq(23, g.runOffThreadScript());
|
||||
if ("gcstate" in this)
|
||||
assertEq(gcstate(), "none");
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
print("done");
|
||||
|
@ -27,7 +27,7 @@ function testAbort(zoneCount, objectCount, sliceCount, abortState)
|
||||
|
||||
var didAbort = false;
|
||||
startgc(sliceCount, "shrinking");
|
||||
while (gcstate() !== "none") {
|
||||
while (gcstate() !== "NotActive") {
|
||||
var state = gcstate();
|
||||
if (state == abortState) {
|
||||
abortgc();
|
||||
@ -38,7 +38,7 @@ function testAbort(zoneCount, objectCount, sliceCount, abortState)
|
||||
gcslice(sliceCount);
|
||||
}
|
||||
|
||||
assertEq(gcstate(), "none");
|
||||
assertEq(gcstate(), "NotActive");
|
||||
if (abortState)
|
||||
assertEq(didAbort, true);
|
||||
|
||||
@ -47,6 +47,8 @@ function testAbort(zoneCount, objectCount, sliceCount, abortState)
|
||||
|
||||
gczeal(0);
|
||||
testAbort(10, 10000, 10000);
|
||||
testAbort(10, 10000, 10000, "mark");
|
||||
testAbort(10, 10000, 10000, "sweep");
|
||||
testAbort(10, 10000, 10000, "compact");
|
||||
testAbort(10, 10000, 10000, "Mark");
|
||||
testAbort(10, 10000, 10000, "Sweep");
|
||||
testAbort(10, 10000, 10000, "Compact");
|
||||
// Note: we do not yield automatically before Finalize or Decommit, as they yield internally.
|
||||
// Thus, we may not witness an incremental state in this phase and cannot test it explicitly.
|
||||
|
@ -27,11 +27,11 @@ function testCompacting(zoneCount, objectCount, sliceCount)
|
||||
}
|
||||
|
||||
// Finish any alloc-triggered incremental GC
|
||||
if (gcstate() !== "none")
|
||||
if (gcstate() !== "NotActive")
|
||||
gc();
|
||||
|
||||
startgc(sliceCount, "shrinking");
|
||||
while (gcstate() !== "none") {
|
||||
while (gcstate() !== "NotActive") {
|
||||
gcslice(sliceCount);
|
||||
}
|
||||
|
||||
|
@ -6,26 +6,26 @@ gczeal(0);
|
||||
|
||||
// Non-incremental GC.
|
||||
gc();
|
||||
assertEq(gcstate(), "none");
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
// Incremental GC in minimal slice. Note that finalization always uses zero-
|
||||
// sized slices while background finalization is on-going, so we need to loop.
|
||||
gcslice(1000000);
|
||||
while (gcstate() == "finalize") { gcslice(1); }
|
||||
while (gcstate() == "decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "none");
|
||||
while (gcstate() == "Finalize") { gcslice(1); }
|
||||
while (gcstate() == "Decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
// Incremental GC in multiple slices: if marking takes more than one slice,
|
||||
// we yield before we start sweeping.
|
||||
gczeal(0);
|
||||
gcslice(1);
|
||||
assertEq(gcstate(), "mark");
|
||||
assertEq(gcstate(), "Mark");
|
||||
gcslice(1000000);
|
||||
assertEq(gcstate(), "mark");
|
||||
assertEq(gcstate(), "Mark");
|
||||
gcslice(1000000);
|
||||
while (gcstate() == "finalize") { gcslice(1); }
|
||||
while (gcstate() == "decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "none");
|
||||
while (gcstate() == "Finalize") { gcslice(1); }
|
||||
while (gcstate() == "Decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
// Zeal mode 8: Incremental GC in two main slices:
|
||||
// 1) mark roots
|
||||
@ -33,11 +33,11 @@ assertEq(gcstate(), "none");
|
||||
// *) finalize.
|
||||
gczeal(8, 0);
|
||||
gcslice(1);
|
||||
assertEq(gcstate(), "mark");
|
||||
assertEq(gcstate(), "Mark");
|
||||
gcslice(1);
|
||||
while (gcstate() == "finalize") { gcslice(1); }
|
||||
while (gcstate() == "decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "none");
|
||||
while (gcstate() == "Finalize") { gcslice(1); }
|
||||
while (gcstate() == "Decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
// Zeal mode 9: Incremental GC in two main slices:
|
||||
// 1) mark roots and marking
|
||||
@ -45,19 +45,19 @@ assertEq(gcstate(), "none");
|
||||
// *) finalize.
|
||||
gczeal(9, 0);
|
||||
gcslice(1);
|
||||
assertEq(gcstate(), "mark");
|
||||
assertEq(gcstate(), "Mark");
|
||||
gcslice(1);
|
||||
while (gcstate() == "finalize") { gcslice(1); }
|
||||
while (gcstate() == "decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "none");
|
||||
while (gcstate() == "Finalize") { gcslice(1); }
|
||||
while (gcstate() == "Decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
||||
// Zeal mode 10: Incremental GC in multiple slices (always yeilds before
|
||||
// sweeping). This test uses long slices to prove that this zeal mode yields
|
||||
// in sweeping, where normal IGC (above) does not.
|
||||
gczeal(10, 0);
|
||||
gcslice(1000000);
|
||||
assertEq(gcstate(), "sweep");
|
||||
assertEq(gcstate(), "Sweep");
|
||||
gcslice(1000000);
|
||||
while (gcstate() == "finalize") { gcslice(1); }
|
||||
while (gcstate() == "decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "none");
|
||||
while (gcstate() == "Finalize") { gcslice(1); }
|
||||
while (gcstate() == "Decommit") { gcslice(1); }
|
||||
assertEq(gcstate(), "NotActive");
|
||||
|
@ -103,7 +103,7 @@ BEGIN_TEST(testGCFinalizeCallback)
|
||||
JS::PrepareForFullGC(cx);
|
||||
js::SliceBudget budget(js::WorkBudget(1));
|
||||
cx->gc.startDebugGC(GC_NORMAL, budget);
|
||||
CHECK(cx->gc.state() == js::gc::MARK);
|
||||
CHECK(cx->gc.state() == js::gc::State::Mark);
|
||||
CHECK(cx->gc.isFullGc());
|
||||
|
||||
JS::RootedObject global4(cx, createTestGlobal());
|
||||
|
127
js/src/jsgc.cpp
127
js/src/jsgc.cpp
@ -53,46 +53,49 @@
|
||||
* The collector proceeds through the following states, the current state being
|
||||
* held in JSRuntime::gcIncrementalState:
|
||||
*
|
||||
* - MARK_ROOTS - marks the stack and other roots
|
||||
* - MARK - incrementally marks reachable things
|
||||
* - SWEEP - sweeps zones in groups and continues marking unswept zones
|
||||
* - MarkRoots - marks the stack and other roots
|
||||
* - Mark - incrementally marks reachable things
|
||||
* - Sweep - sweeps zones in groups and continues marking unswept zones
|
||||
* - Finalize - performs background finalization, concurrent with mutator
|
||||
* - Compact - incrementally compacts by zone
|
||||
* - Decommit - performs background decommit and chunk removal
|
||||
*
|
||||
* The MARK_ROOTS activity always takes place in the first slice. The next two
|
||||
* The MarkRoots activity always takes place in the first slice. The next two
|
||||
* states can take place over one or more slices.
|
||||
*
|
||||
* In other words an incremental collection proceeds like this:
|
||||
*
|
||||
* Slice 1: MARK_ROOTS: Roots pushed onto the mark stack.
|
||||
* MARK: The mark stack is processed by popping an element,
|
||||
* Slice 1: MarkRoots: Roots pushed onto the mark stack.
|
||||
* Mark: The mark stack is processed by popping an element,
|
||||
* marking it, and pushing its children.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice 2: MARK: More mark stack processing.
|
||||
* Slice 2: Mark: More mark stack processing.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice n-1: MARK: More mark stack processing.
|
||||
* Slice n-1: Mark: More mark stack processing.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice n: MARK: Mark stack is completely drained.
|
||||
* SWEEP: Select first group of zones to sweep and sweep them.
|
||||
* Slice n: Mark: Mark stack is completely drained.
|
||||
* Sweep: Select first group of zones to sweep and sweep them.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice n+1: SWEEP: Mark objects in unswept zones that were newly
|
||||
* Slice n+1: Sweep: Mark objects in unswept zones that were newly
|
||||
* identified as alive (see below). Then sweep more zone
|
||||
* groups.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice n+2: SWEEP: Mark objects in unswept zones that were newly
|
||||
* Slice n+2: Sweep: Mark objects in unswept zones that were newly
|
||||
* identified as alive. Then sweep more zone groups.
|
||||
*
|
||||
* ... JS code runs ...
|
||||
*
|
||||
* Slice m: SWEEP: Sweeping is finished, and background sweeping
|
||||
* Slice m: Sweep: Sweeping is finished, and background sweeping
|
||||
* started on the helper thread.
|
||||
*
|
||||
* ... JS code runs, remaining sweeping done on background thread ...
|
||||
@ -141,7 +144,7 @@
|
||||
*
|
||||
* The order of sweeping is restricted by cross compartment pointers - for
|
||||
* example say that object |a| from zone A points to object |b| in zone B and
|
||||
* neither object was marked when we transitioned to the SWEEP phase. Imagine we
|
||||
* neither object was marked when we transitioned to the Sweep phase. Imagine we
|
||||
* sweep B first and then return to the mutator. It's possible that the mutator
|
||||
* could cause |a| to become alive through a read barrier (perhaps it was a
|
||||
* shape that was accessed via a shape table). Then we would need to mark |b|,
|
||||
@ -822,7 +825,7 @@ GCRuntime::GCRuntime(JSRuntime* rt) :
|
||||
#ifdef DEBUG
|
||||
disableStrictProxyCheckingCount(0),
|
||||
#endif
|
||||
incrementalState(gc::NO_INCREMENTAL),
|
||||
incrementalState(gc::State::NotActive),
|
||||
lastMarkSlice(false),
|
||||
sweepOnBackgroundThread(false),
|
||||
foundBlackGrayEdges(false),
|
||||
@ -4176,7 +4179,7 @@ js::gc::MarkingValidator::nonIncrementalMark(AutoLockForExclusiveAccess& lock)
|
||||
|
||||
/* Re-do all the marking, but non-incrementally. */
|
||||
js::gc::State state = gc->incrementalState;
|
||||
gc->incrementalState = MARK_ROOTS;
|
||||
gc->incrementalState = State::MarkRoots;
|
||||
|
||||
{
|
||||
gcstats::AutoPhase ap(gc->stats, gcstats::PHASE_MARK);
|
||||
@ -4196,12 +4199,12 @@ js::gc::MarkingValidator::nonIncrementalMark(AutoLockForExclusiveAccess& lock)
|
||||
|
||||
gc->markRuntime(gcmarker, GCRuntime::MarkRuntime, lock);
|
||||
|
||||
gc->incrementalState = MARK;
|
||||
gc->incrementalState = State::Mark;
|
||||
auto unlimited = SliceBudget::unlimited();
|
||||
MOZ_RELEASE_ASSERT(gc->marker.drainMarkStack(unlimited));
|
||||
}
|
||||
|
||||
gc->incrementalState = SWEEP;
|
||||
gc->incrementalState = State::Sweep;
|
||||
{
|
||||
gcstats::AutoPhase ap1(gc->stats, gcstats::PHASE_SWEEP);
|
||||
gcstats::AutoPhase ap2(gc->stats, gcstats::PHASE_SWEEP_MARK);
|
||||
@ -5621,10 +5624,14 @@ void
|
||||
GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lock)
|
||||
{
|
||||
switch (incrementalState) {
|
||||
case NO_INCREMENTAL:
|
||||
case State::NotActive:
|
||||
return;
|
||||
|
||||
case MARK: {
|
||||
case State::MarkRoots:
|
||||
MOZ_CRASH("resetIncrementalGC did not expect MarkRoots state");
|
||||
break;
|
||||
|
||||
case State::Mark: {
|
||||
/* Cancel any ongoing marking. */
|
||||
marker.reset();
|
||||
marker.stop();
|
||||
@ -5641,14 +5648,14 @@ GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lo
|
||||
|
||||
blocksToFreeAfterSweeping.freeAll();
|
||||
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
incrementalState = State::NotActive;
|
||||
|
||||
MOZ_ASSERT(!marker.shouldCheckCompartments());
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SWEEP: {
|
||||
case State::Sweep: {
|
||||
marker.reset();
|
||||
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||
@ -5673,7 +5680,7 @@ GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lo
|
||||
break;
|
||||
}
|
||||
|
||||
case FINALIZE: {
|
||||
case State::Finalize: {
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
|
||||
rt->gc.waitBackgroundSweepOrAllocEnd();
|
||||
@ -5690,7 +5697,7 @@ GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lo
|
||||
break;
|
||||
}
|
||||
|
||||
case COMPACT: {
|
||||
case State::Compact: {
|
||||
bool wasCompacting = isCompacting;
|
||||
|
||||
isCompacting = true;
|
||||
@ -5704,14 +5711,11 @@ GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lo
|
||||
break;
|
||||
}
|
||||
|
||||
case DECOMMIT: {
|
||||
case State::Decommit: {
|
||||
auto unlimited = SliceBudget::unlimited();
|
||||
incrementalCollectSlice(unlimited, JS::gcreason::RESET, lock);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Invalid incremental GC state");
|
||||
}
|
||||
|
||||
stats.reset(reason);
|
||||
@ -5724,7 +5728,7 @@ GCRuntime::resetIncrementalGC(const char* reason, AutoLockForExclusiveAccess& lo
|
||||
MOZ_ASSERT(!zone->isOnList());
|
||||
}
|
||||
MOZ_ASSERT(zonesToMaybeCompact.isEmpty());
|
||||
MOZ_ASSERT(incrementalState == NO_INCREMENTAL);
|
||||
MOZ_ASSERT(incrementalState == State::NotActive);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -5843,33 +5847,33 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
}
|
||||
|
||||
switch (incrementalState) {
|
||||
case NO_INCREMENTAL:
|
||||
case State::NotActive:
|
||||
initialReason = reason;
|
||||
cleanUpEverything = ShouldCleanUpEverything(reason, invocationKind);
|
||||
isCompacting = shouldCompact();
|
||||
lastMarkSlice = false;
|
||||
|
||||
incrementalState = MARK_ROOTS;
|
||||
incrementalState = State::MarkRoots;
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case MARK_ROOTS:
|
||||
case State::MarkRoots:
|
||||
if (!beginMarkPhase(reason, lock)) {
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
incrementalState = State::NotActive;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!destroyingRuntime)
|
||||
pushZealSelectedObjects();
|
||||
|
||||
incrementalState = MARK;
|
||||
incrementalState = State::Mark;
|
||||
|
||||
if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))
|
||||
break;
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case MARK:
|
||||
case State::Mark:
|
||||
AutoGCRooter::traceAllWrappers(&marker);
|
||||
|
||||
/* If we needed delayed marking for gray roots, then collect until done. */
|
||||
@ -5884,19 +5888,19 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
MOZ_ASSERT(marker.isDrained());
|
||||
|
||||
if (!lastMarkSlice && isIncremental && useZeal &&
|
||||
((initialState == MARK && !hasZealMode(ZealMode::IncrementalRootsThenFinish)) ||
|
||||
((initialState == State::Mark && !hasZealMode(ZealMode::IncrementalRootsThenFinish)) ||
|
||||
hasZealMode(ZealMode::IncrementalMarkAllThenFinish)))
|
||||
{
|
||||
/*
|
||||
* Yield with the aim of starting the sweep in the next
|
||||
* slice. We will need to mark anything new on the stack
|
||||
* when we resume, so we stay in MARK state.
|
||||
* when we resume, so we stay in Mark state.
|
||||
*/
|
||||
lastMarkSlice = true;
|
||||
break;
|
||||
}
|
||||
|
||||
incrementalState = SWEEP;
|
||||
incrementalState = State::Sweep;
|
||||
|
||||
/*
|
||||
* This runs to completion, but we don't continue if the budget is
|
||||
@ -5915,13 +5919,13 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case SWEEP:
|
||||
case State::Sweep:
|
||||
if (sweepPhase(budget, lock) == NotFinished)
|
||||
break;
|
||||
|
||||
endSweepPhase(destroyingRuntime, lock);
|
||||
|
||||
incrementalState = FINALIZE;
|
||||
incrementalState = State::Finalize;
|
||||
|
||||
/* Yield before compacting since it is not incremental. */
|
||||
if (isCompacting && isIncremental)
|
||||
@ -5929,7 +5933,7 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case FINALIZE:
|
||||
case State::Finalize:
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
|
||||
|
||||
@ -5955,11 +5959,11 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!startedCompacting);
|
||||
incrementalState = COMPACT;
|
||||
incrementalState = State::Compact;
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case COMPACT:
|
||||
case State::Compact:
|
||||
if (isCompacting) {
|
||||
if (!startedCompacting)
|
||||
beginCompactPhase();
|
||||
@ -5971,11 +5975,11 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
}
|
||||
|
||||
startDecommit();
|
||||
incrementalState = DECOMMIT;
|
||||
incrementalState = State::Decommit;
|
||||
|
||||
MOZ_FALLTHROUGH;
|
||||
|
||||
case DECOMMIT:
|
||||
case State::Decommit:
|
||||
{
|
||||
gcstats::AutoPhase ap(stats, gcstats::PHASE_WAIT_BACKGROUND_THREAD);
|
||||
|
||||
@ -5987,11 +5991,8 @@ GCRuntime::incrementalCollectSlice(SliceBudget& budget, JS::gcreason::Reason rea
|
||||
}
|
||||
|
||||
finishCollection(reason);
|
||||
incrementalState = NO_INCREMENTAL;
|
||||
incrementalState = State::NotActive;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("unexpected GC incrementalState");
|
||||
}
|
||||
}
|
||||
|
||||
@ -6154,7 +6155,7 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
|
||||
}
|
||||
|
||||
/* The GC was reset, so we need a do-over. */
|
||||
if (prevState != NO_INCREMENTAL && !isIncrementalGCInProgress())
|
||||
if (prevState != State::NotActive && !isIncrementalGCInProgress())
|
||||
return true;
|
||||
|
||||
TraceMajorGCStart();
|
||||
@ -6361,7 +6362,7 @@ GCRuntime::finishGC(JS::gcreason::Reason reason)
|
||||
// compacting phase if we need to finish an ongoing incremental GC
|
||||
// non-incrementally to avoid janking the browser.
|
||||
if (!IsOOMReason(initialReason)) {
|
||||
if (incrementalState == COMPACT) {
|
||||
if (incrementalState == State::Compact) {
|
||||
abortGC();
|
||||
return;
|
||||
}
|
||||
@ -6799,8 +6800,8 @@ GCRuntime::runDebugGC()
|
||||
* or compact phases.
|
||||
*/
|
||||
if (hasZealMode(ZealMode::IncrementalMultipleSlices)) {
|
||||
if ((initialState == MARK && incrementalState == SWEEP) ||
|
||||
(initialState == SWEEP && incrementalState == COMPACT))
|
||||
if ((initialState == State::Mark && incrementalState == State::Sweep) ||
|
||||
(initialState == State::Sweep && incrementalState == State::Compact))
|
||||
{
|
||||
incrementalLimit = zealFrequency / 2;
|
||||
}
|
||||
@ -7313,7 +7314,7 @@ JS::IsIncrementalGCInProgress(JSContext* cx)
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::IsIncrementalBarrierNeeded(JSContext* cx)
|
||||
{
|
||||
return cx->gc.state() == gc::MARK && !cx->isHeapBusy();
|
||||
return cx->gc.state() == gc::State::Mark && !cx->isHeapBusy();
|
||||
}
|
||||
|
||||
struct IncrementalReferenceBarrierFunctor {
|
||||
@ -7596,18 +7597,12 @@ NewMemoryInfoObject(JSContext* cx)
|
||||
const char*
|
||||
StateName(State state)
|
||||
{
|
||||
static const char* names[] = {
|
||||
"None",
|
||||
"MarkRoots",
|
||||
"Mark",
|
||||
"Sweep",
|
||||
"Finalize",
|
||||
"Compact",
|
||||
"Decommit"
|
||||
};
|
||||
MOZ_ASSERT(ArrayLength(names) == NUM_STATES);
|
||||
MOZ_ASSERT(state < NUM_STATES);
|
||||
return names[state];
|
||||
switch(state) {
|
||||
#define MAKE_CASE(name) case State::name: return #name;
|
||||
GCSTATES(MAKE_CASE)
|
||||
#undef MAKE_CASE
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("invalide gc::State enum value");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -43,16 +43,18 @@ namespace gc {
|
||||
|
||||
struct FinalizePhase;
|
||||
|
||||
enum State {
|
||||
NO_INCREMENTAL,
|
||||
MARK_ROOTS,
|
||||
MARK,
|
||||
SWEEP,
|
||||
FINALIZE,
|
||||
COMPACT,
|
||||
DECOMMIT,
|
||||
|
||||
NUM_STATES
|
||||
#define GCSTATES(D) \
|
||||
D(NotActive) \
|
||||
D(MarkRoots) \
|
||||
D(Mark) \
|
||||
D(Sweep) \
|
||||
D(Finalize) \
|
||||
D(Compact) \
|
||||
D(Decommit)
|
||||
enum class State {
|
||||
#define MAKE_STATE(name) name,
|
||||
GCSTATES(MAKE_STATE)
|
||||
#undef MAKE_STATE
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -2829,12 +2829,12 @@ Debugger::markIncomingCrossCompartmentEdges(JSTracer* trc)
|
||||
{
|
||||
JSRuntime* rt = trc->runtime();
|
||||
gc::State state = rt->gc.state();
|
||||
MOZ_ASSERT(state == gc::MARK_ROOTS || state == gc::COMPACT);
|
||||
MOZ_ASSERT(state == gc::State::MarkRoots || state == gc::State::Compact);
|
||||
|
||||
for (Debugger* dbg : rt->debuggerList) {
|
||||
Zone* zone = MaybeForwarded(dbg->object.get())->zone();
|
||||
if ((state == gc::MARK_ROOTS && !zone->isCollecting()) ||
|
||||
(state == gc::COMPACT && !zone->isGCCompacting()))
|
||||
if ((state == gc::State::MarkRoots && !zone->isCollecting()) ||
|
||||
(state == gc::State::Compact && !zone->isGCCompacting()))
|
||||
{
|
||||
dbg->markCrossCompartmentEdges(trc);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user