When the engine executes bytecode, the C++ handlers stack up on the C++ call stack. At the same time, V8 maintains a virtual representation of the JavaScript stack, which holds the state corresponding to the JS calls. Thus, even though the actual call occurs on the C++ stack through the handler functions, V8 associates a frame in its virtual JS stack with each call. In other words, the JavaScript call stack relies on the C++ stack for the physical execution of calls, but it is enhanced by an abstraction layer that allows V8 to manage optimizations and specific execution details of the JavaScript code.
This approach enables V8 to benefit from the memory management and optimization of the native stack while retaining a logical and manipulable view of the JavaScript code execution.
In summary, the JavaScript call stack is not an independent memory stack; it is implemented by leveraging the C++ stack along with an abstraction layer that provides the specialized management necessary for executing JS in either interpreted mode or when compiled by TurboFan.