Post-10d: JIT measurement infrastructure + compiler fixes
Measurement: - JIT hit/miss/skip counters in sx_runtime.ml (jit_try_call) - VM instruction counter enabled in run loop - jit-enable, vm-counters, vm-counters-reset epoch commands - Test runner --jit flag for opt-in JIT measurement - Results (132 tests): 5.8% VM hit, 56% evaluator self-calls, 38% anon Fixes: - Move compile-provide, compile-scope, compile-guard, compile-guard-clauses inside define-library begin block (were orphaned outside, causing "Undefined symbol" JIT failures) - Add deref primitive (signal unwrap with tracking) - Add deref compiler dispatch - Fix compile-expr for scope forms to handle non-keyword args CEK pruning assessment: evaluator self-calls (56%) can't be pruned — the CEK must evaluate itself. Real pruning requires self-hosting compiler (Phase 2+). The VM correctly handles user code that JIT-compiles. 2776/2776 tests pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1455,17 +1455,68 @@ let run_spec_tests env test_files =
|
||||
let () =
|
||||
let args = Array.to_list Sys.argv |> List.tl in
|
||||
let foundation_only = List.mem "--foundation" args in
|
||||
let jit_enabled = List.mem "--jit" args in
|
||||
let test_files = List.filter (fun a -> not (String.length a > 0 && a.[0] = '-')) args in
|
||||
|
||||
(* Always run foundation tests *)
|
||||
run_foundation_tests ();
|
||||
|
||||
if not foundation_only then begin
|
||||
Printf.printf "\n=== SX Spec Tests (CEK Evaluator) ===\n%!";
|
||||
Printf.printf "\n=== SX Spec Tests (CEK Evaluator + JIT) ===\n%!";
|
||||
let env = make_test_env () in
|
||||
(* Load compiler and enable JIT (opt-in via --jit flag) *)
|
||||
if jit_enabled then begin
|
||||
let globals = Hashtbl.create 512 in
|
||||
let rec env_to_globals e =
|
||||
Hashtbl.iter (fun id v ->
|
||||
let name = Sx_types.unintern id in
|
||||
if not (Hashtbl.mem globals name) then
|
||||
Hashtbl.replace globals name v) e.Sx_types.bindings;
|
||||
match e.Sx_types.parent with Some p -> env_to_globals p | None -> ()
|
||||
in
|
||||
env_to_globals env;
|
||||
(try
|
||||
let compiler_path = if Sys.file_exists "lib/compiler.sx" then "lib/compiler.sx"
|
||||
else "../../lib/compiler.sx" in
|
||||
let ic = open_in compiler_path in
|
||||
let src = really_input_string ic (in_channel_length ic) in
|
||||
close_in ic; let _ = src in
|
||||
let exprs = Sx_parser.parse_all src in
|
||||
List.iter (fun e -> ignore (Sx_ref.eval_expr e (Env env))) exprs;
|
||||
env_to_globals env;
|
||||
Sx_runtime._jit_try_call_fn := Some (fun f args ->
|
||||
match f with
|
||||
| Lambda l ->
|
||||
(match l.l_compiled with
|
||||
| Some cl when not (Sx_vm.is_jit_failed cl) ->
|
||||
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref)
|
||||
with _ -> None)
|
||||
| Some _ -> None
|
||||
| None ->
|
||||
if l.l_name = None then None
|
||||
else begin
|
||||
l.l_compiled <- Some Sx_vm.jit_failed_sentinel;
|
||||
match Sx_vm.jit_compile_lambda l globals with
|
||||
| Some cl -> l.l_compiled <- Some cl;
|
||||
(try Some (Sx_vm.call_closure cl args cl.vm_env_ref) with _ -> None)
|
||||
| None -> None
|
||||
end)
|
||||
| _ -> None);
|
||||
Printf.printf "[jit] Compiler loaded, JIT enabled\n%!"
|
||||
with e ->
|
||||
Printf.printf "[jit] Compiler not loaded: %s\n%!" (Printexc.to_string e));
|
||||
end;
|
||||
Sx_runtime.jit_reset_counters ();
|
||||
run_spec_tests env test_files
|
||||
end;
|
||||
|
||||
(* JIT statistics *)
|
||||
let jh = !(Sx_runtime._jit_hit) and jm = !(Sx_runtime._jit_miss) and js = !(Sx_runtime._jit_skip) in
|
||||
let total = jh + jm + js in
|
||||
if total > 0 then
|
||||
Printf.printf "\n[jit] calls=%d hit=%d (%.1f%%) miss=%d skip=%d\n"
|
||||
total jh (100.0 *. float_of_int jh /. float_of_int (max 1 total)) jm js;
|
||||
|
||||
(* Summary *)
|
||||
Printf.printf "\n%s\n" (String.make 60 '=');
|
||||
Printf.printf "Results: %d passed, %d failed\n" !pass_count !fail_count;
|
||||
|
||||
Reference in New Issue
Block a user