Chromium · v8/

The V8 pipeline

Checked out as a dependency and shipped inside the renderer, where Blink drives it through the bindings layer. It has its own release cadence, its own embedders — Node.js among them — and a pipeline of four compile tiers that has nothing to do with the browser around it.

01

Parser & preparser

source → AST

The scanner reads the source once. The preparser skims function bodies it can defer, recording only the scope information needed to compile them later, and a full parse happens the first time a function is actually called. Lazy parsing is why a large bundle costs less than its byte count suggests.

function f() { … }   // pre-parsed, skimmed
f()                  // now fully parsed
02

Ignition

the interpreter

Compiles the AST into a compact register-based bytecode with one implicit accumulator, then interprets it. The handlers themselves are generated machine code, so the interpreter is fast — but the reason it exists is size. Bytecode is a fraction of what full machine code would cost in memory.

LdaSmi [1]      // accumulator ← 1
Star r0         // r0 ← accumulator
03

Sparkplug

the baseline tier

A non-optimising compiler that walks the bytecode once and emits machine code for each instruction. No IR, no register allocation, no analysis — and it keeps the interpreter’s exact stack frame layout, so a function can be swapped between tiers mid-run. It buys a flat speed-up for almost no compile time.

// bytecode → machine code, one pass
// same frame layout as Ignition
04

Maglev

the mid tier

The tier between baseline and full optimisation. It builds a real SSA control-flow graph and specialises on collected feedback, but skips the expensive global reordering TurboFan does. Warm functions get most of the win long before they are hot enough to justify the top tier.

--maglev   // default since Chrome 117
05

TurboFan

the optimising tier

A sea-of-nodes IR where value, effect and control are separate edge kinds, so most nodes float free of any order until scheduling places them. It optimises speculatively on feedback — this argument has only ever been a small integer — inlines aggressively, and guards every assumption it made.

// nodes float; only effect and control
// edges pin them to an order
06

Deoptimisation

the escape hatch

When a guard fails, V8 discards the optimised frame and rebuilds an interpreter frame from it in place, resuming in Ignition at the exact bytecode offset. Nothing observable happens. Speculation is only a sane strategy because being wrong is recoverable rather than fatal.

--trace-deopt
// deoptimizing … reason: wrong map