http://eli.thegreenplace.net/2011/08/22/how-not-to-set-a-timeout-on-a-computation-in-python/#id5
基于frame的vm,而不是想象中的结构:
init for inst in instructions:
run inst
init frame for inst in framecode:
- if inst is newframe:
- FrameVM inst
- else:
- run inst
#define STACK_LEVEL() ((int)(stack_pointer - f->f_valuestack)) #define EMPTY() (STACK_LEVEL() == 0)
frame 结构中存有当前的堆栈信息
遇到块结束的指令,调用 break 其他指令则调用 continue,没有检查错误,也不用退出block,直接执行下一条指令
堆,栈的概念
状态 Code对象:可执行码,程序本身 Frame对象,stack:程序的执行状态
statement比较好理解,一行基本上就是一个statement。block在statement之上,每个 block可以有多个statement,是语句块。if,while,try,for等带:的keyword, 都表示一个新block的开始。
block是最小的控制转移单位,在block之内statement被顺序执行,条件判断,循环,异常处理等 机制都必须借助与block才能实现。运行时,python也会记录block的层级信息,因为异常处理 时需要用到,查找本block的handler。
函数可以看做是代码重用的最小单位,函数内可以有多个,多层block。函数对应于PyCode Object, 每次调用一个函数时,都会生成一个新的frame,所以说frame实际上负责存储运行状态, 是运行时的函数调用栈。
http://docs.python.org/2/library/dis.html#python-bytecode-instructions
Python VM指令可以分为以下几大类。
POP_TOP
ROT_TWO
ROT_THREE
DUP_TOP
ROT_FOUR
DUP_TOPX
NOP
UNARY_POSITIVE
UNARY_NEGATIVE
UNARY_NOT
UNARY_CONVERT
UNARY_INVERT
BINARY_POWER
BINARY_MULTIPLY
BINARY_DIVIDE
BINARY_MODULO
BINARY_ADD
BINARY_SUBTRACT
BINARY_FLOOR_DIVIDE
BINARY_TRUE_DIVIDE
INPLACE_FLOOR_DIVIDE
INPLACE_TRUE_DIVIDE
INPLACE_ADD
INPLACE_SUBTRACT
INPLACE_MULTIPLY
INPLACE_DIVIDE
INPLACE_MODULO
INPLACE_POWER
BINARY_LSHIFT
BINARY_RSHIFT
BINARY_AND
BINARY_XOR
BINARY_OR
INPLACE_LSHIFT
INPLACE_RSHIFT
INPLACE_AND
INPLACE_XOR
INPLACE_OR
LIST_APPEND
SLICE+0
SLICE+1
SLICE+2
SLICE+3
STORE_SLICE+0
STORE_SLICE+1
STORE_SLICE+2
STORE_SLICE+3
DELETE_SLICE+0
DELETE_SLICE+1
DELETE_SLICE+2
DELETE_SLICE+3
BUILD_SLICE
BUILD_LIST
BUILD_TUPLE
UNPACK_SEQUENCE
STORE_MAP
BINARY_SUBSCR
STORE_SUBSCR
DELETE_SUBSCR
BUILD_MAP
BREAK_LOOP
POP_BLOCK
FOR_ITER
COMPARE_OP
JUMP_FORWARD
JUMP_IF_FALSE
JUMP_IF_TRUE
JUMP_ABSOLUTE
CONTINUE_LOOP
SETUP_LOOP
RAISE_VARARGS
END_FINALLY
SETUP_EXCEPT
SETUP_FINALLY
LOAD_LOCALS
LOAD_GLOBAL
LOAD_FAST
STORE_FAST
DELETE_FAST
LOAD_DEREF
STORE_DEREF
STORE_NAME
DELETE_NAME
STORE_GLOBAL
DELETE_GLOBAL
LOAD_CONST
LOAD_NAME
变量的作用域,查找机制在这些LOAD_XXX指令中。
CALL_FUNCTION
MAKE_FUNCTION
MAKE_CLOSURE
LOAD_CLOSURE
CALL_FUNCTION_VAR
CALL_FUNCTION_KW
CALL_FUNCTION_VAR_KW
RETURN_VALUE
BUILD_CLASS
STORE_ATTR
LOAD_ATTR
DELETE_ATTR
调用class创建对象,调用对象的方法,实际上都是函数调用。class的初始化,继承,MRO,magic方法等逻辑, 以及Python模块导入逻辑,都没有在指令上体现出来,它们隐藏在指令的背后,用C实现,固化到VM了。
整个python语言,要区分哪些在VM之上,哪些在VM之下。
IMPORT_STAR
IMPORT_NAME
IMPORT_FROM
WITH_CLEANUP # with
EXEC_STMT # exec
YIELD_VALUE # yield
GET_ITER # iter
PRINT_EXPR
PRINT_ITEM
PRINT_NEWLINE
PRINT_ITEM_TO
PRINT_NEWLINE_TO
STOP_CODE
EXTENDED_ARG