Home > Article > Backend Development > In-depth understanding of the internal structure of the PHP kernel (5) function, in-depth understanding of the internal structure_PHP tutorial
PHP functions include user-defined functions, internal functions (print_r count...), Anonymous function, variable function ($func = 'print_r'; $func(array('a','b'));)
The functions in the PHP kernel source code are divided into the following types
<span>#define</span> ZEND_INTERNAL_FUNCTION 1 <span>#define</span> ZEND_USER_FUNCTION 2 <span>#define</span> ZEND_OVERLOADED_FUNCTION 3 <span>#define</span> ZEND_EVAL_CODE 4 <span>#define</span> ZEND_OVERLOADED_FUNCTION_TEMPORARY 5
1. User function (ZEND_USER_FUNCTION)
Functions do not necessarily have an explicit return value. In PHP implementation, even if there is no explicit return, the PHP kernel will return NULL for us.
During the execution process of ZEND, runtime information will be stored in _zend_execute_data:
<span>struct</span><span> _zend_execute_data { </span><span>//</span><span>...省略部分代码</span> <span> zend_function_state function_state; zend_function </span>*fbc; <span>/*</span><span> Function Being Called </span><span>*/</span> <span>//</span><span>...省略部分代码</span> };
During the program initialization process, function_state will also be initialized. Function_state consists of two parts:
typedef <span>struct</span><span> _zend_function_state { zend_function </span>*<span>function; </span><span>void</span> **<span>arguments; } zend_function_state;</span>
*arguments is a pointer to function parameters, and the function body is stored in *function. *function is a zend_function structure, which ultimately stores all the information of the user-defined function. The specific structure is as follows:
<span>typedef union _zend_function { zend_uchar type; </span><span>/*</span><span> MUST be the first element of this struct! </span><span>*/</span> <span>struct</span><span> { zend_uchar type; </span><span>/*</span><span> never used </span><span>*/</span> <span>char</span> *function_name; <span>//</span><span>函数名称</span> zend_class_entry *scope; <span>//</span><span>函数所在的类作用域</span> zend_uint fn_flags; <span>//</span><span>函数类型,如用户自定义则为 #define </span> ZEND_USER_FUNCTION <span>2</span><span> union _zend_function </span>*prototype; <span>//</span><span>函数原型</span> zend_uint num_args; <span>//</span><span>参数数目</span> zend_uint required_num_args; <span>//</span><span>需要的参数数目</span> zend_arg_info *arg_info; <span>//</span><span>参数信息指针</span> <span> zend_bool pass_rest_by_reference; unsigned </span><span>char</span> return_reference; <span>//</span><span>返回值</span> <span> } common; zend_op_array op_array; </span><span>//</span><span>函数中的操作</span> <span> zend_internal_function internal_function; } zend_function;</span>
The op_array in the zend_function structure stores all the operations in the function. When the function is called, ZEND will execute the oplines in the op_array sequentially one by one and return the final result. The definition and execution of functions are separated, and a function can exist as an independent running unit.
2. Internal function (ZEND_INTERNAL_FUNCTION)
The ZEND_INTERNAL_FUNCTION function is provided by the extension or the Zend/PHP kernel. It is written in c/c and can be executed directly. The following is the structure of the internal function
typedef <span>struct</span><span> _zend_internal_function { </span><span>/*</span><span> Common elements </span><span>*/</span><span> zend_uchar type; </span><span>char</span> *<span> function_name; zend_class_entry </span>*<span>scope; zend_uint fn_flags; union _zend_function </span>*<span>prototype; zend_uint num_args; zend_uint required_num_args; zend_arg_info </span>*<span>arg_info; zend_bool pass_rest_by_reference; unsigned </span><span>char</span><span> return_reference; </span><span>/*</span><span> END of common elements </span><span>*/</span> <span>void</span> (*<span>handler)(INTERNAL_FUNCTION_PARAMETERS); </span><span>struct</span> _zend_module_entry *<span>module; } zend_internal_function;</span>
During module initialization, ZE will traverse each loaded extension module, and then create a zend_internal_function structure for each function (module->functions) specified in function_entry in the module, and set its type to ZEND_INTERNAL_FUNCTION, fill this structure into the global function table (HashTable structure); for the function setting and registration process, see the zend_register_function function in the Zend/zene_API.c file. In addition to processing the function page, this function also processes class methods, including those magic methods.
The structure of the internal function is basically similar to the structure of the user-defined function, with some differences:
3. Variable function
If there are parentheses after a variable name, PHP will look for a function with the same name as the value of the variable and try to execute it.
Variable function $func
$func = <span>'</span><span>print_r</span><span>'</span><span>; $func(</span><span>'</span><span>i am print_r function.</span><span>'</span>);
Compiled intermediate code
function name: (<span>null</span><span>) number of ops: </span><span>9</span><span> compiled vars: </span>!<span>0</span> =<span> $func line # </span>* op fetch ext <span>return</span><span> operands </span>------------------------------------------------------------------------------ - - <span>2</span> <span>0</span> ><span> EXT_STMT </span><span>1</span> ASSIGN !<span>0</span><span>, </span><span>'</span><span>print_r</span><span>'</span> <span>3</span> <span>2</span><span> EXT_STMT </span><span>3</span> INIT_FCALL_BY_NAME !<span>0</span> <span>4</span><span> EXT_FCALL_BEGIN </span><span>5</span><span> SEND_VAL </span><span>'</span><span>i+am+print_r+function.</span><span>'</span> <span>6</span> DO_FCALL_BY_NAME <span>1</span> <span>7</span><span> EXT_FCALL_END </span><span>8</span> > RETURN 1
Internal function
print_r(<span>'</span><span>i am print_r function.</span><span>'</span>);
Compiled intermediate code
function name: (<span>null</span><span>) number of ops: </span><span>6</span><span> compiled vars: none line # </span>* op fetch ext <span>return</span><span> operands </span>------------------------------------------------------------------------------- - - <span>2</span> <span>0</span> ><span> EXT_STMT </span><span>1</span><span> EXT_FCALL_BEGIN </span><span>2</span><span> SEND_VAL </span><span>'</span><span>i+am+print_r+function.</span><span>'</span> <span>3</span> DO_FCALL <span>1</span> <span>'</span><span>print_r</span><span>'</span> <span>4</span><span> EXT_FCALL_END </span><span>5</span> > RETURN <span>1</span>
Comparison shows that there are some differences between the two in calling the intermediate code. The variable function is DO_FCALL_BY_NAME, while the internal function is DO_FCALL. This has already been decided during syntax parsing. See part of the code in the zend_do_end_function_call function in the Zend/zend_complie.c file:
<span>if</span> (!is_method && !is_dynamic_fcall && function_name->op_type==<span>IS_CONST) { opline</span>->opcode =<span> ZEND_DO_FCALL; opline</span>->op1 = *<span>function_name; ZVAL_LONG(</span>&opline-><span>op2.u.constant, zend_hash_func(Z_STRVAL(function_name</span>->u.constant), Z_STRLEN(function_name- >u.constant) + <span>1</span><span>)); } </span><span>else</span><span> { opline</span>->opcode =<span> ZEND_DO_FCALL_BY_NAME; SET_UNUSED(opline</span>-><span>op1); }</span>
If it is not a method and is not called dynamically, and the function name is a string variable, the intermediate code generated is ZEND_DO_FCALL. Otherwise it is ZEND_DO_FCALL_BY_NAME. In addition, the variable function is used as a callback function, and its processing process is in the zend_do_pass_param function of the Zend/zend_complie.c file, which will eventually be reflected in ZEND_SEND_VAL_SPEC_CONST_HADNLER and other functions during the execution of the intermediate code.
4. Anonymous functions
Anonymous function is a type of function or subroutine that can be called without specifying an identifier. Anonymous functions can be conveniently passed as parameters to other functions.