Fix root cause: skip JIT for closure lambdas in BOTH hook and vm_call
The closure check was only in vm_call (sx_vm.ml) but inner functions like read-list-loop were also compiled through the JIT hook in sx_server.ml. The hook compiled them with closure merging, producing incorrect bytecode (read-list-loop mishandled closing parens). Added the same closure check to the JIT hook: skip lambdas with non-empty closures. Now sx-parse works correctly: (a (b) (c)) → 3 siblings, not (a (b (c))) Pre-compiled count increased from 17 to 33 — more top-level functions compiled (inner ones correctly skipped to CEK). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -913,6 +913,10 @@ let register_jit_hook env =
|
|||||||
| Some _ -> None (* compile failed — CEK handles *)
|
| Some _ -> None (* compile failed — CEK handles *)
|
||||||
| None ->
|
| None ->
|
||||||
if !_jit_compiling then None
|
if !_jit_compiling then None
|
||||||
|
else if Hashtbl.length l.l_closure.bindings > 0
|
||||||
|
|| l.l_closure.parent <> None then
|
||||||
|
(* Skip JIT for lambdas with closure bindings *)
|
||||||
|
None
|
||||||
else begin
|
else begin
|
||||||
let fn_name = match l.l_name with Some n -> n | None -> "?" in
|
let fn_name = match l.l_name with Some n -> n | None -> "?" in
|
||||||
_jit_compiling := true;
|
_jit_compiling := true;
|
||||||
|
|||||||
@@ -440,16 +440,6 @@ class OcamlBridge:
|
|||||||
_logger.warning("OCaml load skipped %s: %s",
|
_logger.warning("OCaml load skipped %s: %s",
|
||||||
filepath, e)
|
filepath, e)
|
||||||
|
|
||||||
# JIT workaround: sx-parse has a complex letrec (20 mutually
|
|
||||||
# recursive functions) that the JIT compiles incorrectly —
|
|
||||||
# closing parens cause siblings to become children.
|
|
||||||
# CEK-interpreted sx-parse works correctly.
|
|
||||||
try:
|
|
||||||
await self._send('(vm-reset-fn "sx-parse")')
|
|
||||||
await self._read_until_ok(ctx=None)
|
|
||||||
except OcamlBridgeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# SSR overrides: effect is a no-op on the server (prevents
|
# SSR overrides: effect is a no-op on the server (prevents
|
||||||
# reactive loops during island SSR — effects are DOM side-effects)
|
# reactive loops during island SSR — effects are DOM side-effects)
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user