This article GitHub address:
Https://github.com/wusuopubupt/phpLib/blob/master/global%E5%85%B3%E9%94%AE%E5%AD%97%E7%9A%84%E8%A7%A3%E6%9E%90 %e8%bf%87%e7%a8%8b%e5%88%86%e6%9e%90
|=-----------------------------------------------------------------------=|| =--------------------parsing Process Analysis of =[global keywords]=-------------------=| | =-----------------------------------------------------------------------=|| =--------------------------=[by D4shman]=---------------------------=| | =-----------------------------------------------------------------------=|| =-------------------------=[May 8,]=---------------------------=| | =-----------------------------------------------------------------------=|
[Catalogue]0x01 Lexical Analysis 0X02 Syntax Analysis 0x03 explanation implementation 0x04 Reference
0x01 Lexical analysis
[Email protected]# vi/php-dev/php-5.4.8/zend/zend_language_scanner.l Find Global:
<ST_IN_SCRIPTING> "Global" {return t_global; } found returning a token T_global
0X02 Syntax Analysis
By token T_global come to zend_language_parser.y find: | T_global global_var_list '; '
Global_var_list:global_var_list ', ' Global_var {zend_do_fetch_global_variable (&$3, NULL, ZEND_FETCH_GLOB Al_lock tsrmls_cc); } | Global_var {zend_do_fetch_global_variable (&$1, NULL, Zend_fetch_global_lock tsrmls_cc);} The above refers to the global_val, as you can see, for global variables, the parser calls the Zend_do_fetch_globa_variable function of the Zend engine. The declaration of this function is zend/zend_compile.c
0X03 Interpreting execution
Find the Zend_do_fetch_global_variable function definition in zend/zend_compile.c:
void Zend_do_fetch_global_variable (Znode *varname, const znode *static_assignment, int fetch_type TSRMLS_DC) { Zend_op *opline; Znode lval; Znode result;
/* If the variable type is constant and not a string, it is converted to a string type */ if (Varname->op_type = = Is_ CONST) { if (Z_type (varname-> u.constant)! = is_string) { convert_to_string (&varname->u.constant); } } opline = Get_next_op (CG (Active_op_array) tsrmls_cc); /* Cg:compile_global */ opline->opcode = ZEND_FETCH_W; /* The default mode must be write */ opline->result_type = is_var; opline->result.var = get_temporary_variable (CG (active_op_array));   Set_node (OPLINE->OP1, varname); if (Opline->op1_type = IS_ CONST) { calculate_literal_hash (opline- >op1.constant); } set_unused (OPLINE->OP2); opline->extended_value = Fetch_type; get_node (&result, Opline->result); if (Varname->op_type = = IS_CONST) { zval_copy_ctor (&varname->u.constant); }/* relies on the fact, the default fetch is Bp_var_w */ & Nbsp; fetch_simple_variable (&lval, varname, 0 tsrmls_cc); zend_do_assign_ref (NULL, &lval, &result TSRMLS_CC) ; &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;CG (Active_op_array)->OPCODES[CG (Active_op_array), Last-1].result_type |= ext_type_unused; }
The code above confirms that opcode is zend_fetch_w and executes the ZEND_DO_ASSIGN_REF function. There is such a key statement in the ZEND_DO_ASSIGN_REF function:
Opline->opcode = Zend_assign_ref;
So, in the process of parsing, 2 opcode:zend_fetch_w and zend_assign_ref are actually executed, and the corresponding opcode are 83 and 39 respectively in Zend_vm_opcodes.h. The method to calculate the last call is (defined in zend_execute.c:):
Zend_opcode_handlers[opcode * + Zend_vm_decode[op->op1.op_type] * 5 + zend_vm_decode[op->op2.op_type]];
After the calculation (///////////I did not figure out how to calculate the//////////), the function that gets called is:
static int Zend_fastcall Zend_fetch_w_spec_cv_handler (Zend_opcode_handler_args) {return zend_fetch_var_address _HELPER_SPEC_CV (Bp_var_w, Zend_opcode_handler_args_passthru); }
In ZEND_FETCH_VAR_ADDRESS_HELPER_SPEC_CV, call the following code to get the symbol table:
target_symbol_table = zend_get_target_symbol_table (Opline, EX (Ts), type, varname tsrmls_cc);
The implementation of the Zend_get_target_symbol_table function is as follows (in):
static inline HashTable *zend_get_target_symbol_table (int fetch_type tsrmls_dc) { switch (Fetch_type) { case zend_fetch_local: if (! EG (active_symbol_table)) { zend_rebuild_symbol_table (Tsrmls_c); } return EG (active_symbol_table); break; case ZEND_FETCH_GLOBAL:&NBSp; case zend_fetch_global_lock: return &EG (symbol_table ); /* Returns the address of the global variable symbol table */ break; case ZEND_FETCH_STATIC: if (! EG (Active_op_array)->static_variables) { alloc_hashtable (EG (Active_op_array)->static_variables ); zend_hash_init (EG (Active_op_array)->static_variables, 2, NULL, Zval_ptr_dtor, 0); } return EG (Active_op_array)->static_variables; break; empty_switch_default_case () } return NULL; }
The code can see that the function uses the EG (EXCUTOR_GLOBAL) macro to return the symbol table address of the GLOBAL variable when the passed Fetch_type is Zend_fetch_global (_lock).
The above is the whole process of the global variable parsing execution.
0X04 Reference Documents
In-depth understanding of the PHP kernel