Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| --no-ion; --no-baseline; --no-blinterp; skip-if: !hasFunction.gczeal || !hasFunction.oomAtAllocation
// Gray unmarking can run out of memory after a zone has finished marking in an
// incremental GC. Finishing that GC must not make the incomplete graph valid.
gczeal(0);
(function() {
const root = grayRoot();
const child = {deep: {x: 123}};
root[0] = child;
addMarkObservers([root, child, child.deep]);
})();
gc();
assertEq(grayBitsValid(), true);
assertEq(getMarks().join(","), "gray,gray,gray");
// Yield before sweeping objects, after this zone's marking has finished.
gczeal(21, 0);
startgc(1);
while (gcstate(this) !== "Sweep") {
assertEq(gcstate(), "Sweep");
gcslice(1);
}
assertEq(gcstate(), "Sweep");
assertEq(getMarks().join(","), "gray,gray,gray");
// Fail the first allocation of the gray unmarking stack. The root is marked
// black, but its children remain gray.
oomAtAllocation(1);
let exposed = grayRoot();
assertEq(resetOOMFailure(), true);
assertEq(grayBitsValid(), false);
assertEq(getMarks().join(","), "black,gray,gray");
finishgc();
assertEq(gcstate(), "NotActive");
assertEq(grayBitsValid(), false);
assertEq(getMarks().join(","), "black,gray,gray");
// A subsequent full GC must still be able to restore validity.
gczeal(0);
gc();
assertEq(grayBitsValid(), true);
assertEq(getMarks().join(","), "black,black,black");