您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

PHP execute

2024/5/30 11:40:01发布20次查看
修改一下文章,之前没说明问题。
主要说明一下php的执行过程,涉及到函数执行流程,php 的函数让php强大的特点之一,暂时不讨论类。php 的作用域控制只有两处,函数和类,在实际中感觉函数控制作用域的概念更多一点。
函数分为用户自定义函数,和内部函数。内部函数是php用c 或者是c++编写,这里分析的时候,不会涉及到作用域的切换,在模块初始化的时候就会加载到全局的函数表中eg(function_table)。
内部函数,用户自定义函数,op_array 三者的数据结构如下所示:
struct _zend_op_array { /* common elements */ zend_uchar type; char *function_name; 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; zend_bool pass_rest_by_reference; unsigned char return_reference; /* end of common elements */ zend_bool done_pass_two; zend_uint *refcount; zend_op *opcodes; zend_uint last, size; zend_compiled_variable *vars; int last_var, size_var; zend_uint t; zend_brk_cont_element *brk_cont_array; int last_brk_cont; int current_brk_cont; zend_try_catch_element *try_catch_array; int last_try_catch; /* static variables support */ hashtable *static_variables; zend_op *start_op; int backpatch_count; zend_uint this_var; char *filename; zend_uint line_start; zend_uint line_end; char *doc_comment; zend_uint doc_comment_len; zend_uint early_binding; /* the linked list of delayed declarations */ void *reserved[zend_max_reserved_resources];};typedef struct _zend_internal_function { /* common elements */ zend_uchar type; char * function_name; 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; zend_bool pass_rest_by_reference; unsigned char return_reference; /* end of common elements */ void (*handler)(internal_function_parameters); struct _zend_module_entry *module;} zend_internal_function;typedef union _zend_function { zend_uchar type; /* must be the first element of this struct! */ struct { zend_uchar type; /* never used */ char *function_name; 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; zend_bool pass_rest_by_reference; unsigned char return_reference; } common; zend_op_array op_array; zend_internal_function internal_function;} zend_function;typedef struct _zend_function_state { zend_function *function; void **arguments;} zend_function_state
这三个数据结构之间可以相互转换,我在上面也列出了一个_zend_function_state 的数据结构,会讲op_array 中的 function 赋值给执行数据_zend_execute_data 的function_state字段的 function,从而将普通代码中切入一个函数,对于作用域的切换稍后说明。
在excute 执行过程中,有ex(function_state).function = (zend_function *) op_array;可以说明一切。
一个重要的数据结构:
struct _zend_execute_data { struct _zend_op *opline; zend_function_state function_state; zend_function *fbc; /* function being called */ zend_class_entry *called_scope; zend_op_array *op_array; zval *object; union _temp_variable *ts; zval ***cvs; hashtable *symbol_table; struct _zend_execute_data *prev_execute_data; zval *old_error_reporting; zend_bool nested; zval **original_return_value; zend_class_entry *current_scope; zend_class_entry *current_called_scope; zval *current_this; zval *current_object; struct _zend_op *call_opline;}
用于保存执行期间的数据,在作用域切换的时候起至关重要的作用。
zend_api void execute(zend_op_array *op_array tsrmls_dc){ zend_execute_data *execute_data; zend_bool nested = 0; zend_bool original_in_execution = eg(in_execution); if (eg(exception)) { return; } eg(in_execution) = 1;zend_vm_enter: /* initialize execute_data */ execute_data = (zend_execute_data *)zend_vm_stack_alloc( zend_mm_aligned_size(sizeof(zend_execute_data)) + zend_mm_aligned_size(sizeof(zval**) * op_array->last_var * (eg(active_symbol_table) ? 1 : 2)) + zend_mm_aligned_size(sizeof(temp_variable)) * op_array->t tsrmls_cc); ex(cvs) = (zval***)((char*)execute_data + zend_mm_aligned_size(sizeof(zend_execute_data))); memset(ex(cvs), 0, sizeof(zval**) * op_array->last_var); ex(ts) = (temp_variable *)(((char*)ex(cvs)) + zend_mm_aligned_size(sizeof(zval**) * op_array->last_var * (eg(active_symbol_table) ? 1 : 2))); ex(fbc) = null; ex(called_scope) = null; ex(object) = null; ex(old_error_reporting) = null; ex(op_array) = op_array; ex(symbol_table) = eg(active_symbol_table); ex(prev_execute_data) = eg(current_execute_data); eg(current_execute_data) = execute_data; ex(nested) = nested; nested = 1; if (op_array->start_op) { zend_vm_set_opcode(op_array->start_op); } else { zend_vm_set_opcode(op_array->opcodes); } if (op_array->this_var != -1 && eg(this)) { z_addref_p(eg(this)); /* for $this pointer */ if (!eg(active_symbol_table)) { ex(cvs)[op_array->this_var] = (zval**)ex(cvs) + (op_array->last_var + op_array->this_var); *ex(cvs)[op_array->this_var] = eg(this); } else { if (zend_hash_add(eg(active_symbol_table), this, sizeof(this), &eg(this), sizeof(zval *), (void**)&ex(cvs)[op_array->this_var])==failure) { z_delref_p(eg(this)); } } } eg(opline_ptr) = &ex(opline); ex(function_state).function = (zend_function *) op_array; ex(function_state).arguments = null; while (1) { int ret;#ifdef zend_win32 if (eg(timed_out)) { zend_timeout(0); }#endif if ((ret = ex(opline)->handler(execute_data tsrmls_cc)) > 0) { switch (ret) { case 1: eg(in_execution) = original_in_execution; return; case 2: op_array = eg(active_op_array); goto zend_vm_enter; case 3: execute_data = eg(current_execute_data); default: break; } } } zend_error_noreturn(e_error, arrived at end of main loop which shouldn't happen);}
执行期间 有ex(prev_execute_data) = eg(current_execute_data);会保存一下现场,
然后eg(current_execute_data) = execute_data;
当执行到函数的op_array时,eg(active_op_array) = &ex(function_state).function->op_array;
会执行到
   case 2:
     op_array = eg(active_op_array);
     goto zend_vm_enter;
当函数将要执行完毕或者返回的时候,可以主动调用return 或者php 会自动放回一个null,然后是zend_do_return 生成 zend_return的opcode ,根据类型不同会调用几个不同的函数,但总之会调用一个名为zend_leave_helper_spec 的函数,其中:
eg(current_execute_data) = ex(prev_execute_data);会将返回以前的场景,保证回到执行函数以前的作用域。
个人觉得关键的是以上的一些数据结构,以及相互之间的联系。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product