What is v8 architecture, and how does it works?
v8 architecture defines how v8 engine works. And what goes into when we perform any javascript task. v8 uses both interpreter and compiler to executes the javascript code. This flexibility between interpreter and compiler is what makes javascript run so fast even on single call stack.
Key Components of V8 Architecture
1. Parser
The first component of the V8 architecture is the parser. It takes JavaScript source code and translates it into an Abstract Syntax Tree, which is represented in a hierarchical form according to the structure of the code. This AST is essential for V8, as it allows easier manipulation and optimization of the code.
AST - Abstract Syntax Tree, is a tree which is used for syntax analysis of the user code. The AST is?used intensively during semantic analysis, where the compiler checks for correct usage of the elements of the program and the language. The syntax error is generated by AST.
2. Ignition Interpreter
Ignition is a lightweight interpreter that works on a low level within V8. It compiles AST down to bytecode, which acts like a high-level efficient representation of the JavaScript source code. This serves as a bridge between high-level JavaScript and low-level machine code, which executes more efficiently.
领英推荐
3. TurboFan Compiler
TurboFan is an optimizing compiler for V8. It compiles bytecode produced by Ignition into high-optimized machine code. With that, TurboFan makes many optimizations based on runtime feedback — such as inlining functions and eliminating dead codes — at a more advanced level to provide higher performance. TurboFan compiler also deoptimise the code when needed.
For example, if we have a function that takes two variables and returns their sum, and we pass in numbers, here’s what happens when we run this code in the V8 engine:
function addition(a,b){
return a+b;
}
addition(1,2); //3
addition(3,2); //5
addition(5,2); //7 - somewhere here code gets optimized and compier now executes the code
addition(7,2); //9
addition(8,2); //10
addition(9,2); //11
addition("Mayur","Hanwate") //MayurHanwate - Code gets deoptimized
First, the JavaScript code is parsed by V8, which generates an Abstract Syntax Tree (AST). The AST is then processed by the Ignition interpreter, which compiles it into bytecode—a lower-level, platform-independent representation.
Ignition starts executing the bytecode line by line, interpreting it. This allows the code to run immediately without needing to be fully compiled into machine code.
As we call the function repeatedly, Ignition identifies it as "hot" (frequently used). Ignition then hands this "hot" bytecode over to the Turbofan optimizing compiler for further optimization.
Turbofan uses runtime information (like types and usage patterns) collected by Ignition to compile the "hot" code directly into optimized machine code. This optimized machine code allows the function to bypass Ignition’s interpretation and run directly on the CPU, making it significantly faster.
Suppose we later call the function with strings instead of numbers. This change in data type invalidates the assumptions made by Turbofan during optimization. TurboFan then deoptimizes the function, discarding the optimized machine code. Execution falls back to Ignition’s interpreted bytecode, which is flexible enough to handle new or unexpected types.