region rule (25.3c): keep() and intern(), frame_keeps, and --arena-strict
keep(x) copies a string, a slice (header and elements) or a record (shallow) onto the heap; intern(s) hands back one heap string per distinct text from a fixed table in the runtime (FNV-1a, 65536 slots, copied the first time; past 49152 only copied). Both are how frame code keeps what it made on purpose: the escape analysis takes the copy as the heap's and leaves the argument LOCAL. The analysis now records why a class escapes (the store, the event, the global it reached) and ludic deps lists every allocation frame code makes and keeps - fkeep lines, 'ludic deps --keeps', the frame_keeps number --check ratchets - leaving out what is under @alloc_ok and a push's growth (25.5's capacities). --arena-strict (or 'arena strict') makes each an error naming the store, before anything is emitted. A test: a template stored into a state is the one error; keep and intern of the next two, an @alloc_ok push and a scratch temporary are not; 195 frames of arena resets under R3D_ARENA_CHECK=1 later the kept and interned texts read as made, and intern gives the same string. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cd71da9330
commit
a0b030290b
10 changed files with 80528 additions and 76677 deletions
|
|
@ -1314,3 +1314,67 @@ function emit_fence_win() -> void {
|
|||
emith(" ret i64 0\n")
|
||||
emith("}\n")
|
||||
}
|
||||
function emit_fence_intern() -> void {
|
||||
emith("@lp_itab = global [65536 x ptr] zeroinitializer\n")
|
||||
emith("@lp_icount = global i64 0\n")
|
||||
emith("define internal ptr @lp_copystr(ptr %s, i64 %n) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %n1 = add i64 %n, 1\n")
|
||||
emith(" %p = call ptr @lp_malloc(i64 %n1)\n")
|
||||
emith(" call ptr @memcpy(ptr %p, ptr %s, i64 %n1)\n")
|
||||
emith(" ret ptr %p\n")
|
||||
emith("}\n")
|
||||
emith("define ptr @lp_intern(ptr %s) {\n")
|
||||
emith("entry:\n")
|
||||
emith(" %null = icmp eq ptr %s, null\n")
|
||||
emith(" br i1 %null, label %none, label %hl\n")
|
||||
emith("none:\n")
|
||||
emith(" ret ptr null\n")
|
||||
emith("hl:\n")
|
||||
emith(" %i = phi i64 [ 0, %entry ], [ %i1, %hb ]\n")
|
||||
emith(" %h = phi i64 [ -3750763034362895579, %entry ], [ %h2, %hb ]\n")
|
||||
emith(" %cp = getelementptr i8, ptr %s, i64 %i\n")
|
||||
emith(" %c = load i8, ptr %cp\n")
|
||||
emith(" %end = icmp eq i8 %c, 0\n")
|
||||
emith(" br i1 %end, label %probe, label %hb\n")
|
||||
emith("hb:\n")
|
||||
emith(" %cz = zext i8 %c to i64\n")
|
||||
emith(" %h1 = xor i64 %h, %cz\n")
|
||||
emith(" %h2 = mul i64 %h1, 1099511628211\n")
|
||||
emith(" %i1 = add i64 %i, 1\n")
|
||||
emith(" br label %hl\n")
|
||||
emith("probe:\n")
|
||||
emith(" %k = phi i64 [ 0, %hl ], [ %k1, %next ]\n")
|
||||
emith(" %far = icmp uge i64 %k, 64\n")
|
||||
emith(" br i1 %far, label %copy_only, label %look\n")
|
||||
emith("look:\n")
|
||||
emith(" %slot0 = add i64 %h, %k\n")
|
||||
emith(" %slot = and i64 %slot0, 65535\n")
|
||||
emith(" %sp = getelementptr [65536 x ptr], ptr @lp_itab, i64 0, i64 %slot\n")
|
||||
emith(" %v = load ptr, ptr %sp\n")
|
||||
emith(" %empty = icmp eq ptr %v, null\n")
|
||||
emith(" br i1 %empty, label %store, label %cmp\n")
|
||||
emith("cmp:\n")
|
||||
emith(" %r = call i32 @strcmp(ptr %v, ptr %s)\n")
|
||||
emith(" %same = icmp eq i32 %r, 0\n")
|
||||
emith(" br i1 %same, label %found, label %next\n")
|
||||
emith("next:\n")
|
||||
emith(" %k1 = add i64 %k, 1\n")
|
||||
emith(" br label %probe\n")
|
||||
emith("found:\n")
|
||||
emith(" ret ptr %v\n")
|
||||
emith("store:\n")
|
||||
emith(" %cnt = load i64, ptr @lp_icount\n")
|
||||
emith(" %full = icmp uge i64 %cnt, 49152\n")
|
||||
emith(" br i1 %full, label %copy_only, label %keep\n")
|
||||
emith("keep:\n")
|
||||
emith(" %c2 = call ptr @lp_copystr(ptr %s, i64 %i)\n")
|
||||
emith(" store ptr %c2, ptr %sp\n")
|
||||
emith(" %cnt1 = add i64 %cnt, 1\n")
|
||||
emith(" store i64 %cnt1, ptr @lp_icount\n")
|
||||
emith(" ret ptr %c2\n")
|
||||
emith("copy_only:\n")
|
||||
emith(" %c3 = call ptr @lp_copystr(ptr %s, i64 %i)\n")
|
||||
emith(" ret ptr %c3\n")
|
||||
emith("}\n")
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue