、初始化 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, ){
// 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;
}
}
、注入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, 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 * + zend_vm_decode[op->op1_type] * + zend_vm_decode[op->op2_type]];
}
}
}
}
}
opline++;
}
op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return ;
...
}
zend_release_labels( TSRMLS_CC);
} else {
efree(op_array);
retval = NULL;
}
}
...
}
、执行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, 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) = ; // 正在执行中
if () {
zend_vm_enter:
execute_data = i_create_execute_data_from_op_array(EG(active_op_array), TSRMLS_CC);
}
LOAD_REGS();
LOAD_OPLINE();
while () {
int ret;
#ifdef ZEND_WIN32
if (EG(timed_out)) {
zend_timeout();
}
#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)) > ) { // execute_data.opline->handler(execute_data TSRMLS_CC) // 调用“opcode对应的处理函数”
switch (ret) {
case :
EG(in_execution) = original_in_execution; // 还原现场
return;
case :
goto zend_vm_enter; // 进入虚拟机
break;
case :
execute_data = EG(current_execute_data); // 当前正在执行的数据
break;
default:
break;
}
}
}
zend_error_noreturn(E_ERROR, "Arrived at end of main loop which shouldn't happen");
}
}
}
|
、初始化 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, ){
...
// 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[] = {
,
| SPEC_RULE_OP1 | SPEC_RULE_OP2,
| SPEC_RULE_OP1 | SPEC_RULE_OP2,
...省略...
| SPEC_RULE_OP1 | SPEC_RULE_OP2,
};
#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
}
...
}
...
}
}
}
...
}
}
、注入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) = ;
CG(ast) = NULL;
CG(ast_arena) = zend_arena_create( * );
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 = ;
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 = ;
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 - ];
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 = ;
if (spec & SPEC_RULE_OP1) offset = offset * + zend_vm_decode[op->op1_type];
if (spec & SPEC_RULE_OP2) offset = offset * + zend_vm_decode[op->op2_type];
if (spec & SPEC_RULE_OP_DATA) offset = offset * + zend_vm_decode[(op + )->op1_type];
if (spec & SPEC_RULE_RETVAL) offset = offset * + (op->result_type != IS_UNUSED);
if (spec & SPEC_RULE_QUICK_ARG) offset = offset * + (op->op2.num < MAX_ARG_FLAG_NUM);
if (spec & SPEC_RULE_SMART_BRANCH) {
offset = offset * ;
if ((op+)->opcode == ZEND_JMPZ) {
offset += ;
} else if ((op+)->opcode == ZEND_JMPNZ) {
offset += ;
}
}
if (spec & SPEC_RULE_DIM_OBJ) {
offset = offset * ;
if (op->extended_value == ZEND_ASSIGN_DIM) {
offset += ;
} else if (op->extended_value == ZEND_ASSIGN_OBJ) {
offset += ;
}
}
return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];
}
}
}
}
}
opline++;
}
if (op_array->live_range) {
int i;
for (i = ; 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;
}
}
、执行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, , 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 () {
#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)) != )) { // 调用“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 > )) {
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");
}
|