diff --git a/dom/base/CCGCScheduler.h b/dom/base/CCGCScheduler.h index 09e992bce606..e61fbdc70e16 100644 --- a/dom/base/CCGCScheduler.h +++ b/dom/base/CCGCScheduler.h @@ -167,8 +167,14 @@ class CCGCScheduler { mNeedsGCAfterCC = true; } - void NoteReadyForMajorGC() { + // Returns false if we started and finished a major GC while waiting for a + // response. + [[nodiscard]] bool NoteReadyForMajorGC() { + if (mMajorGCReason == JS::GCReason::NO_REASON) { + return false; + } mReadyForMajorGC = true; + return true; } void NoteGCBegin() { @@ -681,6 +687,8 @@ CCRunnerStep CCGCScheduler::AdvanceCCRunner(TimeStamp aDeadline) { } GCRunnerStep CCGCScheduler::GetNextGCRunnerAction(TimeStamp aDeadline) { + MOZ_ASSERT(mMajorGCReason != JS::GCReason::NO_REASON); + if (InIncrementalGC()) { return {GCRunnerAction::GCSlice, mMajorGCReason}; } diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 3707c5b6bc63..f970e63171df 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1606,8 +1606,7 @@ bool GCRunnerFired(TimeStamp aDeadline, void* aClosure) { GCRunnerStep step = sScheduler.GetNextGCRunnerAction(aDeadline); switch (step.mAction) { case GCRunnerAction::None: - nsJSContext::KillGCRunner(); - return false; + MOZ_CRASH("Unexpected GCRunnerAction"); case GCRunnerAction::WaitToMajorGC: { RefPtr mbPromise = MayGCNow(step.mReason); @@ -1621,7 +1620,9 @@ bool GCRunnerFired(TimeStamp aDeadline, void* aClosure) { mbPromise->Then( GetMainThreadSerialEventTarget(), __func__, [](bool aIgnored) { - sScheduler.NoteReadyForMajorGC(); + if (!sScheduler.NoteReadyForMajorGC()) { + return; // Another GC completed while waiting. + } // If a new runner was started, recreate it with a 0 delay. The new // runner will continue in idle time. nsJSContext::KillGCRunner();