Restore JIT closure injection — needed for top-level function JIT

Removing injection broke GLOBAL_GET for all JIT-compiled functions,
not just mutable closures. Top-level functions like render-to-html
need their referenced bindings in the VM globals table.

Restore the original injection (only injects values not already in
globals). Mutable closure vars (parser's pos etc.) still get stale
snapshots and fall back to CEK — that's the known limitation to fix
with cell-based boxing later.

1166 passed, 0 failed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 21:19:35 +00:00
parent 97e711a80d
commit b4107fa52b

View File

@@ -582,10 +582,30 @@ let jit_compile_lambda (l : lambda) globals =
| _ ->
(* Compiler loaded from source — call through CEK *)
Sx_ref.eval_expr (List [compile_fn; quoted]) (Env (make_env ())) in
(* Don't inject closure bindings into globals GLOBAL_GET falls through
to vm_closure_env which has LIVE bindings. Injecting creates stale
snapshots that break mutable closure variables (set! on pos, etc.). *)
let effective_globals = globals in
(* Inject closure bindings into globals so GLOBAL_GET can find them.
Only injects values not already present in globals (preserves
existing defines). Mutable closure vars get stale snapshots here
but GLOBAL_SET writes back to vm_closure_env, and GLOBAL_GET
falls through to vm_closure_env if the global is stale. *)
let effective_globals =
let closure = l.l_closure in
let count = ref 0 in
let rec inject env =
Hashtbl.iter (fun id v ->
let name = Sx_types.unintern id in
if not (Hashtbl.mem globals name) then begin
Hashtbl.replace globals name v;
incr count
end
) env.bindings;
match env.parent with Some p -> inject p | None -> ()
in
if Hashtbl.length closure.bindings > 0 || closure.parent <> None then
inject closure;
if !count > 0 then
Printf.eprintf "[jit] %s: injected %d closure bindings\n%!" fn_name !count;
globals
in
(match result with
| Dict d when Hashtbl.mem d "bytecode" ->
let outer_code = code_from_value result in