Python Source -- PVM
Frame
- Linked list of
PyFrameObject
-- x86 stack frame f_back
function --esp
,ebp
Namespace: mapping from name (string) to object (pointer)
f_buitins
f_globals
f_locals
Actually, we already know the needed size of stack size when compilingPyCodeObject
, asf_stacksize
.
Another thing is that, the use of closure will also cause extra space in the PyFrameObject
.
We can get access to the frame object at runtime through Python interface, which is basically a hack based on the exception mechanism of VM.
Scope
One .py
file is one module, which is the highest level of scope.
How to understand assignment in Python: Binding an object to name in specified scope. It can also be viewed as a "constraint".
Object also has its own namespace, in which the method names and attribute names are defined.
LGB rule
Priority in descending order:
- L: function / method - local
- G: module - global scope
- B: builtin scope
Considering closure, we have:
LEGB
- E: Enclosing function
global
Force use the name in global scope
Runtime Framework
- Environment Initialization:
PyEval_EvalFrameEx
PyFrameOjbect
's informationPyCodeOjbect
's informationf_stacktop
- main thread
- Loop
why
: exception
Thread information: PyThreadState
. Imported modules are shared across the threads. Sync -- GIL, or Global Interpreter Lock.
Process abstraction: PyInterpreterState
The interaction between frame and thread:
When the evaluation starts, we will use PyThreadState_GET()
to get current active thread object, then set its frame. When we need to create new PyFrameObject
object, we will retrieve old frame from thread state, create new execution environment, link the new frame to old one.