PHP内核编译for语句

我们有如下脚本:

1
2
3
4
5
<?php

for ($i = 0; $i < 10; $i = $i + 1) {
echo $i;
}

对应的opcode为:

1
2
3
4
5
6
7
8
L3    #0     ASSIGN                  $i                   0
L3 #1 JMP J5
L4 #2 ECHO $i
L3 #3 ADD $i 1 ~1
L3 #4 ASSIGN $i ~1
L3 #5 IS_SMALLER $i 10 ~3
L3 #6 JMPNZ ~3 J2
L6 #7 RETURN<-1> 1

首先,我们把for语句的组成部分说一下:

1
T_FOR '(' init_exprs ';' cond_exprs ';' loop_exprs ')' for_statement

对应:

1
2
3
4
5
T_FOR => for
init_exprs => $i = 0
cond_exprs => $i < 10
loop_exprs => $i = $i + 1
for_statement => echo $i;

因为,这些opcode是没有经过任何优化的,所以,我们看到的opcode顺序就是PHP解释器去编译的顺序。

OK,我们来从编译出来的opcode总结出编译for语句的一般规律。

首先是:

1
L3    #0     ASSIGN                  $i                   0

这对应着我们的init_exprs

接着是:

1
L3    #1     JMP                     J5

没有对应的代码。

接着是:

1
L4    #2     ECHO                    $i

对应着我们的for_statement

接着是:

1
2
L3    #3     ADD                     $i                   1                    ~1
L3 #4 ASSIGN $i ~1

对应着我们的loop_exprs

接着是:

1
L3    #5     IS_SMALLER              $i                   10                   ~3

对应着我们的cond_exprs

最后是:

1
L3    #6     JMPNZ                   ~3                   J2

没有对应的代码。

我们可以得到如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
   ┌──────────────────────────────┐   
│ │
│ init_exprs │
│ │
└──────────────────────────────┘



┌──────────────────────────────┐
│ │
┌──│ JMP │◀─┐
│ │ │ │
│ └──────────────────────────────┘ │
│ │ │
│ │ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ │ │
│ │ for_statement │ │
│ │ │ │
│ └──────────────────────────────┘ │
│ │ │
│ │ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ │ │
│ │ loop_exprs │ │
│ │ │ │
│ └──────────────────────────────┘ │
│ │ │
│ │ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────┐ │
│ │ │ │
└─▶│ cond_exprs │ │
│ │ │
└──────────────────────────────┘ │
│ │
│ │
│ │
▼ │
┌──────────────────────────────┐ │
│ │ │
│ JMPNZ │──┘
│ │
└──────────────────────────────┘

这实际上,就是通过ifgoto来实现for循环。

我们在写编译器的时候,就可以借鉴这个模型。