Generators still run on the same single call stack that normal functions do. There are no multiple stacks that evaluation jumps around between.
When you instantiate a generator (by calling a generator function) and then call its
.next() method, it just pushes that call on the top of the stack. It will then run the code inside the generator function.
When it encounters a
yield statement, it just pops the call from the stack and returns from the
.next() method, continuing as usual after any function call.
The difference between a generator call and a normal function call is what happens when entering and leaving the code.
A normal function leaves at the end of the function body or a
throw statement, it's finished then. A generator also leaves on
yield, but it has to remember the state (basically storing the instruction pointer in the generator instance) so that it can resume execution after the
yield. Also it has to remember the state of all local variables, but engines already know how to do that from the implementation of closures.
A normal function enters a call by setting up a fresh environment, and starting execution at the top of the function body. A generator call will restore the state so that it can continue where it left off.
The normal behaviour of the stack is not affected by this.
OK, I lied.
yield* makes it all a bit more complicated. A chain of recursively
yield*ed generators will need to push and pop multiple stack frames when entering or leaving a
.next() call. An engine might optimise this context switch by using multiple stacks. Still, one would see them as stacked atop each other, forming one large stack, and during execution only the top of that single stack is manipulated.
In Chrome/V8's current implementation, as part of
yielding, all state that the generator needs for resuming execution later is written to an object. There is only one stack for function call frames.
The details are complicated; if you want to read the source, start at
BytecodeGenerator::VisitYield in (v8)/src/interpreter/bytecode-generator.cc.
©2020 All rights reserved.