Skip to content

Commit fb0787a

Browse files
committed
Merge branch 'master' of github.com:pangudashu/php7-internal
2 parents e542a3d + 98a47a4 commit fb0787a

File tree

5 files changed

+8
-8
lines changed

5 files changed

+8
-8
lines changed

2/zend_ht.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff 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

4343
HashTable中另外一个非常重要的值`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
161161
ZEND_API int ZEND_FASTCALL zend_hash_rehash(HashTable *ht)

2/zval.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff 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`类型直接存储值外,其它类型都为指针,指向各自的结构。

3/zend_compile_opcode.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff 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;

4/include.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN
9494
9595
![](../img/include_2.png)
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.

0 commit comments

Comments
 (0)