vm-ext: document CL call/cc-caller exclusion in plan

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 16:32:17 +00:00
parent 27b3aaedce
commit 3049ff92e4

View File

@@ -203,3 +203,34 @@ general fix is propagate-don't-rerun (run_tests' hook semantics) but that
surfaces genuine mid-run miscompiles as errors and must land with fixing/ surfaces genuine mid-run miscompiles as errors and must land with fixing/
excluding those — deferred (shared CEK/VM change). The default-OFF gate makes excluding those — deferred (shared CEK/VM change). The default-OFF gate makes
all of this opt-in, so nothing regresses by default. all of this opt-in, so nothing regresses by default.
---
## common-lisp residual resolved — call/cc-caller exclusion (2026-06-28)
Investigated the 6 CL opt-in-JIT failures. Findings:
- **geometry / mop-trace (0/0) are NOT JIT regressions** — they error "Undefined
symbol: refl-class-chain-depth-with" on BOTH CEK and JIT (the CLOS suites in
conformance.sh don't preload lib/guest/reflective/class-chain.sx). Pre-existing
harness gap; not counted in the 6.
- The **6 real failures** (parse-recover 4, interactive-debugger 2) were all
condition-system continuation escape. cl-restart-case/cl-handler-case/
cl-handler-bind wrap their body in call/cc. When an SX function driving the
condition system (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 → restart fails to abort,
body falls through. Seen as accumulation ((1 3 0 3) vs (1 3)) and no-abort
(999 sentinel). Also produced a +3 double-execution over-count (490 vs 487).
Fix: a third interpret-only signal beyond name/prefix and PUSH_HANDLER —
`jit-exclude-callers-of!` registers call/cc-establishing/invoking form names;
`jit_compile_lambda` skips any function whose constant pool (recursively)
references one (`code_refs_escaping_caller`). Guarded so it's a no-op for guests
that don't register. CL registers cl-restart-case/cl-handler-case/cl-handler-bind
(establish) + cl-invoke-restart/cl-invoke-debugger/cl-signal/cl-error-with-debugger
(invoke). Result: **CL under SX_SERVING_JIT=1 = 487/0, exactly matching CEK.**
The three interpret-only signals now: (1) name / "ns-*" prefix [jit-exclude!],
(2) PUSH_HANDLER in bytecode [guard users, structural], (3) references a
registered escaping form [call/cc-establishing callers]. Together they cover the
continuation-unsafe surface without a deep VM continuation rewrite.