escape (fix): a node walked more than once is scratch only if every walk found it LOCAL

A field's default is one expression, walked at every 'new' of its record: marked LOCAL by a frame's
temporary, it stayed marked when a record a pool keeps was made from it, and that record's list came
from the frame's scratch. The marks are now taken off any node one walk found kept.
examples/lang/arena_defaults.ludic is the case (a pool's record made in frame 3, a temporary of the
same type every frame): foundations 1315baf crashes on it poisoned; this prints '497 124747', as the
heap does. In ludic-dev test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 17:17:33 +03:00
parent 1315baf332
commit bad7c4a255
5 changed files with 44624 additions and 44209 deletions

View file

@ -627,6 +627,9 @@ function escape_analyse() -> void {
li += 1
}
es_solve()
# a node analysed more than once (a field's default, walked at every `new` of its record) is
# scratch only if every walk found it LOCAL: mark the LOCAL ones, then take the mark off any node
# one walk found kept
var s = 0
while s < len(g_es_site) {
let n = g_es_site[s]
@ -648,6 +651,15 @@ function escape_analyse() -> void {
}
s += 1
}
var u = 0
while u < len(g_es_site) {
let n2 = g_es_site[u]
let c2 = g_es_site_cls[u]
let fi2 = g_es_site_fn[u]
let spans2 = fi2 < 0 or g_es_fspans[fi2]
if n2.uns == ES_SCRATCH and (c2 < 0 or (g_es_flag[c2] & (ES_ESC | ES_HEAP)) != 0 or spans2) { n2.uns = 0 }
u += 1
}
}
var g_es_report: bool = false