const gC = newGlobal({newCompartment: true}); // zone C: transplantable targets (not collected) const gZ = newGlobal({newCompartment: true}); // zone Z: dead weakrefs (collected) const gD = newGlobal({newCompartment: true}); // zone D: transplant destination (not collected)
const NT = 64; // number of important weakref/target pairs const NFILLER = 200000; // dead weakrefs in Z to stall foreground finalization
gC.evaluate(` var pairs = []; for (let i = 0; i < ${NT}; i++) pairs.push(transplantableObject());
`);
gZ.evaluate(` function makeWeak(t) { new WeakRef(t); } function filler(n) {
let keep = []; for (let i = 0; i < n; i++) { let o = {i: i}; keep.push(o); new WeakRef(o); } return keep;
}
`);
// Fillers first: their (dead) weakrefs are finalized first and stall // foreground finalization across many slices. Targets stay alive via `keep`.
let keep = gZ.filler(NFILLER);
// Important weakrefs last: their arenas are finalized last. for (let i = 0; i < NT; i++) {
gZ.makeWeak(gC.pairs[i].object);
}
// Clean nursery + store buffer before starting; tenure everything live.
minorgc();
// Incremental GC collecting ONLY zone Z.
schedulezone(gZ);
startgc(1);
let transplanted = 0;
let sliceCount = 0; while (gcstate() !== "NotActive") {
gcslice(10000, {dontStart: true});
sliceCount++; if (gcstate() === "Sweep" && transplanted < NT) { for (let k = 0; k < 4 && transplanted < NT; k++) { // Transplant target into zone D. The new identity proxy is // nursery-allocated; relocateFinalizationObserverTarget writes it into // the dead WeakRef's TargetSlot -> whole-cell entry for dead cell.
gC.pairs[transplanted].transplant(gD);
transplanted++;
}
} if (sliceCount > 10000) { break; }
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.