Browser JIT: compile SX lambdas to bytecode VM in WASM kernel
- Wire up jit_call_hook in sx_browser.ml (same pattern as server) - Deferred JIT: _jit_enabled flag, enabled after boot-init completes (prevents "Undefined symbol" errors from compiling during .sx loading) - enable-jit! native function called by sx-platform.js after boot - sx-platform.js: async WASM kernel polling + JIT enable after init - Error logging for JIT compile failures and runtime fallbacks Performance: 858ms → 431ms (WASM CEK) → 101ms (WASM JIT) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -555,7 +555,62 @@ let () =
|
||||
bind "request-arg" (fun args -> match args with [_; d] -> d | _ -> Nil);
|
||||
bind "request-method" (fun _ -> String "GET");
|
||||
bind "ctx" (fun _ -> Nil);
|
||||
bind "helper" (fun _ -> Nil)
|
||||
bind "helper" (fun _ -> Nil);
|
||||
()
|
||||
|
||||
(* ================================================================== *)
|
||||
(* JIT compilation hook *)
|
||||
(* *)
|
||||
(* On first call to a named lambda, try to compile it to bytecode via *)
|
||||
(* compiler.sx (loaded as an .sx platform file). Compiled closures run *)
|
||||
(* on the bytecode VM; failures fall back to the CEK interpreter. *)
|
||||
(* ================================================================== *)
|
||||
|
||||
let _jit_compiling = ref false
|
||||
let _jit_enabled = ref false
|
||||
|
||||
let () =
|
||||
(* Convert int-keyed env.bindings to string-keyed Hashtbl for VM globals *)
|
||||
let env_to_vm_globals env =
|
||||
let g = Hashtbl.create (Hashtbl.length env.bindings) in
|
||||
Hashtbl.iter (fun id v -> Hashtbl.replace g (unintern id) v) env.bindings;
|
||||
g
|
||||
in
|
||||
Sx_ref.jit_call_hook := Some (fun f args ->
|
||||
match f with
|
||||
| Lambda l when !_jit_enabled ->
|
||||
(match l.l_compiled with
|
||||
| Some cl when not (Sx_vm.is_jit_failed cl) ->
|
||||
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
|
||||
with e ->
|
||||
let fn_name = match l.l_name with Some n -> n | None -> "?" in
|
||||
Printf.eprintf "[jit] DISABLED %s — %s\n%!" fn_name (Printexc.to_string e);
|
||||
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
|
||||
None)
|
||||
| Some _ -> None
|
||||
| None ->
|
||||
if !_jit_compiling then None
|
||||
else begin
|
||||
_jit_compiling := true;
|
||||
let globals = env_to_vm_globals global_env in
|
||||
let compiled = Sx_vm.jit_compile_lambda l globals in
|
||||
_jit_compiling := false;
|
||||
let fn_name = match l.l_name with Some n -> n | None -> "?" in
|
||||
(match compiled with
|
||||
| Some cl ->
|
||||
l.l_compiled <- Some cl;
|
||||
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
|
||||
with e ->
|
||||
Printf.eprintf "[jit] DISABLED %s — %s\n%!" fn_name (Printexc.to_string e);
|
||||
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
|
||||
None)
|
||||
| None ->
|
||||
Printf.eprintf "[jit] FAIL %s\n%!" fn_name;
|
||||
None)
|
||||
end)
|
||||
| _ -> None)
|
||||
|
||||
let () = ignore (env_bind global_env "enable-jit!" (NativeFn ("enable-jit!", fun _ -> _jit_enabled := true; Nil)))
|
||||
|
||||
(* ================================================================== *)
|
||||
(* Register global SxKernel object *)
|
||||
|
||||
Reference in New Issue
Block a user