diff options
Diffstat (limited to 'js/src/jit-test/tests/gc/compartment-revived-gc.js')
-rw-r--r-- | js/src/jit-test/tests/gc/compartment-revived-gc.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/gc/compartment-revived-gc.js b/js/src/jit-test/tests/gc/compartment-revived-gc.js new file mode 100644 index 0000000000..881f4a622a --- /dev/null +++ b/js/src/jit-test/tests/gc/compartment-revived-gc.js @@ -0,0 +1,133 @@ +// Test 'compartment revived' GCs, where we do an extra GC if there are +// compartments which we expected to die but were kept alive. + +// A global used as the destination for transplants. +let transplantTargetGlobal = newGlobal(); + +function didCompartmentRevivedGC() { + return performance.mozMemory.gc.lastStartReason === "COMPARTMENT_REVIVED"; +} + +function compartmentCount() { + let r = performance.mozMemory.gc.compartmentCount; + return r; +} + +function startIncrementalGC() { + startgc(1); + while (gcstate() === "Prepare") { + gcslice(100, {dontStart: true}); + } + assertEq(gcstate(), "Mark"); +} + +function finishIncrementalGC() { + while (gcstate() !== "NotActive") { + gcslice(100, {dontStart: true}); + } + assertEq(gcstate(), "NotActive"); +} + +// Create a new compartment and global and return the global. +function createCompartment() { + return newGlobal({newCompartment: true}); +} + +// Create a transplantable object and create a wrapper to it from a new +// compartment. Return a function to transplant the target object. +function createTransplantableWrapperTarget(wrapperGlobal) { + let {object: target, transplant} = transplantableObject(); + wrapperGlobal.wrapper = target; + return transplant; +} + +// Transplant an object to a new global by calling the transplant +// function. This remaps all wrappers pointing to the target object, +// potentially keeping dead compartments alive. +function transplantTargetAndRemapWrappers(transplant) { + transplant(transplantTargetGlobal); +} + +// Test no compartment revived GC triggered in normal cases. +function testNormal() { + gc(); + assertEq(didCompartmentRevivedGC(), false); + + startIncrementalGC(); + finishIncrementalGC(); + assertEq(didCompartmentRevivedGC(), false); + + let initialCount = compartmentCount(); + createCompartment(); + startIncrementalGC(); + finishIncrementalGC(); + assertEq(compartmentCount(), initialCount); +} + +// Test compartment revived GC is triggered by wrapper remapping. +function testCompartmentRevived1() { + let initialCount = compartmentCount(); + let compartment = createCompartment(); + let transplant = createTransplantableWrapperTarget(compartment); + compartment = null; + + startIncrementalGC(); + transplantTargetAndRemapWrappers(transplant); + finishIncrementalGC(); + + assertEq(didCompartmentRevivedGC(), true); + assertEq(compartmentCount(), initialCount); +} + +// Test no compartment revived GC is triggered for compartments transitively +// kept alive by black roots. +function testCompartmentRevived2() { + let initialCount = compartmentCount(); + let compartment = createCompartment(); + let transplant = createTransplantableWrapperTarget(compartment); + let liveCompartment = createCompartment(); + liveCompartment.wrapper = compartment; + compartment = null; + + startIncrementalGC(); + transplantTargetAndRemapWrappers(transplant); + finishIncrementalGC(); + + assertEq(didCompartmentRevivedGC(), false); + assertEq(compartmentCount(), initialCount + 2); + + liveCompartment = null; + gc(); + + assertEq(compartmentCount(), initialCount); +} + +// Test no compartment revived GC is triggered for compartments transitively +// kept alive by gray roots. +function testCompartmentRevived3() { + let initialCount = compartmentCount(); + let compartment = createCompartment(); + let transplant = createTransplantableWrapperTarget(compartment); + let liveCompartment = createCompartment(); + liveCompartment.wrapper = compartment; + liveCompartment.eval('grayRoot()[0] = this'); + liveCompartment = null; + gc(); + + startIncrementalGC(); + transplantTargetAndRemapWrappers(transplant); + finishIncrementalGC(); + + assertEq(didCompartmentRevivedGC(), false); + assertEq(compartmentCount(), initialCount + 2); + + // There's no easy way to clear gray roots for a compartment we don't have + // any reference to. +} + +gczeal(0); + +testNormal(); +testCompartmentRevived1(); +testCompartmentRevived2(); +testCompartmentRevived3(); |