Browser Engine Internals
How V8 turns your JavaScript into machine code at incredible speed.
JS Engines
The programs that execute your JavaScript code.
| Engine | Used by | Created by |
|---|---|---|
| V8 | Chrome, Edge, Node.js, Deno | |
| SpiderMonkey | Firefox | Mozilla |
| JavaScriptCore | Safari, Bun | Apple |
// A JS engine's job: // 1. Parse your source code into an AST // 2. Compile it (bytecode → machine code) // 3. Execute the machine code // 4. Optimize hot paths (JIT) // 5. Manage memory (garbage collection) // The engine is ONE part of the browser: // Browser = Engine + Rendering + Networking + Storage + ... // // V8 Pipeline (Chrome/Node): // Source → Parser → AST → Ignition (bytecode) // → TurboFan (optimized machine code) // // Hot code gets compiled to fast machine code. // Assumptions wrong? Deoptimize back to bytecode.
Parsing
Turning source code into a tree the engine can work with.
// Step 1: Tokenization (Lexer)
// Source: "const x = 5 + 3;"
// Tokens: [const] [x] [=] [5] [+] [3] [;]
// Step 2: Parse into Abstract Syntax Tree (AST):
// VariableDeclaration
// ├─ kind: "const"
// └─ declarations:
// └─ VariableDeclarator
// ├─ id: Identifier("x")
// └─ init: BinaryExpression
// ├─ operator: "+"
// ├─ left: Literal(5)
// └─ right: Literal(3)
// You can see ASTs at: astexplorer.netThe parser converts source text into a structured tree. Each language construct becomes a node in the AST.
1 / 2
JIT Compilation
Just-In-Time: compile hot code to machine code on the fly.
// V8's two-tier compilation:
//
// Tier 1: Ignition (interpreter)
// - Compiles to bytecode quickly
// - Slower execution, but fast startup
// - Collects type feedback (profiling)
//
// Tier 2: TurboFan (optimizing compiler)
// - Compiles hot functions to machine code
// - Much faster execution
// - Uses type feedback for aggressive optimization
// - Can "deoptimize" if assumptions break
// Example of optimization:
function add(a, b) {
return a + b;
}
// Called 1000x with numbers:
for (let i = 0; i < 1000; i++) add(i, i);
// V8 thinks: "add always gets numbers → optimize for numbers"
// TurboFan generates fast machine code for number addition
// Then:
add("hello", " world"); // string! Assumption broken!
// V8: "deoptimize! Back to bytecode interpreter"
// Has to re-learn the typesWrite optimization-friendly code:
- • Use consistent types (don't mix numbers and strings)
- • Initialize objects with all properties upfront
- • Avoid deleting properties (use undefined instead)
- • Use typed arrays for number-heavy code
Garbage Collection
Automatic memory management — freeing objects you no longer need.
// V8 uses "generational" garbage collection: // // Young Generation (Scavenger): // - Small, fast area for new objects // - Most objects die young (temporary values) // - Collected frequently (~every few ms) // - Uses "semi-space" copy algorithm // // Old Generation (Major GC): // - Large area for long-lived objects // - Objects that survive multiple young GCs // - Collected less often // - Uses "mark-sweep-compact" algorithm // The GC process: // 1. Mark: find all reachable objects from roots // (global, stack variables, closures) // 2. Sweep: free memory of unmarked objects // 3. Compact: defragment (move objects together)
V8 splits memory into two generations. Most objects die quickly (young gen), so collecting them is fast. Long-lived objects are promoted to old gen.
1 / 2
FAQ
Common questions about JS engine internals.