File tree Expand file tree Collapse file tree 5 files changed +8
-8
lines changed Expand file tree Collapse file tree 5 files changed +8
-8
lines changed Original file line number Diff line number Diff line change @@ -38,7 +38,7 @@ struct _zend_array {
3838 dtor_func_t pDestructor; 
3939};
4040``` 
41- HashTable中有两个非常相近的值:` nNumUsed ` 、` nNumOfElements ` ,` nNumOfElements ` 表示哈希表已有元素数,那这个值不跟` nNumUsed ` 一样吗?为什么要定义两个呢?实际上它们有不同的含义,当将一个元素从哈希表删除时并不会将对应的Bucket移除,而是将Bucket存储的zval标示为 ` IS_UNDEF ` ,只有扩容时发现nNumOfElements与nNumUsed相差达到一定数量(这个数量是:` ht->nNumUsed - ht->nNumOfElements > (ht->nNumOfElements >> 5) ` )时才会将已删除的元素全部移除,重新构建哈希表。所以` nNumUsed ` >=` nNumOfElements ` 。
41+ HashTable中有两个非常相近的值:` nNumUsed ` 、` nNumOfElements ` ,` nNumOfElements ` 表示哈希表已有元素数,那这个值不跟` nNumUsed ` 一样吗?为什么要定义两个呢?实际上它们有不同的含义,当将一个元素从哈希表删除时并不会将对应的Bucket移除,而是将Bucket存储的zval修改为 ` IS_UNDEF ` ,只有扩容时发现nNumOfElements与nNumUsed相差达到一定数量(这个数量是:` ht->nNumUsed - ht->nNumOfElements > (ht->nNumOfElements >> 5) ` )时才会将已删除的元素全部移除,重新构建哈希表。所以` nNumUsed ` >=` nNumOfElements ` 。
4242
4343HashTable中另外一个非常重要的值` arData ` ,这个值指向存储元素数组的第一个Bucket,插入元素时按顺序 __ 依次插入__  数组,比如第一个元素在arData[ 0] 、第二个在arData[ 1] ...arData[ nNumUsed] 。PHP数组的有序性正是通过` arData ` 保证的,这是第一个与普通散列表实现不同的地方。
4444
@@ -155,7 +155,7 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
155155``` 
156156
157157### 2.2.6 重建散列表 
158- 当删除元素达到一定数量或扩容后都需要重建散列表,因为value在Bucket位置移动了或哈希数组nTableSize变化了导致key与value的映射关系改变,重建过程实际就是遍历Bucket数组中的value,然后重新计算映射值更新到散列表,除了更新散列表之外,这里还有一个重要的处理:移除已删除的value,开始的时候我们说过,删除value时只是将value的type表为了IS_UNDEF ,并没有实际从Bucket数组中删除,如果这些value一直存在那么将浪费很多空间,所以这里会把它们移除,操作的方式也比较简单:将后面未删除的value依次前移,具体过程如下: 
158+ 当删除元素达到一定数量或扩容后都需要重建散列表,因为value在Bucket位置移动了或哈希数组nTableSize变化了导致key与value的映射关系改变,重建过程实际就是遍历Bucket数组中的value,然后重新计算映射值更新到散列表,除了更新散列表之外,这里还有一个重要的处理:移除已删除的value,开始的时候我们说过,删除value时只是将value的type设置为IS_UNDEF ,并没有实际从Bucket数组中删除,如果这些value一直存在那么将浪费很多空间,所以这里会把它们移除,操作的方式也比较简单:将后面未删除的value依次前移,具体过程如下: 
159159```c 
160160//zend_hash.c 
161161ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht) 
Original file line number Diff line number Diff line change @@ -60,7 +60,7 @@ struct _zval_struct {
6060};
6161``` 
6262` zval ` 结构比较简单,内嵌一个union类型的` zend_value ` 保存具体变量类型的值或指针,` zval ` 中还有两个union:` u1 ` 、` u2 ` :
63- *  __ u1:__  它的意义比较直观,变量的类型就通过` u1.type ` 区分,另外一个值` type_flags ` 为类型掩码,在变量的内存管理、gc机制中会用到,第三部分会详细分析,至于后面两个` const_flags ` 、` reserved ` 暂且不管
63+ *  __ u1:__  它的意义比较直观,变量的类型就通过` u1.v. type ` 区分,另外一个值` type_flags ` 为类型掩码,在变量的内存管理、gc机制中会用到,第三部分会详细分析,至于后面两个` const_flags ` 、` reserved ` 暂且不管
6464*  __ u2:__  这个值纯粹是个辅助值,假如` zval ` 只有:` value ` 、` u1 ` 两个值,整个zval的大小也会对齐到16byte,既然不管有没有u2大小都是16byte,把多余的4byte拿出来用于一些特殊用途还是很划算的,比如next在哈希表解决哈希冲突时会用到,还有fe_pos在foreach会用到......
6565
6666从` zend_value ` 可以看出,除` long ` 、` double ` 类型直接存储值外,其它类型都为指针,指向各自的结构。
Original file line number Diff line number Diff line change @@ -245,7 +245,7 @@ int main()
245245 return 0; 
246246} 
247247``` 
248- 我们知道name的值分配在栈上 ,而" pangudashu" " name" 
248+ 我们知道指针name分配在栈上 ,而" pangudashu" " name" 
249249
250250实际上C里面是不会存变量名称的,编译的过程会将变量名替换为偏移量表示:`ebp - 偏移量`或`esp + 偏移量`,将上面的代码转为汇编:
251251```c
@@ -272,7 +272,7 @@ main:
272272
273273![ php vs c] ( ../img/php_vs_c.png ) 
274274
275- 在编译时就可确定且不会改变的量称为字面量,也称作常量(IS_CONST),这些值在编译阶段就已经分配zval,保存在` zend_op_array->literals ` 数组中(对应c程序的常量内存区 ),访问时通过` _zend_op_array->literals + 偏移量 ` 读取,举个例子:
275+ 在编译时就可确定且不会改变的量称为字面量,也称作常量(IS_CONST),这些值在编译阶段就已经分配zval,保存在` zend_op_array->literals ` 数组中(对应c程序的常量存储区 ),访问时通过` _zend_op_array->literals + 偏移量 ` 读取,举个例子:
276276``` c 
277277<?php
278278$a = 56 ;
@@ -372,11 +372,11 @@ void zend_compile_stmt(zend_ast *ast)
372372 switch (ast->kind) { 
373373  case xxx: 
374374  ... 
375-      break;
375+  break; 
376376  case ZEND_AST_ECHO: 
377377  zend_compile_echo(ast); 
378378  break; 
379-    ... 
379+  ... 
380380  default: 
381381  { 
382382  znode result; 
Original file line number Diff line number Diff line change @@ -94,7 +94,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN
9494
9595 
9696
97- > 注意:这里include文件中定义的var_1实际是替换了原文件中的变量,也就是只有一个var_1 ,所以此处zend_array的引用是1而不是2 
97+ > 注意:这里include文件中定义的var_2实际是替换了原文件中的变量,也就是只有一个var_2 ,所以此处zend_array的引用是1而不是2 
9898
9999接下来就是被包含文件的执行,执行到`$var_2 = array()`时,将原array(1,2,3)引用减1变为0,这时候将其释放,然后将新的value:array()赋给$var_2,这个过程就是普通变量的赋值过程,注意此时调用文件中的$var_2仍然指向被释放掉的value,此时的内存关系: 
100100
File renamed without changes.
                         You can’t perform that action at this time. 
           
                  
0 commit comments