摘要:前言字节码生成编译的代码主要集中在,文件中包含大量的函数,基本上一个函数对应语法规则文件一个非终结符,函数是所有函数的入口数据结构结构体是字节码抽象结构体并没有像名字那样简单,它包含了大量的字段供虚拟机在运行时使用一如既往的简单,直观,相比
前言
字节码生成(编译)的代码主要集中在 zend_compile.c ,文件中包含大量的 zend_compile_xxx 函数,基本上一个函数对应 语法规则文件 zend_language_parser.y 一个非终结符,zend_compile_top_stmt 函数是所有 zend_compile_xxx 函数的入口
数据结构 zend_opzend_op 结构体是 PHP 字节码抽象
// zend_compile.h struct _zend_op { const void *handler; znode_op op1; znode_op op2; znode_op result; uint32_t extended_value; uint32_t lineno; zend_uchar opcode; zend_uchar op1_type; zend_uchar op2_type; zend_uchar result_type; }zend_op_array
zend_op_array 结构体并没有像名字那样简单 zend op array,它包含了大量的字段供虚拟机在运行时使用
// zend_compile.h struct _zend_op_array { }zend_compile_top_stmt
zend_compile_top_stmt 一如既往的简单,直观,相比之前看 ruby 源代码而言,感觉 欧美工程师 可能真的比 岛国工程师 牛叉一些
// zend_compile.c void zend_compile_top_stmt(zend_ast *ast) { if (!ast) { return; } if (ast->kind == ZEND_AST_STMT_LIST) { zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < list->children; ++i) { zend_compile_top_stmt(list->child[i]); } return; } zend_compile_stmt(ast); if (ast->kind != ZEND_AST_NAMESPACE && ast->kind != ZEND_AST_HALT_COMPILER) { zend_verify_namespace(); } if (ast->kind == ZEND_AST_FUNC_DECL || ast->kind == ZEND_AST_CLASS) { CG(zend_lineno) = ((zend_ast_decl *) ast)->end_lineno; zend_do_early_binding(); } }
ast 是抽象语法树(AST)的根节点(参考 PHP-7.1 源代码学习:语法分析 之 概述),函数首先对 ast 进行参数验证,针对 ZEND_AST_STMT_LIST 节点类型进行递归调用,然后调用 zend_compile_stmt 编译 各个 stmt,这个流程和语法规则也是精确对应的:
start: top_statement_list { CG(ast) = $1 } top_statement_list: top_statement_list top_statement { $$ = zend_ast_list_add($1, $2) } | /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); } top_statement: statement ...zend_compile_stmt
zend_compile_stmt 函数基本上就是根据 zend_ast 类型(kind)进行 switch case
void zend_compile_stmt(zend_ast *ast) { if (!ast) { return; } CG(zend_lineno) = ast->lineno; ... switch (ast->kind) { case ZEND_AST_STMT_LIST: zend_compile_stmt_list(ast); break; case ZEND_AST_GLOBAL: zend_compile_global_var(ast); break; ... default: { znode result; zend_compile_expr(&result, ast); zend_do_free(&result); } } ... }总结
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/22323.html
摘要:前言本文简要介绍虚拟机解释执行字节码的基本逻辑以及相关的数据结构,关于源代码的下载,编译,调试可以参考之前的系列文章我们来看看执行一个简单的脚本的调用栈由于是执行脚本文件,所以调用了函数,最终调用函数和其它语言编写的系统软件类似,函数中 前言 本文简要介绍 zend 虚拟机解释执行字节码的基本逻辑以及相关的数据结构,关于 PHP 源代码的下载,编译,调试可以参考之前的系列文章 exec...
摘要:前言本文通过分析这个语句的编译和执行来窥探解释执行逻辑准备参考之前的系列文章,在环境下下载,编译源代码将代码导入中编辑运行选项,增加运行参数设置断点开始调试是一个测试脚本,放在目录下,中只包含一条简单的赋值语句调用堆栈参考之前的系列文章 前言 本文通过分析 $a=1 这个 PHP 语句的编译和执行来窥探 php-cli 解释执行逻辑 准备 参考之前的系列文章,在 ubuntu 环境下...
摘要:前言本文从函数定义的语法规则开始,简要介绍解释器如何编译函数定义函数对应的节点为了看起来清楚一些,我们将语法规则定义与语法动作分开根据语法动作,这条函数定义规则会创建一个类型的结点,我们来看看方法是一个通用的方法,通 前言 本文从函数定义的语法规则开始,简要介绍 PHP 解释器如何 编译 函数定义 函数对应的 AST 节点 为了看起来清楚一些,我们将 语法规则定义 与 语法动作分开: ...
摘要:前言函数默认构建目标为,相关代码在目录下,文件中能够找到入口函数,大概流程如下命令行参数处理初始化清理工作语言系统编程常用手法,通过中声明函数指针类型的字段来实现类似面向对象中抽象类的概念,在文件中可以找到该结构体的定义,这里只列出部分 前言 php cli main 函数 configure & make 默认构建目标为 php-cli,相关代码在 sapi/cli 目录下,php_...
阅读 1873·2021-11-22 09:34
阅读 1142·2021-10-09 09:44
阅读 3003·2021-09-29 09:35
阅读 3619·2021-09-14 18:01
阅读 1467·2021-08-16 10:49
阅读 1086·2019-08-29 14:11
阅读 851·2019-08-29 12:47
阅读 3070·2019-08-26 13:47