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:
@@ -1393,6 +1393,20 @@ let () =
|
||||
end else Nil
|
||||
| _ -> Nil);
|
||||
|
||||
(* deref — unwrap a signal value with reactive dependency tracking.
|
||||
If value is a Signal, returns s_value and registers in tracking context.
|
||||
Otherwise returns value as-is. *)
|
||||
register "deref" (fun args ->
|
||||
match args with
|
||||
| [Signal sig'] ->
|
||||
if !_tracking_active then begin
|
||||
if not (List.memq (Signal sig') !_tracking_deps) then
|
||||
_tracking_deps := Signal sig' :: !_tracking_deps
|
||||
end;
|
||||
sig'.s_value
|
||||
| [v] -> v
|
||||
| _ -> Nil);
|
||||
|
||||
(* bind — create a tracked computation. Takes a body-fn (lambda).
|
||||
Starts tracking, evaluates body, collects deps, subscribes.
|
||||
On dep change: unsubscribes, re-evaluates, re-subscribes.
|
||||
|
||||
@@ -470,13 +470,17 @@ let mutable_list () = ListRef (ref [])
|
||||
(* JIT try-call — ref set by sx_server.ml after compiler loads.
|
||||
Returns Nil (no JIT) or the result value. Spec calls this. *)
|
||||
let _jit_try_call_fn : (value -> value list -> value option) option ref = ref None
|
||||
let _jit_hit = ref 0
|
||||
let _jit_miss = ref 0
|
||||
let _jit_skip = ref 0
|
||||
let jit_reset_counters () = _jit_hit := 0; _jit_miss := 0; _jit_skip := 0
|
||||
let jit_try_call f args =
|
||||
match !_jit_try_call_fn with
|
||||
| None -> Nil
|
||||
| None -> incr _jit_skip; Nil
|
||||
| Some hook ->
|
||||
match f with
|
||||
| Lambda l when l.l_name <> None ->
|
||||
let arg_list = match args with List a | ListRef { contents = a } -> a | _ -> [] in
|
||||
(match hook f arg_list with Some result -> result | None -> Nil)
|
||||
| _ -> Nil
|
||||
(match hook f arg_list with Some result -> incr _jit_hit; result | None -> incr _jit_miss; Nil)
|
||||
| _ -> incr _jit_skip; Nil
|
||||
|
||||
|
||||
@@ -204,6 +204,7 @@ let jit_compile_comp ~name ~params ~has_children ~body ~closure globals =
|
||||
Returns the result value, or raises VmSuspended if CEK suspends.
|
||||
Saves the suspended CEK state in vm.pending_cek for later resume. *)
|
||||
let cek_call_or_suspend vm f args =
|
||||
incr _vm_cek_count;
|
||||
let a = match args with Nil -> [] | List l -> l | _ -> [args] in
|
||||
let state = Sx_ref.continue_with_call f (List a) (Env (Sx_types.make_env ())) (List a) (List []) in
|
||||
let final = Sx_ref.cek_step_loop state in
|
||||
@@ -358,6 +359,7 @@ and run vm =
|
||||
let saved_ip = frame.ip in
|
||||
let op = bc.(frame.ip) in
|
||||
frame.ip <- frame.ip + 1;
|
||||
incr _vm_insn_count;
|
||||
(try match op with
|
||||
(* ---- Constants ---- *)
|
||||
| 1 (* OP_CONST *) ->
|
||||
|
||||
Reference in New Issue
Block a user