From 55f3024743d4686f63b2f44f5816408be6ebcba1 Mon Sep 17 00:00:00 2001 From: giles Date: Sat, 25 Apr 2026 04:57:49 +0000 Subject: [PATCH] forth: JIT cooperation hooks (vm-eligible flag + call-count + forth-hot-words) --- lib/forth/interpreter.sx | 34 +++++++++++++++++++++++++++++++++- lib/forth/runtime.sx | 8 ++++++++ lib/forth/scoreboard.json | 2 +- lib/forth/scoreboard.md | 2 +- plans/forth-on-sx.md | 14 +++++++++++++- 5 files changed, 56 insertions(+), 4 deletions(-) diff --git a/lib/forth/interpreter.sx b/lib/forth/interpreter.sx index 4ffba3f1..fe6ac569 100644 --- a/lib/forth/interpreter.sx +++ b/lib/forth/interpreter.sx @@ -5,7 +5,39 @@ (define forth-execute-word - (fn (state word) (let ((body (get word "body"))) (body state)))) + (fn + (state word) + (dict-set! word "call-count" (+ 1 (or (get word "call-count") 0))) + (let ((body (get word "body"))) (body state)))) + +(define + forth-hot-words + (fn + (state threshold) + (forth-hot-walk + (keys (get state "dict")) + (get state "dict") + threshold + (list)))) + +(define + forth-hot-walk + (fn + (names dict threshold acc) + (if + (= (len names) 0) + acc + (let + ((n (first names))) + (let + ((w (get dict n))) + (let + ((c (or (get w "call-count") 0))) + (forth-hot-walk + (rest names) + dict + threshold + (if (>= c threshold) (cons (list n c) acc) acc)))))))) (define forth-interpret-token diff --git a/lib/forth/runtime.sx b/lib/forth/runtime.sx index a0c4919f..fd9308e2 100644 --- a/lib/forth/runtime.sx +++ b/lib/forth/runtime.sx @@ -193,6 +193,12 @@ forth-emit-str (fn (state s) (dict-set! state "output" (str (get state "output") s)))) +;; The body is always a plain SX lambda — primitives and colon-def +;; bodies alike — which means the SX VM's JIT-on-first-call can lift +;; the body directly into bytecode. We tag every word `:vm-eligible? +;; true` so downstream JIT cooperation (a tracing layer, a hot-call +;; counter) can pick out the JIT-friendly entries by metadata rather +;; than by inspecting the body shape. (define forth-make-word (fn @@ -202,6 +208,8 @@ (dict-set! w "kind" kind) (dict-set! w "body" body) (dict-set! w "immediate?" immediate?) + (dict-set! w "vm-eligible?" true) + (dict-set! w "call-count" 0) w))) (define diff --git a/lib/forth/scoreboard.json b/lib/forth/scoreboard.json index 5f7d0569..6b605a51 100644 --- a/lib/forth/scoreboard.json +++ b/lib/forth/scoreboard.json @@ -1,6 +1,6 @@ { "source": "gerryjackson/forth2012-test-suite src/core.fr", - "generated_at": "2026-04-25T04:00:01Z", + "generated_at": "2026-04-25T04:57:22Z", "chunks_available": 638, "chunks_fed": 638, "total": 638, diff --git a/lib/forth/scoreboard.md b/lib/forth/scoreboard.md index ad1b1fc6..fc8d8485 100644 --- a/lib/forth/scoreboard.md +++ b/lib/forth/scoreboard.md @@ -11,7 +11,7 @@ | percent | 96% | - **Source**: `gerryjackson/forth2012-test-suite` `src/core.fr` -- **Generated**: 2026-04-25T04:00:01Z +- **Generated**: 2026-04-25T04:57:22Z - **Note**: completed A "chunk" is any preprocessed segment ending at a `}T` (every Hayes test diff --git a/plans/forth-on-sx.md b/plans/forth-on-sx.md index 7476f759..96fb0ebc 100644 --- a/plans/forth-on-sx.md +++ b/plans/forth-on-sx.md @@ -100,12 +100,24 @@ Representation: ### Phase 6 — speed - [x] Inline primitive calls during compile (skip dict lookup) - [x] Tail-call optimise colon-def endings -- [ ] JIT cooperation: mark compiled colon-defs as VM-eligible +- [x] JIT cooperation: mark compiled colon-defs as VM-eligible ## Progress log _Newest first._ +- **Phase 6 close — JIT cooperation hooks (Hayes unchanged at 618/638).** + Every word record now carries `:vm-eligible? true` and a + `:call-count` counter that `forth-execute-word` bumps on every + invocation. The flag is a hint for downstream JIT consumers — our + bodies are plain SX lambdas already, so the existing SX VM's + on-first-call JIT lifts them into bytecode automatically; the + metadata just makes that fact discoverable. Added + `forth-hot-words state threshold` returning `(name count)` + pairs above a threshold so a future tracing JIT can pick out + hot definitions to specialise. Phase 6 boxes all ticked. + All 306 internal tests green; Hayes Core stays at 618/638. + - **Phase 6 — TCO at colon-def endings (Hayes unchanged at 618/638).** `forth-run-body` now special-cases the final op when it's a plain function (not a branch dict): we call it in tail position with no