Merge branch 'lang/intern-store' into lang/foundations

This commit is contained in:
Orkun ÇAKILKAYA 2026-09-29 00:33:43 +03:00
commit a99f75f2a4
2 changed files with 43 additions and 4 deletions

View file

@ -258,15 +258,19 @@ function value_num_set(v: Val, n: int) -> void {
} }
# a number's text, kept on the Value until the number changes (a count shown in a HUD every frame wrote # a number's text, kept on the Value until the number changes (a count shown in a HUD every frame wrote
# its text every frame; Ludic frees nothing) # its text every frame; Ludic frees nothing)
# interned, and the text written for it given back: a number that changed dropped its last text
function value_num_text(v: Val) -> string { function value_num_text(v: Val) -> string {
if v.txt != null { return v.txt } if v.txt != null { return v.txt }
if v.tag == 1 { v.txt = string(v.num) } var t: string = null
if v.tag == 1 { t = string(v.num) }
else if v.tag == 7 { else if v.tag == 7 {
let f = float_from_bits(v.num) let f = float_from_bits(v.num)
if f == float(int(f)) { v.txt = string(int(f)) } else { v.txt = string(f) } if f == float(int(f)) { t = string(int(f)) } else { t = string(f) }
} }
else if v.tag == 2 { v.txt = json_fixed_str(v.num) } else if v.tag == 2 { t = json_fixed_str(v.num) }
if v.txt == null { return "" } if t == null { return "" }
v.txt = intern(t)
free(t)
return v.txt return v.txt
} }
# a list or an object emptied in place, its room kept - for one filled again every frame # a list or an object emptied in place, its room kept - for one filled again every frame

View file

@ -253,6 +253,16 @@ function emit_fence_entry() -> void {
emith("}\n") emith("}\n")
emith("define void @lp_free(ptr %o) {\n") emith("define void @lp_free(ptr %o) {\n")
emith("entry:\n") emith("entry:\n")
emith(" %ist = ptrtoint ptr @lp_istore to i64\n") # an interned text is the store's: never freed
emith(" %ien = add i64 %ist, 4194304\n")
emith(" %ix = ptrtoint ptr %o to i64\n")
emith(" %ige = icmp uge i64 %ix, %ist\n")
emith(" %ilt = icmp ult i64 %ix, %ien\n")
emith(" %iin = and i1 %ige, %ilt\n")
emith(" br i1 %iin, label %istore, label %free0\n")
emith("istore:\n")
emith(" ret void\n")
emith("free0:\n")
emith(" %x = ptrtoint ptr %o to i64\n") emith(" %x = ptrtoint ptr %o to i64\n")
emith(" %lo = load i64, ptr @lp_ar_lo\n") emith(" %lo = load i64, ptr @lp_ar_lo\n")
emith(" %hi = load i64, ptr @lp_ar_hi\n") emith(" %hi = load i64, ptr @lp_ar_hi\n")
@ -1837,6 +1847,16 @@ function emit_fence_win() -> void {
emith("}\n") emith("}\n")
emith("define void @lp_free(ptr %o) {\n") emith("define void @lp_free(ptr %o) {\n")
emith("entry:\n") emith("entry:\n")
emith(" %ist = ptrtoint ptr @lp_istore to i64\n") # an interned text is the store's: never freed
emith(" %ien = add i64 %ist, 4194304\n")
emith(" %ix = ptrtoint ptr %o to i64\n")
emith(" %ige = icmp uge i64 %ix, %ist\n")
emith(" %ilt = icmp ult i64 %ix, %ien\n")
emith(" %iin = and i1 %ige, %ilt\n")
emith(" br i1 %iin, label %istore, label %free0\n")
emith("istore:\n")
emith(" ret void\n")
emith("free0:\n")
emith(" tail call void @free(ptr %o)\n") emith(" tail call void @free(ptr %o)\n")
emith(" ret void\n") emith(" ret void\n")
emith("}\n") emith("}\n")
@ -1872,9 +1892,24 @@ function emit_fence_win() -> void {
function emit_fence_intern() -> void { function emit_fence_intern() -> void {
emith("@lp_itab = global [65536 x ptr] zeroinitializer\n") emith("@lp_itab = global [65536 x ptr] zeroinitializer\n")
emith("@lp_icount = global i64 0\n") emith("@lp_icount = global i64 0\n")
# the interned texts' bytes: one store in the binary, filled front to back and never given back, so
# a text seen for the first time costs no allocation (a HUD's clock made one a minute); the heap
# only past its 4 MB
emith("@lp_istore = internal global [4194304 x i8] zeroinitializer\n")
emith("@lp_ipos = internal global i64 0\n")
emith("define internal ptr @lp_copystr(ptr %s, i64 %n) {\n") emith("define internal ptr @lp_copystr(ptr %s, i64 %n) {\n")
emith("entry:\n") emith("entry:\n")
emith(" %n1 = add i64 %n, 1\n") emith(" %n1 = add i64 %n, 1\n")
emith(" %pos = load i64, ptr @lp_ipos\n")
emith(" %end = add i64 %pos, %n1\n")
emith(" %fits = icmp ule i64 %end, 4194304\n")
emith(" br i1 %fits, label %bump, label %heap\n")
emith("bump:\n")
emith(" %b = getelementptr inbounds [4194304 x i8], ptr @lp_istore, i64 0, i64 %pos\n")
emith(" store i64 %end, ptr @lp_ipos\n")
emith(" call ptr @memcpy(ptr %b, ptr %s, i64 %n1)\n")
emith(" ret ptr %b\n")
emith("heap:\n")
emith(" %p = call ptr @lp_malloc(i64 %n1)\n") emith(" %p = call ptr @lp_malloc(i64 %n1)\n")
emith(" call ptr @memcpy(ptr %p, ptr %s, i64 %n1)\n") emith(" call ptr @memcpy(ptr %p, ptr %s, i64 %n1)\n")
emith(" ret ptr %p\n") emith(" ret ptr %p\n")