php 中间表示语言,[转载]php 底层 探究之php编译过程及中间语言 opcode

Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码:

echo

"Hello World";

$a

= 1 + 1;

echo

$a;

?>

PHP执行这段代码会经过如下4个步骤(确切的来说,应该是PHP的语言引擎Zend)

1.Scanning(Lexing)

,将PHP代码转换为语言片段(Tokens)

2.Parsing, 将Tokens转换成简单而有意义的表达式

3.Compilation, 将表达式编译成Opocdes

4.Execution,

顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。

题外话:现在有的Cache比如APC,可以使得PHP缓存住Opcodes,这样,每次有请求来临的时候,就不需要重复执行前面3步,从而能大幅的提高PHP的执行速度。

那什么是Lexing? 学过编译原理的同学都应该对编译原理中的词法分析步骤有所了解,Lex就是一个词法分析的依据表。

Zend/zend_language_scanner.c会根据Zend/zend_language_scanner.l(Lex文件),来输入的

PHP代码进行词法分析,从而得到一个一个的“词”,PHP4.2开始提供了一个函数叫token_get_all,这个函数就可以讲一段PHP代码

Scanning成Tokens;

如果用这个函数处理我们开头提到的PHP代码,将会得到如下结果:

Array

(

[0]

=> Array

(

[0]

=> 367

[1]

=> Array

(

[0]

=> 316

[1]

=> echo

)

[2]

=> Array

(

[0]

=> 370

[1]

=>

)

[3]

=> Array

(

[0]

=> 315

[1]

=> "Hello World"

)

[4]

=> ;

[5]

=> Array

(

[0]

=> 370

[1]

=>

)

[6]

=> =

[7]

=> Array

(

[0]

=> 370

[1]

=>

)

[8]

=> Array

(

[0]

=> 305

[1]

=> 1

)

[9]

=> Array

(

[0]

=> 370

[1]

=>

)

[10]

=> +

[11]

=> Array

(

[0]

=> 370

[1]

=>

)

[12]

=> Array

(

[0]

=> 305

[1]

=> 1

)

[13]

=> ;

[14]

=> Array

(

[0]

=> 370

[1]

=>

)

[15]

=> Array

(

[0]

=> 316

[1]

=> echo

)

[16]

=> Array

(

[0]

=> 370

[1]

=>

)

[17]

=> ;

)

分析这个返回结果我们可以发现,源码中的字符串,字符,空格,都会原样返回。每个源代码中的字符,都会出现在相应的顺序处。而,其他的比如标签,操作符,语句,都会被转换成一个包含俩部分的Array:

Token ID

(也就是在Zend内部的改Token的对应码,比如,T_ECHO,T_STRING),和源码中的原来的内容。

接下来,就是Parsing阶段了,Parsing首先会丢弃Tokens

Array中的多于的空格,然后将剩余的Tokens转换成一个一个的简单的表达式

1.echo a constant string

2.add two numbers together

3.store the result of the prior expression to

a variable

4.echo a variable

然后就改Compilation阶段了,它会把Tokens编译成一个个op_array,

每个op_arrayd包含如下5个部分:

1.Opcode数字的标识,指明了每个op_array的操作类型,比如add ,

echo

2.结果 存放Opcode结果

3.操作数1 给Opcode的操作数

4.操作数2

5.扩展值 1个整形用来区别被重载的操作符

比如,我们的PHP代码会被Parsing成:

* ZEND_ECHO 'Hello World'

* ZEND_ADD ~0 1 1

* ZEND_ASSIGN !0 ~0

* ZEND_ECHO !0

呵呵,你可能会问了,我们的$a去那里了?

恩,这个要介绍操作数了,每个操作数都是由以下俩个部分组成:

a)op_type : 为IS_CONST, IS_TMP_VAR, IS_VAR,

IS_UNUSED, or IS_CV

b)u,一个联合体,根据op_type的不同,分别用不同的类型保存了这个操作数的值(const)或者左值(var)

