diff options
| author | 2026-10-15 02:39:49 +0330 | |
|---|---|---|
| committer | 2026-10-15 02:40:51 +0330 | |
| commit | 7ff224faa88725fe59441e73c70dfa4eedd76345 (patch) | |
| tree | 2c8af51b9fc3ea3efe45e43ac0c8ab38ab709fe8 /src/compiler | |
| parent | rt: memreport marks a leaked value whose drop never ran with (drop); spec 4.1... (diff) | |
o3: break and continue out of an o3 { } block call rt.o3_leave for each block they leave (the loop records the o3 depth it began at), so the depth returns to 0 and pending collections and drops run; spec 4.10.3, o3_break_continue_leave.zc
Diffstat (limited to 'src/compiler')
| -rw-r--r-- | src/compiler/stmt.zc | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/src/compiler/stmt.zc b/src/compiler/stmt.zc index 6d5abe7..703f2db 100644 --- a/src/compiler/stmt.zc +++ b/src/compiler/stmt.zc @@ -232,8 +232,18 @@ int kw_if() { // loops and switches share a frame stack (R_LOOP, 8 words each). a break adds // an exit record (the analyzer state at that point) with a jump to patch; // loop_end joins all of them with the normal fall-out and patches the jumps. +// lpo3[k]: how many o3 blocks were open when loop or switch k began; a break or +// continue out of an o3 { } block to it leaves those blocks (rt.o3_leave), as a return does +word lpo3; int lpo3cap; +int o3_leave_to(int k) { + int n = o3blk - lpo3[k]; + while (n > 0) { callname(intern("rt.o3_leave")); op(O_DROP); n--; } + return 0; +} int loop_push(int cont, int s0) { word f; + if (lsp >= lpo3cap) { lpo3 = chk_resize(lpo3, lpo3cap, lsp * 2 + 16); lpo3cap = lsp * 2 + 16; } + lpo3[lsp] = o3blk; reserve_R_LOOP((lsp + 1) * 8); if (lsp >= loopfacts_cap) { lpfact = chk_resize(lpfact, loopfacts_cap, loopfacts_cap * 2); loopfacts_cap = loopfacts_cap * 2; } f = R_LOOP + lsp * 8; @@ -412,6 +422,7 @@ int kw_break() { if (dfr_on && dfr_ctx == ctxsp && lsp <= dfr_lsp) { serr("break can't leave a deferred statement"); return 0; } defer_run(f[2] + 1, 0); exit_vars(f[2] + 1, 0); + o3_leave_to(lsp - 1); if (live) exit_rec(hole()); else hole(); op(O_JMP); live = 0; @@ -430,6 +441,7 @@ int kw_continue() { defer_run(f[2] + 1, 0); backedge(f[3]); exit_vars(f[2] + 1, 0); + o3_leave_to(j); if (f[0] == -2) { f[7] = fixnew(hole(), f[7]); op(O_JMP); } // do/while: the condition isn't placed yet else jmp(f[0]); live = 0; |
