JIT: VM fast path, &rest support, locals scan, test runner fixes
- jit_compile_lambda: call compile directly via VM when it has bytecode (100-400x faster JIT compilation, server pre-warm 1.6s vs hung) - code_from_value: scan bytecode for highest LOCAL_GET/SET slot to compute vc_locals correctly (fixes hyperscript LOCAL_GET overflow) - code_from_value: accept both compiler keys (bytecode) and SX VM keys (vc-bytecode) for interop - jit_compile_lambda: skip &key/:as params (compiler can't emit them) - Test runner: seed VM globals with primitives + env bindings, native vm-execute-module with suspension fallback to SX version, _jit_refresh_globals syncs globals after module loading, VmSuspended + "VM undefined" caught and sentineled 3127/3127 without JIT, 3116/3127 with JIT (11 hyperscript on-event parsing — specific closure/scope issue, not infrastructure). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1309,16 +1309,39 @@ let run_spec_tests env test_files =
|
||||
(* Rebind vm-execute-module and code-from-value to native OCaml implementations.
|
||||
The SX versions from vm.sx run bytecode step-by-step in the interpreter —
|
||||
far too slow for the test suite. Native versions use the compiled OCaml VM. *)
|
||||
(* Rebind vm-execute-module to use the native OCaml VM directly.
|
||||
The SX version from vm.sx runs bytecode step-by-step in the interpreter.
|
||||
code-from-value stays as the SX version — it produces dicts that
|
||||
vm-execute-module converts to native vm_code internally. *)
|
||||
(* Wrap SX vm-execute-module to seed empty globals with primitives + env.
|
||||
The SX VM resolves CALL_PRIM/GLOBAL_GET from globals — without seeding,
|
||||
even (+ 1 2) fails. We keep the SX version (not native Sx_vm) so
|
||||
suspension tests work (SX VM suspends via dict, native VM via exception). *)
|
||||
let sx_vm_execute = try Some (Sx_types.env_get env "vm-execute-module") with _ -> None in
|
||||
ignore (Sx_types.env_bind env "vm-execute-module" (NativeFn ("vm-execute-module", fun args ->
|
||||
match args with
|
||||
| [code; Dict globals] ->
|
||||
if Hashtbl.length globals = 0 then begin
|
||||
Hashtbl.iter (fun name fn ->
|
||||
Hashtbl.replace globals name (NativeFn (name, fn))
|
||||
) Sx_primitives.primitives;
|
||||
let rec add_env e =
|
||||
Hashtbl.iter (fun id v ->
|
||||
let name = Sx_types.unintern id in
|
||||
if not (Hashtbl.mem globals name) then
|
||||
Hashtbl.replace globals name v) e.Sx_types.bindings;
|
||||
match e.Sx_types.parent with Some p -> add_env p | None -> ()
|
||||
in add_env env
|
||||
end;
|
||||
(* Use native VM for speed — much faster than SX step-by-step *)
|
||||
let c = Sx_vm.code_from_value code in
|
||||
Sx_vm.execute_module c globals
|
||||
| _ -> Nil)));
|
||||
(try Sx_vm.execute_module c globals
|
||||
with Sx_vm.VmSuspended (_request, _saved_vm) ->
|
||||
(* Fall back to SX version for suspension handling *)
|
||||
Hashtbl.remove globals "__io_request";
|
||||
match sx_vm_execute with
|
||||
| Some fn -> Sx_ref.cek_call fn (List [code; Dict globals])
|
||||
| None -> Nil)
|
||||
| _ ->
|
||||
match sx_vm_execute with
|
||||
| Some fn -> Sx_ref.cek_call fn (List args)
|
||||
| None -> Nil)));
|
||||
load_module "signals.sx" spec_dir; (* core reactive primitives *)
|
||||
load_module "signals.sx" web_dir; (* web extensions *)
|
||||
load_module "freeze.sx" lib_dir;
|
||||
|
||||
Reference in New Issue
Block a user