// |jit-test| skip-if: !hasFunction["gczeal"] // Check zeal modes trigger GC as expected. // JIT compiled allocations don't trigger GC zeal. const jitCompilerOptions = getJitCompilerOptions(); if (jitCompilerOptions["blinterp.warmup.trigger"] === 0 || jitCompilerOptions["baseline.warmup.trigger"] === 0 || jitCompilerOptions["ion.warmup.trigger"] === 0) { quit(); } gczeal(0); gcparam('minNurseryBytes', 1024 * 1024); gcparam('maxNurseryBytes', 1024 * 1024); gc(); function checkGCsWithZeal(mode, freq, allocCount, expectedCounts) { let counts = countGCsWithZeal(mode, freq, allocCount); print(`checkGCsWithZeal ${mode} ${freq} ${allocCount}: ${JSON.stringify(expectedCounts)}`) print(` got ${JSON.stringify(counts)}`); for (const name in expectedCounts) { assertEq(counts[name], expectedCounts[name], name); } } function countGCsWithZeal(mode, freq, allocCount) { gc(); gczeal(mode, freq); const counts = countGCs(allocCount); gczeal(0); return counts; } function countGCs(allocCount) { const init = { minor: gcparam("minorGCNumber"), major: gcparam("majorGCNumber"), slice: gcparam("sliceNumber") } for (let i = 0; i < allocCount - 1 ; i++) { let o = {x: i}; } finishgc(); return { minor: gcparam("minorGCNumber") - init.minor, major: gcparam("majorGCNumber") - init.major, slice: gcparam("sliceNumber") - init.slice } } // 0: (None) Normal amount of collection (resets all modes) // // This also delazifies the test scripts which can otherwise allocate and // confuse the measurements. checkGCsWithZeal(0, 0, 100, {major: 0, minor: 0, slice: 0}); // 1: (RootsChange) Collect when roots are added or removed checkGCsWithZeal(1, 0, 100, {major: 0, minor: 0, slice: 0}); // 2: (Alloc) Collect when every N allocations (default: 100) checkGCsWithZeal(2, 10, 100, {major: 10, minor: 10, slice: 10}); checkGCsWithZeal(2, 20, 100, {major: 5, minor: 5, slice: 5}); // 4: (VerifierPre) Verify pre write barriers between instructions // This may trigger minor GCs because the pre barrier verifer disables and // reenables generational GC every time it runs. checkGCsWithZeal(4, 10, 100, {major: 0, slice: 0}); // 6: (YieldBeforeRootMarking) Incremental GC in two slice that yields before root marking checkGCsWithZeal(6, 10, 100, {major: 5, minor: 5, slice: 10}); // 7: (GenerationalGC) Collect the nursery every N nursery allocations checkGCsWithZeal(7, 10, 100, {major: 0, minor: 10, slice: 0}); // 8: (YieldBeforeMarking) Incremental GC in two slices that yields between // the root marking and marking phases checkGCsWithZeal(8, 10, 100, {major: 5, minor: 5, slice: 10}); // 9: (YieldBeforeSweeping) Incremental GC in two slices that yields between // the marking and sweeping phases checkGCsWithZeal(9, 10, 100, {major: 5, minor: 5, slice: 10}); // 10: (IncrementalMultipleSlices) Incremental GC in many slices // // This produces non-deterministic results as we poll for background // finalization to finish. The work budget is ignored for this phase. let counts = countGCsWithZeal(10, 10, 1000); print(`check IncrementalMultipleSlices mode: got ${JSON.stringify(counts)}`); assertEq(counts.major >= 1, true); assertEq(counts.minor >= 1, true); assertEq(counts.slice >= 70, true); // 11: (IncrementalMarkingValidator) Verify incremental marking checkGCsWithZeal(11, 0, 100, {major: 0, minor: 0, slice: 0}); // 12: (ElementsBarrier) Use the individual element post-write barrier // regardless of elements size checkGCsWithZeal(12, 0, 100, {major: 0, minor: 0, slice: 0}); // 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC checkGCsWithZeal(13, 0, 100, {major: 0, minor: 0, slice: 0}); // 14: (Compact) Perform a shrinking collection every N allocations checkGCsWithZeal(14, 10, 100, {major: 10, minor: 10, slice: 10}); // 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC checkGCsWithZeal(15, 0, 100, {major: 0, minor: 0, slice: 0}); // 17: (YieldBeforeSweepingAtoms) Incremental GC in two slices that yields // before sweeping the atoms table checkGCsWithZeal(17, 10, 100, {major: 5, minor: 5, slice: 10}); // 18: (CheckGrayMarking) Check gray marking invariants after every GC checkGCsWithZeal(18, 0, 100, {major: 0, minor: 0, slice: 0}); // 19: (YieldBeforeSweepingCaches) Incremental GC in two slices that yields // before sweeping weak caches checkGCsWithZeal(19, 10, 100, {major: 5, minor: 5, slice: 10}); // 21: (YieldBeforeSweepingObjects) Incremental GC in multiple slices that // yields before sweeping foreground finalized objects checkGCsWithZeal(21, 10, 120, {major: 4, minor: 4, slice: 12}); // 22: (YieldBeforeSweepingNonObjects) Incremental GC in multiple slices // that yields before sweeping non-object GC things checkGCsWithZeal(22, 10, 120, {major: 4, minor: 4, slice: 12}); // 23: (YieldBeforeSweepingPropMapTrees) Incremental GC in multiple slices // that yields before sweeping shape trees checkGCsWithZeal(23, 10, 120, {major: 4, minor: 4, slice: 12}); // 24: (CheckWeakMapMarking) Check weak map marking invariants after every // GC checkGCsWithZeal(24, 0, 100, {major: 0, minor: 0, slice: 0}); // 25: (YieldWhileGrayMarking) Incremental GC in two slices that yields // during gray marking checkGCsWithZeal(25, 10, 100, {major: 5, minor: 5, slice: 10}); // 26: (CheckHeapBeforeMinorGC) Check for invariant violations before every // minor GC checkGCsWithZeal(26, 0, 100, {major: 0, minor: 0, slice: 0});