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
|=-----------------------------------------------------------------------=|
|=--------------------=[Global keyword parsing process analysis]=-------------------=|
|=-----------------------------------------------------------------------=|
|=--------------------------=[by D4shman]=---------------------------=|
|=-----------------------------------------------------------------------=|
|=-------------------------=[May 8,]=---------------------------=|
|=-----------------------------------------------------------------------=|
Directory
0x01 Lexical analysis
0X02 Syntax Analysis
0X03 Interpreting execution
0X04 Reference Documents
0x01 Lexical analysis
d4shman@gentoo# VI/PHP-DEV/PHP-5.4.8/ZEND/ZEND_LANGUAGE_SCANNER.L
Find Global:
"Global" {
return t_global;
}
Found returning a token T_global
0X02 Syntax Analysis
By token T_global come to Zend_language_parser.y to find:
| T_global global_var_list '; '
Global_var_list:
Global_var_list ', ' Global_var {zend_do_fetch_global_variable (&$3, NULL, Zend_fetch_global_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 engine
The Zend_do_fetch_globa_variable function. 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, convert it 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 */
Fetch_simple_variable (&lval, varname, 0 tsrmls_cc);
Zend_do_assign_ref (NULL, &lval, &result tsrmls_cc);
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. In the Zend_do_assign_ref function
There is such a key statement:
Opline->opcode = Zend_assign_ref;
So, during the parsing process, 2 opcode:zend_fetch_w and Zend_assign_ref were actually executed, in Zend_vm_opcodes.h
found that their corresponding opcode were 83 and 39 respectively. 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:
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 when the passed Fetch_type is Zend_fetch_global (_lock).
Returns the symbol table address for the global variable.
The above is the whole process of the global variable parsing execution.
0X04 Reference Documents
In-depth understanding of the PHP kernel