diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index 1e4b4212447..6c666f17ec0 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -1037,8 +1037,16 @@ class GCRuntime }; GrayBufferState grayBufferState; bool hasBufferedGrayRoots() const { return grayBufferState == GrayBufferState::Okay; } + + // Clear each zone's gray buffers, but do not change the current state. void resetBufferedGrayRoots() const; + // Reset the gray buffering state to Unused. + void clearBufferedGrayRoots() { + grayBufferState = GrayBufferState::Unused; + resetBufferedGrayRoots(); + } + /* * The gray bits can become invalid if UnmarkGray overflows the stack. A * full GC will reset this bit, since it fills in all the gray bits. diff --git a/js/src/gc/Tracer.cpp b/js/src/gc/Tracer.cpp index ffa699d984f..c8f64cfc1d2 100644 --- a/js/src/gc/Tracer.cpp +++ b/js/src/gc/Tracer.cpp @@ -554,9 +554,6 @@ GCMarker::stop() /* Free non-ballast stack memory. */ stack.reset(); - - runtime()->gc.resetBufferedGrayRoots(); - runtime()->gc.grayBufferState = GCRuntime::GrayBufferState::Unused; } void @@ -650,6 +647,8 @@ GCMarker::checkZone(void *p) void GCRuntime::resetBufferedGrayRoots() const { + MOZ_ASSERT(grayBufferState != GrayBufferState::Okay, + "Do not clear the gray buffers unless we are Failed or becoming Unused"); for (GCZonesIter zone(rt); !zone.done(); zone.next()) zone->gcGrayRoots.clearAndFree(); } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 946002c1050..486a9dd0e78 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -5373,6 +5373,7 @@ GCRuntime::finishCollection(JS::gcreason::Reason reason) { MOZ_ASSERT(marker.isDrained()); marker.stop(); + clearBufferedGrayRoots(); uint64_t currentTime = PRMJ_Now(); schedulingState.updateHighFrequencyMode(lastGCTime, currentTime, tunables); @@ -5496,6 +5497,7 @@ GCRuntime::resetIncrementalGC(const char *reason) marker.reset(); marker.stop(); + clearBufferedGrayRoots(); for (GCCompartmentsIter c(rt); !c.done(); c.next()) ResetGrayList(c);