php虚拟机,认识PHP 7虚拟机(2)

认识PHP 7虚拟机(2)

认识PHP 7虚拟机(2)

### OPArray

OPArray是指一个包含许多要被顺序执行的OPCode的数组,如下图:

![](/uploads/image/2016/11/08/20161108012913_21400.png)

OPArray由结构体_zend_op_array表示:

struct _zend_op_array {

/* Common elements */

/* 省略 */

/* END of common elements */

/* 省略 */

zend_op *opcodes; //handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); //执行OPCode对应的C函数

if (UNEXPECTED(!OPLINE)) { //当前OPArray执行完

execute_data = orig_execute_data;

opline = orig_opline;

return;

}

}

zend_error_noreturn(E_CORE_ERROR, "Arrived at end of main loop which shouldn't happen");

}

那么是如何切换到下一个OPCode去执行的呢?每个OPCode的Handler中都会调用到一个宏:

#define ZEND_VM_NEXT_OPCODE_EX(check_exception, skip) \

CHECK_SYMBOL_TABLES() \

if (check_exception) { \

OPLINE = EX(opline) + (skip); \

} else { \

OPLINE = opline + (skip); \

} \

ZEND_VM_CONTINUE()

该宏会把当前的opline+skip(skip通常是1),将opline指向下一条OPCode。opline是一个全局变量,指向当前执行的OPCode。

编译器优化

在Zend/zend_vm_execute.h中,会看到如下奇怪的代码:

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)

{

/* 省略 */

if (IS_CONST == IS_UNUSED) {

ZEND_VM_NEXT_OPCODE();

#if 0 || (IS_CONST != IS_UNUSED)

} else {

ZEND_VM_TAIL_CALL(ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));

#endif

}

}

你可能会对if (IS_CONST == IS_UNUSED)和#if 0 || (IS_CONST != IS_UNUSED)感到奇怪。看下其对应的模板代码:

ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)

{

zval *array;

uint32_t size;

USE_OPLINE

array = EX_VAR(opline->result.var);

if (OP1_TYPE != IS_UNUSED) {

size = opline->extended_value >> ZEND_ARRAY_SIZE_SHIFT;

} else {

size = 0;

}

ZVAL_NEW_ARR(array);

zend_hash_init(Z_ARRVAL_P(array), size, NULL, ZVAL_PTR_DTOR, 0);

if (OP1_TYPE != IS_UNUSED) {

/* Explicitly initialize array as not-packed if flag is set */

if (opline->extended_value & ZEND_ARRAY_NOT_PACKED) {

zend_hash_real_init(Z_ARRVAL_P(array), 0);

}

}

if (OP1_TYPE == IS_UNUSED) {

ZEND_VM_NEXT_OPCODE();

if !defined(ZEND_VM_SPEC) || (OP1_TYPE != IS_UNUSED)

} else {

ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ADD_ARRAY_ELEMENT);

#endif

}

}

php zend_vm_gen.php在生成zend_vm_execute.h时,会把OP1_TYPE替换为op1的类型,从而生成这样子的代码:if (IS_CONST == IS_UNUSED),但C编译器会把这些代码优化掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值