mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-03 11:58:11 +08:00
Rewrite the runtime representation to the landed frame model
This commit is contained in:
@@ -7,7 +7,7 @@ declare their attribute reads and writes in their signatures, and the
|
|||||||
compiler resolves every access to a byte offset during wiring, so there is
|
compiler resolves every access to a byte offset during wiring, so there is
|
||||||
no name lookup at runtime. Storage and batch results are per-attribute
|
no name lookup at runtime. Storage and batch results are per-attribute
|
||||||
columns. The contiguous record only exists as a per-lane view, assembled
|
columns. The contiguous record only exists as a per-lane view, assembled
|
||||||
into activation frames on a per-thread stack. All of the machinery that could
|
into frames claimed from the evaluation's frame space. All of the machinery that could
|
||||||
corrupt a layout is generated code, so getting it wrong is a type error or
|
corrupt a layout is generated code, so getting it wrong is a type error or
|
||||||
a graph compile error rather than undefined behavior.
|
a graph compile error rather than undefined behavior.
|
||||||
|
|
||||||
@@ -431,34 +431,37 @@ level with resolved offsets is the base case both are built on.
|
|||||||
|
|
||||||
## Runtime representation
|
## Runtime representation
|
||||||
|
|
||||||
- Every node's per-lane output is an activation frame on a per-thread
|
- Every node's per-lane output lands in a frame claimed from the
|
||||||
record stack, callee-fills-then-reclaims discipline: an evaluation
|
evaluation's frame space: a grow-only buffer the executor owns and
|
||||||
claims its frame at the stack pointer, evaluates its inputs beyond it,
|
lends down, sized at wiring by folding each path's frame need, so
|
||||||
writes its result into the frame, and then reclaims everything above
|
exhaustion is an accounting failure a debug assertion catches rather
|
||||||
the frame while keeping the frame itself for its consumer. So a node
|
than a hot-path branch, and frame bytes carry no drop glue. A node's
|
||||||
advances the stack by exactly its own frame, and every already-
|
caller mints the node's frame claim out of its own free space; the
|
||||||
evaluated input stays live until the node returns, which makes values
|
node writes through the claim and closes it through `serve`, the
|
||||||
held across sibling evaluations safe by construction. "Allocating" a
|
`Node` trait's one required method, whose `Served` proof is mintable
|
||||||
result is pointer arithmetic; transients never touch the arena, and
|
only by the claim's closing methods, so a served record is of the
|
||||||
publishing into a cache copies out of the stack. An inline node
|
claimed layout by construction. The claim carries the free space
|
||||||
returns its output by value with no frame, so it reclaims its inputs
|
beyond the frame, the node's inputs claim past it one after another,
|
||||||
by rewinding to its entry pointer instead. A loop that re-evaluates a
|
and a claim's space is free again when the claim dies, on value,
|
||||||
subtree per iteration rewinds to a checkpoint each time, reusing the
|
error, and pending exits alike, with no per-exit ritual. "Allocating"
|
||||||
slots.
|
a result is cursor arithmetic; a droppable payload parks in the arena
|
||||||
|
once and the record carries the reference.
|
||||||
- No global slot assignment exists: a node's wiring state is its own
|
- No global slot assignment exists: a node's wiring state is its own
|
||||||
frame size, so incremental recompiles and instance reuse cannot
|
frame size, so incremental recompiles and instance reuse cannot
|
||||||
invalidate storage, and the stack belongs to whichever thread runs
|
invalidate storage. The frame space belongs to the evaluation rather
|
||||||
the evaluation, created lazily in thread-local storage, so worker
|
than to a thread, so worker counts never enter wiring. The reserve is
|
||||||
counts never enter wiring. The reserve is the peak of a per-path fold
|
the peak of a per-path fold over the graph (a node's need is its own
|
||||||
over the graph (a node's need is its own frame plus its inputs' frames
|
frame plus its inputs' frames plus the deepest input's peak), computed
|
||||||
plus the deepest input's peak), computed once at wiring; it exceeds
|
once at wiring; it exceeds the plain sum of node frames because
|
||||||
the plain sum of node frames because fan-out re-evaluation keeps
|
fan-out re-evaluation keeps several copies of a shared node's frame
|
||||||
several copies of a shared node's frame live at once.
|
live at once.
|
||||||
- Held record values are safe without a guard: a frame keeps its output
|
- Held record values are safe without a guard: a claim keeps its record
|
||||||
until its consumer reclaims it, so no input is released while a later
|
until it dies, so no input is released while a later sibling
|
||||||
sibling evaluates. This relies on stack records being single-consumer,
|
evaluates. Shared subtrees additionally rely on single consumption.
|
||||||
which the frame-memo insertion at fan-out points guarantees by copying
|
The compiler's boundary frame memos provide it where the
|
||||||
a shared value off the stack rather than holding it across consumers.
|
nullification pass inserts them; automatic insertion at every fan-out
|
||||||
|
is designed but not built, and until it lands it gates the
|
||||||
|
stack-return optimization for shared un-memoized subtrees.
|
||||||
- Batch results are a run of lanes behind a resolved offset per field,
|
- Batch results are a run of lanes behind a resolved offset per field,
|
||||||
and the target form is per-field columns, each statically Varying (an
|
and the target form is per-field columns, each statically Varying (an
|
||||||
array) or Uniform (a single value) per the residency analysis. A node
|
array) or Uniform (a single value) per the residency analysis. A node
|
||||||
@@ -470,7 +473,9 @@ level with resolved offsets is the base case both are built on.
|
|||||||
first implementation lays the run out as an array of records and
|
first implementation lays the run out as an array of records and
|
||||||
resolves each marker to an offset within a lane; moving that to
|
resolves each marker to an offset within a lane; moving that to
|
||||||
struct-of-arrays, and then to flat tables, happens behind the same
|
struct-of-arrays, and then to flat tables, happens behind the same
|
||||||
accessors.
|
accessors. A batched producer serves lanes in place over the caller's
|
||||||
|
scratch through a claimed run of same-layout slots, so a lane serves
|
||||||
|
with no staging copy.
|
||||||
- A materialized level carries its lane count beside its layout and its
|
- A materialized level carries its lane count beside its layout and its
|
||||||
storage, which is either an arena-resident run or an owned copy.
|
storage, which is either an arena-resident run or an owned copy.
|
||||||
Erased consumers (the Data panel, capture, deep copy) read the count
|
Erased consumers (the Data panel, capture, deep copy) read the count
|
||||||
@@ -480,7 +485,7 @@ level with resolved offsets is the base case both are built on.
|
|||||||
a batch result, so materializing a level and returning a batch are one
|
a batch result, so materializing a level and returning a batch are one
|
||||||
format. A record value is one pointer wide, and only a record whose
|
format. A record value is one pointer wide, and only a record whose
|
||||||
layout is empty rides inside the value itself; everything else spills
|
layout is empty rides inside the value itself; everything else spills
|
||||||
to the stack.
|
to claimed frame space.
|
||||||
- Alignment padding is what the column form buys. In a row, a `u8`
|
- Alignment padding is what the column form buys. In a row, a `u8`
|
||||||
element costs the same as a `u64`, while packed columns keep the cost
|
element costs the same as a `u64`, while packed columns keep the cost
|
||||||
proportional to the element size (2x cheaper than rows when
|
proportional to the element size (2x cheaper than rows when
|
||||||
|
|||||||
Reference in New Issue
Block a user