05 / 06

Explain how code is executed in the JavaScript engine in detail. Give specific examples of how it differs in popular engines like V8, SpiderMonkey, etc.

JavaScript code execution in modern engines involves parsing, interpretation, and Just-In-Time (JIT) compilation, with each engine employing unique architectures for optimization.

At a high level, all JavaScript engines follow a similar workflow: The source code is first fed into a parser, which performs lexical analysis to break the code into tokens and then syntactic analysis to build an Abstract Syntax Tree (AST) . This AST is a tree-like representation of the code's structure. From here, the path diverges slightly based on the engine's architecture, but the goal is the same: to get the code running as efficiently as possible.

Sample JavaScript Function

The AST is then passed to an interpreter, which generates and executes platform-independent bytecode. This allows execution to start immediately. While the code runs, the engine monitors its behavior, identifying 'hot' functions or code paths that are executed frequently . These hot spots are then sent to a compiler to be optimized into machine code, which is faster. This combination of an interpreter and an optimizing compiler is the essence of JIT compilation. If the compiler's assumptions about the code (e.g., the types of variables) turn out to be incorrect, it performs 'deoptimization,' reverting to the interpreted bytecode .

V8 (Chrome, Node.js) - Optimized for Speed
  1. 1

    V8 uses a two-tier execution model with the Ignition interpreter and the TurboFan optimizing compiler .

  2. 2

    Ignition quickly generates and executes bytecode from the AST, collecting type feedback (e.g., 'the variable 'a' in sum() is always a number') .

  3. 3

    TurboFan uses this feedback to generate highly-optimized machine code for hot functions. It performs aggressive optimizations like function inlining and type specialization.

  4. 4

    If the optimized code encounters a situation that violates its assumptions (like 'a' suddenly becoming a string), TurboFan deoptimizes it, and execution falls back to Ignition .

SpiderMonkey (Firefox) - Balanced for Compatibility
  1. 1

    SpiderMonkey employs a more complex multi-tier architecture: Interpreter → Baseline Compiler → IonMonkey Compiler.

  2. 2

    The interpreter executes bytecode and monitors for hot code. Once a threshold is hit, the Baseline compiler generates a simply-optimized version of the code quickly .

  3. 3

    For extremely hot code, the IonMonkey compiler steps in to perform deep, aggressive optimizations, taking more time for potentially greater performance gains .

  4. 4

    This layered approach allows SpiderMonkey to better balance startup speed, steady-state performance, and the need to support all JavaScript language features robustly, including older or more complex patterns .

In addition to JIT compilation, engines manage memory through garbage collection. V8 uses a generational garbage collector called Orinoco, which employs different strategies for the 'young' and 'old' generations to minimize pause times . SpiderMonkey also uses a sophisticated generational collector. A key difference observed in empirical studies is that the 'Compiler' component in V8 is the most bug-prone, while the 'DOM' (Document Object Model) component is the most bug-prone in SpiderMonkey, reflecting their different host environments and optimization focuses .

Difficulty: 8/10
Topics: parsing & AST, JIT compilation, engine-specific optimizations

Scenario Questions

0-2 years experience
  1. 1

    If you write a simple function that adds two numbers, walk me through what the JavaScript engine does from parsing to execution in Chrome's V8.

  2. 2

    What changes in the engine's behavior when you replace a direct function call with eval inside that same function?

  3. 3

    How does the engine decide whether to interpret or compile a small script you just loaded?

2-5 years experience
  1. 1

    We added a new nested loop and saw a performance regression in Chrome but not in Firefox; how would you use your knowledge of V8 and SpiderMonkey to diagnose the cause?

  2. 2

    Explain why a piece of code that uses many object property accesses runs faster in Chrome than in Safari, focusing on engine‑specific optimizations.

  3. 3

    During debugging you see de‑optimisation warnings in Chrome DevTools; what do they mean and how would you address them?

5-8 years experience
  1. 1

    Design a profiling and optimisation strategy for a large single‑page app that must perform well on both V8 and SpiderMonkey.

  2. 2

    When would you deliberately write code that leverages hidden classes or inline caches versus keeping it generic for cross‑browser consistency?

  3. 3

    If you had to build a custom JavaScript runtime for an embedded device, which parts of the engine pipeline would you prioritize and why?

8+ years experience
  1. 1

    Our legacy codebase runs on an older SpiderMonkey version and we plan to migrate to V8; what architectural considerations and migration steps would you propose to minimise runtime behavior changes?

  2. 2

    How would you evaluate the trade‑offs of JIT strategies, garbage‑collection models, and memory layouts when choosing between V8, SpiderMonkey, and JavaScriptCore for a new product?

  3. 3

    Lead a cross‑team effort to standardise performance benchmarks that fairly account for engine‑specific execution differences; what metrics and processes would you establish?

Follow-up Questions

  • Can you show a code snippet that would cause V8 to de‑optimise a function?
  • How do inline caches speed up property accesses across engines?
  • What are the UI‑responsiveness implications of a stop‑the‑world GC pause?