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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user