frame allocs: a click is not a frame, a reducer is its dispatch's, a capped push is bounded; ludic.photo at 0
The analysis made every component function a frame root, event handlers (cmp_x_on_delete) too, and every reducer, whether its action is dispatched every frame or once a trip: a component's 'on' handlers are no longer roots, and a dispatch is an edge to its action's reducers, so a reducer counts only when frame code dispatches it. A push into a field declared @max(n) is bounded by the fence's own check and no longer counted. Maroon Lake: frame_allocs 395 -> 337, frame_keeps 188 -> 169. ludic.photo: the roll's order and a page of it are kept lists refilled in place (the pack's page asked for both every frame), its kept lists say @max(256), and a shot's tags, a photograph's fact and a new roll are declared (once per shot, sale or trip). 18 allocs and 9 keeps -> 0 and 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5be2422c84
commit
3b9b4a589b
7 changed files with 58578 additions and 57763 deletions
|
|
@ -304,6 +304,14 @@ function dr_walk(n: Node, refs: []int) -> void {
|
|||
return
|
||||
}
|
||||
if dr_reg_field(n, refs) { return }
|
||||
if n.kind == E_NEW and n.b != null and n.s != null { # 25.2: a dispatch reaches its action's reducers
|
||||
let pre = `ludic_reduce__{n.s}__`
|
||||
var ri = 0
|
||||
while ri < len(g_dr_name) {
|
||||
if str_starts(g_dr_name[ri], pre) { push(refs, ri) }
|
||||
ri += 1
|
||||
}
|
||||
}
|
||||
if n.kind == S_EMIT and n.s != null { # 25.2: an emit reaches its event's listeners
|
||||
var li = 0
|
||||
while li < len(g_onlisten) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,27 @@ function fr_has_aok(n: Node) -> bool {
|
|||
var g_fr_root: []bool = new []bool
|
||||
var g_fr_from: []int = new []int # the node a reached one was first reached from
|
||||
|
||||
function fr_capped(t: Node) -> bool {
|
||||
if t == null or t.kind != E_MEMBER or t.s == null { return false }
|
||||
let tail = `.{t.s}`
|
||||
var i = 0
|
||||
while i < len(g_cap_keys) {
|
||||
let k = g_cap_keys[i]
|
||||
if len(k) > len(tail) and (k[len(k) - len(tail) .. len(k)] == tail) { return true }
|
||||
i += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function fr_is_event_handler(name: pointer) -> bool {
|
||||
var i = 0
|
||||
while i + 4 <= len(name) {
|
||||
if name[i] == '_' and name[i + 1] == 'o' and name[i + 2] == 'n' and name[i + 3] == '_' { return true }
|
||||
i += 1
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function fr_phase_frame(ph: pointer) -> bool {
|
||||
return (ph == "Input") or (ph == "FixedUpdate") or (ph == "Update") or (ph == "LateUpdate") or (ph == "Render") or (ph == "Overlay")
|
||||
}
|
||||
|
|
@ -96,7 +117,11 @@ function fr_alloc_kind(n: Node, text_above: bool) -> pointer {
|
|||
if n.kind == E_BIN and (n.s == "+") and not text_above and fr_is_textish(n) { return "text" }
|
||||
if n.kind == E_CALL and n.a != null and n.a.kind == E_ID and n.a.s != null {
|
||||
let c = n.a.s
|
||||
if (c == "push") { return "grow" }
|
||||
if (c == "push") {
|
||||
# a push into a field declared @max(n) grows to n at most, and the fence fails the run past it
|
||||
if len(n.kids) > 0 and fr_capped(n.kids[0]) { return null }
|
||||
return "grow"
|
||||
}
|
||||
if (c == "words") or (c == "floats") or (c == "doubles") or (c == "buffer") or (c == "bytes") or (c == "fixeds") or (c == "pointers") { return `{c}()` }
|
||||
}
|
||||
return null
|
||||
|
|
@ -150,8 +175,9 @@ function deps_frame(f: pointer) -> void {
|
|||
while i < len(prog) {
|
||||
let d = prog[i]
|
||||
if d.kind == N_SYS and d.s != null and fr_phase_frame(d.ty) { fr_mark_root(d.s) }
|
||||
if d.kind == N_FN and d.s != null and str_starts(d.s, "ludic_reduce__") { fr_mark_root(d.s) }
|
||||
if d.kind == N_FN and d.s != null and d.cm >= 0 { fr_mark_root(d.s) } # a component's own: it runs while its page is open
|
||||
# a component's own functions run while its page is open - but not its event handlers (`on click`),
|
||||
# which run when the player does something; a reducer is reached from its action's dispatch
|
||||
if d.kind == N_FN and d.s != null and d.cm >= 0 and not fr_is_event_handler(d.s) { fr_mark_root(d.s) }
|
||||
fr_find_roots(d)
|
||||
i += 1
|
||||
}
|
||||
|
|
|
|||
58156
selfhost/ludicc.seed.ll
58156
selfhost/ludicc.seed.ll
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue