What is JIT Compilation?

JIT combines an interpreter (fast startup) with a compiler (fast execution) to make JavaScript run near native speed. Here's how V8's two-tier pipeline works.

4 min read
JavaScript
V8
Fundamentals

TABLE OF CONTENTS
What is JIT Compilation?

JIT (Just-In-Time) compilation is a hybrid approach to executing code — it combines an interpreter (which runs code immediately) with a compiler (which produces optimized machine code for frequently used functions). V8, the JavaScript engine in Chrome and Node.js, uses JIT to make JavaScript run close to native speed.


Interpreter vs Compiler: Two Extremes

A pure interpreter reads source code line by line and executes it immediately. It starts fast — no waiting for compilation — but runs slow, because each line is re-translated every time it's encountered.

A pure compiler (AOT — Ahead of Time) translates the entire program to machine code before execution. It runs fast because the translation is done once, but startup is slow — especially for large programs — and the compiler can't observe how the code actually runs.

JIT sits in the middle: start with the interpreter for fast startup, then compile the parts that matter.


How V8's JIT Works

V8 (Chrome, Node.js, Edge) uses a two-tier JIT pipeline:

Ignition is the interpreter. It parses JavaScript into an AST, compiles it to compact bytecode, and executes that bytecode immediately. Bytecode is faster to produce than machine code and uses less memory — ideal for code that runs once or infrequently.

TurboFan is the optimizing compiler. It identifies "hot" functions — functions called many times — and compiles them to highly optimized machine code based on the types it has observed.


The Optimization: Speculative Compilation

TurboFan doesn't just translate bytecode to machine code — it specializes the output based on what it has observed. If a function always receives two numbers and returns a number, TurboFan compiles it assuming that will always be true. The resulting machine code is single-purpose and fast.

If that assumption later breaks — a string arrives where a number was expected — TurboFan deoptimizes: discards the optimized code and falls back to the interpreter. Deoptimization is cheap as a one-off event but hurts throughput if it happens frequently.

This is why consistent types in hot functions matter for JavaScript performance. A function that always receives objects of the same shape stays optimized. A function that receives five different object shapes keeps deoptimizing and re-optimizing.


JIT vs AOT

JIT (JavaScript, Java, C#)AOT (C, Rust, Go)
StartupFast (interpreter starts immediately)Slower (must compile first)
Peak performanceClose to native, needs warm-upNative from the start
Optimization dataReal runtime typesStatic analysis only
Binary sizeBytecode + compiled codeCompiled code only
Adaptive to usage patternsYes — only hot code gets compiledNo — everything is compiled

JIT compilation is the reason JavaScript can run at near-native speed despite being a dynamically typed, high-level language. The engine does the hard work of making your code fast — but it can only do that if your code is consistent enough for the optimizer to trust its assumptions.


Let's Connect

© 2026 Naveen Karthik // Built with React & MUI