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:
Terrence Cole 2016-07-25 11:10:15 -07:00
parent 5c68ffe2b9
commit baaf9059ef
13 changed files with 122 additions and 139 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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
}

View File

@ -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)

View File

@ -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);

View File

@ -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");

View File

@ -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.

View File

@ -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);
}

View File

@ -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");

View File

@ -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());

View File

@ -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

View File

@ -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
};
/*

View File

@ -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);
}