24.1-Engine-Architecture
22.1 Engine Architecture Deep Dive
Understanding how JavaScript engines work internally helps you write more performant code and debug complex issues.
Table of Contents
- β’JavaScript Engine Overview
- β’The Parser
- β’Abstract Syntax Tree (AST)
- β’Bytecode Generation
- β’The Interpreter
- β’JIT Compilation
- β’Optimization Pipeline
- β’Engine Comparison
JavaScript Engine Overview
A JavaScript engine is a program that executes JavaScript code. Modern engines are highly sophisticated, using multiple techniques to achieve near-native performance.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JAVASCRIPT ENGINE ARCHITECTURE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Source Code: "function add(a, b) { return a + b; }" β
β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β PARSING PHASE β β
β β βββββββββββ βββββββββββ βββββββββββ β β
β β β Lexer β β β Tokens β β β Parser β β AST β β
β β βββββββββββ βββββββββββ βββββββββββ β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β COMPILATION PHASE β β
β β βββββββββββββββββ βββββββββββββββββ β β
β β β Interpreter β ββββββ β JIT Compiler β β β
β β β (Ignition) β β (TurboFan) β β β
β β βββββββββββββββββ βββββββββββββββββ β β
β β β β β β
β β Bytecode Optimized Machine Code β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β EXECUTION PHASE β β
β β CPU executes bytecode or machine code β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Major JavaScript Engines
| Engine | Browser/Runtime | Company | Key Components |
|---|---|---|---|
| V8 | Chrome, Node.js, Deno | Ignition + TurboFan | |
| SpiderMonkey | Firefox | Mozilla | Baseline + IonMonkey |
| JavaScriptCore | Safari | Apple | LLInt + DFG + FTL |
| Chakra | Legacy Edge | Microsoft | SimpleJIT + FullJIT |
The Parser
The parser converts source code text into a structured representation the engine can work with.
Two-Phase Parsing
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PARSING PHASES β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β PHASE 1: LEXICAL ANALYSIS (Tokenization) β
β βββββββββββββββββββββββββββββββββββββββββ β
β β
β Source: "let x = 10 + 5;" β
β β
β Tokens: β
β βββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ¬ββββββ β
β β let β x β = β 10 β + β 5 β ; β β
β βββββββΌββββββΌββββββΌββββββΌββββββΌββββββΌββββββ€ β
β β KWD β ID β OP β NUM β OP β NUM β PUN β β
β βββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ΄ββββββ β
β β
β PHASE 2: SYNTACTIC ANALYSIS (Parsing) β
β βββββββββββββββββββββββββββββββββββββββββ β
β β
β Tokens β Abstract Syntax Tree (AST) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Lazy Parsing (Pre-parsing)
Engines don't parse everything immediatelyβthey use lazy parsing for performance:
// Full parse - executed immediately
function greet() {
console.log('Hello!');
}
greet(); // Called, so fully parsed
// Lazy parse - only pre-parsed initially
function unused() {
// Complex code here...
// Not fully parsed until called
return computeComplexValue();
}
// 'unused' is pre-parsed (syntax checked) but not fully compiled
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LAZY PARSING β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β EAGER PARSING (Full Parse) β
β β’ Function is called immediately β
β β’ Top-level code β
β β’ IIFEs (Immediately Invoked Function Expressions) β
β β
β LAZY PARSING (Pre-Parse) β
β β’ Inner functions β
β β’ Functions not immediately called β
β β’ Checks syntax, finds variables β
β β’ Doesn't generate AST until needed β
β β
β Benefits: β
β β’ Faster initial page load β
β β’ Lower memory usage β
β β’ Parse on demand β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Abstract Syntax Tree (AST)
The AST is a tree representation of the source code's structure.
Example AST
// Source code
let sum = a + b;
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ABSTRACT SYNTAX TREE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Program β
β β β
β VariableDeclaration β
β (kind: "let") β
β β β
β VariableDeclarator β
β / \ β
β Identifier BinaryExpression β
β (name: "sum") (operator: "+") β
β / \ β
β Identifier Identifier β
β (name: "a") (name: "b") β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
AST Node Types
| Category | Node Types |
|---|---|
| Declarations | VariableDeclaration, FunctionDeclaration, ClassDeclaration |
| Expressions | BinaryExpression, CallExpression, MemberExpression |
| Statements | IfStatement, ForStatement, ReturnStatement |
| Literals | NumericLiteral, StringLiteral, BooleanLiteral |
| Patterns | ObjectPattern, ArrayPattern, RestElement |
AST in Action
// You can explore ASTs with tools like AST Explorer
// or programmatically with parsers
// Example: Simple function
function multiply(x, y) {
return x * y;
}
/*
AST Structure:
{
type: "FunctionDeclaration",
id: { type: "Identifier", name: "multiply" },
params: [
{ type: "Identifier", name: "x" },
{ type: "Identifier", name: "y" }
],
body: {
type: "BlockStatement",
body: [{
type: "ReturnStatement",
argument: {
type: "BinaryExpression",
operator: "*",
left: { type: "Identifier", name: "x" },
right: { type: "Identifier", name: "y" }
}
}]
}
}
*/
Bytecode Generation
After parsing, the interpreter generates bytecodeβa low-level, platform-independent representation.
V8 Ignition Bytecode
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β BYTECODE GENERATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β JavaScript: β
β ββββββββββ β
β function add(a, b) { β
β return a + b; β
β } β
β β
β Bytecode (Ignition): β
β βββββββββββββββββββ β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Ldar a1 ; Load argument 'a' into accumulator β β
β β Add a2 ; Add argument 'b' to accumulator β β
β β Return ; Return accumulator value β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Bytecode Properties: β
β β’ Register-based (uses accumulator) β
β β’ Compact representation β
β β’ Quick to generate β
β β’ Portable across architectures β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Common Bytecode Instructions
| Instruction | Description | Example |
|---|---|---|
Ldar | Load from register to accumulator | Ldar r0 |
Star | Store accumulator to register | Star r1 |
Add | Add register to accumulator | Add r2 |
LdaSmi | Load small integer | LdaSmi [42] |
Call | Call function | Call r0, r1-r3 |
Return | Return from function | Return |
JumpIfFalse | Conditional jump | JumpIfFalse [offset] |
Viewing Bytecode
// In Node.js, you can view bytecode with:
// node --print-bytecode --print-bytecode-filter=functionName script.js
function example(x) {
if (x > 0) {
return x * 2;
}
return 0;
}
/*
Bytecode for 'example':
LdaZero ; Load 0
Star r0 ; Store in r0
Ldar a0 ; Load argument x
TestGreaterThan r0 ; Compare x > 0
JumpIfFalse [offset] ; Jump if false
Ldar a0 ; Load x
LdaSmi [2] ; Load 2
Mul r0 ; x * 2
Return ; Return result
LdaZero ; Load 0
Return ; Return 0
*/
The Interpreter
The interpreter executes bytecode directly, providing fast startup.
Ignition (V8's Interpreter)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β IGNITION INTERPRETER β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Bytecode Stream β β
β β ββββββ¬βββββ¬βββββ¬βββββ¬βββββ¬βββββ¬βββββ¬βββββ¬βββββ β β
β β βLdarβStarβAdd βLdarβCallβJumpβRet β... β... β β β
β β ββββββ΄βββββ΄βββββ΄βββββ΄βββββ΄βββββ΄βββββ΄βββββ΄βββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Interpreter Loop β β
β β β β
β β while (hasMoreBytecodes) { β β
β β bytecode = fetchNextBytecode(); β β
β β dispatch(bytecode); // Execute handler β β
β β collectTypeFeedback(); // For optimization β β
β β } β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Type Feedback β β
β β β β
β β "add(1, 2)" β Records: both args are SMI (small integers) β β
β β "obj.x" β Records: obj has shape X, x at offset 8 β β
β β β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Interpreter vs. Compiler Trade-offs
| Aspect | Interpreter | JIT Compiler |
|---|---|---|
| Startup time | Fast β | Slow (compilation) |
| Execution speed | Slower | Fast β |
| Memory usage | Lower β | Higher (code cache) |
| Best for | Short-running code | Hot loops |
JIT Compilation
Just-In-Time (JIT) compilation converts hot bytecode to optimized machine code.
TurboFan (V8's Optimizing Compiler)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β TURBOFAN OPTIMIZATION PIPELINE β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. GRAPH BUILDING β
β Bytecode β Sea of Nodes (SSA form) β
β β
β 2. TYPE INFERENCE β
β Use type feedback from Ignition β
β β
β 3. OPTIMIZATION PHASES β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β’ Inlining (inline function calls) β β
β β β’ Escape Analysis (stack allocate objects) β β
β β β’ Loop Optimization (unrolling, invariant motion) β β
β β β’ Dead Code Removal (eliminate unused code) β β
β β β’ Constant Folding (compute at compile time) β β
β β β’ Bounds Check Elim (remove redundant checks) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β 4. REGISTER ALLOCATION β
β Map virtual registers to physical CPU registers β
β β
β 5. CODE GENERATION β
β Generate platform-specific machine code (x64, ARM, etc.) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
When Does JIT Kick In?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HOT CODE DETECTION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β V8 tracks function execution: β
β β
β function process(data) { β
β // Called 100 times β still "warm" β
β // Called 1000+ times β HOT! β Optimize! β
β } β
β β
β Optimization Triggers: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β’ Loop back-edges (iterations) β β
β β β’ Function call count β β
β β β’ Time spent in function β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Timeline: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΊ β
β β β β
β β Ignition β TurboFan β β β
β β (interpreted) β (optimized) β β β
β β ββββββββββββββββ β ββββββββββββββββββββ β β β
β β β β β β
β β<βββ Cold ββββββββββ>β<βββββββ Hot ββββββββββ>β β β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Optimization Pipeline
Speculative Optimization
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β SPECULATIVE OPTIMIZATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β function add(a, b) { β
β return a + b; β
β } β
β β
β // Ignition collects type feedback: β
β add(1, 2); // a: SMI, b: SMI β
β add(3, 4); // a: SMI, b: SMI β
β add(5, 6); // a: SMI, b: SMI β
β // ... 1000 more calls with integers β
β β
β TurboFan ASSUMES: a and b are always integers β
β β
β OPTIMIZED CODE: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β ; Skip type checks - we "know" they're integers β β
β β mov eax, [a] β β
β β add eax, [b] ; Direct integer addition β β
β β jo bailout ; But... check for overflow β β
β β ret β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β If assumption is WRONG: β
β add("hello", "world"); // Strings! Assumption broken! β
β β DEOPTIMIZATION β Back to Ignition β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Deoptimization (Bailout)
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DEOPTIMIZATION β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β What triggers deoptimization? β
β β
β 1. TYPE CHANGE β
β function calc(x) { return x * 2; } β
β calc(5); // Optimized for integers β
β calc("5"); // String! Deoptimize! β
β β
β 2. HIDDEN CLASS CHANGE β
β function getX(obj) { return obj.x; } β
β // Optimized for specific object shape β
β getX({ x: 1, y: 2 }); // Different shape! Deoptimize! β
β β
β 3. PROTOTYPE CHANGE β
β Object.prototype.foo = 42; // Invalidates assumptions β
β β
β 4. ARGUMENTS OBJECT β
β function f() { return arguments; } // Hard to optimize β
β β
β Deoptimization is EXPENSIVE: β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β’ Discards optimized code β β
β β β’ Reconstructs interpreter state β β
β β β’ May need to re-optimize later β β
β β β’ Causes performance jank β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Engine Comparison
Compilation Tiers
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ENGINE COMPILATION TIERS β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β V8 (Chrome): β
β βββββββββββββ β
β Source β Parser β Ignition (interpreter) β TurboFan (optimizer) β
β β β β
β Bytecode Optimized Machine Code β
β β
β SpiderMonkey (Firefox): β
β βββββββββββββββββββββββββ β
β Source β Parser β Baseline (quick JIT) β IonMonkey (optimizer) β
β β β β
β Simple Machine Code Optimized Machine Code β
β β
β JavaScriptCore (Safari): β
β ββββββββββββββββββββββββ β
β Source β Parser β LLInt β Baseline β DFG β FTL β
β β β β β β
β Interp Quick Mid Full Optimization β
β JIT JIT β
β β
β Tier Comparison: β
β βββββββββββββββ β
β Speed: Slow ββββββββββββββββββββββββββββββββββββΊ Fast β
β Compile: Fast ββββββββββββββββββββββββββββββββββββΊ Slow β
β β
β LLInt/Ignition β Baseline β DFG β TurboFan/IonMonkey/FTL β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Takeaways
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ENGINE ARCHITECTURE SUMMARY β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β 1. PARSING β
β β’ Lexer β Tokens β Parser β AST β
β β’ Lazy parsing for unused functions β
β β
β 2. BYTECODE β
β β’ Intermediate representation β
β β’ Fast to generate, portable β
β β’ Executed by interpreter β
β β
β 3. INTERPRETER β
β β’ Executes bytecode directly β
β β’ Collects type feedback β
β β’ Fast startup β
β β
β 4. JIT COMPILER β
β β’ Compiles hot code to machine code β
β β’ Uses type feedback for speculation β
β β’ Much faster execution β
β β
β 5. DEOPTIMIZATION β
β β’ When assumptions are violated β
β β’ Falls back to interpreter β
β β’ Avoid by keeping types stable β
β β
β WRITE OPTIMIZATION-FRIENDLY CODE: β
β β’ Use consistent types β
β β’ Initialize object properties in constructors β
β β’ Avoid deleting properties β
β β’ Avoid changing prototypes β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Next Steps
Continue to 22.2 Hidden Classes & Inline Caching to learn how V8 optimizes property access and what makes code fast or slow.