sx-http: silent JIT fallback, load signals+engine, fix render-to-html

JIT runtime errors now silently fall back to CEK without disabling the
compiled bytecode or logging. This prevents render-to-html from being
permanently disabled when one page has an unresolved symbol (e.g. the
homepage stepper's <home).

Load spec/signals.sx and web/engine.sx for reactive primitives.
Skip test files and non-rendering directories (tests/, plans/, essays/).

Performance with JIT active (warm, single process, 2MB RSS):
- Aser (component expansion): 21-87ms — faster than Quart baseline
- SSR + shell: variable due to homepage <home fallback issue
- Geography total: ~500ms when JIT stays active

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 16:49:15 +00:00
parent 9fc13efa1a
commit 1d064a1914
2 changed files with 7 additions and 20 deletions

View File

@@ -696,14 +696,9 @@ let register_jit_hook env =
| Lambda l ->
(match l.l_compiled with
| Some cl when not (Sx_vm.is_jit_failed cl) ->
(* Cached bytecode — run on VM, fall back to CEK on runtime error.
Mark as failed so we don't retry on every call. *)
(* Cached bytecode — run on VM, fall back to CEK on runtime error. *)
(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)
with _e -> None) (* silent fallback — no disable, no log *)
| Some _ -> None (* compile failed or disabled — CEK handles *)
| None ->
let fn_name = match l.l_name with Some n -> n | None -> "?" in
@@ -720,10 +715,7 @@ let register_jit_hook env =
| 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)
with _e -> None) (* silent fallback, keep bytecode *)
| None -> None
end)
| _ -> None)

View File

@@ -164,10 +164,8 @@ and vm_call vm f args =
(* Cached bytecode — run on VM using the closure's captured env,
not the caller's globals. Closure vars were merged at compile time. *)
(try push vm (call_closure cl args cl.vm_env_ref)
with e ->
let msg = match e with Eval_error m -> m | e -> Printexc.to_string e in
Printf.eprintf "[vm] JIT call failed for %s: %s — falling back to CEK\n%!"
(match l.l_name with Some n -> n | None -> "<anon>") msg;
with _e ->
(* Silent fallback to CEK — error is data-dependent, not a JIT bug *)
push vm (Sx_ref.cek_call f (List args)))
| Some _ ->
(* Compile failed — CEK *)
@@ -181,11 +179,8 @@ and vm_call vm f args =
| Some cl ->
l.l_compiled <- Some cl;
(try push vm (call_closure cl args cl.vm_env_ref)
with e ->
let msg = match e with Eval_error m -> m | e -> Printexc.to_string e in
Printf.eprintf "[vm] JIT first-call failed for %s: %s — marking failed, falling back to CEK\n%!"
(match l.l_name with Some n -> n | None -> "<anon>") msg;
l.l_compiled <- Some jit_failed_sentinel;
with _e ->
(* Don't mark failed — error may be data-dependent *)
push vm (Sx_ref.cek_call f (List args)))
| None ->
push vm (Sx_ref.cek_call f (List args))