Take this modest JavaScript function:
```js
function hot(a, b) {
return a + b;
}
```
It sits in a tight loop, called again and again — always with small integers. V8’s first‑tier compiler, Ignition, cheerfully interprets its bytecode, but all the while it’s also collecting a tiny memory: a feedback vector that clings to the function, silently recording what types actually show up at each operation. That scrap of runtime intelligence is the seed from which TurboFan grows its speculative, near‑native machine code. Let’s watch the transformation step by step, from raw feedback to the planted type guard and the control fork that makes it lightning fast.
The feedback vector is an array of slots, one for each bytecode that can benefit from profiling. For our `+` operation at bytecode offset 3, Ignition has stored a hint in the slot that indicates the operands have consistently been small integers (Smis). The hint is encoded compactly — a type feedback summary derived from observed object shapes and values — and its meaning is simply: “At this call site, the operands are always Smis.” This is the shapeless observation, a heat signature waiting to be read.
When TurboFan decides to optimise `hot`, it enters the Graph Builder phase. Here, each bytecode is translated into nodes in the Sea of Nodes IR. The builder encounters the `Add` bytecode and immediately reaches for the FeedbackNexus that wraps that feedback slot. The nexus reads the hint and hands it to a selector, which decides which high‑level node to plant:
- If the hint indicated no useful feedback (a polymorphic or unknown usage), it would emit a generic `JSAdd` node that can handle anything — slow, full of implicit calls and type coercions.
- With the hint signalling Smis, it selects a `SpeculativeSafeIntegerAdd` (or, in other configurations, a `SpeculativeNumberAdd`). This node is an assertion carved in IR: *I will assume both inputs are Smis, and I will add them without overflow handling; if the assumption ever fails, execution must bail out.*
And here the transformation becomes tangible. The `SpeculativeSafeIntegerAdd` node is not a simple arithmetic operator. In the Sea of Nodes, it takes the two value inputs (the loaded registers for `a` and `b`) and, crucially, it also weaves itself into the control and effect chains. Its output is a split: one control edge continues to the next bytecode’s node on the happy path, and another forks off to a `Deoptimize` node — a quiet trapdoor. If either input ever turns out not to be a Smi at runtime, the CPU never attempts the speculative addition; instead, control leaps directly along that deoptimization edge. V8’s runtime machinery then reconstructs the interpreter state at exactly this point and resumes execution in Ignition, using the fully generic `+` semantics. The graph already contains the diamond: one path to a `Return`, the other to a `Deoptimize`.
Later, during the lowering and typing phases, this high‑level speculation is mechanically refined. The graph is restructured: explicit type guard nodes are inserted to check the Smi condition, a pure integer addition replaces the speculative arithmetic, and the deoptimization branch is preserved as the fallback. The fork becomes more granular, but the seed was planted the moment the Graph Builder read the hint. That’s the alchemy: a compact type record in a feedback slot grows into a guarded control split, a hard‑wired commitment that turns a generic `a + b` into a single integer addition with a built‑in safety net.
The result is a shape in the Sea of Nodes that looks nothing like the original bytecode. Where there was once a single generic `Add` instruction, there now stands a type‑checking fork, a pure arithmetic node, and a deoptimization branch — all because the profiler whispered “they’re always Smis.” That is how raw, shapeless observation is transmuted into concrete IR structure that a scheduling pass can linearize into a tight sequence of machine instructions worth a few cycles. The feedback vector is not just a record; it is the blueprint for a speculation that, guarded by that control split, can run at full metal speed, knowing it can always safely fall back to the interpreter if the world changes.
Comments
No comments yet — be the first.