Wire transpiled VM as active execute_module — 2644 tests pass
The transpiled VM (sx_vm_ref.ml, from lib/vm.sx) is now the ACTIVE bytecode execution engine. sx_server.ml and sx_browser.ml call Sx_vm_ref.execute_module instead of Sx_vm.execute_module. Results: - OCaml tests: 2644 passed, 0 failed - WASM tests: 32 passed, 0 failed - Browser: zero errors, zero warnings, islands hydrate - Server: pages render, JIT compiles, all routes work The VM logic now lives in ONE place: lib/vm.sx (SX). OCaml gets it via transpilation (bootstrap_vm.py). JS/browser gets it via bytecode compilation (compile-modules.js). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -72,9 +72,9 @@ SKIP = {
|
||||
"vm-create-closure",
|
||||
# Lambda accessors (native type)
|
||||
"lambda?", "lambda-compiled", "lambda-set-compiled!", "lambda-name",
|
||||
# JIT dispatch (platform-specific)
|
||||
# JIT dispatch + active VM (platform-specific)
|
||||
"*active-vm*", "*jit-compile-fn*",
|
||||
"try-jit-call",
|
||||
"try-jit-call", "vm-call-closure",
|
||||
# Env access (used by env-walk)
|
||||
"env-walk", "env-walk-set!",
|
||||
# CEK interop
|
||||
@@ -372,6 +372,13 @@ let vm_create_closure vm_val frame_val code_val =
|
||||
VmClosure { vm_code = code; vm_upvalues = upvalues; vm_name = None;
|
||||
vm_env_ref = m.vm_globals; vm_closure_env = f.vf_closure.vm_closure_env }
|
||||
|
||||
(* --- JIT sentinel --- *)
|
||||
let _jit_failed_sentinel = {
|
||||
vm_code = { vc_arity = -1; vc_locals = 0; vc_bytecode = [||]; vc_constants = [||] };
|
||||
vm_upvalues = [||]; vm_name = Some "__jit_failed__"; vm_env_ref = Hashtbl.create 0; vm_closure_env = None
|
||||
}
|
||||
let _is_jit_failed cl = cl.vm_code.vc_arity = -1
|
||||
|
||||
(* --- Lambda accessors --- *)
|
||||
let is_lambda v = match v with Lambda _ -> Bool true | _ -> Bool false
|
||||
let lambda_compiled v = match v with
|
||||
@@ -380,7 +387,7 @@ let lambda_compiled v = match v with
|
||||
let lambda_set_compiled_b v c = match v with
|
||||
| Lambda l -> (match c with
|
||||
| VmClosure cl -> l.l_compiled <- Some cl; Nil
|
||||
| String "jit-failed" -> l.l_compiled <- Some Sx_vm.jit_failed_sentinel; Nil
|
||||
| String "jit-failed" -> l.l_compiled <- Some _jit_failed_sentinel; Nil
|
||||
| _ -> l.l_compiled <- None; Nil)
|
||||
| _ -> Nil
|
||||
let lambda_name v = match v with
|
||||
@@ -424,26 +431,45 @@ let env_walk_set_b env name value =
|
||||
if find e then Nil else Nil
|
||||
| _ -> Nil
|
||||
|
||||
(* --- Active VM tracking (module-level mutable state) --- *)
|
||||
let _active_vm : vm_machine option ref = ref None
|
||||
|
||||
(* Forward ref — resolved after transpiled let rec block *)
|
||||
let _vm_run_fn : (value -> value) ref = ref (fun _ -> Nil)
|
||||
let _vm_call_fn : (value -> value -> value -> value) ref = ref (fun _ _ _ -> Nil)
|
||||
|
||||
(* vm-call-closure: creates fresh VM, runs closure, returns result *)
|
||||
let vm_call_closure closure_val args globals =
|
||||
let cl = unwrap_closure closure_val in
|
||||
let prev_vm = !_active_vm in
|
||||
let g = match globals with Dict d -> d | _ -> Hashtbl.create 0 in
|
||||
let m = { vm_stack = Array.make 4096 Nil; vm_sp = 0;
|
||||
vm_frames = []; vm_globals = g; vm_pending_cek = None } in
|
||||
let vm_val = VmMachine m in
|
||||
_active_vm := Some m;
|
||||
ignore (vm_push_frame vm_val closure_val args);
|
||||
(try ignore (!_vm_run_fn vm_val) with e -> _active_vm := prev_vm; raise e);
|
||||
_active_vm := prev_vm;
|
||||
vm_pop vm_val
|
||||
|
||||
(* --- JIT dispatch (platform-specific) --- *)
|
||||
let try_jit_call vm_val f args =
|
||||
let m = unwrap_vm vm_val in
|
||||
match f with
|
||||
| Lambda l ->
|
||||
(match l.l_compiled with
|
||||
| Some cl when not (Sx_vm.is_jit_failed cl) ->
|
||||
(* Already compiled — run on VM *)
|
||||
(try vm_push vm_val (Sx_vm.call_closure cl (to_ocaml_list args) cl.vm_env_ref)
|
||||
| Some cl when not (_is_jit_failed cl) ->
|
||||
(try vm_push vm_val (vm_call_closure (VmClosure cl) args (Dict cl.vm_env_ref))
|
||||
with _ -> vm_push vm_val (cek_call_or_suspend vm_val f args))
|
||||
| Some _ ->
|
||||
(* Compile failed before — CEK fallback *)
|
||||
vm_push vm_val (cek_call_or_suspend vm_val f args)
|
||||
| None ->
|
||||
if l.l_name <> None then begin
|
||||
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
|
||||
l.l_compiled <- Some _jit_failed_sentinel;
|
||||
match !Sx_vm.jit_compile_ref l m.vm_globals with
|
||||
| Some cl ->
|
||||
l.l_compiled <- Some cl;
|
||||
(try vm_push vm_val (Sx_vm.call_closure cl (to_ocaml_list args) cl.vm_env_ref)
|
||||
(try vm_push vm_val (vm_call_closure (VmClosure cl) args (Dict cl.vm_env_ref))
|
||||
with _ -> vm_push vm_val (cek_call_or_suspend vm_val f args))
|
||||
| None ->
|
||||
vm_push vm_val (cek_call_or_suspend vm_val f args)
|
||||
@@ -536,7 +562,45 @@ def main():
|
||||
|
||||
bridge.stop()
|
||||
|
||||
output = PREAMBLE + "\n(* === Transpiled from lib/vm.sx === *)\n" + result + "\n"
|
||||
fixups = """
|
||||
|
||||
(* Wire forward references to transpiled functions *)
|
||||
let () = _vm_run_fn := vm_run
|
||||
let () = _vm_call_fn := vm_call
|
||||
|
||||
(* ================================================================
|
||||
Public API — matches Sx_vm interface for drop-in replacement
|
||||
================================================================ *)
|
||||
|
||||
(** Execute a compiled module — entry point for load-sxbc, compile-blob. *)
|
||||
let execute_module (code : vm_code) (globals : (string, value) Hashtbl.t) =
|
||||
let cl = { vm_code = code; vm_upvalues = [||]; vm_name = Some "module";
|
||||
vm_env_ref = globals; vm_closure_env = None } in
|
||||
let m = { vm_stack = Array.make 4096 Nil; vm_sp = 0;
|
||||
vm_frames = []; vm_globals = globals; vm_pending_cek = None } in
|
||||
let vm_val = VmMachine m in
|
||||
let frame = { vf_closure = cl; vf_ip = 0; vf_base = 0; vf_local_cells = Hashtbl.create 4 } in
|
||||
for _ = 0 to code.vc_locals - 1 do
|
||||
m.vm_stack.(m.vm_sp) <- Nil; m.vm_sp <- m.vm_sp + 1
|
||||
done;
|
||||
m.vm_frames <- [frame];
|
||||
ignore (vm_run vm_val);
|
||||
vm_pop vm_val
|
||||
|
||||
(** Execute a closure with args — entry point for JIT Lambda calls. *)
|
||||
let call_closure (cl : vm_closure) (args : value list) (globals : (string, value) Hashtbl.t) =
|
||||
vm_call_closure (VmClosure cl) (List args) (Dict globals)
|
||||
|
||||
(** Reexport code_from_value for callers *)
|
||||
let code_from_value = code_from_value
|
||||
|
||||
(** Reexport jit refs *)
|
||||
let jit_compile_ref = Sx_vm.jit_compile_ref
|
||||
let jit_failed_sentinel = _jit_failed_sentinel
|
||||
let is_jit_failed = _is_jit_failed
|
||||
|
||||
"""
|
||||
output = PREAMBLE + "\n(* === Transpiled from lib/vm.sx === *)\n" + result + "\n" + fixups
|
||||
|
||||
# Write output
|
||||
out_path = os.path.join(_HERE, "sx_vm_ref.ml")
|
||||
|
||||
Reference in New Issue
Block a user