PHP kernel learning tutorial PHP opcode kernel Implementation _php instance

Source: Internet
Author: User
Tags goto php script zend

OpCode is a part of the computer instruction that specifies the action to be performed, and the format and specification of the instruction is specified by the processor's instruction specification. In addition to the instruction itself, there is usually an operand required for the instruction, which may not require an explicit operand. These operands may be values in registers, values in the stack, values in a block of memory, or values in IO ports, and so on.

Usually opcode also has another title: Byte Code (byte codes). For example, the Java Virtual Machine (JVM). NET Universal Intermediate language (Cil:common intermeditate Language) and so on.

1. OpCode Introduction

OpCode is a part of the computer instruction that specifies the action to be performed, and the format and specification of the instruction is specified by the processor's instruction specification. In addition to the instruction itself, there is usually an operand required for the instruction, which may not require an explicit operand. These operands may be values in registers, values in stacks, values in a block of memory, or values in IO ports, and so on

Usually opcode also has another title: Byte Code (byte codes). For example, the Java Virtual Machine (JVM). NET Universal Intermediate language (Cil:common intermeditate Language), etc.

OpCode in PHP belongs to the previous introduction, PHP is built on the Zend virtual machine (Zend VM). php's opcode is the Zend virtual machine instructions (based on the Zend of the Intermediate code)

Relevant Link:

Http://www.luocong.com/learningopcode/doc/1._%E4%BB%80%E4%B9%88%E6%98%AFOpCode%EF%BC%9F.htm

2. OpCode in PHP

0x1: Data structure

Inside the PHP implementation, the opcode is represented by the following structure body

\php-5.6.17\zend\zend_compile.h

