1.2 PHP 8的执行原理
首先我们来学习几个关键术语。
1.Token
Token是PHP代码被切割成的有意义的标识。PHP提供了token_get_all()函数来获取PHP代码被切割后的Token。二维数组的每个成员数组的第一个值为Token对应的枚举值,第二个值为Token对应的原始字符串内容,第三个值为代码对应的行号,可见Token就是一个个的“词块”。但是单独存在的词块不能表达完整的语义,还需要借助规则进行组织串联。语法分析器就是这个组织者,它会检查语法,匹配Token,并对Token进行关联。
2.AST
抽象语法树(简称AST)是PHP 7版本的新特性。在这之前的版本中,PHP代码的执行过程中是没有生成AST这一步的。AST的结点分为多种类型,对应着PHP语法。通常使用PHP-Parser工具查看PHP代码生成的AST。注意,PHP-Parser是《PHP 7内核》作者之一Nikic编写的将PHP源码生成AST的工具,其源码参见https://github.com/nikic/PHP-Parser。
3.opcodes
opcode只是单条指令,opcodes是opcode的集合形式,是PHP执行过程中的中间代码。opcode生成之后,由虚拟机执行。PHP工程优化措施中有一个比较常见的“开启opcache”,指的就是这里的opcodes的缓存(opcodes cache)。通过省去从源码到opcode的阶段,引擎可以直接执行缓存的opcode,以此提升性能。借助vld插件,可以直观地看到一段PHP代码生成的opcode。opcode是PHP 7定义的一组指令标识,指令对应着相应的handler(处理函数)。当虚拟机调用opcode时,会找到opcode背后的处理函数,执行真正的处理程序。
了解以上几个术语知识后,我们来看PHP的执行原理。
在PHP 5中,从PHP脚本到opcodes的执行过程如下。
(1)词法分析。源代码首先进行词法分析,切割为多个字符串单元,得到Token。
(2)语法分析。独立的Token无法表达完整语义,因此需经过语法分析,将Token转换为opcodes。
在PHP 7和PHP 8中,执行原理如图1.3所示。
(1)词法分析。源代码首先进行词法分析,切割为多个字符串单元,得到Token。
(2)语法分析。独立的Token无法表达完整语义,因此需经过语法分析,将Token转换为AST。
(3)编译。抽象语法树被转换为机器指令并执行。在PHP中,这些指令被称为opcode,由PHP解释执行。
图1.3 PHP 7、PHP 8的执行原理