而对于var来说,每个var也不一样

IS_TMP_VAR,

顾名思义,这个是一个临时变量,保存一些op_array的结果,以便接下来的op_array使用,这种的操作数的u保存着一个指向变量表的一个句柄(整数),这种操作数一般用~开头,比如~0,表示变量表的0号未知的临时变量

IS_VAR 这种就是我们一般意义上的变量了,他们以$开头表示

IS_CV

表示ZE2.1/PHP5.1以后的编译器使用的一种cache机制,这种变量保存着被它引用的变量的地址,当一个变量第一次被引用的时候,就会被CV起来,以后对这个变量的引用就不需要再次去查找active符号表了,CV变量以!开头表示。

这么看来,我们的$a被优化成!0了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574311.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈数据结构-选择排序(简单、堆排序)

选择排序:每趟从待排序的记录中选出关键字最小的记录,顺序放在已排序的记录序列末尾,直到全部排序结束为止。 选择排序正如定义所讲,在数组查询出最小值,然后放在此次循环开始位置(前一次循环已经获取比它更…

php 去掉多维数组的键名,去除多维数组的最外层key 保留值

如果你是要将JSON转成PHP数组,方法如下首先,你这个数据格式是JSON的,要先转成PHP数组。$a json_decode($a, TRUE);json_decode第二个参数为TRUE表示保留键名,否则JSON转PHP数组之后,PHP数组的键名会重新排序。然后将你…

安装php7的mysql扩展,php7安装mysql扩展的方法是什么

php7安装mysql扩展的方法:1、下载mysql扩展并解压;2、使用phpize工具初始化并进行configure;3、执行【make && make install】命令;4、编辑php.ini文件;5、重启服务。本文环境:windows10系统、php7…

什么是简单的分析SQL注入漏洞

如今非常多人在入侵的过程中基本都是通过SQL注入来完毕的,可是有多少人知道为什么会有这种注入漏洞呢?有的会随口说着对于字符的过滤不严造成的。可是事实是这样吗?我们学这些。不仅要知其然。更要知其所以然!理论联系实际&#x…

python发布服务,Python服务发现:在本地n上发布服务

在本地网络上执行服务通告/发现的一个简单方法是广播UDP包。常数:PORT 50000MAGIC "fna349fn" #to make sure we dont confuse or get confused by other programs公告:from time import sleepfrom socket import socket, AF_INET, SOCK_DGR…

[codevs1262] 不要把球传我 数论+组合数学

没什么好说的,很容易分析出递推公式f[n](n-2)*(n-1)*(n-3) div 6; 代码 beginreadln(n);     writeln((n-2)*(n-1)*(n-3) div 6);end. 巨短,就是这样233() 我不会告诉你这一张是…

php可以用水晶报表吗,什么是水晶报表与水晶报表功能分析

水晶报表水晶报表(Crystal Report)是业内最专业、功能最强的报表系统,它除了强大的报表功能外,最大的优势是实现了与绝大多数流行开发工具的集成和接口。在VS.Net平台做过报表开发的程序员,一定都对水晶报表强大、高效、集成等特性留下了深刻…

大数据笔记11:MapReduce的运行流程

1.基本概念 (1)Job & Task (2)JobTracker (3)TaskTracker转载于:https://www.cnblogs.com/hebao0514/p/4825280.html

php 表格分页代码,[Php]分页及表格样式

writer:web wu 2007/11/29这个分页代码比较简单一些.操作用户列表include "conn.php"; //连接数据库文件mysql_select_db("admin"); //打开数据表$ssqlmysql_query("select count(*) as amcount from alluser",$con); //统计记录数if($my…

iPhone屏幕尺寸、分辨率及适配

目录(?)[-] iPhone尺寸规格单位inch英吋iPhone手机宽高屏幕尺寸像素密度PPI缩放因子scale factor between logic point and device pixel1Scale起源 2UIScreenscale 3UIScreennativeScale 4机型判别Resolutions Rendering2x3x以及高倍图适配12x 23x 3高倍图文件…

oracle中的and用法,Oracle bitand( )函数简介

Oracle bitand( )函数在Oracle数据库中是很常见的,下面就为您详细介绍Oracle bitand( )函数的用法,如果您感兴趣的话,不妨一看。Oracle bitand( )函数:返回两个数值型数值在按位进行AND 运算后的结果。语法BITAND(nExpression1, n…

Nagios显示器mysql定从库: libmysqlclient.so.18: cannot open shared object file: No such

做mysql的slave时间监控,必须check_mysql文字,check当误差:error while loading shared libraries: libmysqlclient.so.18: cannot open shared object file: No such file or directory1,错误信息例如以下:[rootslave…

oracle包如何进入编辑,修改 Oracle 的process和Session

1.process 和session的概念:process:这个参数限制了能够连接到SGA的操作系统进程数(或者是Windows 系统中的线程数),这个总数必须足够大,从而能够适用于后台进程与所有的专用服务器进程,此外,共享服务器进程与调度进程的数目也被计算在内.此外,共享 服务器进程与调度进程的数目…

Head First Python学习笔记4——处理数据

有这么几组数据需要你处理: James  2-34,3:21,2.34,2.45,3.01,2:01,2:01,3:10,2-22 Julia   2.59,2.11,2:11,2:23,3-10,2-23,3:10,3.21,3-21 Mikey  2:22,3.01,3:01,3.02,3:02,3.02,3:22,2.49,2:38 Sarah  2:58,2.58,2:39,2-25,2-55,2:54,2.18,2:55,2:55 这…

oracle ora 00910,NVARCHAR2字段超长问题:ORA-00910: specified length too long for its datatype

NVARCHAR2字段超长问题:ORA-00910: specified length too long for its datatype前几天在IMP的时候遇到了个问题:IMP-00017: following statement failed with ORACLE error 910:"CREATE TABLE "T_CSL_DYNAITEMDATAENTRY" ("FID&quo…

Swift - 触摸事件(点击,移动,抬起等)说明及用例

在iOS开发中,UIGestureRecognizer可以方便的响应处理手势事件。 而如果要想更精细的处理,我们还需要借助touchesBegan,touchesMoved,touchesEnded等触摸方法。这些方法 都是UIResponder中的方法。视图控制器和视图类,都…

鼠标移动响应php程序,jQuery实现的响应鼠标移动方向插件用法示例【附源码下载】...

本文实例讲述了jQuery实现的响应鼠标移动方向插件用法。分享给大家供大家参考,具体如下:HTML代码如下:www.jb51.net jQuery响应鼠标移动*{margin:0;padding:0;}ul,li{list-style:none;}div{font-family:"Microsoft YaHei";}html,bo…

读《大道至简—是懒人造就了方法 》有感

读了大道至简第一章编程的精义之后,我觉得感触颇深,于是乎我又读了第二章是懒人造就了方法 ,之后果然没有让我失望,第二章写的也是非常的好,非常的吸引我。 第二章的开头便引用了李冰凿山的故事,在战国时代…

《大道至简》第二篇读后感

今天把周爱民大道至简的第二章关于是懒人造就了方法读了几遍,作者通过战国时李冰凿山与愚公移山的比较来阐述懒人早就方法主题,以前听历史老师讲课的时候正是因为懒人才会有那么多可以节省人们力气和时间的发明,但懒人并不是真的懒&#xff0…

oracle备份磁盘头,ASM 磁盘头信息备份

ASM磁盘头信息保存在每个磁盘的前4K里面,这个信息的备份对于ASM的恢复非常重要,有下面的几种方法1.直接做dd来备份磁盘的前4K,磁盘头信息丢失时,dd回来 备份:dd if/dev/raw/raw1 of/gyj/asmheader.dd bs4096 coun…