smalltalk: per-call-site inline cache + 10 IC tests
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled

This commit is contained in:
2026-04-25 15:30:36 +00:00
parent 5d369daf2b
commit df62c02a21
4 changed files with 137 additions and 2 deletions

View File

@@ -212,6 +212,23 @@
exprs)
result))))
;; Per-call-site monomorphic inline cache: each `send` AST node stores
;; the receiver class and method record from the last dispatch. When the
;; next dispatch sees the same class AND the runtime's IC generation
;; hasn't changed, we skip the global method-lookup. Mutations to the
;; class table bump `st-ic-generation` (defined in runtime.sx) so stale
;; method records can't fire.
(define st-ic-hits 0)
(define st-ic-misses 0)
(define
st-ic-reset-stats!
(fn () (begin (set! st-ic-hits 0) (set! st-ic-misses 0))))
(define
st-ic-stats
(fn () {:hits st-ic-hits :misses st-ic-misses :gen st-ic-generation}))
(define
st-eval-send
(fn
@@ -223,7 +240,35 @@
(cond
(super?
(st-super-send (get frame :self) selector args (get frame :method-class)))
(else (st-send receiver selector args))))))
(else
(let ((cls (st-class-of-for-send receiver)))
(cond
;; Inline-cache hit: same receiver class, same generation.
((and (has-key? ast :ic-class)
(= (get ast :ic-class) cls)
(has-key? ast :ic-gen)
(= (get ast :ic-gen) st-ic-generation)
(has-key? ast :ic-method))
(begin
(set! st-ic-hits (+ st-ic-hits 1))
(st-invoke (get ast :ic-method) receiver args)))
(else
(begin
(set! st-ic-misses (+ st-ic-misses 1))
(let
((class-side? (st-class-ref? receiver))
(recv-class (if (st-class-ref? receiver)
(get receiver :name)
cls)))
(let ((method (st-method-lookup recv-class selector class-side?)))
(cond
((not (= method nil))
(begin
(dict-set! ast :ic-class cls)
(dict-set! ast :ic-method method)
(dict-set! ast :ic-gen st-ic-generation)
(st-invoke method receiver args)))
(else (st-send receiver selector args))))))))))))))
(define
st-eval-cascade