struct _zend_op { const void *handler; //对应执行的C语言function,即每条opcode都有一个C function处理 znode_op op1; //操作数1 znode_op op2; //操作数2 znode_op result; //返回值 uint32_t extended_value; uint32_t lineno; zend_uchar opcode; //opcode指令 zend_uchar op1_type; //操作数1类型 zend_uchar op2_type; //操作数2类型 zend_uchar result_type; //返回值类型 };
struct _zend_op_array { //common是普通函数或类成员方法对应的opcodes快速访问时使用的字段 /* Common elements */ zend_uchar type; zend_uchar arg_flags[3]; /* bitset of arg_info.pass_by_reference */ uint32_t fn_flags; zend_string *function_name; zend_class_entry *scope; zend_function *prototype; uint32_t num_args; uint32_t required_num_args; zend_arg_info *arg_info; /* END of common elements */ uint32_t *refcount; uint32_t last; //opcode指令数组 zend_op *opcodes; //PHP代码里定义的变量数:op_type为IS_CV的变量,不含IS_TMP_VAR、IS_VAR的 //编译前此值为0,然后发现一个新变量这个值就加1 int last_var; //临时变量数:op_type为IS_TMP_VAR、IS_VAR的变量 uint32_t T; //PHP变量名数组 zend_string **vars;//这个数组在ast编译期间配合last_var用来确定各个变量的编号,非常重要的一步操作 int last_live_range; int last_try_catch; zend_live_range *live_range; zend_try_catch_element *try_catch_array; //静态变量符号表:通过static声明的 /* static variables support */ HashTable *static_variables; zend_string *filename; uint32_t line_start; uint32_t line_end; zend_string *doc_comment; uint32_t early_binding; /* the linked list of delayed declarations */ //字面量数量 int last_literal; //字面量(常量)数组,这些都是在PHP代码定义的一些值 zval *literals; //运行时缓存数组大小 int cache_size; //运行时缓存,主要用于缓存一些znode_op以便于快速获取数据,后面单独介绍这个机制 void **run_time_cache; void *reserved[ZEND_MAX_RESERVED_RESOURCES]; };
opcode指令:即PHP代码具体对应的处理动作,与二进制程序中的代码段对应
字面量存储:PHP代码中定义的一些变量初始值、调用的函数名称、类名称、常量名称等等称之为字面量,这些值用于执行时初始化变量、函数调用等等
变量分配情况:与字面量类似,这里指的是当前opcodes定义了多少变量、临时变量,每个变量都有一个对应的编号,执行初始化按照总的数目一次性分配zval,使用时也完全按照编号索引,而不是根据变量名索引
从PHP代码到opcode是怎么实现的?
最容易想到的方式就是正则匹配,当然过程没有这么简单。PHP编译过程包括词法分析、语法分析,使用re2c、bison完成,旧的PHP版本直接生成了opcode,PHP7新增了抽象语法树(AST),在语法分析阶段生成AST,然后再生成opcode数组
以上就是如何编译php文件的详细内容,更多请关注Gxl网其它相关文章!
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did62554