struct _zend_op 
{
opcode_handler_t handler;//The handler function that was invoked when the opcode was executed znode_op OP1
;//opcode the number of operations
Znode _op OP2; The operation number of opcode
znode_op result;
ULONG Extended_value;
UINT Lineno;
Zend_uchar opcode; OpCode code
zend_uchar op1_type;
Zend_uchar Op2_type;
Zend_uchar result_type;

Like the CPU instructions, there is a opcode field that marks the instruction, and the number of operations that the opcode operates, PHP is not as low as the assembly, and when the script actually executes it may need additional information, the Extended_value field holds this kind of information, Where the result field is saved after the execution of the instruction is completed

For example, the following code is a function that compiles when the compiler encounters a print statement

\php-5.6.17\zend\zend_compile.c

void Zend_do_print (Znode *result, const znode *ARG tsrmls_dc)/* {{*
* 
///New Create a zend_op zend_op *opline 
= Get _next_op (CG (Active_op_array) tsrmls_cc);

Sets the return value type of the new zend_op to a temporary variable (IS_TMP_VAR) because the memory in print is only for temporary output and does not need to be saved
opline->result_type = Is_tmp_var;
Request space for a temporary variable
opline->result.var = get_temporary_variable (CG (Active_op_array));
Designate opcode as zend_print
opline->opcode = zend_print;
Assign the passed in parameters to the first operand of the opcode
set_node (OPLINE->OP1, arg);
Set_unused (OPLINE->OP2);
Get_node (result, Opline->result);
}

0x2:opcode type: Zend_op->zend_uchar opcode

Compared to the concept of assembly language, each opcode corresponds to a type, indicating that the OPCPDE's "operation instruction", opcode type is Zend_uchar,zend_uchar is actually unsigned char, this field holds the reshaping value is the OP's number, To distinguish between different op types, the opcode value is defined as a macro

/zend/zend_vm_opcodes.h

#define ZEND_NOP 0 #define ZEND_ADD 1 #define ZEND_SUB 2 #define ZEND_MUL 3 #define ZEND_DIV 4 #define ZEND_MOD 5 #define ZEND_SL 6 #define ZEND_SR 7 #define ZEND_CONCAT 8 #define ZEND_BW_OR 9 #define Zend_bw_and #define ZEND_BW_XOR One #def INE zend_bw_not #define ZEND_BOOL_NOT #define ZEND_BOOL_XOR #define ZEND_IS_IDENTICAL #define Zend_is_not_iden  Tical #define ZEND_IS_EQUAL #define ZEND_IS_NOT_EQUAL #define Zend_is_smaller #define Zend_is_smaller_or_equal #define ZEND_CAST #define ZEND_QM_ASSIGN #define ZEND_ASSIGN_ADD #define ZEND_ASSIGN_SUB #define Zend_assi Gn_mul #define ZEND_ASSIGN_DIV #define ZEND_ASSIGN_MOD #define ZEND_ASSIGN_SL #define ZEND_ASSIGN_SR #defin E zend_assign_concat #define ZEND_ASSIGN_BW_OR #define Zend_assign_bw_and #define ZEND_ASSIGN_BW_XOR #define Z End_pre_inc #define ZEND_PRE_DEC #define ZEND_POST_INC #define ZEND_POST_DEC Notoginseng #define ZEND_ASSIGN #define ZE Nd_assign_ref #define Zend_echo #define ZEND_PRINT #define ZEND_JMP #define ZEND_JMPZ #define ZEND_JMPNZ #define ZEND_JMPZNZ 45 #define ZEND_JMPZ_EX #define ZEND_JMPNZ_EX #define ZEND_CASE #define ZEND_SWITCH_FREE #define ZEND_BRK #def INE Zend_cont #define ZEND_BOOL #define ZEND_INIT_STRING #define ZEND_ADD_CHAR #define Zend_add_string #def INE Zend_add_var #define ZEND_BEGIN_SILENCE #define ZEND_END_SILENCE #define ZEND_INIT_FCALL_BY_NAME #define Z End_do_fcall #define ZEND_DO_FCALL_BY_NAME #define Zend_return #define ZEND_RECV #define ZEND_RECV_INIT #de Fine zend_send_val #define ZEND_SEND_VAR #define ZEND_SEND_REF #define ZEND_NEW #define Zend_init_ns_fcall_by_
NAME #define ZEND_FREE #define ZEND_INIT_ARRAY #define Zend_add_array_element #define ZEND_INCLUDE_OR_EVAL 73 #define ZEND_UNSET_VAR #define ZEND_UNSET_DIM #define ZEND_UNSET_OBJ #define ZEND_FE_RESET #define Zend_fe_fet CH #define Zend_exit#define ZEND_FETCH_R #define ZEND_FETCH_DIM_R bayi #define ZEND_FETCH_OBJ_R #define ZEND_FETCH_W #define Zend_fe Tch_dim_w #define ZEND_FETCH_OBJ_W #define ZEND_FETCH_RW #define ZEND_FETCH_DIM_RW #define ZEND_FETCH_OBJ_RW 8 8 #define ZEND_FETCH_IS #define ZEND_FETCH_DIM_IS #define ZEND_FETCH_OBJ_IS #define ZEND_FETCH_FUNC_ARG #defin E zend_fetch_dim_func_arg #define ZEND_FETCH_OBJ_FUNC_ARG #define ZEND_FETCH_UNSET #define Zend_fetch_dim_unset
#define ZEND_FETCH_OBJ_UNSET #define ZEND_FETCH_DIM_TMP_VAR #define ZEND_FETCH_CONSTANT #define ZEND_GOTO 100  #define ZEND_EXT_STMT #define ZEND_EXT_FCALL_BEGIN 102 #define ZEND_EXT_FCALL_END #define ZEND_EXT_NOP #define Zend_ticks #define ZEND_SEND_VAR_NO_REF #define ZEND_CATCH #define ZEND_THROW 108 #define ZEND_FETCH_CLASS 10 9 #define Zend_clone #define ZEND_RETURN_BY_REF #define ZEND_INIT_METHOD_CALL 112 #define Zend_init_static_method _call 113 #define Zend_issEt_isempty_var 114 #define ZEND_ISSET_ISEMPTY_DIM_OBJ #define ZEND_PRE_INC_OBJ 132 #define Zend_pre_dec_obj #defi NE zend_post_inc_obj 134 #define ZEND_POST_DEC_OBJ 135 #define ZEND_ASSIGN_OBJ 136 #define ZEND_INSTANCEOF 138 #define ZEN D_declare_class 139 #define ZEND_DECLARE_INHERITED_CLASS 140 #define Zend_declare_function #define Zend_raise_ Abstract_error #define ZEND_DECLARE_CONST 143 #define ZEND_ADD_INTERFACE 144 #define Zend_declare_inherited_class_ Delayed 145 #define ZEND_VERIFY_ABSTRACT_CLASS 146 #define ZEND_ASSIGN_DIM 147 #define ZEND_ISSET_ISEMPTY_PROP_OBJ 148 #d Efine zend_handle_exception 149 #define ZEND_USER_OPCODE #define ZEND_JMP_SET 152 #define Zend_declare_lambda_ FUNCTION 153 #define ZEND_ADD_TRAIT 154 #define ZEND_BIND_TRAITS #define ZEND_SEPARATE 156 #define Zend_qm_assign_var 157 #define ZEND_JMP_SET_VAR 158 #define ZEND_DISCARD_EXCEPTION 159 #define ZEND_YIELD 160 #define Zend_generator_return 1 #define ZEND_FAST_CALL 162 #define Zend_fasT_ret 163 #define ZEND_RECV_VARIADIC 164 #define ZEND_SEND_UNPACK 165 #define ZEND_POW 166 #define ZEND_ASSIGN_POW 167  

0x3:opcode execution handle: Zend_op->handler

The execution handle of the OP, which is of type opcode_handler_t

typedef int (Zend_fastcall *opcode_handler_t) (Zend_opcode_handler_args);
This function pointer defines the execution method for the OP, each opcode field corresponds to a kind of handler, such as if $a = 1; Such code generates OP, operand is const and CV, finally can be determined handler as function zend_assign_spec_ Cv_const_handler

/zend/zend_vm_execute.h

void Zend_init_opcodes_handlers (void)
{
static const opcode_handler_t labels[] = {
..
Zend_assign_spec_cv_const_handler,
..
}
}

0x4:opcpde operand Znode

The operand segment is a more important part of the _zend_op type, where Op1,op2,result three operands are defined as Znode types

\php-5.6.17\zend\zend_compile.h

typedef struct _ZNODE {/* used only during compilation/* This int type of field defines the type of Znode operand #define IS_CONST (1<<0)//Express Quantity, for example $a = 123; $b = "Hello"; After the code generates the OP, 123 and "Hello" are #define IS_TMP_VAR (1<<1)//representing temporary variables in the constant type operand, and temporary variables are generally preceded by a ~ to indicate, This is some intermediate variables that need to be used during OP execution, such as initializing an array, a temporary variable is needed to temporarily store the array zval, and then assigning the array to the variable #define IS_VAR (1&LT;&LT;2)//general variables, with $ development representation # Define is_unused (1&LT;&LT;3)//Unused variable #define IS_CV (1<<4)//Compiled variable, this type of operand is more important, this type is in PHP later In the version (about 5.1), CV meaning is compiled variable, that is, the compiled variables, variables are stored in a symbolic table, the symbol table is a hash table, if each read and write variables need to go to the hash tables to retrieve, will have a certain impact on efficiency, As a result, some variables generated during compilation are cached in the execution context environment.
This type of operand is usually represented by the start, such as variable $a=123; $b = "Hello" code, $a and $b corresponding operands may be!0 and! 1, 0 and 1 are equivalent to an index number, and the corresponding value is obtained from the cache by index number/int op_type; /* This field is a union, depending on the op_type, u take a different value of 1. In Op_type=is_const, the constant in U holds the ZVAL structure 2 of the operand corresponding. For example, when $a=123, in the 123 operand, the constant in U is a is_long type of zval whose value is lval to 123/union {ZNODE_OP op; zval constant;/* Replaced by literal
/ZV * * Zend_op_array *op_array;
Zend_ast *ast;
} u; Zend_uint EA; /* ExtEnded attributes */} Znode;  

