PHP-7.1 源代码学习:字节码生成 之 "$a = 1"
前言
本文通过分析 "$a=1" 这个 PHP 语句的编译和执行来窥探 php-cli 解释执行逻辑
准备
参考之前的系列文章,在 ubuntu 环境下下载,编译 PHP 源代码
将代码导入 idea clion IDE 中
编辑运行选项,增加运行参数:-f test.php
设置断点开始调试
test.php 是一个测试脚本,放在 sapi/cli/ 目录下,test.php 中只包含一条简单的赋值语句:
<?php
$a = 1
?>
调用堆栈
参考之前的系列文章来了解 php-cli 启动过程以及语法分析和字节码生成的基本概念,这里直接给出调用堆栈:
我们尝试从 zend_compile_expr 函数说起
zend_compile_expr
赋值语句 is-a 表达式,zend_compile_expr新视觉影院 函数根据 ast 类型选择调用 zend_compile_assign:
// zend_compile.c
void zend_compile_expr(znode *result, zend_ast *ast) {
...
switch (ast->kind) {
...
case ZEND_AST_ASSIGN:
zend_compile_assign(result, ast);
break;
}
}
zend_compile_assign
赋值语句的 ast 包含两个 child ast,即 left hand side var(ast->child[0]) 和 right hand side expr(ast->child[1]),var_node 和 expr_node 两个 znode 类型的变量是生成字节码过程使用的中间变量
// zend_compile.c
void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *var_ast = ast->child[0];
zend_ast *expr_ast = ast->child[1];
znode var_node, expr_node;
zend_op *opline;
uint32_t offset;
if (is_this_fetch(var_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}
zend_ensure_writable_variable(var_ast);
然后我们来看看 switch case 语句
// zend_compile.c
switch (var_ast->kind) {
case ZEND_AST_VAR:
case ZEND_AST_STATIC_PROP:
offset = zend_delayed_compile_begin();
zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W);
zend_compile_expr(&expr_node, expr_ast);
zend_delayed_compile_end(offset);
zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node);
return;
}
刚看到这段代码可能会觉得挺绕的:zend_delayed_xxx 函数是干啥的?最终生成的字节码又保存在哪呢?
zend_emit_op
emit 有 "发射,散播"的意思,所以光棍影院 zend_emit_op 可能和字节码保存相关:
// zend_compile.c
static zend_op *zend_emit_op(znode *result, zend_uchar opcode,
znode *op1, znode *op2) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array));
opline->opcode = opcode;
if (op1 == NULL) {
SET_UNUSED(opline->op1);
} else {
SET_NODE(opline->op1, op1);
}
if (op2 == NULL) {
SET_UNUSED(opline->op2);
} else {
SET_NODE(opline->op2, op2);
}
zend_check_live_ranges(opline);
if (result) {
zend_make_var_result(result, opline);
}
return opline;
}
这里我们又遇到了全局变量 CG(compile globals),zend_emit_op 先调用 get_next_op 获取可用的 zend_op(虚拟机指令),然后设置 op1, op2 为 opline 的两个操作数
现在我们知道生成的字节码保存在 CG 的 active_op_array 数组里
总结
PHP-7.1 源代码学习:字节码生成 之 "$a = 1"的更多相关文章
- Java代理全攻略【有瑕疵:字节码生成部分没看到,最后两节没仔细看,累了】
Java代理 1.代理模式 定义:给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原对象,而是通过代理对象间接地操控原对象. 其实就是委托.聚合.中间人. 为了保持行为的 ...
- 曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎
曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎 写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean De ...
- [WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析
[WebKit内核] JavaScript引擎深度解析--基础篇(一)字节码生成及语法树的构建详情分析 标签: webkit内核JavaScriptCore 2015-03-26 23:26 2285 ...
- 谁还没遇上过NoClassDefFoundError咋地——浅谈字节码生成与热部署
谁还没遇上过NoClassDefFoundError咋地--浅谈字节码生成与热部署 前言 在Java程序员的世界里,NoClassDefFoundError是一类相当令人厌恶的错误,因为这类错误通常非 ...
- 深入浅出Java探针技术2---java字节码生成框架ASM、Javassist和byte buddy的使用
目前Java字节码生成框架大致有ASM.Javassist和byte buddy三种 ASM框架介绍及使用 1.ASM介绍 ASM是一种Java字节码操控框架,能够以二进制形式修改已有的类或是生成类, ...
- [WebKit内核] JavaScriptCore深度解析--基础篇(一)字节码生成及语法树的构建
看到HorkeyChen写的文章<[WebKit] JavaScriptCore解析--基础篇(三)从脚本代码到JIT编译的代码实现>,写的很好,深受启发.想补充一些Horkey没有写到的 ...
- Kotlin字节码生成机制详尽分析
通过注解修改Kotlin的class文件名: 对于Kotlin文件在编译之后生成的class文件名默认是有一定规则的,比如: 而其实这个生成字节码的文件名称是可以被改的,之前https://www.c ...
- 透过字节码生成审视Java动态代理运作机制
对于动态代理我想应该大家都不陌生,就是可以动态去代理实现某个接口的类来干一些我们自己想要的功能,但是在字节码层面它的表现是如何的呢?既然目前刚好在研究字节码相关的东东,有必要对其从字节码角度来审视一下 ...
- JVM学习——字节码(学习过程)
JVM--字节码 为什么要学字节码 字节码文件,有什么用? JVM虚拟机的特点:一处编译,多处运行. 多处运行,靠的是.class 字节码文件. JVM本身,并不是跨平台的.Java之所以跨平台,是因 ...
随机推荐
- Android--View事件传递
Android--View事件传递 View事件传递首先要明白以下要素: 事件就是MotionEvent.该对象包含了传递的事件中的所有信息 事件的来源是Window(即PhoneWindow),包含 ...
- css隐藏元素的几种方法与区别
css隐藏元素的几种方法与区别 一:display:none;隐藏不占位 display 除了不能加入 CSS3 动画豪华大餐之外,基本效果卓越,没什么让人诟病的地方. 二:position:abso ...
- [LR]遇到的坑及常用技巧
解决问题是需要智慧的 1.LR内部问题可以查看帮助文档 一般位于LR安装目录的bin目录下,如下图 打开Troubleshooting.chm文件,比如我们跑场景的过程中报错,报错信息为:-27995 ...
- .net后台使用post方式对指定地址的方法传值并且获取结果的方法
/// <summary> /// .net 后台 post http地址请求 /// </summary> /// <param name="uri" ...
- ubuntu 使用apt命令时报错 E: Could not get lock /var/lib/dpkg/lock - open...
问题描述: 刚刚安装好Ubuntu16.04.使用apt命令时,提示报错信息: abc@pc:~$ sudo apt-get install openssh-server E: Could not g ...
- AMD、CMD规范
本文原链接:https://cloud.tencent.com/developer/article/1177217 AMD && CMD 前言 一.模块 二.CommonJS 三.AM ...
- kubernetes-深入理解pod对象(七)
Pod中如何管理多个容器 Pod中可以同时运行多个进程(作为容器运行)协同工作.同一个Pod中的容器会自动的分配到同一个 node 上.同一个Pod中的容器共享资源.网络环境和依赖,它们总是被同时调度 ...
- JavaScript -- 条件语句和循环语句
if语句 在我们开发程序的时候,经常会遇到选择题,例如,年龄大于18,你就可以抽烟喝酒烫头,年龄小于18,你就只能吃饭喝水.在我们的代码中,我们可以用if语句来实现这种判断 语法一: if( cond ...
- Java基础面试操作题: File IO 文件过滤器FileFilter 练习 把一个文件夹下的.java文件复制到另一个文件夹下的.txt文件
package com.swift; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File ...
- 【js】【转发】jreturn;、return true、return false;区别
一.返回控制与函数结果, 语法为:return 表达式; 语句结束函数执行,返回调用函数,而且把表达式的值作为函数的结果 二.返回控制, 无函数结果,语法为:return; 在大多数情况下,为事件 ...