Restore recursive cek_run, remove step counter/limit
The iterative cek_run with Atomic step counting and debug prints added overhead and complexity. The debug print called value_to_str twice per million steps which could be very slow on large expressions. Restore the original recursive cek_run from before the iterative conversion. Remove the step limit mechanism (was causing render timeouts). The recursive version is simpler and proven. 1166 passed, 0 failed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2017,9 +2017,6 @@ let http_mode port =
|
|||||||
in
|
in
|
||||||
match work with
|
match work with
|
||||||
| Some (fd, path, headers) ->
|
| Some (fd, path, headers) ->
|
||||||
(* ~10M steps ≈ 3-5 seconds of CEK evaluation *)
|
|
||||||
Atomic.set Sx_ref._step_count 0;
|
|
||||||
Atomic.set Sx_ref._step_limit 10_000_000;
|
|
||||||
let response =
|
let response =
|
||||||
try
|
try
|
||||||
let is_ajax = List.exists (fun (k, _) -> k = "sx-request" || k = "hx-request") headers in
|
let is_ajax = List.exists (fun (k, _) -> k = "sx-request" || k = "hx-request") headers in
|
||||||
@@ -2035,7 +2032,6 @@ let http_mode port =
|
|||||||
Printf.eprintf "[render] Error for %s: %s\n%!" path (Printexc.to_string e);
|
Printf.eprintf "[render] Error for %s: %s\n%!" path (Printexc.to_string e);
|
||||||
http_response ~status:500 "<h1>Internal Server Error</h1>"
|
http_response ~status:500 "<h1>Internal Server Error</h1>"
|
||||||
in
|
in
|
||||||
Atomic.set Sx_ref._step_limit 0;
|
|
||||||
write_response fd response
|
write_response fd response
|
||||||
| None -> ()
|
| None -> ()
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -30,12 +30,6 @@ let _last_error_kont : value ref = ref Nil
|
|||||||
|
|
||||||
(* === Transpiled from evaluator (frames + eval + CEK) === *)
|
(* === Transpiled from evaluator (frames + eval + CEK) === *)
|
||||||
|
|
||||||
(* Per-domain step limit (0 = no limit).
|
|
||||||
Set by the HTTP render worker before each page render.
|
|
||||||
Checked every 4096 CEK steps in cek_run. *)
|
|
||||||
let _step_limit : int Atomic.t = Atomic.make 0
|
|
||||||
let _step_count : int Atomic.t = Atomic.make 0
|
|
||||||
|
|
||||||
(* make-cek-state *)
|
(* make-cek-state *)
|
||||||
let rec make_cek_state control env kont =
|
let rec make_cek_state control env kont =
|
||||||
(CekState { cs_control = control; cs_env = env; cs_kont = kont; cs_phase = "eval"; cs_value = Nil })
|
(CekState { cs_control = control; cs_env = env; cs_kont = kont; cs_phase = "eval"; cs_value = Nil })
|
||||||
@@ -378,29 +372,13 @@ and sf_provide args env =
|
|||||||
and expand_macro mac raw_args env =
|
and expand_macro mac raw_args env =
|
||||||
(let local = (env_merge ((macro_closure (mac))) (env)) in (let () = ignore ((List.iter (fun pair -> ignore ((env_bind local (sx_to_string (first (pair))) (if sx_truthy ((prim_call "<" [(nth (pair) ((Number 1.0))); (len (raw_args))])) then (nth (raw_args) ((nth (pair) ((Number 1.0))))) else Nil)))) (sx_to_list (List (List.mapi (fun i p -> let i = Number (float_of_int i) in (List [p; i])) (sx_to_list (macro_params (mac)))))); Nil)) in (let () = ignore ((if sx_truthy ((macro_rest_param (mac))) then (env_bind local (sx_to_string (macro_rest_param (mac))) (prim_call "slice" [raw_args; (len ((macro_params (mac))))])) else Nil)) in (trampoline ((eval_expr ((macro_body (mac))) (local)))))))
|
(let local = (env_merge ((macro_closure (mac))) (env)) in (let () = ignore ((List.iter (fun pair -> ignore ((env_bind local (sx_to_string (first (pair))) (if sx_truthy ((prim_call "<" [(nth (pair) ((Number 1.0))); (len (raw_args))])) then (nth (raw_args) ((nth (pair) ((Number 1.0))))) else Nil)))) (sx_to_list (List (List.mapi (fun i p -> let i = Number (float_of_int i) in (List [p; i])) (sx_to_list (macro_params (mac)))))); Nil)) in (let () = ignore ((if sx_truthy ((macro_rest_param (mac))) then (env_bind local (sx_to_string (macro_rest_param (mac))) (prim_call "slice" [raw_args; (len ((macro_params (mac))))])) else Nil)) in (trampoline ((eval_expr ((macro_body (mac))) (local)))))))
|
||||||
|
|
||||||
(* cek-run — iterative loop to avoid JS stack overflow in WASM *)
|
(* cek-run *)
|
||||||
and cek_run state =
|
and cek_run state =
|
||||||
let s = ref state in
|
(if sx_truthy ((cek_terminal_p (state))) then (cek_value (state)) else
|
||||||
(try
|
try cek_run ((cek_step (state)))
|
||||||
let n = ref 0 in
|
with Eval_error msg ->
|
||||||
while not (match cek_terminal_p !s with Bool true -> true | _ -> false) do
|
(if !_last_error_kont = Nil then _last_error_kont := cek_kont state);
|
||||||
s := cek_step !s;
|
raise (Eval_error msg))
|
||||||
incr n;
|
|
||||||
if !n land 4095 = 0 then begin
|
|
||||||
let lim = Atomic.get _step_limit in
|
|
||||||
if lim > 0 && !n >= lim then
|
|
||||||
raise (Eval_error (Printf.sprintf "Render step limit exceeded (%d steps)" !n));
|
|
||||||
if !n land 1048575 = 0 then
|
|
||||||
Printf.eprintf "[cek] %d steps, phase=%s control=%s\n%!" !n
|
|
||||||
(match cek_phase !s with String p -> p | _ -> "?")
|
|
||||||
(String.sub (Sx_runtime.value_to_str (cek_control !s)) 0
|
|
||||||
(min 80 (String.length (Sx_runtime.value_to_str (cek_control !s)))))
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
cek_value !s
|
|
||||||
with Eval_error msg ->
|
|
||||||
(if !_last_error_kont = Nil then _last_error_kont := cek_kont !s);
|
|
||||||
raise (Eval_error msg))
|
|
||||||
|
|
||||||
(* cek-step *)
|
(* cek-step *)
|
||||||
and cek_step state =
|
and cek_step state =
|
||||||
|
|||||||
Reference in New Issue
Block a user