prototype: shape-record representation for vec3 maps (jolt-t34, JOLT_SHAPE)
Validated prototype of the hidden-class object-model change. A vec3-shaped
{:r :g :b} map literal is represented as a cheap Janet tuple [shape vb vg vr]
instead of a struct (~2x cheaper to construct); a lookup on a value the
inference PROVES is the shape reads by bare index with no runtime check.
Result on the ray tracer (direct-link): 12.3s -> 10.7s (~13% faster), with
byte-identical pixel output. The shape value flows transparently through
hit-info/ray/material containers and the colors vector; core-get handles it
(inline check, no fn call) so an unspecialized access is still correct.
Key lessons baked in: the lookup MUST compile to a bare index (a runtime
shape check, even inlined, taxed every field read and made it 2.5-3.4x
SLOWER) — so the inference gained a :shape hint (struct type with keys
exactly {:r :g :b}) that the back end turns into (in m idx). The descriptor
is quoted when embedded (its keys are a parens tuple Janet would otherwise
try to CALL).
All behind JOLT_SHAPE (off by default). Gate green, suite 4718, default-path
bench even. Scoped to the one shape; NOT yet sound in general (assumes every
vec3-shaped value is a shape-rec, true under the flag for the ray tracer) nor
fully transparent (only core-get + the inlined lookup; jolt-call/equality/
print/keys not yet covered). Those are the next steps toward a real feature.
This commit is contained in:
parent
50d8b13ca3
commit
d33fb85041
3 changed files with 93 additions and 9 deletions
|
|
@ -806,6 +806,17 @@
|
|||
;; k, if known, else :any.
|
||||
(defn- struct-safe? [t] (struct-type? t))
|
||||
(defn- field-type [t k] (if (struct-type? t) (get (sfields t) k :any) :any))
|
||||
;; vec3 shape detection (jolt-t34, prototype): a struct type whose key set is
|
||||
;; exactly {:r :g :b}. The back end represents such maps as shape tuples, so a
|
||||
;; lookup on a value PROVEN to be this shape can read by bare index with no
|
||||
;; runtime check. Scoped to the one shape for the prototype.
|
||||
(defn- vec3-shape? [t]
|
||||
(and (struct-type? t)
|
||||
(let [fs (sfields t)]
|
||||
(and (get fs :r) (get fs :g) (get fs :b) (= 3 (count (keys fs)))))))
|
||||
;; the structural hint for a subject: :shape when provably the vec3 shape (bare
|
||||
;; indexed read), else :struct when raw-get-safe.
|
||||
(defn- struct-hint [t] (if (vec3-shape? t) :shape :struct))
|
||||
;; tag a node (any expression, not just a :local) so the back end can specialize
|
||||
;; a lookup whose SUBJECT is that node — this is what makes nested access work:
|
||||
;; (:direction ray) is tagged struct, so (:r (:direction ray)) drops its guard.
|
||||
|
|
@ -929,7 +940,7 @@
|
|||
(let [t (get tenv (get node :name))]
|
||||
[(if t t :any)
|
||||
(cond
|
||||
(struct-safe? t) (assoc node :hint :struct)
|
||||
(struct-safe? t) (assoc node :hint (struct-hint t))
|
||||
(vec-type? t) (assoc node :hint :vector)
|
||||
:else node)])
|
||||
(= op :map)
|
||||
|
|
@ -987,7 +998,7 @@
|
|||
(and (= :const (get fnode :op)) (keyword? (get fnode :val)) (>= n 1) (<= n 2))
|
||||
(let [mr (infer (nth args 0) tenv)
|
||||
mt (nth mr 0)
|
||||
msub (if (struct-safe? mt) (mark-hint (nth mr 1) :struct) (nth mr 1))
|
||||
msub (if (struct-safe? mt) (mark-hint (nth mr 1) (struct-hint mt)) (nth mr 1))
|
||||
ft (field-type mt (get fnode :val))
|
||||
dr (when (= n 2) (infer (nth args 1) tenv))]
|
||||
[(if dr (join ft (nth dr 0)) ft)
|
||||
|
|
@ -998,7 +1009,7 @@
|
|||
(>= n 2) (= :const (get (nth args 1) :op)) (keyword? (get (nth args 1) :val)))
|
||||
(let [mr (infer (nth args 0) tenv)
|
||||
mt (nth mr 0)
|
||||
msub (if (struct-safe? mt) (mark-hint (nth mr 1) :struct) (nth mr 1))
|
||||
msub (if (struct-safe? mt) (mark-hint (nth mr 1) (struct-hint mt)) (nth mr 1))
|
||||
kr (infer (nth args 1) tenv)
|
||||
ft (field-type mt (get (nth args 1) :val))
|
||||
dr (when (= n 3) (infer (nth args 2) tenv))]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue