diff options
| author | 2026-10-15 02:44:26 +0330 | |
|---|---|---|
| committer | 2026-10-15 02:44:26 +0330 | |
| commit | a175ffd5d18d2883279c94d727f5966ecda409ab (patch) | |
| tree | ef1c895dfb1c95ae36fe540ce333103aa0991e70 /src/runtime/rt.zc | |
| parent | o3: an o3 function called from normal code as a receiver method (run.method) ... (diff) | |
rt: gc_drops finalizes a droppable value that reaches itself (a cycle, or a drop capturing its own value), one per collection, each once; before, each waited for the other forever; spec 6.15.3, drop_gc_cycle.zc, drop_gc_self_capture.zc, design doc lists what landed
Diffstat (limited to 'src/runtime/rt.zc')
| -rw-r--r-- | src/runtime/rt.zc | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/runtime/rt.zc b/src/runtime/rt.zc index 3d448b0..906e56a 100644 --- a/src/runtime/rt.zc +++ b/src/runtime/rt.zc @@ -427,7 +427,7 @@ const int F_SHARE = 8; // p[-4] bits for drops (docs/design/destructors.md): the value has a drop in the side // 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; +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; // flags live in these bits; the size class is above them. const int F_LOW = 65535; @@ -1415,7 +1415,8 @@ int o3_leave() { // the collector's part, between mark and sweep. the drops of live values are kept; // 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). nothing runs user code here. +// it waits for a later collection) and it doesn't reach itself (a cycle drops one +// value per collection). nothing runs user code here. int gc_drops() { int i, again = 1; word k; while (again) { @@ -1436,6 +1437,7 @@ int gc_drops() { k[-4] = k[-4] | F_FINAL; markrange(k, k + k[-5] - HDR); mark(dtab[i * 3 + 1] - 1); mark(dtab[i * 3 + 2] - 1); drain(); + if ((k[-4] & 7) != 1) k[-4] = k[-4] | F_CYCLE; // what it reaches (or its drop) reaches it back: a cycle } i++; } @@ -1443,7 +1445,11 @@ int gc_drops() { while (i < dt_cap) { k = dtab[i * 3]; if (k > 1 && (k[-4] & F_FINAL)) { - if ((k[-4] & 7) == 1) mark(k); else k[-4] = k[-4] & ~F_FINAL; // reached from another candidate: later + // 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; + k[-4] = k[-4] & ~F_CYCLE; } i++; } |
