php-7.2.3源代码和php-5.6.26源代码摘录,对比 “汇编php文件”和“执行opcode代码”...

 

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.26php-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");
}
            

 

转载于:https://www.cnblogs.com/xiaoyaogege/p/8631441.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值