This is more an observation and question than anything else, but perhaps it will stimulate some ideas from the experts. Consider this trivial generator function: def gen(a): yield a When the YIELD_VALUE instruction is executed, it executes (in the non-async case): retval = POP(); f->f_stacktop = stack_pointer; goto exiting; This is fine as far as it goes. However, execution eventually leads to Objects/genobject.c where we hit this code (I think after falling off the YIELD_VALUE instruction, but perhaps virtual machine execution reaches RETURN_VALUE): /* If the generator just returned (as opposed to yielding), signal * that the generator is exhausted. */ if (result && f->f_stacktop == NULL) { There are several other references to f->f_stacktop in genobject.c. I've not yet investigated all of them. As I'm working on a register-based virtual machine implementation, I don't fiddle with the stack at all, so it's a bit problematic that the generator implementation is so intimate with the stack. As this is an area of the core which is completely new to me, I wonder if someone can suggest alternate ways of achieving the same effect without relying on the state of the stack. It seems to me that from within PyEval_EvalFrameDefault the implementations of relevant instructions could reference the generator object via f->f_gen and call some (new?) private API on generators which toggles the relevant bit of state in the generator. I think it's worse that this though, as it seems that in gen_send_ex() it actually pushes a value onto the stack. That can't be solved by simply adding a state attribute to the generator object struct. Skip