0x5:opcode compiled array Op_array

In the first line of the Zend_do_print function, we notice that the following line of code

 
  

The PHP script code is compiled with opcode saved in Op_array, and its internal storage structure is as follows

\php-5.6.17\zend\zend_compile.h

struct _zend_op_array {/* Common elements/Zend_uchar type; const char *function_name;//If it is a user-defined function, the name of the function will be saved here Zend
_class_entry *scope;
Zend_uint Fn_flags;
Union _zend_function *prototype;
Zend_uint Num_args;
Zend_uint Required_num_args;
Zend_arg_info *arg_info;
/* End of common elements * * Zend_uint *refcount; Zend_op *opcodes;
OpCode array Zend_uint last;
Zend_compiled_variable *vars;
int Last_var;
Zend_uint T;
Zend_uint Nested_calls;
Zend_uint Used_stack;
Zend_brk_cont_element *brk_cont_array;
int Last_brk_cont;
Zend_try_catch_element *try_catch_array;
int last_try_catch;
Zend_bool Has_finally_block;
/* Static Variables Support * * HashTable *static_variables;
Zend_uint This_var;
const char *filename;
Zend_uint Line_start;
Zend_uint Line_end;
const char *doc_comment;
Zend_uint Doc_comment_len; Zend_uint early_binding;
/* The linked list of delayed declarations * * zend_literal *literals;
int last_literal;
void **run_time_cache;
int last_cache_slot; void *reserved[zend_max_reservEd_resources];  };

The entire PHP script code is saved here by the compiled opcodes, executed by the following execute function

Zend_api void Execute (zend_op_array *op_array tsrmls_dc)
{
//... Loop through opcode in op_array or perform opcode in other Op_array

Each opcode has a opcode_handler_t function pointer field that is used to perform the opcode,php in three ways for opcode processing

1. call:php uses the call method by default, which is the way the function is called
2. Switch: Because opcode execution is frequently required by each PHP program, you can use switch or goto to distribute
3. Goto: The efficiency of Goto is usually higher, but whether the efficiency is increased depends on the different CPU
In fact, we will find that in/zend/zend_language_parser.c is Zend's opcode interpretation of the implementation process, which includes call, switch, goto three kinds of opcode execution way

This is why PHP is called the core principle of interpreted language, PHP after the completion of the lex lexical parsing, in the parsing of the generation generated, directly through the call, switch, Goto way to invoke the Zend API, even if the interpretation of the implementation

Relevant Link:

http://www.nowamagic.net/librarys/veda/detail/1325
http://php.net/manual/zh/internals2.opcodes.list.php
http://www.nowamagic.net/librarys/veda/detail/1543
http://www.nowamagic.net/librarys/veda/detail/1324
http://www.nowamagic.net/librarys/veda/detail/1543 
http://www.laruence.com/2008/06/18/221.html

3. OpCode translation Implementation (instant interpretation)

Relevant Link:

Http://www.php-internals.com/book/?p=chapt02/02-03-03-from-opcode-to-handler

The above described in this article to introduce the PHP kernel learning tutorials PHP opcode kernel Implementation of the relevant knowledge, hope to help everyone.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.