fence: every runtime call is its line's site, and site 0 comes back when it returns
A block took whatever @lp_site held when it was made. Only malloc, calloc, realloc, concat, the number texts, the float text, a substring and Text.* set one, so every other runtime helper - intern, Text.repeat and the string builders, the Fs, Os, unicode, uuid and crypto helpers - was charged to whichever line had allocated last (walk 9 blamed gvk_tex_storage, m4_new, kept_push$int and survey_op_reward for intern's 16 B copies). - Any `call ptr @lp_*` now takes a site of its own, its kind the callee's name when no better one is known (intern, str_repeat, fs_list, ...). What the helper makes, in however many blocks and through whichever helpers it calls in turn, is that line's. - When the call returns, @lp_site goes back to site 0, now named "(runtime) (no site) unsited": a block made with no site of its own says so instead of borrowing the last one. - The ECS stores' grows and a mod's registered stores - the only allocations emitted outside emit_bind - take a site each. Golden alloc_fence_sites: two lines take turns keeping memory, Text.repeat and a record, every frame judged. Each report names its own line (25 x +32 B str_repeat at :11, 25 x +16 B new Box at :12); the toolchain before this charges 23 of the 32 B texts to the new Box line. The other fence and arena goldens are unchanged; ludic.base's tests pass; the game's frame ratchets are 0 on main 7cb2b164. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
48a8caa292
commit
6ab98292d2
8 changed files with 98453 additions and 79775 deletions
|
|
@ -96,10 +96,15 @@ function emit_site(kind: pointer) -> void {
|
|||
emit(` store i32 {itoa(id)}, ptr @lp_site\n`)
|
||||
}
|
||||
|
||||
# emit_bind's hook: a call that allocates gets a site first, its kind read off the callee; when the
|
||||
# emit_bind's hook: a call into the runtime gets a site first, its kind read off the callee - what the
|
||||
# callee allocates, however many blocks and through whichever helpers, is that line's - and
|
||||
# g_site_reset puts site 0 back once it returns, so nothing after it is charged to it. When the
|
||||
# expression being emitted is a LOCAL site (25.3) it also raises @lp_want for that one call
|
||||
var g_site_reset: bool = false
|
||||
function fence_bind(rest: pointer) -> bool {
|
||||
g_site_reset = false
|
||||
if not str_starts(rest, "call ptr @lp_") { return false }
|
||||
g_site_reset = true
|
||||
var alloc = true
|
||||
if str_starts(rest, "call ptr @lp_malloc(") { emit_site("alloc") }
|
||||
else if str_starts(rest, "call ptr @lp_calloc(") { emit_site("slice data") }
|
||||
|
|
@ -109,7 +114,11 @@ function fence_bind(rest: pointer) -> bool {
|
|||
else if str_starts(rest, "call ptr @lp_fp_str(") { emit_site("string(x)") }
|
||||
else if str_starts(rest, "call ptr @lp_str_slice(") { emit_site("substring") }
|
||||
else if str_starts(rest, "call ptr @lp_text_") { emit_site("Text"); alloc = false }
|
||||
else { alloc = false }
|
||||
else if str_starts(rest, "call ptr @lp_intern(") { emit_site("intern"); alloc = false }
|
||||
else {
|
||||
emit_site(fence_callee(rest)) # any other runtime helper: named by the callee
|
||||
alloc = false
|
||||
}
|
||||
if alloc and g_arena and g_es_walked and g_es_node != null {
|
||||
emit(" store i8 1, ptr @lp_want\n")
|
||||
return true
|
||||
|
|
@ -117,6 +126,14 @@ function fence_bind(rest: pointer) -> bool {
|
|||
return false
|
||||
}
|
||||
|
||||
# "call ptr @lp_fs_read(ptr %a)" -> "fs_read"
|
||||
function fence_callee(rest: pointer) -> pointer {
|
||||
let at = len("call ptr @lp_")
|
||||
var e = at
|
||||
while e < len(rest) and not (rest[e] == '(') { e += 1 }
|
||||
return rest[at..e]
|
||||
}
|
||||
|
||||
function fence_int(s: pointer) -> int {
|
||||
var n = 0
|
||||
var neg = false
|
||||
|
|
@ -227,8 +244,8 @@ function emit_fence_runtime() -> void {
|
|||
emit_fence_control()
|
||||
emit_fence_report()
|
||||
emit_fence_frame()
|
||||
let unknown = emit_str_const("?")
|
||||
g_site_fn[0] = unknown; g_site_file[0] = unknown; g_site_kind[0] = unknown
|
||||
# site 0 is what allocates with no site of its own: every sited call puts it back when it returns
|
||||
g_site_fn[0] = emit_str_const("(runtime)"); g_site_file[0] = emit_str_const("(no site)"); g_site_kind[0] = emit_str_const("unsited")
|
||||
let n = len(g_site_line)
|
||||
let sn = itoa(n)
|
||||
var dflt = itoa(g_fence_mode)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue