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 *)
|
(* Compiler loaded from source — call through CEK *)
|
||||||
Sx_ref.eval_expr (List [compile_fn; quoted]) (Env (make_env ())) in
|
Sx_ref.eval_expr (List [compile_fn; quoted]) (Env (make_env ())) in
|
||||||
(* Don't inject closure bindings into globals — GLOBAL_GET falls through
|
(* Inject closure bindings into globals so GLOBAL_GET can find them.
|
||||||
to vm_closure_env which has LIVE bindings. Injecting creates stale
|
Only injects values not already present in globals (preserves
|
||||||
snapshots that break mutable closure variables (set! on pos, etc.). *)
|
existing defines). Mutable closure vars get stale snapshots here
|
||||||
let effective_globals = globals in
|
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
|
(match result with
|
||||||
| Dict d when Hashtbl.mem d "bytecode" ->
|
| Dict d when Hashtbl.mem d "bytecode" ->
|
||||||
let outer_code = code_from_value result in
|
let outer_code = code_from_value result in
|
||||||
|
|||||||
Reference in New Issue
Block a user