From d715d8c4aca54568a48d4842e09a36b397701b2d Mon Sep 17 00:00:00 2001 From: giles Date: Wed, 8 Apr 2026 11:24:50 +0000 Subject: [PATCH] JIT: closure env merge + bytecode locals scan for closure functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - jit_compile_lambda: merge closure bindings into effective_globals so GLOBAL_GET resolves variables from let/define blocks (emit-on, etc.) - code_from_value: scan bytecode for max LOCAL_GET/SET slot to compute vc_locals (fixes LOCAL_GET overflow in large functions like hs-parse) 3127/3127 no-JIT, 3116/3127 JIT (11 hyperscript on-event: specific bytecode correctness issue in recursive parser — wrong branch taken strips on/event-name from result). Co-Authored-By: Claude Opus 4.6 (1M context) --- hosts/ocaml/lib/sx_vm.ml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hosts/ocaml/lib/sx_vm.ml b/hosts/ocaml/lib/sx_vm.ml index a79ab860..f61f9d1b 100644 --- a/hosts/ocaml/lib/sx_vm.ml +++ b/hosts/ocaml/lib/sx_vm.ml @@ -881,7 +881,23 @@ let jit_compile_lambda (l : lambda) globals = Sx_ref.eval_expr (List [Symbol "compile"; quoted]) (Env compile_env) in _jit_compiling := false; - let effective_globals = globals in + (* Merge closure bindings into effective_globals so GLOBAL_GET resolves + variables from let/define blocks. The compiler emits GLOBAL_GET for + free variables; the VM resolves them from vm_env_ref. *) + let effective_globals = + if Hashtbl.length l.l_closure.Sx_types.bindings > 0 then begin + let merged = Hashtbl.copy globals in + let rec merge_env env = + Hashtbl.iter (fun id v -> + let name = Sx_types.unintern id in + if not (Hashtbl.mem merged name) then + Hashtbl.replace merged name v) env.Sx_types.bindings; + match env.Sx_types.parent with Some p -> merge_env p | None -> () + in + merge_env l.l_closure; + merged + end else globals + in (match result with | Dict d when Hashtbl.mem d "bytecode" || Hashtbl.mem d "vc-bytecode" -> let outer_code = code_from_value result in