sx-http: log JIT fallbacks once per function, not silently or flooding

JIT runtime errors now log once per function name via _jit_warned
hashtable, then stay quiet for that function. No more silent swallowing
(which hid real errors) or per-call flooding (which spammed thousands
of lines and blocked the server).

VM-level fallbacks (inside JIT-compiled code calling other JIT code)
are silent — dedup happens at the hook level.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 17:02:27 +00:00
parent 8e1870246d
commit 3620a433c1
2 changed files with 18 additions and 7 deletions

View File

@@ -690,15 +690,24 @@ let _jit_compiling = ref false (* re-entrancy guard *)
(* JIT compilation is lazy-only: every named lambda gets one compile
attempt on first call. Failures are sentineled (never retried). *)
let _jit_warned : (string, bool) Hashtbl.t = Hashtbl.create 16
let register_jit_hook env =
Sx_ref.jit_call_hook := Some (fun f args ->
match f with
| 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. *)
(* Cached bytecode — run on VM, fall back to CEK on runtime error.
Log once per function name, then stay quiet. Don't disable. *)
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
with _e -> None) (* silent fallback — no disable, no log *)
with e ->
let fn_name = match l.l_name with Some n -> n | None -> "?" in
if not (Hashtbl.mem _jit_warned fn_name) then begin
Hashtbl.replace _jit_warned fn_name true;
Printf.eprintf "[jit] %s runtime fallback to CEK: %s\n%!" fn_name (Printexc.to_string e)
end;
None)
| Some _ -> None (* compile failed or disabled — CEK handles *)
| None ->
let fn_name = match l.l_name with Some n -> n | None -> "?" in
@@ -715,7 +724,10 @@ 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 -> None) (* silent fallback, keep bytecode *)
with e ->
Printf.eprintf "[jit] %s first-call fallback to CEK: %s\n%!" fn_name (Printexc.to_string e);
Hashtbl.replace _jit_warned fn_name true;
None)
| None -> None
end)
| _ -> None)

View File

@@ -165,7 +165,8 @@ and vm_call vm f args =
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 ->
(* Silent fallback to CEK — error is data-dependent, not a JIT bug *)
(* Fallback to CEK — data-dependent error, not a JIT bug.
Dedup logging happens in register_jit_hook. *)
push vm (Sx_ref.cek_call f (List args)))
| Some _ ->
(* Compile failed — CEK *)
@@ -179,9 +180,7 @@ 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 ->
(* Don't mark failed — error may be data-dependent *)
push vm (Sx_ref.cek_call f (List args)))
with _e -> push vm (Sx_ref.cek_call f (List args)))
| None ->
push vm (Sx_ref.cek_call f (List args))
end