3.2.1 PHP5的zval
PHP5的zval核心由一个zvalue_value的联合体和zend_uchar类型的type组成。在PHP5.3之后相继引入了refcount_gc字段通过引用计数进行垃圾回收,同时增加了新的字段is_ref_gc来标记是否为引用类型。
zval结构体24字节
union u联合体8字节 (解决循环引用问题)
zend_mm_block结构体16字节 (开启zend内存池情况下)
所以一个变量在PHP5中实际占用的内存大小为48字节
3.2.2 PHP7的zval
PHP7的zval保留了value字段,value支持更丰富的类型。且zval不再存储复杂类型的结构,复杂类型的数据都是通过指针操作的,新的联合体中value内存只占用8个字节。
zval中还有两个重要字段u1和u2,都是联合体结构。
u1中字段含义
type:记录变量类型
type_flag:对应变量特有的标记
const_flag:常量类型的标记
reserved:保留字段
u2中字段含义
next:解决哈希冲突问题
cache_slot:运行时缓存
lineno:文件执行的行号,应用在AST节点上
num_argus:函数调用时,传入参数的个数
fe_pos:遍历数组时的当前位置
fe_iter_idx:遍历对象的属性
access_flags:对象类的访问标志,常用的有pulic,protected,private
property_guard:防止类中魔术方法的循环调用,比如get,set等
PHP5时代,所有的变量都在堆中申请,但是对于临时变量是没有必要的。
PHP7临时变量直接在类中申请。
3.2.3 PHP7变量类型
PHP7中定义了20种宏,用来标记u1.v.type字段,根据不同的type值取value对应的不同值。
新增的类型:
IS_UNDEF:标记未定义,表示数据可以被覆盖或删除
IS_TRUE 和 IS_FALSE:这里将 IS_BOOL 优化成两个,直接将布尔类型的标记记录在 type 中,这样做可以优化类型的检查,不需要再做一次类型判断。
IS_REFERENCE:处理引用「&」
IS_INDIRECT
iS_PTR:该类型被定义为指针类型
_IS_ERROR:检查zval的类型是否合法
3.2.4 整型和浮点型
3.2.5 字符串类型
PHP7中的字符串是通过zval.value.str指向zend_string结构体的
3.2.6 数组
PHP的数组是有序的字典,即它们表示key-value对的有序列表,其中key-value映射是使用HashTable实现的。
3.2.7 传引用
正常赋值
3.2.7 引用
当使用「&」时,会创建一种新的中间结构体zend_reference,这个结构体会指向真正的zend_string结构体
3.2.8 间接zval
PHP代码通过词法和语法解析成AST树,zend引擎根据AST树生成opcodes数组,zend引擎模拟了一个执行栈来逐条执行opcodes数组中的opcode。
在编译时已知所有变量都被赋予一个索引,并且将他们的值将存储在编译变量(cv)表中。
PHP允许使用变量来动态的引用变量,或者如果在全局范围内,则使用$GLOBALS。
如果发生这样的访问,PHP将为函数/脚本创建一个符号表,其中包含从变量名到其值的映射。
3.2.9 常量和常量AST
常量就是指固定值,在执行期间不会改变,这些固定的值也叫做字面量。
PHP 底层在做词法和语法解析时会将字面量解析,并将其类型修改为 IS_CONST。
3.2.10 资源类型