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
、初始化 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");
}

php-7.2.3源代码和php-5.6.26源代码摘录,对比 “汇编php文件”和“执行opcode代码”的更多相关文章

  1. OpenStack_Swift源代码分析——Ring的rebalance算法源代码具体分析

    1 Command类中的rebalnace方法 在上篇文章中解说了,创建Ring已经为Ring加入设备.在加入设备后须要对Ring进行平衡,平衡 swift-ring-builder object.b ...

  2. PHP 在源代码中实现换行使得页面源代码更精致美观

    常量 : PHP_EOL 换行实例: <? php echo $this->doctype($this->doctype) . PHP_EOL;?> <html> ...

  3. 目录重定向的源代码工程( linux平台利用VFS实现目录重定向驱动)虚拟磁盘MINIPORT驱动代码(雨中风华)

    http://download.csdn.net/user/fanxiushu/uploads/2 http://download.csdn.net/user/fanxiushu/uploads/1

  4. php-5.6.26源代码 - hash存储结构 - 添加

    添加 , (void *)module, sizeof(zend_module_entry), (void**)&module_ptr){ // zend_hash_add 定义在文件“php ...

  5. php-5.6.26源代码 - hash存储结构 - 初始化

    初始化 有指定析构函数,在销毁hash的时候会调用,如:“类似extension=test.so扩展”也是存放在HashTable中的,“类似extension=test.so扩展”的module_s ...

  6. php-5.6.26源代码 - hash存储结构 - hash算法

    // zend_inline_hash_func 实现在文件“php-5.6.26\Zend\zend_hash.h” h = zend_inline_hash_func(arKey, nKeyLen ...

  7. php-5.6.26源代码 - include_once、require_once、include、require、eval 的opcode处理器

    # ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER 实现在文件 php-\Zend\zend_vm_execute.h static int ZEND_FASTCALL ...

  8. php-5.6.26源代码 - 如何用C语言支持“类似异常”机制

    代码编写在文件php-\Zend\zend.h #define zend_bailout() _zend_bailout(__FILE__, __LINE__) #ifdef HAVE_SIGSETJ ...

  9. php-5.6.26源代码 - opcode处理器,“函数调用opcode”处理器,如何调用扩展模块的函数

    // opcode处理器 --- ZEND_DO_FCALL_SPEC_CONST_HANDLER实现在 php-5.6.26\Zend\zend_vm_execute.h static int ZE ...

随机推荐

  1. mybooklist.cn 书单de故事六月十六日

    1.我的30年30本书 刘苏里书单北京万圣书园总经理,以经营人文社科类图书著称.生于1960年,1983年毕业于北京大学国际政治系,1986年毕业于中国政法大学研究生院.

  2. jQuery判断checkbox是否选中?操作checkbox(不)选中?

    HTML      <form action="">          <input type="checkbox" name="c ...

  3. SVNKit学习——svn二次开发背景和闲谈(一)

    开发背景: 简述现有流程:代码的合并.提交是以任务为最小单元的.例如A和B两个同学开发不同的任务,那就是两个任务号.合并的时候可能会先合并A的代码,在合并B的代码. 需求:SVN合并程序开发——一款能 ...

  4. solidity语言7

    单位和全局变量 Ether Units: wei, finney, szabo, ether Time Units: 1 == 1 seconds 1 minutes == 60 seconds 1 ...

  5. 【SQL Server 2012】按倒序存储“分组统计”结果的临时表到新建表

    程序预先说明: 本文访问的数据库是基于存有RDF三元组的开源数据库Localyago修改的库,其中只有一个表,表中有五个属性:主语subject.谓语predict.宾语object.主语的编号sub ...

  6. Windows远程桌面,出现身份验证错误,要求的函数不正确

    升级windows10 1803后,mstsc远程桌面出现 mstsc 远程桌面要求的函数不受支持,这可能是由于 CredSSP 加密 Oracle 修正.如图所示: 运行(win+r) gpedit ...

  7. VSCode-python 进阶配置

    VSCode-python 进阶配置 中文乱码 中文乱码,网上一堆解决方法,但是根本没有有效起作用的. 在python脚本的前面添加: # -*- coding:utf-8 -*- 并不能在控制台输出 ...

  8. Windows 2012R2远程桌面服务简介

    一.远程桌面服务概述 远程桌面服务加快并扩展了到任何设备的桌面和应用程序部署,在帮助保护关键知识产权的安全的同时提高了工作人员的工作效率,简化了法规遵从性. 远程桌面服务启用虚拟机基础结构 (VDI) ...

  9. 一点一点学写Makefile(3)-增加第三方库和头文件

    我们在写代码的时候不一定都是有自己来完成,一个工程中会大量使用一些比较优秀的动态库.静态库等,我们在使用这些库完成所有的代码后,需要在编译的时候将这些库使用的头文件添加到我们的工程上,将他的库文件也添 ...

  10. Git 还没push 前可以做的事(转)

    Git 版本控制系統(3) 還沒 push 前可以做的事 转载:http://ihower.tw/blog/archives/2622   這一集要講的是:還沒 push 前可以做的壞事,也就是 re ...