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
|
|
@ -17,7 +17,7 @@
|
|||
[jolt.passes.fold :refer [const-fold]]
|
||||
[jolt.passes.inline :refer [inline-node flatten-lets scalar-replace dirty set-rec-shapes!]]
|
||||
[jolt.passes.types :refer [run-inference
|
||||
check-form infer-body reinfer-def
|
||||
check-form infer-body reinfer-def phint-seed
|
||||
set-rtenv! set-vtypes! join-types
|
||||
set-record-shapes! set-map-shapes! set-protocol-methods!
|
||||
reset-escapes! collected-escapes
|
||||
|
|
|
|||
|
|
@ -791,6 +791,24 @@
|
|||
(get fnode :arities))))
|
||||
def-node)))
|
||||
|
||||
(defn phint-seed
|
||||
"Positional declared-hint type seeds for a fn arity. Given the param-name
|
||||
vector and the arity's :phints (a seq of [name ctor-key] pairs), return a
|
||||
vector parallel to params whose slot i is the resolved record TYPE of that
|
||||
param's ^Record hint (via the record-shapes registry), or nil. The
|
||||
whole-program fixpoint seeds these as a param-type FLOOR so a declared hint
|
||||
propagates to a fn's callees DURING inference — not only at the final re-emit
|
||||
(reinfer-def). Without it a hinted param with no callers stays :any through the
|
||||
fixpoint, so a field read off it (e.g. (:origin ^Ray r)) never tells a shared
|
||||
callee its arg is a Vec3 (jolt-3ko)."
|
||||
[params phints]
|
||||
(let [m (reduce (fn [acc pr] (assoc acc (nth pr 0) (nth pr 1))) {} phints)]
|
||||
(mapv (fn [nm]
|
||||
(let [ck (get m nm)
|
||||
e (and ck (get @record-shapes-box ck))]
|
||||
(when e (record-type-from-entry e type-depth))))
|
||||
params)))
|
||||
|
||||
;; Piggyback checking (jolt audit). In direct-link mode infer-top already runs
|
||||
;; one inference pass for specialization; turning checking? on during it makes
|
||||
;; the success checker nearly free there (no extra traversal — just the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue