保存一个HashTable结构体
/* Zend/zend_type.h */
typedef struct _zend_array HashTable;
//这个结构体64位平台占56个字节.
struct _zend_array {
zend_refcounted_h gc; //引用计数信息,与字符串相同
union {
struct {
ZEND_ENDIAN_LOHI_4(
zend_uchar flags,//zend_hash.h:line 38
zend_uchar nApplyCount,//数组循环递归保护
zend_uchar nIteratorsCount,//数组迭代深度
zend_uchar consistency)//一致性状态 zend_hash.c line 38
} v;
uint32_t flags; //标志位
} u;
uint32_t nTableMask; //计算bucket索引时的掩码,等于nTableSize的负值(nTableMask = -nTableSize)
Bucket *arData; //指向 Bucket 类型数据的指针,插入时只会在 arData 数组的结尾插入,而不会填充已经被删除的节点.
uint32_t nNumUsed; //arData数组已经使用bucket数,每当添加一个新的数据时,此成员会加1.
uint32_t nNumOfElements; //有效bucket数,nNumOfElements <= nNumUsed,因为删除的并不是直接从arData中移除
uint32_t nTableSize; //hash表的大小,为2^n,默认为8
uint32_t nInternalPointer; //数值索引,用于HashTable遍历
zend_long nNextFreeElement; //下一个空闲可用位置的数字索引
dtor_func_t pDestructor; //析构函数,销毁时调用的函数指针
};
typedef struct _Bucket {
zval val;
zend_ulong h; /* hash value (or numeric index) */
zend_string *key; /* string key or NULL for numerics */
} Bucket;
//引用结构
typedef struct _zend_refcounted_h {
uint32_t refcount; /* reference counter 32-bit */
union {
struct {
ZEND_ENDIAN_LOHI_3(
zend_uchar type, //zend_value的类型,与zval.u1.type一致
zend_uchar flags, /* line:438 used for strings & objects */
uint16_t gc_info) /* GC信息,垃圾回收的过程会用到 keeps GC root number (or 0) and color */
} v;
uint32_t type_info;
} u;
} zend_refcounted_h;
unset 某个元素,将u1.type设置为IS_UNDEF,并没有真正的清空内存
重复元素,同样会增加到结构体中,只是链表到相同的元素上,即u2.next=1(图例的第二元素,其实是相同元素的key)
nIndex ,根据key生成的哈希,保存key值