The V8 JavaScript Engine

Deep dive in Nodejs Internals

Manik Mudholkar
5 min readJan 2, 2024

By Manik Mudholkar (Sr. Sw. Development Engineer)

This article is the first article of my Advanced NodeJS for Senior Engineers Series. In this article, I’m going to explain what, why and how they work in detail, and how of the V8 Engine. You can find the other articles of the Advanced NodeJS for Senior Engineers series below:

Post Series Roadmap

* The V8 JavaScript Engine (This Article)
* Async IO in NodeJS
* Event Loop in NodeJS
* Worker Threads : Multitasking in NodeJS
* Child Processes : Multitasking in NodeJS
* Clustering and PM2: Multitasking in NodeJS
* Debunking Common NodeJS Misconceptions
Table of Content

* Why the V8?
* How is it used in Nodejs?
* How V8 works?
* Creating your own Javascript Runtime

We have reached the lowest level of Node.js, where things become messy and complicated. JavaScript is a dynamically-typed interpreted language, and everything we execute in JavaScript is passed to the engine. The engine then interacts with its environment and generates the necessary bytecode for the machine to run our program. The engine responsible for this is called V8, which is an open-source high-performance JavaScript and WebAssembly engine developed by Google. V8 is written in C++ and is utilized in both Chrome (or similar environments) and Node.js. V8 fully supports ECMAScript and WebAssembly. Interestingly, V8 is not limited to browsers; it can also be run independently and embedded into any C++ application.

Why the V8?

The more lower level the more responsibilities. For converting c/c++ into assembly we need a compiler. To convert assembly into machine we have an assembler.
So to convert Js into runnable code we need JS Engine. Spidermonkey was was used in Firefox and later V8 was created & was used in Google Chrome & which is used in Nodejs.
A noticeable difference between Spidermonkey and V8 is that like you saw we need to convert the js code into bytecode (bytecode is an abstraction of machine code) to intermediate language and then to machine code. That is how Spidermonkey works. But V8 directly concerts JS into machine code.

How is it used in Nodejs?

If you look in the V8 code source code you’ll find implementation for objects, JSON, date, and so on but you won’t find things like document object used in Chrome or require() used in nodejs because nodejs and chrome implement these new functionalities in c++ and binds them to a javascript function by using V8. Why is it done this way? As we said before more low level means more responsibilities and more power. So c/cpp has a way to access & utilize low-level resources like network card, the js use cpp to make it do what it want to do. So you’ll find required in NodeJS source code rather than in V8.

This is why you are seeing js being used in so many places cause other people are able to do the same for their own use case e.g. js being used in robotics by creating their own cpp functionality implementation and binding them to js function like move right, left. That being said V8 is not suitable for this particular use case as you will have very little memory available so Duktape or Jerryscript js engines could be a better choice.

So V8 ultimately becomes a dependency for Nodejs and that can be seen on their official website.

How V8 works?

V8 engine compiles the code in two phases. First code into a machine which is not optimal but the compilation is fast. This is particularly enough to get started. while that is happening in background another compilation takes place which create very optimal code but compilation is slow. Once that slow compiled code is compiled Javascript switches to that optimal compiled code. These two phases are known as Ignition(a fast low-level register-based interpreter) and Turbofan(optimising compiler). A new approach was created called Just-in-Time (JIT) compilation. It combines the best from interpretation and compilation.

V8 uses an interpreter called Ignition. Initially, it takes an abstract syntax tree and generates byte code. Ignition only gets us so far. If a function gets hot enough, it will be optimized in the compiler, Turbofan, to make it faster.

We’ll go over it step by step:

  1. V8 parses the source code and turns it into an Abstract Syntax Tree (AST) as V8 doesn’t understand JS code and its more digestible to V8. Along with it scopes are generated.
  2. Based on that AST and scopes, the Ignition interpreter can produce bytecode.
  3. At that point, the engine starts running the code and collecting type feedback. (the execution stage provides the type feedback about the code.)
  4. To make it run faster, the byte code can be sent to the optimizing compiler along with feedback data. The optimizing compiler makes certain assumptions based on it and then produces highly-optimized machine code. This happens in parallel and V8 marks frequently used bytecodes as “hot” codes and converts it into more efficient machine code. But why do we not use machine code directly rather than bytecode, following are the reasons
  5. Machine codes requires a great amount of memory
  6. Machine codes are not always faster than bytecodes. Machine codes take a longer time to compile, although it is lighting-fast in terms of execution. Bytecodes need a shorter time to compile, but the trade-off is a slower execution step.
  7. If, at some point, one of the assumptions turns out to be incorrect, the optimizing compiler de-optimizes and goes back to the interpreter.

Creating your own JavaScript Runtime

If you are intrested in building your own JS runtime or want to see if its even possible, check out my Latest projects where I have created my very own JavaScript Runtime! Powered by the incredible V8 Javascript Engine and Libuv. With a foundation built on V8, Libuv, and C++, I’ve set out to recreate the powerful Node.js from scratch. Join me on this exciting journey as we dive deep into the world of JavaScript runtime development.

Before you go!

  • Stay tuned for more insights! Follow and subscribe.
  • Did you see what happens when you click and hold the clap 👏 button?

--

--