PHP is an analytic high-level language, in fact, from the point of view of the Zend kernel PHP is a normal C program, it has a main function, we write the PHP code is the input of this program, and then through the kernel processing output, the kernel will php code "translated" The process that can be recognized for C programs is PHP compilation.
C program compiles a line of code into machine code at compile time, each operation is considered as a machine instruction, these instructions are written into the compiled binary program, execute the binary program load into the corresponding memory area (constant area, data area, code area), allocation run stack, It is then executed from the beginning of the code area, which is a simple process of compiling and executing the C program.
Similarly, the PHP compiler is similar to the normal C program, but the PHP code is not compiled into machine code, but parse into a number of opcode arrays, each opcode is C inside the ordinary struct, meaning corresponding to the C program's machine instructions, the process of execution is the engine sequentially executes opcode, For example, we define a variable in PHP: $a = 123;
Eventually the kernel executes the malloc piece of memory, and then writes the value in.
In the zend_compile.h file, the opcode structure:
1 struct_zend_op {2 Const void*handler;//corresponding to the execution of the C language function, that is, each opcode has a C function processing3Znode_op OP1;//Number of Operations 14Znode_op OP2;//Number of Operations 25Znode_op result;//return value6 uint32_t Extended_value;7 uint32_t Lineno;8Zend_uchar opcode;//opcode Directive9Zend_uchar Op1_type;//operand 1 TypeTenZend_uchar Op2_type;//operand 2 Type OneZend_uchar result_type;//return value type A};
So the PHP parsing process task is to convert the PHP code (through lexical analysis re2c, parsing bison) into the opcode array, all the information in the code is stored in the opcode, and then the opcode array to the Zend engine execution, OpCode is the kernel of the specific execution of commands, such as assignment, add and subtract operations, function calls, and so on, each opcode corresponds to a processing handle, these handler are defined in advance C function.
1 struct_zend_op_array {2 //Common is the field used by the opcodes quick access corresponding to a normal function or class member method3 /*Common Elements*/4 Zend_uchar type;5Zend_uchar arg_flags[3];/*Bitset of Arg_info.pass_by_reference*/6 uint32_t fn_flags;7Zend_string *function_name;8Zend_class_entry *scope;9Zend_function *prototype;Ten uint32_t Num_args; One uint32_t Required_num_args; AZend_arg_info *Arg_info; - /*END of common elements*/ - theuint32_t *RefCount; - - uint32_t last; - //opcode instruction Array +ZEND_OP *opcodes; - + //the number of variables defined in the PHP code: Op_type is a variable of IS_CV, not including Is_tmp_var, Is_var A //compile before this value is 0, and then find a new variable this value is added 1 at intLast_var; - //number of temporary variables: Op_type is a variable of Is_tmp_var, Is_var - uint32_t t; - //PHP variable an array group -Zend_string **vars;//This array is a very important step in using the Last_var to determine the number of each variable during the AST compilation . - in intLast_live_range; - intLast_try_catch; toZend_live_range *Live_range; +Zend_try_catch_element *Try_catch_array; - the //static variable symbol table: declared by static * /*Static variables support*/ $HashTable *Static_variables;Panax Notoginseng -Zend_string *filename; the uint32_t Line_start; + uint32_t line_end; AZend_string *doc_comment; theuint32_t early_binding;/*The linked list of delayed declarations*/ + - //literal quantity $ intlast_literal; $ //literal (constant) arrays, which are some of the values defined in the PHP code -Zval *literals; - the //run-time cache array size - intcache_size;Wuyi //runtime caching, mainly used to cache some znode_op for fast data acquisition, which is described separately later the void**Run_time_cache; - Wu void*Reserved[zend_max_reserved_resources]; -};
opcode directive: The PHP code corresponds to the specific processing action, and the code snippet in the binary program corresponds to
Literal storage: Some of the variable initial values defined in PHP code, called function names, class names, constant names, and so on, are called literals, which are used to initialize variables, function calls, and so on at execution time.
Variable allocation: Similar to the literal, this refers to the current opcodes defines how many variables, temporary variables, each variable has a corresponding number, the execution of initialization by the total number of one-time allocation of zval, when used is also fully indexed by the number, rather than the variable name index
How does it come from PHP code to opcode? The easiest way to think about it is to match it, but the process is not so simple. PHP compilation process includes lexical analysis, parsing, using RE2C, Bison completed, the old PHP version directly generated OPCODE,PHP7 new abstract Syntax tree (AST), in the parsing phase to generate an AST, and then generate opcode array
Compilation of PHP code