How V8 compiles JavaScript code ?
Last Updated :
01 Aug, 2021
V8 is a high-performance, open-source JavaScript and WebAssembly engine used by Google Chrome and Node.js. In this article, we will be going to see what happens behind the scene of V8 Architecture.
There are basically three steps involved in processing the code:
- Parsing the code
- Compiling the code
- Executing the code
Now let’s understand each of these phases in depth.
1. Parsing Phase: During the parsing phase, the code is broken down into its respective tokens.
Example:
const sum = 5 + 7
Here const is a token, sum is a token, 5 is a token, ‘+’ is a token, and 7 is a token. After the code is broken down into tokens, it is given to the syntax parser which converts the code into an Abstract Syntax Tree (AST).
Below is the generated AST for the above Example:

An Abstract Syntax Tree
2. Compilation phase: Compilation is the process of converting human-readable code to machine code. There are two ways to compile the code :
- Using an Interpreter: The interpreter scans the code line by line and converts it into byte code. Example: Python
- Using a Compiler: The Compiler scans the entire document and compiles it into highly optimized byte code. Example: Java
Unlike other languages, The V8 engine uses both a compiler and an interpreter and follows Just in Time(JIT) Compilation for improved performance.
Just in Time(JIT) Compilation: The V8 engine initially uses an interpreter, to interpret the code. On further executions, the V8 engine finds patterns such as frequently executed functions, frequently used variables, and compiles them to improve performance. Suppose the performance degrades or the parameters passed to the function change their type, then the V8 simply decompiles the compiled code and falls back to the interpreter.
Example: If the compiler compiles a function assuming the data fetched from the API call is of type String, the code fails when the data received is of type object. In this case, the compiler de-compiles the code, falls back to the interpreter, and updates the feedback. The V8 engine uses the Ignition interpreter, which takes in the Abstract Syntax Tree as the input and gives the byte code as the output, which further proceeds to the execution phase. When the code is being interpreted, the compiler tries to talk with the interpreter to optimize the code. The V8 engine uses the Turbofan compiler, which takes the byte code from the interpreter and feedback(from the interpreter) as the input and gives the optimized machine code as the output.
3. Execution Phase: The byte code is executed by using the Memory heap and the Call Stack of the V8 engine’s runtime environment. Memory Heap is the place where all the variables and functions are assigned memory. Call Stack is the place where each individual functions, when called are pushed to the stack, and popped out after their execution. When the interpreter interprets the code, using an object structure, where the keys are the byte code and the values the functions which handle the corresponding byte code. The V8 engine orders the values in the form of a list in memory, which is saved into a Map thereby saving a lot of memory.
Example:
let Person = {name: "GeeksforGeeks"}
Person.age = 20;
In the above example, a map holds the Person object, which has the property name. The second line creates a new object with the property age and links it back to the Person object. The problem with the above approach is that it takes linear time to search through the linked lists. To combat the problem, V8 has provided us with Inline Cache(IC).
Inline Cache: Inline Cache is a data structure used to keep track of the addresses of the properties on objects, thereby reducing the lookup time. It tracks all the LOAD, STORE, and CALL events within a function, by maintaining a Feedback Vector. Feedback Vector is simply an array used to track all the Inline Caches of a particular function.
Example :
const sum = (a, b) => {
return a+b;
}
For the above example, the IC is :
[{ slot: 0, icType: LOAD, value: UNINIT}]
Here, the function has one IC with type LOAD and value UNINIT, which means that the function has not yet been initialized.
Upon Calling the function :
sum(5, 10)
sum(5, "GeeksForGeeks")
On the first call, the IC changes to:
[{ slot: 0, icType: LOAD, value: MONO(I) }]
Here the code is interpreted in a manner, where the arguments passed are only of integer type. i.e the function will only work for integer values.
On the second call, the IC changes to:
[{ slot: 0, icType: LOAD, value: POLY[I,S] }]
Here the code is interpreted in a manner, where the arguments passed can either be of integer type or string. i.e the function will work for both integers as well as strings. Thereby, the running time of the function is faster if the type of arguments received is not modified. Inline caches keep track of how frequently they’re used and provide necessary feedback to the Turbofan compiler. The Compiler takes the byte code and type feedback from the interpreter and tries to optimize the code and produces new byte code. Suppose the compiler compiles a function assuming the data fetched from the API call is of type String, the code fails when the data received is of type object. In this case, the compiler de-compiles the code, falls back to the interpreter, and updates the feedback.
The Compilation and Execution of the JavaScript code go hand in hand.
Below is the diagrammatic representation of the compilation of JavaScript code.

