What is JavaScript Engine?
The JavaScript Engine is an open-source computer program whose responsibility is to execute/run JavaScript. There are a lot of steps involved in executing the JavaScript Engine, but essentially executing JavaScript code is what an engine does. All modern browsers have their own version of the JavaScript Engine. But Google's V8 Engine is the most popular JavaScript Engine.
An elementary JavaScript engine includes a baseline compiler whose job is to compile JavaScript source code into an intermediate representation (IR) called the bytecode and feeds this bytecode to the interpreter. The interpreter takes this bytecode and converts it to the machine code, which is ultimately run on the machine’s hardware (CPU).
ECMAScript Standards are being followed by the JavaScript engines to execute the code on the browser. The role of these standards is to give a definition and specification to JavaScript engines on how they should work and what features they should have.
Here is a list of JavaScript Engines for major Internet browsers:
What are the components of JavaScript Engine?
The engine consists of two main elements:
Memory Heap
Heap is a large unstructured data structure that stores all the dynamic data like function definitions, objects, arrays, etc. The memory heap is where the memory allocation happens, it is a location in memory where memory may be allocated at random access. Individual data elements distributed on the heap are typically released in ways that are asynchronous from one another. The memory occupied in the heap continues to exist even after JavaScript code execution has been completed and is later removed by the JavaScript Garbage Collector if needed.
Call Stack
The Call stack is a data structure that functions on the Last In First Out (LIFO) principle. The call stack stores the execution context or code for each function. It is defined as an object which stores local variables, functions, and objects of the codes and how would they appear on the screen. Primitive values like int, bool, etc are stored inside the call stack. While function definitions and objects are not stored inside the call stack, they are stored inside the memory heap. The call stack just has the reference or memory address of where these function definitions and objects are stored and would appear on the search engine.
How JavaScript engine works?
The JavaScript engine works on the JavaScript source code and puts it and then executes the compilation to binary instructions (machine code) that are easily understandable by the CPU. A JavaScript engine generally consists of a baseline compiler that works on the compilation of the code in the form of intermediate representation (IR) /byte code and then passes the byte code to the interpreter.
Later, the interpreter takes this byte code and makes the conversion into machine code, which will further run this code on the hardware of the machine to generate the results and thats how JS engine works. The assignment of a baseline compiler is to perform the compilation of the code as fast as possible and to generate less-optimized byte codes.
A JavaScript engine can make an intuition about the data types of the variables and perform the generation of much better code that increases the effectiveness of the system and user experience at large.
The JavaScript engine can also work on gathering, and profiling data on the execution of the code and analyzing the speed of the code. Codes that run slow or take time to process are commonly known as "Hot" codes as they get burned in the CPU. System designers have the option to further optimize and replace machine code that has already been optimized to avoid burns.
What are different JavaScript engines?
Now that you have a better understanding of how javascript engine works, it's also necessary to understand the different javascript engines-
1. V8
It is a JavaScript engine developed by the Chromium Project for Google Chrome and Chromium web browsers which can run standalone or be embedded into any C++ application. V8 uses its own parser and generates an abstract syntax tree, used for generating bytecode by Ignition using the internal V8 bytecode format. V8 provides an edge as it allows JavaScript to run much faster, which improves users' experience of the web and the overall functionality of the system.
2. Chakra
Chakra is a JavaScript engine developed by Microsoft used for Microsoft Internet Explorer. It is proprietary software with distinctive features. Chakra can JIT compile scripts on a separate CPU core parallel to the web browser. Firstly, Chakra Core reads through the Javascript code syntax and parses it to generate its AST. After the AST is generated, the code is passed to the byte code generator to profile the byte codes. Chakra works a bit differently from V8, as V8 has a decision process that decides whether a piece of code should be profiled and optimized or should be turned into byte code.
3. Spider Monkey
SpiderMonkey is the first JavaScript engine, written by Brendan Eich at Netscape Communications, released as open-source, and is currently maintained and used by the Mozilla Foundation. It contains a JavaScript compiler and interpreter along with several service programs. It is written in C++, Rust and JavaScript can be embedded into C++ and Rust projects and run as a stand-alone shell.
How JavaScript is optimized?
There are various measures for optimizing JavaScript code. For example, before JavaScript code is pushed to the interpreter or baseline compiler, it has to be parsed into an Abstract Syntax Tree (AST).
While running a JavaScript application, we do not need all the code at the application startup time. For instance, if we have a function presented on the user action, like a button click, that code can be parsed later. Identifying inputs and things that need to be parsed on priority and generating machine code is the best strategy for faster application bootstrap. Another way to optimize JavaScript is to analyze the code and simply the complex logic that can help for better processing and quick runtime.
The lack of type methods in JavaScript is what makes the JavaScript engine produce less optimized machine code. Hence, based on already defined values, a JavaScript engine can speculate on the data types of the variables and produce better machine code.
Let's take an example of Loop Unrolling, a 'for' loop to increment an integer can be inlined using '+' operations 'n' number of times to optimize the script. Similar optimizations can be achieved using functions in-line.
This is why JavaScript engine is needed, since it can also gather profiling data on code execution and look for code that runs slower or is lagging for some reason. Fixing "Hot" code is really important because it burns the CPU and slows down the system. These slow codes can be further optimized and replaced with an optimized machine code to smoothly execute and run the codes.
What is JavaScript Runtime?
As compared with other programming languages, the functionality of JavaScript differs from the rest. JavaScript is a single-threaded language that means the execution of code will be done one piece at a time.
For the reason that code execution is done sequentially, any code that takes a long time to execute will block anything that needs to be executed after that and will extend the processing time. Hence, sometimes you will be observing a small bar showing the progress below the screen while using Google Chrome.
When a user hits a website on their browser, it triggers a single thread of execution, that is JavaScript. That single thread is responsible for handling everything like scrolling the web pages, printing something on the webpage, listening to DOM events, and so on. Once the result appears on the screen, the execution of the JavaScript stops, and the browser will automatically stop doing those tasks for the time being. The execution of the thread will stop or freeze and will be stagnant until the task is completed.