tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 12bf2b1c5311094236999130012b1d1b6e3846f9
parent 0c8cb1c7fba82367dd0611d62fc2d0ed7e446ef3
Author: pstanciu <pstanciu@mozilla.com>
Date:   Thu, 30 Oct 2025 13:02:15 +0200

Revert "Bug 1997118 - Mark gray bits as invalid if we abort GC during marking r=sfink" for causing assertion failure in Bug 1997268

This reverts commit 7a852d3774bf3ab127c44b5a4859326450100d78.

Diffstat:
Mjs/src/builtin/TestingFunctions.cpp | 10----------
Mjs/src/gc/GC.cpp | 5-----
Mjs/src/gc/Marking.cpp | 8++------
Djs/src/jit-test/tests/gc/gray-unmarking.js | 89-------------------------------------------------------------------------------
Mxpcom/base/nsCycleCollector.cpp | 3+--
5 files changed, 3 insertions(+), 112 deletions(-)

diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp @@ -3264,12 +3264,6 @@ static bool NondeterministicGetWeakMapKeys(JSContext* cx, unsigned argc, return true; } -static bool GrayBitsValid(JSContext* cx, unsigned argc, Value* vp) { - CallArgs args = CallArgsFromVp(argc, vp); - args.rval().setBoolean(cx->runtime()->gc.areGrayBitsValid()); - return true; -} - static bool SetGrayBitsInvalid(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); cx->runtime()->gc.setGrayBitsInvalid(); @@ -10413,10 +10407,6 @@ gc::ZealModeHelpText), "nondeterministicGetWeakMapKeys(weakmap)", " Return an array of the keys in the given WeakMap."), - JS_FN_HELP("grayBitsValid", GrayBitsValid, 0, 0, -"grayBitsValid()", -" Return whether the gray bits state is valid."), - JS_FN_HELP("setGrayBitsInvalid", SetGrayBitsInvalid, 0, 0, "setGrayBitsInvalid()", " Set the gray bits state to invalid."), diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp @@ -3803,11 +3803,6 @@ GCRuntime::IncrementalResult GCRuntime::resetIncrementalGC( resetGrayList(c); } - // The gray marking state may not be valid. We depend on the mark stack to - // do gray unmarking in zones that are being marked by the GC and we've - // just cancelled that part way through. - setGrayBitsInvalid(); - // Wait for sweeping of nursery owned sized allocations to finish. nursery().joinSweepTask(); diff --git a/js/src/gc/Marking.cpp b/js/src/gc/Marking.cpp @@ -2929,11 +2929,6 @@ void UnmarkGrayTracer::onChild(JS::GCCellPtr thing, const char* name) { void UnmarkGrayTracer::unmark(JS::GCCellPtr cell) { MOZ_ASSERT(stack.empty()); - GCRuntime* gc = &runtime()->gc; - if (!gc->areGrayBitsValid()) { - return; - } - onChild(cell, "unmarking root"); while (!stack.empty() && !oom) { @@ -2944,7 +2939,8 @@ void UnmarkGrayTracer::unmark(JS::GCCellPtr cell) { // If we run out of memory, we take a drastic measure: require that we // GC again before the next CC. stack.clear(); - gc->setGrayBitsInvalid(); + runtime()->gc.setGrayBitsInvalid(); + return; } } diff --git a/js/src/jit-test/tests/gc/gray-unmarking.js b/js/src/jit-test/tests/gc/gray-unmarking.js @@ -1,89 +0,0 @@ -// Test interaction of gray marking / cross zone pointers / aborted GC marking. - -gczeal(0); - -gc(); -assertEq(grayBitsValid(), true); - -// Create some globals in different zones. -let g1 = newGlobal({newCompartment: true}); -let g2 = newGlobal({newCompartment: true}); -let g3 = newGlobal({newCompartment: true}); - -// Set up a linked list of objects in different zones: a --> b --> c -g1.eval('var a = {}'); -g2.eval('var b = {}'); -g3.eval('var c = {}'); -g1.a.next = g2.b; -g2.b.next = g3.c; - -// Observe mark state of the objects and remove extra references from the globals. -g1.eval('addMarkObservers([a])'); -g2.eval('addMarkObservers([b])'); -g3.eval('addMarkObservers([c])'); -g2.b = undefined; -g3.c = undefined; - -function checkMarks(a, b, c) { - assertEq(getMarks().join(", "), [a, b, c].join(", ")); -} - -// Check GC initially marks everything black. -gc(); -checkMarks("black", "black", "black"); - -// Replace root with a gray one and check GC marks everything gray. -g1.eval('grayRoot()[0] = a'); -g1.a = undefined; -gc(); -checkMarks("gray", "gray", "gray"); - -// Read the gray root and check gray unmarking marks everything black again. -g1.eval('grayRoot()[0]'); -checkMarks("black", "black", "black"); - -// Reset everything to gray. -gc(); -checkMarks("gray", "gray", "gray"); - -// Start marking zone 2. -schedulezone(g2); -startgc(10); -while (gcstate() === "Prepare" || gcstate() === "MarkRoots") { - gcslice(10); -} -assertEq(gcstate(), "Mark"); -assertEq(gcstate(g1), "NoGC"); -assertEq(gcstate(g2), "MarkBlackOnly"); -assertEq(gcstate(g3), "NoGC"); - -// Check zone 2's mark bits have been cleared. -checkMarks("gray", "unmarked", "gray"); - -// Gray unmarking stops at the zone that is being mraked -g1.eval('grayRoot()[0]'); -checkMarks("black", "black", "gray"); - -// GC marking handles the gray unmarking by propagaing b's mark state. -finishgc(); -assertEq(grayBitsValid(), true); -checkMarks("black", "black", "black"); - -// Reset everything to gray. -gc(); -checkMarks("gray", "gray", "gray"); - -// Repeat the previous test but abort marking after unmarking a. c is -// left as 'gray' (incorrect) but the gray marking state is marked as invalid. -schedulezone(g2); -startgc(10); -while (gcstate() === "Prepare" || gcstate() === "MarkRoots") { - gcslice(10); -} -assertEq(gcstate(), "Mark"); -checkMarks("gray", "unmarked", "gray"); -g1.eval('grayRoot()[0]'); -assertEq(grayBitsValid(), true); -abortgc(); -assertEq(grayBitsValid(), false); -checkMarks("black", "black", "gray"); diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp @@ -3470,8 +3470,7 @@ static void SendNeedGCTelemetry(bool needGC) { // reachable only from XPConnect roots that might participate in cycles. // // That data might not currently be valid, requiring a GC to restore it. This is -// rare in practice and is caused by an OOM during gray unmarking or aborting GC -// part way through marking. +// rare in practice and is caused by an OOM during gray unmarking. // // We also force GCs on shutdown to collect cycles involving both DOM and JS, // and in WantAllTraces CCs to prevent hijinks from ForgetSkippable and