vm-ext: fix common-lisp condition-system JIT residual (call/cc-caller exclusion)
The 6 common-lisp opt-in-JIT failures were all condition-system continuation escape: cl-restart-case/cl-handler-case/cl-handler-bind wrap their body in call/cc (restarts + non-local handler exit). When an SX function that drives the condition system (the parse-recover / interactive-debugger fixtures, e.g. parse-numbers, make-policy-debugger) is JIT-compiled, the call/cc form runs in a NESTED cek-run where invoking the captured continuation runs-to-completion-and-returns instead of escaping — so a restart fails to abort and the body falls through. Observed as result accumulation (got (1 3 0 3) vs (1 3)) and no-abort (restart returns the 999 sentinel). These callers are arbitrary user/fixture code, not a fixed namespace, so they can't be prefix-excluded. New data-driven mechanism: - jit-exclude-callers-of! registers call/cc-establishing form names in Sx_types.jit_excluded_caller_names. - jit_compile_lambda skips any function whose constant pool (recursively, incl. nested closures) references a registered name — code_refs_escaping_caller. Guarded by Hashtbl.length > 0 so it's a no-op for every guest that doesn't register (zero effect outside CL). - lib/common-lisp/runtime.sx registers the establish side (cl-restart-case, cl-handler-case, cl-handler-bind) and the invoke side (cl-invoke-restart, cl-invoke-debugger, cl-signal, cl-error-with-debugger). Result: CL conformance under SX_SERVING_JIT=1 = 487/0, EXACTLY matching the CEK baseline (was 484/6 with a +3 double-execution over-count). parse-recover 3/4 -> 6/0, interactive-debugger 7/2 -> 7/0. Note: the geometry/mop-trace suites report 0/0 on BOTH CEK and JIT — they error "Undefined symbol: refl-class-chain-depth-with" (the CLOS suites don't preload lib/guest/reflective/class-chain.sx). Pre-existing conformance-harness gap, not a JIT issue; left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4175,6 +4175,16 @@ let () =
|
||||
match args with
|
||||
| [String n] | [Symbol n] -> Bool (Sx_types.jit_name_excluded n)
|
||||
| _ -> Bool false);
|
||||
register "jit-exclude-callers-of!" (fun args ->
|
||||
(* Register call/cc-establishing forms (e.g. cl-restart-case). Any function
|
||||
whose bytecode references one of these is itself interpret-only — JIT
|
||||
would force the form into a nested cek-run where its continuation can't
|
||||
escape. A guest declares its condition-system / escaping forms here. *)
|
||||
List.iter (fun a ->
|
||||
match a with
|
||||
| String n | Symbol n -> Hashtbl.replace Sx_types.jit_excluded_caller_names n ()
|
||||
| _ -> ()) args;
|
||||
Nil);
|
||||
register "jit-reset-counters!" (fun _args ->
|
||||
Sx_types.jit_compiled_count := 0;
|
||||
Sx_types.jit_skipped_count := 0;
|
||||
|
||||
Reference in New Issue
Block a user