PHP源码学习探索PHP中while是怎么实现的

grape

全部视频:https://segmentfault.com/a/11…


引入

在我们平常写PHP代码总是会用到while语句,那么我们有没有去考虑过while语句是怎么实现的呢?

我们来看下面的这段代码:

<?php
$a = 1;
while($a){
}

我们知道这段代码是个死循环,毋庸置疑,但是在PHP中,它是如何做到的呢?请看下文。

分析

首先,我们自己分析一下这个while语句,如果让我们来设计,我们会如何设计呢?笔者写出脑补几点:

  1. PHP是C语言编写的,直接去沿用C的语法,while套用。
  2. 在源码设计中加入goto语句。
  3. for循环嵌套if语句
  4. 等等(大家可以头脑风暴下)

接下来我们看一下PHP源码中是如何实现的。
俗话说,实践是检验真理的唯一道路,那么我们就去gdb一下,调试上边的代码,用事实说话。
接下来是gdb的过程,因为是ast树的构建过程,之前文章已经详细解释过,此处不再赘述,文章传送门:2019-05-07 发布【PHP源码学习】2019-03-21 AST,gdb过程如图1所示:

图1
此时我们可以知道AST就是长的图二的样子,如图2:

图2

ast树建立好了,但是他执行了什么指令,我们还是得去看看他的opcode是什么,继续gdb代码,执行到zend_file_context_end之后,此时opcode已经执行完成,我们打印下gdb结果,如图3所示:

图3
ps:在图三中我们可以看到有四条指令,对应下分别为:ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER ,ZEND_JMP_SPEC_HANDLER,ZEND_JMPNZ_SPEC_CV_HANDLER,ZEND_RETURN_SPEC_CONST_HANDLER,由此我们可以发现while语句的实现由ZEND_JMP_SPEC_HANDLER,ZEND_JMPNZ_SPEC_CV_HANDLER来实现,学过汇编的同学应该知道,jmp是跳转的意思,jumpnz则是不为0跳转。由此我们可以画出while的执行流程,如图4所示:

图4
至此我们可以得到while的执行流程了,当然如果想知道这些是如何进行运作的,建议大家去看一看pass_two这个函数,里边有如何设置opcode的。

结论

while语句并不是嵌套C语言的while语句,也不是我们之前的种种猜测,他的核心是通过jump,jumpnz来进行控制的。
ps:设计者可真是个天才。 :手动滑稽

延伸

如果说明白了while语句,那么do_while又是怎么一回事呢?大家可以自行思考一下

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理