code wiki / (root) / nx_wasm_scratch.nx

nx_wasm_scratch.nx source

↩ module page · 46 lines · 2373 B

1// nx_wasm_scratch.nx -- WASM-lane framed SCRATCH allocator: the linear-memory port of nx_scratch 2// (nx_u256.nx), which is NATIVE-ONLY because it grows via sys_mmap (no wasm shim). This gives WASM organs 3// the SAME save/alloc/restore shadow-stack the native lane has -> native<->wasm parity for multi-word locals, 4// matching the language's REAL idiom (nx_scratch pointers) rather than a [i64;N] stack-array compiler feature 5// the codebase deliberately rejects (nx_types.nx:469). Backed by a fixed linear-memory arena + a cursor cell; 6// uses ONLY i64.load/store + arithmetic, so it runs in nx_wasm_vm and the browser with no syscalls. 7// license_tier: ORIGINAL (API + frame discipline from nx_scratch in nx_u256.nx; mmap-arena -> linear-mem arena) 8// 9// Memory map (within the backend's 32-page / 2 MiB linear memory): 10// [0 .. WS_BASE) organ's own fixed-offset region (framebuffers, guest RAM, etc.) 11// [WS_BASE .. WS_TOP) the scratch arena (grows UP) 12// [WS_CUR_CELL .. +8) the live cursor (the single-i64 frame mark), at the very top 13const WS_BASE: i64 = 1048576 // 1 MiB 14const WS_TOP: i64 = 2097144 // arena end (just below the cursor cell) 15const WS_CUR_CELL: i64 = 2097144 // 8-byte cursor cell at the top of the 2 MiB memory 16 17// read the live cursor; self-initialise to WS_BASE on first use (a real cursor is never 0). 18func ws_cur_load() -> i64 { 19 let cell: *i64 = WS_CUR_CELL as *i64 20 var c: i64 = cell[0] 21 if c == 0 { c = WS_BASE } 22 return c 23} 24func ws_cur_store(c: i64) -> i64 { 25 let cell: *i64 = WS_CUR_CELL as *i64 26 cell[0] = c 27 return 0 28} 29 30// allocate n bytes (rounded up to 8), zeroed; returns the linear-memory address as *u8. 31// fail-closed (return null) on arena overflow -- NEVER corrupt the cursor cell / silently wrap. 32func nx_scratch(n: i64) -> *u8 { 33 let aligned: i64 = ((n + 7) / 8) * 8 34 let cur: i64 = ws_cur_load() 35 if cur + aligned > WS_TOP { return 0 as *u8 } 36 ws_cur_store(cur + aligned) 37 let pw: *i64 = cur as *i64 38 let words: i64 = aligned / 8 39 var i: i64 = 0 40 while i < words { pw[i] = 0; i = i + 1 } 41 return cur as *u8 42} 43 44// LIFO frame: save returns the current cursor; restore rewinds to it (reclaims every alloc since). 45func nx_scratch_save() -> i64 { return ws_cur_load() } 46func nx_scratch_restore(mark: i64) -> i64 { ws_cur_store(mark); return 0 }