escape (fix): the arena took ludic.ui's pooled nodes - a generic's call and an unknown callee now keep what they are handed
memory_final's gate crashed in all 13 scenarios at the first frame of play, R3D_ARENA_CHECK=1 reading 0xDD in ludic.ui's nd_take: a node the pool keeps had come from the frame's scratch. Two holes: - a call to a generic (ui_kept(list, n)) names the generic, and the analysis knows only its instances (ui_kept$UiNode), so the callee looked unknown - and an unknown callee was taken to keep nothing. A generic's call now reaches every instance, and an unknown callee keeps everything it is handed, but for a short list of intrinsics known to keep nothing; view() shares its list's storage. - a push's growth into a parameter's list was LOCAL whenever the list was not seen kept, though a parameter may be a state's list. A site is LOCAL now only when its class is neither ESC nor HEAP. examples/lang/arena_pool.ludic is the shape (a pool keeping records across frames through a generic push): built with --arena it prints '7 3498' poisoned on every reset and with the arena off, in ludic-dev test. On the valley every ludic.ui pool site is kept; 5480 sites local, 6431 kept. Also, from ECS: a record's field defaults are stored into it when it is made, a global's initializer is kept, and a component's own functions are frame roots (they run while its page is open). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
a6364199da
commit
c8a588b2de
6 changed files with 62210 additions and 59807 deletions
40
examples/lang/arena_pool.ludic
Normal file
40
examples/lang/arena_pool.ludic
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# arena_pool.ludic - a pool that keeps its records across frames through a generic push (the shape of
|
||||
# ludic.ui's nd_take and ui_kept). Built with --arena, a record the pool keeps must not come from the
|
||||
# frame's scratch: run with R3D_ARENA_CHECK=1 (each reset filled with 0xDD) it prints what it prints
|
||||
# with the arena off (R3D_ARENA=0) - `7 3498`.
|
||||
program ArenaPool {
|
||||
property Cell { v: int = 0, tag: string = "" }
|
||||
property Pool { cells: []Cell = new []Cell, used: int = 0 }
|
||||
function kept<T>(xs: []T, v: T) -> void { push(xs, v) }
|
||||
function take(p: Pool, f: int) -> Cell {
|
||||
if p.used < len(p.cells) {
|
||||
let c = p.cells[p.used]
|
||||
p.used += 1
|
||||
return c
|
||||
}
|
||||
let c = new Cell { v: f }
|
||||
kept(p.cells, c)
|
||||
p.used += 1
|
||||
return c
|
||||
}
|
||||
function step(p: Pool, f: int) -> int {
|
||||
p.used = 0
|
||||
var s = 0
|
||||
for k in 0 .. (f % 8) {
|
||||
let c = take(p, f)
|
||||
c.v = f + k
|
||||
s += c.v
|
||||
}
|
||||
return s
|
||||
}
|
||||
entry {
|
||||
let p = new Pool
|
||||
for f in 0 .. 500 {
|
||||
step(p, f)
|
||||
Mem.frame()
|
||||
}
|
||||
var sum = 0
|
||||
for i in 0 .. len(p.cells) { sum += p.cells[i].v }
|
||||
print(`{len(p.cells)} {sum}`)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue