17db96d56Sopenharmony_ci# The Frame Stack
27db96d56Sopenharmony_ci
37db96d56Sopenharmony_ciEach call to a Python function has an activation record,
47db96d56Sopenharmony_cicommonly known as a "frame".
57db96d56Sopenharmony_ciPython semantics allows frames to outlive the activation,
67db96d56Sopenharmony_ciso they have (before 3.11) been allocated on the heap.
77db96d56Sopenharmony_ciThis is expensive as it requires many allocations and
87db96d56Sopenharmony_ciresults in poor locality of reference.
97db96d56Sopenharmony_ci
107db96d56Sopenharmony_ciIn 3.11, rather than have these frames scattered about memory,
117db96d56Sopenharmony_cias happens for heap-allocated objects, frames are allocated
127db96d56Sopenharmony_cicontiguously in a per-thread stack. 
137db96d56Sopenharmony_ciThis improves performance significantly for two reasons:
147db96d56Sopenharmony_ci* It reduces allocation overhead to a pointer comparison and increment.
157db96d56Sopenharmony_ci* Stack allocated data has the best possible locality and will always be in 
167db96d56Sopenharmony_ci  CPU cache.
177db96d56Sopenharmony_ci
187db96d56Sopenharmony_ciGenerator and coroutines still need heap allocated activation records, but
197db96d56Sopenharmony_cican be linked into the per-thread stack so as to not impact performance too much.
207db96d56Sopenharmony_ci
217db96d56Sopenharmony_ci## Layout
227db96d56Sopenharmony_ci
237db96d56Sopenharmony_ciEach activation record consists of four conceptual sections:
247db96d56Sopenharmony_ci
257db96d56Sopenharmony_ci* Local variables (including arguments, cells and free variables)
267db96d56Sopenharmony_ci* Evaluation stack
277db96d56Sopenharmony_ci* Specials: The per-frame object references needed by the VM: globals dict,
287db96d56Sopenharmony_ci  code object, etc.
297db96d56Sopenharmony_ci* Linkage: Pointer to the previous activation record, stack depth, etc.
307db96d56Sopenharmony_ci
317db96d56Sopenharmony_ci### Layout
327db96d56Sopenharmony_ci
337db96d56Sopenharmony_ciThe specials and linkage sections are a fixed size, so are grouped together.
347db96d56Sopenharmony_ci
357db96d56Sopenharmony_ciEach activation record is laid out as:
367db96d56Sopenharmony_ci* Specials and linkage
377db96d56Sopenharmony_ci* Locals
387db96d56Sopenharmony_ci* Stack
397db96d56Sopenharmony_ci
407db96d56Sopenharmony_ciThis seems to provide the best performance without excessive complexity.
417db96d56Sopenharmony_ciIt needs the interpreter to hold two pointers, a frame pointer and a stack pointer.
427db96d56Sopenharmony_ci
437db96d56Sopenharmony_ci#### Alternative layout
447db96d56Sopenharmony_ci
457db96d56Sopenharmony_ciAn alternative layout that was used for part of 3.11 alpha was:
467db96d56Sopenharmony_ci
477db96d56Sopenharmony_ci* Locals
487db96d56Sopenharmony_ci* Specials and linkage
497db96d56Sopenharmony_ci* Stack
507db96d56Sopenharmony_ci
517db96d56Sopenharmony_ciThis has the advantage that no copying is required when making a call,
527db96d56Sopenharmony_cias the arguments on the stack are (usually) already in the correct
537db96d56Sopenharmony_cilocation for the parameters. However, it requires the VM to maintain
547db96d56Sopenharmony_cian extra pointer for the locals, which can hurt performance.
557db96d56Sopenharmony_ci
567db96d56Sopenharmony_ciA variant that only needs the need two pointers is to reverse the numbering
577db96d56Sopenharmony_ciof the locals, so that the last one is numbered `0`, and the first in memory
587db96d56Sopenharmony_ciis numbered `N-1`.
597db96d56Sopenharmony_ciThis allows the locals, specials and linkage to accessed from the frame pointer.
607db96d56Sopenharmony_ciWe may implement this in the future.
617db96d56Sopenharmony_ci
627db96d56Sopenharmony_ci#### Note:
637db96d56Sopenharmony_ci
647db96d56Sopenharmony_ci> In a contiguous stack, we would need to save one fewer registers, as the
657db96d56Sopenharmony_ci> top of the caller's activation record would be the same at the base of the
667db96d56Sopenharmony_ci> callee's. However, since some activation records are kept on the heap we 
677db96d56Sopenharmony_ci> cannot do this.
687db96d56Sopenharmony_ci
697db96d56Sopenharmony_ci### Generators and Coroutines
707db96d56Sopenharmony_ci
717db96d56Sopenharmony_ciGenerators and coroutines contain a `_PyInterpreterFrame`
727db96d56Sopenharmony_ciThe specials sections contains the following pointers:
737db96d56Sopenharmony_ci
747db96d56Sopenharmony_ci* Globals dict
757db96d56Sopenharmony_ci* Builtins dict
767db96d56Sopenharmony_ci* Locals dict (not the "fast" locals, but the locals for eval and class creation)
777db96d56Sopenharmony_ci* Code object
787db96d56Sopenharmony_ci* Heap allocated `PyFrameObject` for this activation record, if any.
797db96d56Sopenharmony_ci* The function.
807db96d56Sopenharmony_ci
817db96d56Sopenharmony_ciThe pointer to the function is not strictly required, but it is cheaper to
827db96d56Sopenharmony_cistore a strong reference to the function and borrowed references to the globals
837db96d56Sopenharmony_ciand builtins, than strong references to both globals and builtins.
847db96d56Sopenharmony_ci
857db96d56Sopenharmony_ci### Frame objects
867db96d56Sopenharmony_ci
877db96d56Sopenharmony_ciWhen creating a backtrace or when calling `sys._getframe()` the frame becomes
887db96d56Sopenharmony_civisible to Python code. When this happens a new `PyFrameObject` is created 
897db96d56Sopenharmony_ciand a strong reference to it placed in the `frame_obj` field of the specials
907db96d56Sopenharmony_cisection. The `frame_obj` field is initially `NULL`.
917db96d56Sopenharmony_ci
927db96d56Sopenharmony_ciThe `PyFrameObject` may outlive a stack-allocated `_PyInterpreterFrame`.
937db96d56Sopenharmony_ciIf it does then `_PyInterpreterFrame` is copied into the `PyFrameObject`,
947db96d56Sopenharmony_ciexcept the evaluation stack which must be empty at this point.
957db96d56Sopenharmony_ciThe linkage section is updated to reflect the new location of the frame.
967db96d56Sopenharmony_ci
977db96d56Sopenharmony_ciThis mechanism provides the appearance of persistent, heap-allocated
987db96d56Sopenharmony_ciframes for each activation, but with low runtime overhead.
997db96d56Sopenharmony_ci
1007db96d56Sopenharmony_ci### Generators and Coroutines
1017db96d56Sopenharmony_ci
1027db96d56Sopenharmony_ci
1037db96d56Sopenharmony_ciGenerator objects have a `_PyInterpreterFrame` embedded in them.
1047db96d56Sopenharmony_ciThis means that creating a generator requires only a single allocation,
1057db96d56Sopenharmony_cireducing allocation overhead and improving locality of reference.
1067db96d56Sopenharmony_ciThe embedded frame is linked into the per-thread frame when iterated or
1077db96d56Sopenharmony_ciawaited. 
1087db96d56Sopenharmony_ci
1097db96d56Sopenharmony_ciIf a frame object associated with a generator outlives the generator, then
1107db96d56Sopenharmony_cithe embedded `_PyInterpreterFrame` is copied into the frame object.
1117db96d56Sopenharmony_ci
1127db96d56Sopenharmony_ci
1137db96d56Sopenharmony_ciAll the above applies to coroutines and async generators as well.
1147db96d56Sopenharmony_ci
1157db96d56Sopenharmony_ci### Field names
1167db96d56Sopenharmony_ci
1177db96d56Sopenharmony_ciMany of the fields in `_PyInterpreterFrame` were copied from the 3.10 `PyFrameObject`.
1187db96d56Sopenharmony_ciThus, some of the field names may be a bit misleading.
1197db96d56Sopenharmony_ci
1207db96d56Sopenharmony_ciFor example the `f_globals` field has a `f_` prefix implying it belongs to the
1217db96d56Sopenharmony_ci`PyFrameObject` struct, although it belongs to the `_PyInterpreterFrame` struct.
1227db96d56Sopenharmony_ciWe may rationalize this naming scheme for 3.12.