The V8 engine tries to free up the memory heap, by clearing out unused functions, clearing out timeouts, clearing out intervals, etc.
Now, let’s understand the process of Garbage Collection.
Garbage Collection: It is an important aspect of programming and the techniques used by the garbage collector have improved the latency, page load, pause times, etc. The V8 engine is provided with the Orinoco Garbage Collector which internally uses the Mark and Sweep Algorithm to free up space from the memory heap.
The Orinoco Garbage Collector uses three ways to collect the trash:
- Parallel: In the parallel collection, the main JavaScript thread uses the help of few helper threads parallelly to clear out the garbage, as a result, the main execution is stopped only for a while.
- Incremental: In the incremental collection, the main JavaScript thread takes turns to collect the garbage i.e in an incremental fashion. This type of collection is used to further reduce the latency of the main thread. Example: The JavaScript thread first collects the garbage for some time and then switches to the main execution for a while and then switches back to garbage collection. This process goes on until the entire garbage is collected.
- Concurrent: In the concurrent collection, the main JavaScript thread is not disturbed and the entire Garbage is collected by the helper threads in the background.
Similar Reads
How to Execute JavaScript Code ?
Javascript is a high-level, Just In Time compiled programming language which converts the entire machine code at once and then executes it immediately. Javascript code is executed by the Javascript Engine, which is separate software. Different browsers have their own implementation of JS Engine embe
2 min read
How to debug JavaScript File ?
Debugging is essential because there are many errors that are not giving any kind of messages so to find out that we debug the code and find out the missing point. Example 1: Using console.log() Method In this, we can find out the error by consoling the code in various places. Using a console is one
2 min read
How to Become a JavaScript Developer?
JavaScript is Everywhere. If we talk about any small startup or big company most of them are working on any kind of website or an app always looking for someone with JavaScript knowledge. Millions of web pages are built on JavaScript and it's not going anywhere at least for now. This language is hug
7 min read
JavaScript Cookies
JavaScript cookies are small data stored on a user's device by a web browser. These cookies play a crucial role in web development, enabling websites to store and retrieve information about user preferences, session states, and other data. Cookies facilitate a more personalized browsing experience b
3 min read
JavaScript Code Execution
JavaScript is a synchronous (Moves to the next line only when the execution of the current line is completed) and single-threaded (Executes one command at a time in a specific order one after another serially) language. To know behind the scene of how JavaScript code gets executed internally, we hav
4 min read
JavaScript Online Compiler
The JavaScript (JS) Online Compiler and Editor is a free online tool providing an integrated development environment (IDE) for creating and executing JavaScript code. Whether you are a beginner looking to learn JavaScript or an experienced developer want to test snippets of code quickly, an online c
5 min read
How to run JavaScript in Chrome Browser ?
Javascript is a highly flexible scripting language that enables developers to incorporate interactive elements into web pages. Web development could not be imagined without it as one of the most widely used methods to implement JavaScript is via web browsers. One of the very popular web browsers is
5 min read
How to share code between files in JavaScript ?
JavaScript is a powerful and popular programming language that is widely used for web development. One of the key features of JavaScript is its ability to share code between files. This can be useful for organizing large projects, reusing code, and maintaining code quality. In this article, we'll se
6 min read
How to convert CoffeeScript code in JavaScript ?
CoffeeScript is a lightweight programming language that compiles into JavaScript. It provides simple and easy-to-learn syntax, avoiding the complex syntax of JavaScript. CoffeeScript is influenced by JavaScript, Ruby, YAML, Haskell, Perl, and Python and has influenced MoonScript, LiveScript, and Jav
2 min read
Console in JavaScript
The console object provides access to the browser's debugging console (or terminal in Node.js). It is used to log information, debug code, and interact with the runtime environment during development. Commonly Used console MethodsHere are the most frequently used methods of the console object: 1. co
3 min read