From e7fe081efaae893ed46548fdbc3bfa39b2879878 Mon Sep 17 00:00:00 2001 From: zinc Date: Thu, 15 Oct 2026 18:29:55 +0330 Subject: duplicate case labels are an error (b.2.15); unterminated string literal reported where it starts (b.2.11); an unreachable droppable cycle drops whole in one collection (6.15.3) --- src/runtime/rt.zc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src/runtime/rt.zc') diff --git a/src/runtime/rt.zc b/src/runtime/rt.zc index 149138b..4f96320 100644 --- a/src/runtime/rt.zc +++ b/src/runtime/rt.zc @@ -428,7 +428,7 @@ const int F_SHARE = 8; // table (dtab), its drop has run (it never runs again), and the collector found it // unreachable and runs its drop once the sweep is over. const int F_HASDROP = 16, F_DROPPED = 32, F_FINAL = 64, F_CYCLE = 128; // F_CYCLE: during gc_drops only, a candidate its own contents reach -int o3_depth, gc_pending; +int o3_depth, gc_pending, gc_cyc; // gc_cyc: the last sweep found a cycle with drops to run // flags live in these bits; the size class is above them. const int F_LOW = 65535; int hbump; word[32] freel; int gc_runs, gc_freed, gc_auto = 1; @@ -1456,7 +1456,7 @@ int o3_leave() { // an unreachable value with a drop that hasn't run is kept for one more cycle and // flagged F_FINAL, unless another such value reaches it (its parent drops first and // it waits for a later collection) and it doesn't reach itself (a cycle drops one -// value per collection). nothing runs user code here. +// value per sweep, and gc() repeats the sweep until the cycle is done). nothing runs user code here. int gc_drops() { int i, again = 1; word k; while (again) { @@ -1486,9 +1486,9 @@ int gc_drops() { k = dtab[i * 3]; if (k > 1 && (k[-4] & F_FINAL)) { // reached from another candidate: later. one in a cycle has nothing outside it - // to drop first, so it drops now (it is marked, so kept), and the rest of the - // cycle in later collections, one each, never twice - if ((k[-4] & 7) == 1) mark(k); else if (!(k[-4] & F_CYCLE)) k[-4] = k[-4] & ~F_FINAL; + // to drop first, so it drops now (it is marked, so kept); gc() then sweeps again + // for the rest of the cycle, one each, never twice + if ((k[-4] & 7) == 1) mark(k); else if (!(k[-4] & F_CYCLE)) k[-4] = k[-4] & ~F_FINAL; else gc_cyc = 1; k[-4] = k[-4] & ~F_CYCLE; } i++; @@ -1549,8 +1549,12 @@ unchecked int gc_sweep() { unchecked int gc() { int n; if (o3_depth) { gc_pending = 1; return 0; } + gc_cyc = 0; n = gc_sweep(); if (dcount) gc_finalize(); + // an unreachable cycle with drops finishes in this collection: each sweep drops one + // member (nothing outside the cycle has to go first), and every value drops once + while (gc_cyc) { gc_cyc = 0; n = n + gc_sweep(); if (dcount) gc_finalize(); } return n; } // the number of live heap objects, for tests and leak checks. -- cgit v1.2.3