vld扩展可以输出PHP编译阶段产生的中间码:opcode,对于想要了解PHP内核的人是极好的辅助工具。在研究PHP7的过程中需要这个利器,可是官方发布的最新扩展不兼容PHP7,所以只能自己动手,修复了这个问题。patch文件已经提交,有兴趣的同学可以去看一下:https://bugs.php.net/bug.php?id=70587
在维护过程中发现PHP7与之前版本的不同之处有:
1、64位操作系统下,将 zend_op 中的跳转地址和常量地址都集中放在了一起,充分利用CPU缓存的局部性原理:
/* On 64-bit systems less optimal, but more compact VM code leads to better
* performance. So on 32-bit systems we use absolute addresses for jump
* targets and constants, but on 64-bit systems realtive 32-bit offsets */
#if SIZEOF_SIZE_T == 4
# define ZEND_USE_ABS_JMP_ADDR 1
# define ZEND_USE_ABS_CONST_ADDR 1
# define ZEND_EX_USE_LITERALS 0
# define ZEND_EX_USE_RUN_TIME_CACHE 1
#else
# define ZEND_USE_ABS_JMP_ADDR 0
# define ZEND_USE_ABS_CONST_ADDR 0
# define ZEND_EX_USE_LITERALS 1
# define ZEND_EX_USE_RUN_TIME_CACHE 1
#endif
typedef union _znode_op {
uint32_t constant;
uint32_t var;
uint32_t num;
uint32_t opline_num; /* Needs to be signed */
#if ZEND_USE_ABS_JMP_ADDR
zend_op *jmp_addr;
#else
uint32_t jmp_offset;
#endif
#if ZEND_USE_ABS_CONST_ADDR
zval *zv;
#endif
} znode_op;
2、PHP7引进了 ast,使得像数组初始化之类的工作可以放在编译阶段,并且通过 opcache 缓存下来,提高性能;
3、PHP7的 HashTable 结构体的定义从 zend_hash.h 单独抽出来放到了 zend_types.h。并且结构也更简洁:数据放在 arData列表中;
4、apply_func_* 系列函数的第一个参数由 void * 变为了 zval *,之前有扩展使用这些函数的需要调整。