The computer only understands binary code at the end of the day.
On the 2nd of September 2008, the first version of the V8 engine was released at the same time as the first version of Chrome.
An interpreter is a computer program that immediately executes instructions written in a programming language. It translates and read the files line by line on the fly without the need to previously compile the file into a machine language program.
A compiler is also a computer program that transforms a programming language into a language a computer can understand, but it doesn’t translate on the fly. It first tries to understand what we want to do, and it changes all our code into something else called a lower-level language (such as machine language) so that the computer can understand.
Both compiler and interpreters do the same job which is converting higher-level programming language to machine code, but as we saw they work differently and they have their own pros and cons.
Interpreters are quick to start running because we don’t have to convert our file into another language as we do with a compiler. There’s no compilation step before you can start running your code. It is translated into machine code and executed line by line right away. On the other hand, the compiler has an extra step incurred and every time you want to run the application, the code needs to be compiled.
Even if interpreters are quick to start running, their big problem is that when you’re running the same code more than once, for example in a loop, the compiler will run this piece of code over and over and it can get really slow.
The compiler helps us in this sense. Even if it takes a little more time to start running, our compiler will simplify our code and instead of running our loop over and over, it will generate a code that it is faster to be understood by our machine. These kinds of edits that the compiler does are called optimizations.
To summarize the interpreter is quick to get up and start running but doesn’t produce optimizations. The compiler is slower to start but the code is going to eventually run faster.
So… which one is better? Well, there is a way to get the best of both worlds and instead of using the compiler or interpreter you can combine these two and use something called just-in-time compilation, also known as JIT compilation.
All the modern engines use JIT compilation for improved performance.
So let’s go back to our engine and really understand what is actually happening inside of it. There are small differences in different engines but let’s see how V8 engine does this.
- The first thing that happens inside the engine is that our code is parsed by a parser, which basically reads our code line by line and checks if the syntax of the code that we gave it is correct. During this lexical analysis, it breaks the code into something called tokens to identify their meaning.
- If everything is correct, then the parser takes these tokens to produce a data structure known as the Abstract Syntax Tree. This enables the engine to understand how things are structured in our code.
- The code is then initially sent to our interpreter (the V8 interpreter is called ignition) that takes this Abstract Syntax Tree to create Bytecode.
- In the meanwhile, the profiler tries to understand how we can pass some of this Bytecode to the compiler to optimize it.
- Parts of codes that can be optimized are sent to a compiler (the V8 compiler is called TurboFan).
- The compiler realizes optimizations, so our code runs faster and it then replaces these parts of codes with optimized machine code.
- So the interpreter allows us to run the code right away and the compiler and profiler allow us to optimize this code while it is running. This is the Just In Time Compilation.