JavaScript engines and Just-In-Time compilation: A beginner’s exploration, part 1

Harum Helmy
3 min readAug 29, 2019

One of the most exciting aspects of my journey toward being a novice software engineer has been learning about everything I’ve taken for granted as a person browsing on the World Wide Web. I was once just another user scrolling mindlessly on a web application, now I scroll mindlessly AND I get excited about what’s going on in the browser as I click around.

One of the seemingly magical things under the hood of the Internet I’ve been curious about is the JavaScript engine.

The JavaScript engine is the software (I know, I was disappointed too, I was definitely picturing some steampunk hardware with pistons here) that translates your gorgeous lines of JavaScript code into binary code executable by our machines.

Not the JavaScript engine, all credit belongs to Giphy

All the major browsers develop their own JavaScript engines. Chrome has V8, Firefox runs SpiderMonkey (the evolutionary product of the first JavaScript engine, developed by Brendan Eich in the 90s for Netscape Navigator), Microsoft Edge has Chakra, Safari has Nitro. Node.js is built on Chrome’s V8 engine. An IoT device could also have a JavaScript engine. You can see a full list of JavaScript engines here.

Each JavaScript engine is responsible for using the ECMAScript rules and standards set by the Ecma International’s TC39.

Why modern JavaScript engines do Just-In-Time compilation

JavaScript is a dynamically typed language.

let x = 8
let y = "Henlo fren"

This means that whenever you’re declaring a variable in JavaScript, you don’t have to explicitly say what type of information the variable x stores. The JavaScript engine checks for the type as it executes your source code.

When declaring variables in a language that’s statically typed, like C++, you have to explicitly specify the type of the variable’s value.

int x = 8 
string y = "Henlo fren"

With such strict rules, a statically typed language can have a higher learning curve. You have to know much more about its rules and types before you can attempt to write a simple program.

From a compiler’s perspective, though, a statically typed language allows for faster performance. Upfront, the language gives the compiler a lot of information about the source code as the compiler moves to translate that code into executable machine code binary.

On the other side of the spectrum, dynamically typed languages like JavaScript offer little information about its types to the compiler. This creates another layer of work for the compiler to do before it can generate the machine code, making it move slower than the compilation of a statically written language.

But fear not, this is where Just-In-Time compilation comes in!

When it was first developed, JavaScript was meant to be written as smaller amounts of script used to enhance web pages. As developers started building and using more JavaScript frameworks and libraries, as well as making AJAX requests, the demand for better, faster performance grew.

Customary fetch() joke.

When Chrome launched in 2008, Google also premiered its V8 engine, the first of the modern JavaScript engines. One of the V8's main features was Just-In-Time compilation.

In Ahead-of-Time compilation, the compiling process has to finish before the system runs the executable machine code. With this new feature, the V8 engine compiles the source code as it needs it, collecting the information on types as it executes the machine code generated by the compilation process, then re-compiles the source code based on the information gathered through the execution process. The back-and-forth between the two processes speed up the performance on the execution process.

Stay tuned for part 2 of this blog where I’ll discuss what I’ve learned about optimization, de-optimization and other stuff that happens in a JavaScript engine.

--

--

Harum Helmy

They/she pronouns. Web developer. Abortion doula with the DC Doulas Collective and board member at the DC Abortion Fund. Indonesian.