Propagate declared record hints through the whole-program fixpoint (jolt-3ko) (#134)
A ^Record param hint was applied only at the final re-emit (reinfer-def), not during the inter-procedural fixpoint. So a hinted param with no callers stayed :any while inference ran, and a field read off it (e.g. (:origin ^Ray r)) never told a non-inlined callee that its arg is a Vec3 — the callee's params stayed unproven and its field reads kept the dynamic guard. Seed declared hints as a param-type floor in the fixpoint: phint-seed (passes/ types) resolves an arity's :phints to positional record types via the record-shapes registry, and infer-unit! initializes each fn's fresh param slots from them instead of nil. A fixed declared type can't poison the least-fixpoint the way an early-iteration :any would, and a hinted param now propagates its (and its field reads') types to its callees during inference. Scope: this closes the hinted-propagation gap. It does NOT help the ray tracer, which uses zero ^-hinted params (only hinted fields) — its remaining type gap is unhinted record-param inference on recursive/non-inlined hot fns, and per the jolt-15jq A/B it's allocation-bound regardless (jolt-8flj). Tracked on the bead. Co-authored-by: Yogthos <yogthos@gmail.com>
This commit is contained in:
parent
30a12f39ff
commit
bd9e542c78
4 changed files with 116 additions and 4 deletions
|
|
@ -1023,6 +1023,7 @@
|
|||
(def f-set-rshapes (and pns (ns-find pns "set-record-shapes!"))) # jolt-t34
|
||||
(def f-set-mshapes (and pns (ns-find pns "set-map-shapes!"))) # jolt-t34
|
||||
(def f-set-pmethods (and pns (ns-find pns "set-protocol-methods!"))) # jolt-41m
|
||||
(def f-phint-seed (and pns (ns-find pns "phint-seed"))) # jolt-3ko
|
||||
(def f-get-esc (and pns (ns-find pns "collected-escapes")))
|
||||
(def report @{})
|
||||
(when (and f-set-rtenv f-set-vtypes f-join f-infer-body f-reinfer f-reset-esc f-get-esc)
|
||||
|
|
@ -1048,7 +1049,8 @@
|
|||
(unless (ar :rest)
|
||||
(def pv (vview (ar :params)))
|
||||
(def rec @{:key key :cell v :def d :params (ar :params) :body (ar :body)
|
||||
:np (length pv) :pt (array/new-filled (length pv)) :ret nil})
|
||||
:phints (ar :phints) :np (length pv)
|
||||
:pt (array/new-filled (length pv)) :ret nil})
|
||||
(array/push fns rec)
|
||||
(put by-key key rec)
|
||||
# a fn value is non-nil -> :truthy (sealed root in opt mode)
|
||||
|
|
@ -1060,6 +1062,13 @@
|
|||
# jolt-t34: feed record-ctor shapes + the map-shaping flag to the inference
|
||||
(when f-set-rshapes ((var-get f-set-rshapes) (or (get (ctx :env) :record-shapes) @{})))
|
||||
(when f-set-mshapes ((var-get f-set-mshapes) (get (ctx :env) :map-shapes?)))
|
||||
# jolt-3ko: resolve each fn's declared ^Record param hints to positional
|
||||
# type seeds (needs the registry above). Seeded as a param-type FLOOR in the
|
||||
# fixpoint so a hinted param propagates its (field-read) types to callees
|
||||
# during inference, not only at the final re-emit.
|
||||
(when f-phint-seed
|
||||
(each f fns
|
||||
(put f :phint-types (vview ((var-get f-phint-seed) (f :params) (or (f :phints) []))))))
|
||||
# jolt-41m: feed the protocol-method registry for devirtualization
|
||||
(when f-set-pmethods ((var-get f-set-pmethods) (or (get (ctx :env) :protocol-methods) @{})))
|
||||
# --- param/return/value-type fixpoint (chaotic iteration to LEAST fixpoint) ---
|
||||
|
|
@ -1083,9 +1092,17 @@
|
|||
# infer each def's VALUE type from its init
|
||||
(each dv defs
|
||||
(put dv :tvt (in (vview ((var-get f-infer-body) (dv :init) @{})) 0)))
|
||||
# recompute param types FRESH (start at bottom = nil) from this round's calls
|
||||
# recompute param types FRESH (start at bottom) from this round's calls.
|
||||
# Bottom is nil, EXCEPT a declared ^Record hint seeds its slot as a floor
|
||||
# (jolt-3ko) — a fixed declared type can't poison the fixpoint the way an
|
||||
# early-iteration :any would, and it lets a hinted param propagate to its
|
||||
# callees even when it has no callers of its own.
|
||||
(def newpt @{})
|
||||
(each f fns (put newpt (f :key) (array/new-filled (f :np))))
|
||||
(each f fns
|
||||
(def npa (array/new-filled (f :np)))
|
||||
(def phts (f :phint-types))
|
||||
(when phts (for i 0 (f :np) (when (in phts i) (put npa i (in phts i)))))
|
||||
(put newpt (f :key) npa))
|
||||
(each f fns
|
||||
(each c (vview (f :tcalls))
|
||||
(def cv (vview c))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue