The compilation pipeline
V8 does not choose between an interpreter and a compiler — it runs four tiers at once and moves each function between them by how hot it is. Cold code is interpreted, warm code is compiled cheaply, hot code is compiled speculatively, and code that breaks its own assumptions falls back down.
Ignition → Sparkplug → Maglev → TurboFan
6 sub-nodes →Tagged values
Every JavaScript value is one machine word. The low bit says which kind: clear means a small integer stored inline, set means a pointer to something on the heap. That is why integer arithmetic on Smis never allocates, and why a number that leaves the Smi range suddenly costs a heap object.
…xxxx0 Smi, value is in the word
…xxxx1 pointer to a heap object
Hidden classes
JavaScript objects are dictionaries, but V8 refuses to store them that way. Each object points at a Map — a hidden class describing its layout — and adding a property transitions to a different Map. Objects built the same way share one, so a field read is a fixed offset. Build them in different orders and they do not.
{} → {x} → {x,y} // one transition chainInline caches & feedback
Every property access and call site has a slot in a feedback vector recording the Maps it has actually seen. One Map is monomorphic and inlines to a direct offset load; a few is polymorphic and becomes a short check chain; too many is megamorphic and falls back to a hash lookup. The optimising tiers read nothing else.
monomorphic → polymorphic → megamorphic
Garbage collection
A generational collector, on the assumption that most objects die young: a copying scavenger for the nursery, mark-compact for everything that outlives it, and as much of both as possible pushed onto background threads so the main thread keeps running.
scavenge (minor) · mark-compact (major)
6 sub-nodes →Isolates & contexts
An Isolate is one complete V8 instance — its own heap, its own compiler state — and only one thread may be inside it at a time. A Context is one global object within that isolate. Two tabs on the same site can share an isolate; two workers cannot, which is why a worker cannot pass you a live object.
Isolate ⊃ Context ⊃ global object
WebAssembly
The same engine, a second front end, and the same tiering idea. Liftoff compiles each function in one pass so a module starts almost immediately, while TurboFan recompiles the hot ones in the background. There is no parsing to speculate about — the types are already in the bytes.
Liftoff (start fast) → TurboFan (run fast)