vm: Detect stack underflow in addition to overflow.
vm: Don't unconditionally allocate state on stack, do that only if needed.

This makes sure that only as much stack allocated as actually used, reducing
stack usage for each Python function call.
vm: Factor out structure with code execution state and pass it around.

This improves stack usage in callers to mp_execute_bytecode2, and is step
forward towards unifying execution interface for function and generators
(which is important because generators don't even support full forms
of arguments passing (keywords, etc.)).