fence (25.1): every allocation goes through the fence - sites, frame judging, census, callers
Every allocation the compiler emits goes through @lp_malloc/@lp_calloc/@lp_realloc/@lp_free, and a Ludic-level one first stores its site (function, file, line, kind) in @lp_site. Off, that is one load and a predictable branch (30 M allocations: 0.87-0.91 s against 0.87-0.90 s on leaks2). On (the default in a headless build, and windowed under R3D_DEV), tracking starts at the first frame on its own and judging once R3D_ALLOC_WARM frames in a row kept nothing (600) or R3D_ALLOC_WARM_MAX after (re)start; Mem.play()/Mem.rewarm() sends a load back to its warm-up. A judged frame that ends holding more than it began with is reported by site with its callers (the unwinder, taken only once judging) and fails the run with exit 86 (R3D_ALLOC_FENCE=off|count|warn|fail). R3D_ALLOC_CENSUS writes the totals and top sites at exit. The build's defaults are --fence=, --fence-warm=, --fence-census= or a fence line in the program's package.ludic; the environment overrides them. The runtime is IR (emit_fence_ir.ludic, generated from a template); tracking is a side table in one calloc'd region, so no block carries a header and pointers crossing to natives stay safe. Examples alloc_fence, alloc_fence_leak and alloc_fence_auto with cases in ludic-dev test; reseeded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
fc0f3d3790
commit
a8d54e9878
34 changed files with 106868 additions and 82677 deletions
|
|
@ -7,7 +7,7 @@ function emit_text_prelude() -> void {
|
|||
emith("entry:\n")
|
||||
emith(" %n = call i64 @strlen(ptr %s)\n")
|
||||
emith(" %sz = add i64 %n, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %sz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %sz)\n")
|
||||
emith(" %ip = alloca i64\n")
|
||||
emith(" store i64 0, ptr %ip\n")
|
||||
emith(" br label %cond\n")
|
||||
|
|
@ -37,7 +37,7 @@ function emit_text_prelude() -> void {
|
|||
emith("entry:\n")
|
||||
emith(" %n = call i64 @strlen(ptr %s)\n")
|
||||
emith(" %sz = add i64 %n, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %sz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %sz)\n")
|
||||
emith(" %ip = alloca i64\n")
|
||||
emith(" store i64 0, ptr %ip\n")
|
||||
emith(" br label %cond\n")
|
||||
|
|
@ -104,7 +104,7 @@ function emit_text_prelude() -> void {
|
|||
emith(" %en = load i64, ptr %ep\n")
|
||||
emith(" %len = sub i64 %en, %st\n")
|
||||
emith(" %sz = add i64 %len, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %sz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %sz)\n")
|
||||
emith(" %src = getelementptr i8, ptr %s, i64 %st\n")
|
||||
emith(" call ptr @memcpy(ptr %out, ptr %src, i64 %len)\n")
|
||||
emith(" %tp = getelementptr i8, ptr %out, i64 %len\n")
|
||||
|
|
@ -129,7 +129,7 @@ function emit_text_prelude() -> void {
|
|||
emith(" %L = call i64 @strlen(ptr %s)\n")
|
||||
emith(" %tot = mul i64 %L, %n\n")
|
||||
emith(" %sz = add i64 %tot, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %sz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %sz)\n")
|
||||
emith(" %ip = alloca i64\n")
|
||||
emith(" store i64 0, ptr %ip\n")
|
||||
emith(" br label %cond\n")
|
||||
|
|
@ -157,7 +157,7 @@ function emit_text_prelude() -> void {
|
|||
emith(" br i1 %need, label %do, label %copy\n")
|
||||
emith("copy:\n")
|
||||
emith(" %sz0 = add i64 %L, 1\n")
|
||||
emith(" %o0 = call ptr @malloc(i64 %sz0)\n")
|
||||
emith(" %o0 = call ptr @lp_malloc(i64 %sz0)\n")
|
||||
emith(" %e0 = add i64 %L, 0\n")
|
||||
emith(" call ptr @memcpy(ptr %o0, ptr %s, i64 %L)\n")
|
||||
emith(" %t0 = getelementptr i8, ptr %o0, i64 %L\n")
|
||||
|
|
@ -166,7 +166,7 @@ function emit_text_prelude() -> void {
|
|||
emith("do:\n")
|
||||
emith(" %pad = sub i64 %w0, %L\n")
|
||||
emith(" %sz = add i64 %w0, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %sz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %sz)\n")
|
||||
emith(" br i1 %left, label %padleft, label %padright\n")
|
||||
emith("padleft:\n")
|
||||
emith(" call void @lp_fill_sp(ptr %out, i64 0, i64 %pad)\n")
|
||||
|
|
@ -216,7 +216,7 @@ function emit_text2_prelude() -> void {
|
|||
emith("copyall:\n")
|
||||
emith(" %ls0 = call i64 @strlen(ptr %s)\n")
|
||||
emith(" %sz0 = add i64 %ls0, 1\n")
|
||||
emith(" %o0 = call ptr @malloc(i64 %sz0)\n")
|
||||
emith(" %o0 = call ptr @lp_malloc(i64 %sz0)\n")
|
||||
emith(" call ptr @memcpy(ptr %o0, ptr %s, i64 %sz0)\n")
|
||||
emith(" ret ptr %o0\n")
|
||||
emith("scan:\n")
|
||||
|
|
@ -245,7 +245,7 @@ function emit_text2_prelude() -> void {
|
|||
emith(" %grow = mul i64 %cnt, %delta\n")
|
||||
emith(" %newlen = add i64 %ls, %grow\n")
|
||||
emith(" %osz = add i64 %newlen, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %osz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %osz)\n")
|
||||
emith(" %srcp = alloca ptr\n")
|
||||
emith(" store ptr %s, ptr %srcp\n")
|
||||
emith(" %dstp = alloca ptr\n")
|
||||
|
|
@ -312,7 +312,7 @@ function emit_text2_prelude() -> void {
|
|||
emith(" %tot0 = load i64, ptr %totp\n")
|
||||
emith(" %tot = add i64 %tot0, %sepsz\n")
|
||||
emith(" %osz = add i64 %tot, 1\n")
|
||||
emith(" %out = call ptr @malloc(i64 %osz)\n")
|
||||
emith(" %out = call ptr @lp_malloc(i64 %osz)\n")
|
||||
emith(" %dstp = alloca ptr\n")
|
||||
emith(" store ptr %out, ptr %dstp\n")
|
||||
emith(" %jp = alloca i64\n")
|
||||
|
|
@ -369,9 +369,9 @@ function emit_text2_prelude() -> void {
|
|||
emith(" br label %ccond\n")
|
||||
emith("mk:\n")
|
||||
emith(" %cnt = load i64, ptr %cntp\n")
|
||||
emith(" %hdr = call ptr @malloc(i64 16)\n")
|
||||
emith(" %hdr = call ptr @lp_malloc(i64 16)\n")
|
||||
emith(" %arrsz = mul i64 %cnt, 8\n")
|
||||
emith(" %arr = call ptr @malloc(i64 %arrsz)\n")
|
||||
emith(" %arr = call ptr @lp_malloc(i64 %arrsz)\n")
|
||||
emith(" %d0 = getelementptr inbounds %LSlice, ptr %hdr, i32 0, i32 0\n")
|
||||
emith(" store ptr %arr, ptr %d0\n")
|
||||
emith(" %cnt32 = trunc i64 %cnt to i32\n")
|
||||
|
|
@ -404,7 +404,7 @@ function emit_text2_prelude() -> void {
|
|||
emith("store:\n")
|
||||
emith(" %seg = phi i64 [ %seglen, %mid ], [ %rem, %last ]\n")
|
||||
emith(" %ssz = add i64 %seg, 1\n")
|
||||
emith(" %sub = call ptr @malloc(i64 %ssz)\n")
|
||||
emith(" %sub = call ptr @lp_malloc(i64 %ssz)\n")
|
||||
emith(" %src2 = load ptr, ptr %srcp\n")
|
||||
emith(" call ptr @memcpy(ptr %sub, ptr %src2, i64 %seg)\n")
|
||||
emith(" %tp = getelementptr i8, ptr %sub, i64 %seg\n")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue