摘要:前言本文简要介绍虚拟机解释执行字节码的基本逻辑以及相关的数据结构,关于源代码的下载,编译,调试可以参考之前的系列文章我们来看看执行一个简单的脚本的调用栈由于是执行脚本文件,所以调用了函数,最终调用函数和其它语言编写的系统软件类似,函数中
前言
本文简要介绍 zend 虚拟机解释执行字节码的基本逻辑以及相关的数据结构,关于 PHP 源代码的下载,编译,调试可以参考之前的系列文章
execute_ex我们来看看执行一个简单的脚本 test.php 的调用栈
execute_ex @ zend_vm_execute.h : 411 zend_execute @ zend_vm_execute.h : 474 php_execute_script @ zend.c : 1474 do_cli @ php_cli.c : 993 main @ php_cli.c : 1381
由于是执行脚本文件,所以 do_cli 调用了 php_execute_script 函数,最终调用 execute_ex 函数:
ZEND_API void execute_ex(zend_execute_data *ex) { DCL_OPLINE #ifdef ZEND_VM_IP_GLOBAL_REG const zend_op *orig_opline = opline; #endif #ifdef ZEND_VM_FP_GLOBAL_REG zend_execute_data *orig_execute_data = execute_data; execute_data = ex; #else zend_execute_data *execute_data = ex; #endif LOAD_OPLINE(); ZEND_VM_LOOP_INTERRUPT_CHECK(); while (1) { #if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG) int ret; #endif #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); if (UNEXPECTED(!OPLINE)) { #else if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0)) { #endif #ifdef ZEND_VM_FP_GLOBAL_REG execute_data = orig_execute_data; # ifdef ZEND_VM_IP_GLOBAL_REG opline = orig_opline; # endif return; #else if (EXPECTED(ret > 0)) { execute_data = EG(current_execute_data); ZEND_VM_LOOP_INTERRUPT_CHECK(); } else { # ifdef ZEND_VM_IP_GLOBAL_REG opline = orig_opline; # endif return; } #endif } } zend_error_noreturn(E_CORE_ERROR, "Arrived at end of main loop which shouldn"t happen"); }
和其它 C 语言编写的系统软件类似,函数中使用了大量的宏定义,通过宏定义的名字还是能大概看出其用途
DCL_OPLINE,变量声明
LOAD_OPLINE(),加载指令字节码
ZEND_VM_LOOP_INTERRUPT_CHECK(),interrupt 检测
while (1) 循环,调用指令的处理函数 OPLINE->handler
op_code_handler 总结文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22316.html
摘要:前言字节码生成编译的代码主要集中在,文件中包含大量的函数,基本上一个函数对应语法规则文件一个非终结符,函数是所有函数的入口数据结构结构体是字节码抽象结构体并没有像名字那样简单,它包含了大量的字段供虚拟机在运行时使用一如既往的简单,直观,相比 前言 字节码生成(编译)的代码主要集中在 zend_compile.c ,文件中包含大量的 zend_compile_xxx 函数,基本上一个函数...
摘要:前言本文通过分析这个语句的编译和执行来窥探解释执行逻辑准备参考之前的系列文章,在环境下下载,编译源代码将代码导入中编辑运行选项,增加运行参数设置断点开始调试是一个测试脚本,放在目录下,中只包含一条简单的赋值语句调用堆栈参考之前的系列文章 前言 本文通过分析 $a=1 这个 PHP 语句的编译和执行来窥探 php-cli 解释执行逻辑 准备 参考之前的系列文章,在 ubuntu 环境下...
摘要:前言使用和进行语法分析和词法分析,本文以语法定义文件为起点,使用等命令行工具搜索相关源码,以此来展示探索语法分析源码思路语法定义文件在源代码根目录下通过命令查找文件我们找到了文件,里面定义了脚本的语法语法分析树节点类型在查看具体的语法规则 前言 php 使用 lex 和 bison 进行语法分析和词法分析,本文以 bison 语法定义文件为起点,使用 find, grep 等命令行工具...
摘要:前言函数默认构建目标为,相关代码在目录下,文件中能够找到入口函数,大概流程如下命令行参数处理初始化清理工作语言系统编程常用手法,通过中声明函数指针类型的字段来实现类似面向对象中抽象类的概念,在文件中可以找到该结构体的定义,这里只列出部分 前言 php cli main 函数 configure & make 默认构建目标为 php-cli,相关代码在 sapi/cli 目录下,php_...
摘要:前言本文从函数定义的语法规则开始,简要介绍解释器如何编译函数定义函数对应的节点为了看起来清楚一些,我们将语法规则定义与语法动作分开根据语法动作,这条函数定义规则会创建一个类型的结点,我们来看看方法是一个通用的方法,通 前言 本文从函数定义的语法规则开始,简要介绍 PHP 解释器如何 编译 函数定义 函数对应的 AST 节点 为了看起来清楚一些,我们将 语法规则定义 与 语法动作分开: ...
阅读 639·2021-11-15 11:37
阅读 3953·2021-09-09 09:34
阅读 3523·2019-08-30 15:52
阅读 2531·2019-08-29 14:03
阅读 2805·2019-08-26 13:36
阅读 1527·2019-08-26 12:16
阅读 1560·2019-08-26 11:45
阅读 3430·2019-08-23 18:41