An Introduction To JavaScript’s V8 Engine
As developers, we are familiar with the fact that JavaScript powers the majority of client side web applications. This is because of JavaScript’s ability to be executed in web browsers. This ability is as a result of the JavaScript engine, which web browsers possess. A JavaScript engine is a component that executes and compiles JavaScript code into machine language. The first JavaScript engine was created by Brendan Eich, and this engine was called SpiderMonkey. Other examples of JavaScript engines are Chakra, which was developed by Microsoft, JavascriptCore(Nitro), which was developed by Apple, and Google Chrome’s V8 engine. The most popular of these engines is the V8 engine.
The V8 engine was developed by Google and it is a crucial component of Google’s web browser Chrome. The use of JavaScript engines isn’t limited to only browsers, V8 engine is also what powers Nodejs. It is written in C++ and is open source.
Before we go into the flow of operations of a JavaScript engine, we need some background in understanding some tools related to the engine; Interpreters, and Compilers.
Interpreters: When you execute code that is written in an interpreted programming language, E.g. JavaScript, Python, an interpreter reads the code line by line and executes the code.
Compilers: Code written in a compiled language such as C, C++, Java e.t.c. go through the compiler. A compiler first goes through the entire code file, and translates it into machine code before execution.
When an interpreter sees a code that it has seen before, let's say in the case of a loop function, it has to read it line by line again before execution. A compiler on the other hand will remember what that code does and execute it immediately. Now what this means is that interpreted languages are fast to begin code execution, but can get slow with time, especially when there are loops in the code. Compiled languages on the other hand are slower to start execution because the code compilation process must first be completed, but are fast to run once execution is started. Using a Just In Time Compiler (JIT compiler), we can get the best of both worlds. A Just In Time Compiler is a type of compiler that translates source code or intermediate code during runtime or execution of a program. It can operate on portions of code when needed.
Now let us go into the flow of operations of a JavaScript engine using the V8 engine as an example. Inside JavaScript's V8 engine, there are crucial components which make things work. The parser, the abstract syntax tree, an interpreter, a profiler and a compiler all work together to power the JavaScript engine.
When JavaScript code is passed into the V8 engine, the parser also known as the ignition in V8, does a lexical analysis on javascript code which is the start of the code execution. Lexical analysis breaks the code into parts called tokens, to identify their meaning. The tokens which are obtained from this process are the smallest units of meaning in a programming language, in this case Javascript. Examples of tokens are keywords, operators, numbers and strings.
Next, the tokens are then formed into an abstract syntax tree. An abstract syntax tree is a representation of code structure in computer science. It is a type of data structure that is used to represent the structure of a program. It represents the code in a form which is more understandable by other computer programs.
It is then passed to the interpreter which translates it into bytecode.
While this is going on, the profiler, also known as the monitor, watches the code as it runs and makes notes on how the code can be optimized. If the same lines of code are run a few times, the monitor passes this code into a JIT compiler, in the case of the v8, known as the Turbo Fan. The JIT compiler optimizes the code and replaces the section of the bytecode where the optimized code can be used. What this means is that the execution speed of the code that is being entered into the engine will gradually improve as the profiler and compiler are constantly monitoring and making updates and changes to the code and bytecode.
What this means for javascript, is that with the use of javascript engines it can be both an interpreted language and a compiled language, depending on the environment that it is being used.
Subscribe to my newsletter
Read articles from Valentina Buoro directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Valentina Buoro
Valentina Buoro
I am Valentina Buoro, a software engineer. I'm an avid reader and I love learning new things. I also enjoy writing and talking about software development.