To really get the answer of this question, let's see the process behind How code is executed from beginning to end?
Deep Dive Of Architecture of V-8 Engine:
V8 Engine is Google’s open-source JavaScript engine, written in C++ used to execute Javascript code;
Understanding the diagram:
V-8 Engine exxecutes code in several steps:
-
Parsing:
This phase itself combines two steps:
- Lexical Analysis: In this phase, code is converted into tokens;
- Syntax Analysis: In this phase, the tokens are used and is converted into Abstract Syntax Tree. Abstract Syntax Tree provides more structured way. Example of Abstract Syntax Tree:
However, you can play with it on: https://astexplorer.net/
-
Interpreter:
Google V-8 Engine's Interpreter is called as "Ignition Interpreter";
The interpreter performs two steps:- Firstly it takes Abstract Syntax Tree as input and converts it into bytecode; Bytecode is a lower-level, more compact set of instructions (not machine code yet).
- Interpreter executes bytecode, and along with it, Interpreter which parts of the code run most frequently (called "hot code"). This process is called as "profiling";
If any "hot code" is detected, it is passed to "Turbofan Compiler" of V-8 Engine;
- JIT Compilation (Turbofan Compiler): TurboFan translates bytecode of "hot code" passed by Interpreter into optimized machine code (actual CPU instructions).
So now, if interpreter encounters the hot code again, there is no need to execute bytecode, instead it's machine code is already been generated by Turbofan Compiler and it is directly executed on the hardware. That's why Javascript is fast;
Now, in this step, there is an interesting catch:
So, when interpreter sends hot code to compiler, it sends profile too, it means attached information along with it, such as input parameters etc etc.
Let's understand with an example, suppose there is a sum function defined below, is a hot code:
function sum(a,b){
return a + b;
}
So, when interpreter pass the bytecode of this function to compiler, it passes some profile information, let's say: type of input paramters passed;
Now, turbofan compiler, generates machine code according to it.
Next time, suppose, anyone called this function and instead of Number, they passed string as input parameter, now the machine code that compiler had generates is based on the assumption that input parameters will be Numbers.
But, here comes the unexpected twist in the story, so now, what will turbofan compiler do ?
The previously optimized machine code is no longer valid (it would produce wrong results).
So , here comes the magic of Turbofan Compiler:
- Compiler throws away the optimized machine code for that function.
- Control is handed back to Ignition’s interpreter, which executes the bytecode (slower, but correct).
- From there, profiling starts again → if stable assumptions are observed, TurboFan may re-optimize.
**You can read more about Turbofan Compiler here: **https://v8.dev/docs/turbofan
- Garbage Collection: As code runs, V8 manages memory. The Garbage Collector frees up unused memory (objects, variables no longer needed).
There are various Garbage Collection Algorithms used, such as, Scavenge, Mark-Sweep, Orinoco and many more.
**You can read more orinoco Garbage Collection here: **https://v8.dev/blog/trash-talk
Now, you can answer yourself, Is Javascript - Compiled or Interpreted Language ?
I believe it is pretty clear, that Javascript is both Interpreted and Compiled language.
Go check official V-8 Engine Docs, There are many more things working behind the scene:
https://v8.dev/docs
Top comments (0)