Skip to content

Commit 67ea352

Browse files
committed
update
1 parent 56163b4 commit 67ea352

File tree

1 file changed

+36
-3
lines changed

1 file changed

+36
-3
lines changed

3/zend_global_register.md

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,44 @@ ZEND_API void execute_ex(zend_execute_data *ex)
1818
}
1919
}
2020
```
21-
执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行,如下图。
21+
执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行。opcode执行完后以后指向下一条指令的操作是在当前handler中完成,也就是说每条执行执行完以后会主动更新opline,这里会有下面几个不同的动作:
22+
```c
23+
ZEND_VM_CONTINUE()
24+
ZEND_VM_ENTER()
25+
ZEND_VM_LEAVE()
26+
ZEND_VM_RETURN()
27+
```
28+
ZEND_VM_CONTINUE()表示继续执行下一条opcode;ZEND_VM_ENTER()/ZEND_VM_LEAVE()是调用函数时的动作,普通模式下ZEND_VM_ENTER()实际就是return 1,然后execute_ex()中会将execute_data切换到被调函数的结构上,对应的,在函数调用完成后ZEND_VM_LEAVE()会return 2,再将execute_data切换至原来的结构;ZEND_VM_RETURN()表示执行完成,比如exit,这时候execute_ex()将退出执行。下面看一个具体的例子:
29+
```php
30+
$a = "hi~";
31+
echo $a;
32+
```
33+
执行过程如下图所示:
2234

2335
![](../img/executor.png)
2436

37+
以ZEND_ASSIGN这条赋值指令为例,其handler展开前如下:
38+
```c
39+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
40+
{
41+
USE_OPLINE
42+
...
43+
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
44+
}
45+
```
46+
所有opcode的handler定义格式都是相同的,其参数列表通过ZEND_OPCODE_HANDLER_ARGS宏定义,展开后实际只有一个execute_data;ZEND_FASTCALL这个宏是用于指定C语言函数调用方式的,这里指定的是fastcall方式,GNU C下就是__attribute__((fastcall))。去掉一些非关键操作展开后:
47+
```c
48+
static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_execute_data *execute_data)
49+
{
50+
//USE_OPLINE
51+
const zend_op *opline = execute_data->opline;
52+
...
2553
54+
//ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION()
55+
execute_data->opline = execute_data->opline + 1;
56+
return 0;
57+
}
58+
```
59+
从这个例子可以很清楚的看到,执行完以后会将execute_data->opline加1,也就是指向下一条opcode,然后返回0给execute_ex(),接着执行器在下一次循环时执行下一条opcode,依次类推,直至所有的opcode执行完成。
2660

27-
28-
全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量类型,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。
61+
全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。寄存器变量

0 commit comments

Comments
 (0)