javascriptc++v8

Is the JavaScript call stack actually on a stack?


In V8, the engine is responsible for creating the JavaScript runtime call stack, which allows it to track its position within the code. The engine comprises two main components: Ignition, an interpreter that processes bytecode, and TurboFan, a compiler that generates optimized machine code.

My question is: When Ignition interprets bytecode, it utilizes handlers, which are C++ functions corresponding to specific bytecode instructions. Executing these handlers creates a C++ call stack, distinct from the JavaScript function call stack. How do these two stacks coexist in stack memory?


Solution

  • (V8 developer here.)

    The engine comprises two main components: Ignition, an interpreter that processes bytecode, and TurboFan, a compiler that generates optimized machine code.

    ...and Sparkplug, a non-optimizing baseline compiler; and Maglev, a fast mostly-optimizing compiler; and a bunch of other components aside from the compilers that would probably be offended if they heard you describe them as "not main components" :-)

    When Ignition interprets bytecode, it utilizes handlers, which are C++ functions

    No, they are code stubs generated at V8 compile time.

    Executing these handlers creates a C++ call stack

    No, the handler are tail-calling each other, so there is only one stack frame per JavaScript function activation.

    distinct from the JavaScript function call stack.

    No, stack frames for JavaScript functions, Wasm function, and any C++ helper functions (which we call "runtime functions" and "builtins") are interleaved. On the machine stack.

    Note: WebAssembly is about to get some features ("JSPI", "stack switching") that makes things more complicated. Wasm will then actually use multiple stacks. But for JavaScript, the above will still be true.

    Second note: it is technically possible to split the C++ stack from the JavaScript stack. We do that in our "simulator" builds for cross-platform testing. That technique is not used in production though; regular builds put everything onto the same stack as described above.