leak at birth (25.2d): an allocation nothing keeps, made where the arena does not take it
ludic deps --births lists every site the escape analysis finds kept by nothing and not the frame arena's - boot and load code, a function spanning frames, frame code with the arena off - which is made and dropped and never given back; birth_leaks is a number --check ratchets. A text used up by + or == where it is made is freed at once and not counted; nor is what @alloc_ok covers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
db3a3d80d1
commit
ce2699dfee
5 changed files with 57715 additions and 56121 deletions
|
|
@ -25,6 +25,7 @@ var g_es_aok: int = 0 # inside a statement under @
|
|||
var g_es_site_aok: []bool = new []bool # the site is (not reported by the region rule)
|
||||
var g_es_site_grow: []bool = new []bool # the site is a push's growth (25.5's capacities, not the rule)
|
||||
var g_es_done: bool = false
|
||||
var g_es_consumed: []Node = new []Node # text used up where it is made (a + or == operand): freed at once
|
||||
var g_es_ft: []int = new []int # flow edges
|
||||
var g_es_ff: []int = new []int
|
||||
var g_es_st: []int = new []int # store edges: value, target
|
||||
|
|
@ -114,6 +115,10 @@ function es_val(e: Node) -> int {
|
|||
if k == E_BIN {
|
||||
es_val(e.a)
|
||||
es_val(e.b)
|
||||
if (e.s == "+") or (e.s == "==") or (e.s == "!=") {
|
||||
if e.a != null and (e.a.kind == E_BIN or e.a.kind == E_CALL or e.a.kind == E_SLICE) { push(g_es_consumed, e.a) }
|
||||
if e.b != null and (e.b.kind == E_BIN or e.b.kind == E_CALL or e.b.kind == E_SLICE) { push(g_es_consumed, e.b) }
|
||||
}
|
||||
if (e.s == "+") and fr_is_textish(e) { return es_site(e) }
|
||||
return -1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -227,4 +227,40 @@ function deps_keeps(f: pointer, seen: []bool) -> void {
|
|||
}
|
||||
deps_line(f, `frame_keeps {itoa(n)}`)
|
||||
if g_arena_strict and n > 0 { exit(1) }
|
||||
deps_births(f, seen)
|
||||
}
|
||||
|
||||
function fr_consumed(n: Node) -> bool {
|
||||
var i = 0
|
||||
while i < len(g_es_consumed) { if g_es_consumed[i] == n { return true }; i += 1 }
|
||||
return false
|
||||
}
|
||||
|
||||
# 25.2's leak-at-birth: an allocation nothing keeps, made where the arena does not take it - outside
|
||||
# frame code (a boot, a load), in a function spanning frames, or anywhere with the arena off - is
|
||||
# made and dropped, never given back. `fbirth` lines, and the birth_leaks number
|
||||
function deps_births(f: pointer, seen: []bool) -> void {
|
||||
var n = 0
|
||||
var s = 0
|
||||
while s < len(g_es_site) {
|
||||
let c = g_es_site_cls[s]
|
||||
let fi = g_es_site_fn[s]
|
||||
let site = g_es_site[s]
|
||||
if c >= 0 and fi >= 0 and (g_es_flag[c] & ES_ESC) == 0 and not g_es_site_aok[s] and not g_es_site_grow[s] {
|
||||
let d = g_es_fnode[fi]
|
||||
let k = dr_index(d.s)
|
||||
let inframe = k >= 0 and seen[k]
|
||||
let scratch = g_arena and site.uns == ES_SCRATCH and inframe # before the first frame the arena is not running
|
||||
if not scratch and d.file != null and not is_runtime_file(d.file) and not fr_alloc_ok(d.s) and not fr_consumed(site) {
|
||||
var kind = fr_alloc_kind(site, false)
|
||||
if kind == null { kind = "text" }
|
||||
var where = "outside-a-frame"
|
||||
if inframe { where = fr_chain(k) }
|
||||
deps_line(f, `fbirth {kind} {d.file}:{itoa(site.line)} {d.s} {where}`)
|
||||
n += 1
|
||||
}
|
||||
}
|
||||
s += 1
|
||||
}
|
||||
deps_line(f, `birth_leaks {itoa(n)}`)
|
||||
}
|
||||
|
|
|
|||
56898
selfhost/ludicc.seed.ll
56898
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