php-7.2.3 在“汇编php文件”和“执行opcode代码”上做了大量改变
php-5.6.26 没见到支持抽象语法树的相关代码,php-7.2.3 见到支持抽象语法树的相关代码
php-5.6.26 存在“保存active_op_array现场”的代码,php-7.2.3 去除了“保存active_op_array现场”的代码
php-5.6.26 | php-7.2.3 |
1、初始化 opcode处理器列表// main实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” int main(int argc, char *argv[]) { if (cgi_sapi_module.startup(&cgi_sapi_module){ // php_cgi_startup实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” static int php_cgi_startup(sapi_module_struct *sapi_module) { if (php_module_startup(sapi_module, &cgi_module_entry, 1){ // zend_startup实现在文件“php-5.6.26\sapi\cgi\cgi_main.c” int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules) { // zend_startup实现在文件“php-5.6.26\Zend\zend.c” zend_startup(&zuf, NULL TSRMLS_CC); // !!!! { int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) { ... // zend_init_opcodes_handlers实现在文件php-7.2.3\Zend\zend_vm_execute.h zend_init_opcodes_handlers(); // !!! 初始化“opcodes处理器”列表 ------------ 初始化 { static const opcode_handler_t labels[] = { ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, ZEND_NOP_SPEC_HANDLER, ... ZEND_ASSIGN_POW_SPEC_CV_TMP_HANDLER, ZEND_ASSIGN_POW_SPEC_CV_VAR_HANDLER, ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER, ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; } ... } } } } == FAILURE) { return FAILURE; } return SUCCESS; } } == FAILURE) { // startup ---> php_cgi_startup ---> php_module_startup #ifdef ZTS --- tsrm_shutdown(); #endif return FAILURE; } } 2、注入opcode处理器 EG(active_op_array) = zend_compile_file(file_handle, type TSRMLS_CC); // 编译PHP文件成操作码 op_code ,zend_compile_file == compile_file { // 在文件 php-5.6.26\Zend\zend_language_scanner.c !!!编译文件,编译出opcode ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type TSRMLS_DC) { ... if (retval) { CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场) if (compilation_successful) { // !!!汇编成功 // pass_two实现在文件 php-5.6.26\Zend\zend_opcode.c pass_two(op_array TSRMLS_CC); // !!!! 给每个op_code注册“op_code处理器” { ... while (opline < end) { // 迭代所有操作码 if (opline->op1_type == IS_CONST) { // 如果是是常量 opline->op1.zv = &op_array->literals[opline->op1.constant].constant; } if (opline->op2_type == IS_CONST) { opline->op2.zv = &op_array->literals[opline->op2.constant].constant; } switch (opline->opcode) { case ZEND_GOTO: if (Z_TYPE_P(opline->op2.zv) != IS_LONG) { zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC); } /* break omitted intentionally */ case ZEND_JMP: case ZEND_FAST_CALL: opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num]; break; case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_JMP_SET_VAR: opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num]; break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { if (opline->op1_type != IS_CONST || Z_TYPE_P(opline->op1.zv) != IS_NULL) { CG(zend_lineno) = opline->lineno; zend_error_noreturn(E_COMPILE_ERROR, "Generators cannot return values using \"return\""); } opline->opcode = ZEND_GENERATOR_RETURN; } break; } ZEND_VM_SET_OPCODE_HANDLER(opline); // 设置“opcode处理器” ------------ 注入 { // 宏定义在文件 “php-5.6.26\Zend\zend_vm.h ” #define ZEND_VM_SET_OPCODE_HANDLER(opline) zend_vm_set_opcode_handler(opline) { // zend_vm_set_opcode_handler 实现在文件“php-5.6.26\Zend\zend_vm_execute.h”, ZEND_API void zend_vm_set_opcode_handler(zend_op* op) // 获取“opcode处理器” { op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op); { // zend_vm_get_opcode_handler实现在文件“php-5.6.26\Zend\zend_vm_execute.h”, static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* op) // 获取“opcode处理器” { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 */ _CONST_CODE, /* 1 = IS_CONST */ _TMP_CODE, /* 2 = IS_TMP_VAR */ _UNUSED_CODE, /* 3 */ _VAR_CODE, /* 4 = IS_VAR */ _UNUSED_CODE, /* 5 */ _UNUSED_CODE, /* 6 */ _UNUSED_CODE, /* 7 */ _UNUSED_CODE, /* 8 = IS_UNUSED */ _UNUSED_CODE, /* 9 */ _UNUSED_CODE, /* 10 */ _UNUSED_CODE, /* 11 */ _UNUSED_CODE, /* 12 */ _UNUSED_CODE, /* 13 */ _UNUSED_CODE, /* 14 */ _UNUSED_CODE, /* 15 */ _CV_CODE /* 16 = IS_CV */ }; return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]]; } } } } } opline++; } op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO; return 0; ... } zend_release_labels(0 TSRMLS_CC); } else { efree(op_array); retval = NULL; } } ... } 3、执行opcode处理器 // execute_ex 实现在文件 “php-5.6.26\Zend\zend_vm_execute.h” ZEND_API void zend_execute(zend_op_array *op_array TSRMLS_DC) { if (EG(exception)) { return; } zend_execute_ex(i_create_execute_data_from_op_array(op_array, 0 TSRMLS_CC) TSRMLS_CC); // zend_execute_ex = execute_ex { // execute_ex 实现在文件 “php-5.6.26\Zend\zend_vm_execute.h” ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) { DCL_OPLINE zend_bool original_in_execution; original_in_execution = EG(in_execution); // 保存现场 EG(in_execution) = 1; // 正在执行中 if (0) { zend_vm_enter: execute_data = i_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); } LOAD_REGS(); LOAD_OPLINE(); while (1) { int ret; #ifdef ZEND_WIN32 if (EG(timed_out)) { zend_timeout(0); } #endif /* OPLINE->handler(execute_data TSRMLS_CC) EX(opline)->handler(execute_data TSRMLS_CC) execute_data.opline->handler(execute_data TSRMLS_CC) */ if ((ret = OPLINE->handler(execute_data TSRMLS_CC)) > 0) { // execute_data.opline->handler(execute_data TSRMLS_CC) // 调用“opcode对应的处理函数” switch (ret) { case 1: EG(in_execution) = original_in_execution; // 还原现场 return; case 2: goto zend_vm_enter; // 进入虚拟机 break; case 3: execute_data = EG(current_execute_data); // 当前正在执行的数据 break; default: break; } } } zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen"); } } }
|
1、初始化 opcode处理器列表 // main实现在文件“php-7.2.3\sapi\cgi\cgi_main.c” int main(int argc, char *argv[]) { if (cgi_sapi_module.startup(&cgi_sapi_module){ ... // php_cgi_startup实现在文件“php-7.2.3\sapi\cgi\cgi_main.c” static int php_cgi_startup(sapi_module_struct *sapi_module) { if (php_module_startup(sapi_module, &cgi_module_entry, 1){ ... // zend_startup实现在文件“php-7.2.3\sapi\cgi\cgi_main.c” int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules) { ... // zend_startup实现在文件“php-7.2.3\Zend\zend.c” int zend_startup(zend_utility_functions *utility_functions, char **extensions TSRMLS_DC) { ... // zend_init_opcodes_handlers实现在文件“php-7.2.3\Zend\zend_vm_execute.h” zend_init_opcodes_handlers(); // !!! 初始化“opcodes处理器”列表 { static const void *labels[] = { ZEND_NOP_SPEC_HANDLER, ZEND_ADD_SPEC_CONST_CONST_HANDLER, ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, ...省略... ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER }; static const uint32_t specs[] = { 0, 1 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 26 | SPEC_RULE_OP1 | SPEC_RULE_OP2, ...省略... 3881 | SPEC_RULE_OP1 | SPEC_RULE_OP2, 4921 }; #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) // 当 defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS) zend_opcode_handler_funcs = labels; zend_spec_handlers = specs; execute_ex(NULL); #else zend_opcode_handlers = labels; zend_handlers_count = sizeof(labels) / sizeof(void*); zend_spec_handlers = specs; #endif } ... } ... } } } ... } } 2、注入opcode处理器 op_array = zend_compile_file(file_handle, type); // 编译PHP文件成操作码 op_code ,zend_compile_file == compile_file { // compile_file实现在文件“php-7.2.3\Zend\zend_language_scanner.c” ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type) { zend_lex_state original_lex_state; // 和 php-5.6.26不同,没有所谓的“保存现场”的操作 zend_op_array *op_array = NULL; zend_save_lexical_state(&original_lex_state); // 保存词法分析器的状态(保存现场) if (open_file_for_scanning(file_handle)==FAILURE) { // 打开文件、设置扫描器的指针 if (type==ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); zend_bailout(); // !!! require、require_once 会抛出异常 } else { zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename); // 没有抛出异常 } } else { // zend_compile实现在文件“php-7.2.3\Zend\zend_language_scanner.c” op_array = zend_compile(ZEND_USER_FUNCTION); // 编译文件、给每个op_code注册“op_code处理器” { zend_op_array *op_array = NULL; zend_bool original_in_compilation = CG(in_compilation); CG(in_compilation) = 1; CG(ast) = NULL; CG(ast_arena) = zend_arena_create(1024 * 32); if (!zendparse()) { int last_lineno = CG(zend_lineno); zend_file_context original_file_context; zend_oparray_context original_oparray_context; zend_op_array *original_active_op_array = CG(active_op_array); // 保存 op_code 现场(保存现场) op_array = emalloc(sizeof(zend_op_array)); init_op_array(op_array, type, INITIAL_OP_ARRAY_SIZE); // 1、初始化一些数据、申请空间 2、迭代调用所有 zend_extensions 扩展的 op_array_ctor 函数 CG(active_op_array) = op_array; // 操作码数组 if (zend_ast_process) { zend_ast_process(CG(ast)); // !!!! “抽象语法树”处理器 } zend_file_context_begin(&original_file_context); zend_oparray_context_begin(&original_oparray_context); zend_compile_top_stmt(CG(ast)); CG(zend_lineno) = last_lineno; zend_emit_final_return(type == ZEND_USER_FUNCTION); op_array->line_start = 1; op_array->line_end = last_lineno; // pass_two实现在文件“php-7.2.3\Zend\zend_opcode.c” pass_two(op_array); // !!!! 给每个op_code注册“op_code处理器” { opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { switch (opline->opcode) { case ZEND_FAST_CALL: opline->op1.opline_num = op_array->try_catch_array[opline->op1.num].finally_op; ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; case ZEND_BRK: case ZEND_CONT: { uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline); if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { zend_check_finally_breakout(op_array, opline - op_array->opcodes, jmp_target); } opline->opcode = ZEND_JMP; opline->op1.opline_num = jmp_target; opline->op2.num = 0; ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); } break; case ZEND_GOTO: zend_resolve_goto_label(op_array, opline); if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { zend_check_finally_breakout(op_array, opline - op_array->opcodes, opline->op1.opline_num); } /* break omitted intentionally */ case ZEND_JMP: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); break; case ZEND_JMPZNZ: /* absolute index to relative offset */ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); /* break omitted intentionally */ case ZEND_JMPZ: case ZEND_JMPNZ: case ZEND_JMPZ_EX: case ZEND_JMPNZ_EX: case ZEND_JMP_SET: case ZEND_COALESCE: case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; case ZEND_ASSERT_CHECK: { /* If result of assert is unused, result of check is unused as well */ zend_op *call = &op_array->opcodes[opline->op2.opline_num - 1]; if (call->opcode == ZEND_EXT_FCALL_END) { call--; } if (call->result_type == IS_UNUSED) { opline->result_type = IS_UNUSED; } ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; } case ZEND_DECLARE_ANON_CLASS: case ZEND_DECLARE_ANON_INHERITED_CLASS: case ZEND_CATCH: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: /* absolute index to relative offset */ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; case ZEND_RETURN: case ZEND_RETURN_BY_REF: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { opline->opcode = ZEND_GENERATOR_RETURN; } break; case ZEND_SWITCH_LONG: case ZEND_SWITCH_STRING: { /* absolute indexes to relative offsets */ HashTable *jumptable = Z_ARRVAL_P(CT_CONSTANT(opline->op2)); zval *zv; ZEND_HASH_FOREACH_VAL(jumptable, zv) { Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, Z_LVAL_P(zv)); } ZEND_HASH_FOREACH_END(); opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value); break; } } if (opline->op1_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1); } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { opline->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op1.var); } if (opline->op2_type == IS_CONST) { ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2); } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { opline->op2.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->op2.var); } if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->result.var); } ZEND_VM_SET_OPCODE_HANDLER(opline); // 设置“opcode处理器” { // ZEND_VM_SET_OPCODE_HANDLER 宏定义在文件 “php-7.2.3\Zend\zend_vm.h ” #define ZEND_VM_SET_OPCODE_HANDLER(opline) zend_vm_set_opcode_handler(opline) { // zend_vm_set_opcode_handler 实现在文件“php-7.2.3\Zend\zend_vm_execute.h” ZEND_API void zend_vm_set_opcode_handler(zend_op* op) { op->handler = zend_vm_get_opcode_handler(zend_user_opcodes[op->opcode], op); { // zend_vm_get_opcode_handler_ex 实现在文件“php-7.2.3\Zend\zend_vm_execute.h” return zend_vm_get_opcode_handler_ex(zend_spec_handlers[opcode], op); { static const int zend_vm_decode[] = { _UNUSED_CODE, /* 0 */ _CONST_CODE, /* 1 = IS_CONST */ _TMP_CODE, /* 2 = IS_TMP_VAR */ _UNUSED_CODE, /* 3 */ _VAR_CODE, /* 4 = IS_VAR */ _UNUSED_CODE, /* 5 */ _UNUSED_CODE, /* 6 */ _UNUSED_CODE, /* 7 */ _UNUSED_CODE, /* 8 = IS_UNUSED */ _UNUSED_CODE, /* 9 */ _UNUSED_CODE, /* 10 */ _UNUSED_CODE, /* 11 */ _UNUSED_CODE, /* 12 */ _UNUSED_CODE, /* 13 */ _UNUSED_CODE, /* 14 */ _UNUSED_CODE, /* 15 */ _CV_CODE /* 16 = IS_CV */ }; uint32_t offset = 0; if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type]; if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type]; if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type]; if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED); if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM); if (spec & SPEC_RULE_SMART_BRANCH) { offset = offset * 3; if ((op+1)->opcode == ZEND_JMPZ) { offset += 1; } else if ((op+1)->opcode == ZEND_JMPNZ) { offset += 2; } } if (spec & SPEC_RULE_DIM_OBJ) { offset = offset * 3; if (op->extended_value == ZEND_ASSIGN_DIM) { offset += 1; } else if (op->extended_value == ZEND_ASSIGN_OBJ) { offset += 2; } } return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset]; } } } } } opline++; } if (op_array->live_range) { int i; for (i = 0; i < op_array->last_live_range; i++) { op_array->live_range[i].var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) | (op_array->live_range[i].var & ZEND_LIVE_MASK); } } } zend_oparray_context_end(&original_oparray_context); zend_file_context_end(&original_file_context); CG(active_op_array) = original_active_op_array; // 还原原来 op_code 现场(还原现场) } zend_ast_destroy(CG(ast)); zend_arena_destroy(CG(ast_arena)); CG(in_compilation) = original_in_compilation; return op_array; } } zend_restore_lexical_state(&original_lex_state); // 还原原来词法解析器的状态(还原现场) return op_array; } } 3、执行opcode处理器 // execute_ex 实现在文件 “php-7.2.3\Zend\zend_vm_execute.h” ZEND_API void execute_ex(zend_execute_data *ex) { DCL_OPLINE // 空操作 #ifdef ZEND_VM_IP_GLOBAL_REG const zend_op *orig_opline = opline; #endif #ifdef ZEND_VM_FP_GLOBAL_REG zend_execute_data *orig_execute_data = execute_data; execute_data = ex; #else zend_execute_data *execute_data = ex; #endif #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) // 当 defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS) if (UNEXPECTED(execute_data == NULL)) { static const void* labels[] = { (void*)&&ZEND_NOP_SPEC_LABEL, (void*)&&ZEND_ADD_SPEC_CONST_CONST_LABEL, (void*)&&ZEND_ADD_SPEC_CONST_TMPVAR_LABEL, (void*)&&ZEND_ADD_SPEC_CONST_TMPVAR_LABEL, ...省略... (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL, (void*)&&ZEND_NULL_LABEL }; zend_opcode_handlers = (const void **) labels; zend_handlers_count = sizeof(labels) / sizeof(void*); memset(&hybrid_halt_op, 0, sizeof(hybrid_halt_op)); hybrid_halt_op.handler = (void*)&&HYBRID_HALT_LABEL; goto HYBRID_HALT_LABEL; } #endif LOAD_OPLINE(); // opline = EX(opline); ZEND_VM_LOOP_INTERRUPT_CHECK(); while (1) { #if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG) int ret; #endif #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) // 当 defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS) HYBRID_SWITCH() { // 宏展开为 goto *(void**)(OPLINE->handler) 跳转到函数指针入口,执行“opcode处理器”函数 #else // !!!不使用 ZEND_VM_KIND_HYBRID #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); // 调用“opcode处理器”函数 if (UNEXPECTED(!OPLINE)) { #else if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0)) { // 调用“opcode处理器”函数,类似 php-5.6.26 的执行方式 #endif #endif // 结束 ZEND_VM_KIND 判断 #if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) // 当 defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS) HYBRID_CASE(ZEND_JMP_SPEC): // 宏展开为 ZEND_JMP_SPEC_LABEL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); // 调用函数!!! HYBRID_BREAK(); // 宏展开为 goto *(void**)(OPLINE->handler) 跳转到函数指针入口,执行“opcode处理器”函数 HYBRID_CASE(ZEND_DO_ICALL_SPEC_RETVAL_UNUSED): // 宏展开为 ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_LABEL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(ZEND_DO_ICALL_SPEC_RETVAL_USED): ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); ...省略... HYBRID_CASE(ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ): ZEND_IS_SMALLER_OR_EQUAL_DOUBLE_SPEC_TMPVARCV_TMPVARCV_JMPNZ_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); HYBRID_BREAK(); HYBRID_CASE(HYBRID_HALT): execute_data = orig_execute_data; opline = orig_opline; return; HYBRID_DEFAULT: zend_error_noreturn(E_ERROR, "Invalid opcode %d/%d/%d.", OPLINE->opcode, OPLINE->op1_type, OPLINE->op2_type); HYBRID_BREAK(); /* Never reached */ #else // !!!不使用 ZEND_VM_KIND_HYBRID #ifdef ZEND_VM_FP_GLOBAL_REG execute_data = orig_execute_data; # ifdef ZEND_VM_IP_GLOBAL_REG opline = orig_opline; # endif return; #else if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); ZEND_VM_LOOP_INTERRUPT_CHECK(); } else { # ifdef ZEND_VM_IP_GLOBAL_REG opline = orig_opline; # endif return; } #endif #endif // 结束 ZEND_VM_KIND 判断 } } // END while ... zend_error_noreturn(E_CORE_ERROR, "Arrived at end of main loop which shouldn't happen"); }
|