深入理解PHP原理之Opcodes
2019独角兽企业重金招聘Python工程师标准>>>
最近要给Yahoo的同事们做一个关于PHP和Apache处理请求的内部机制的讲座,刚好写了些关于Opcodes的文字,就发上来了,这个文章基于 Sara Golemon大师的《Understanding OPcode》
Opcode是一种PHP脚本编译后的中间语言,就像Java的ByteCode,或者.NET的MSL,举个例子,比如你写下了如下的PHP代码:
- <?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了。
转载于:https://my.oschina.net/botkenni/blog/755890
深入理解PHP原理之Opcodes相关推荐
- php opcodes 还原代码,深入理解PHP原理之Opcodes(PHP执行代码会经过的4个步骤是什么)...
深入理解PHP原理之Opcodes(PHP执行代码会经过的4个步骤是什么) 一.总结 一句话总结: 1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens) 2.Parsin ...
- 深入理解PHP原理之变量(Variables inside PHP)
或许你知道,或许你不知道,PHP是一个弱类型,动态的脚本语言.所谓弱类型,就是说PHP并不严格验证变量类型(严格来讲,PHP是一个中强类型语言,这部分内容会在以后的文章中叙述),在申明一个变量的时候, ...
- 深入理解PHP原理之变量分离/引用(Variables Separation)
引自: http://www.laruence.com/ [风雪之隅 ] 在前面的文章中我已经介绍了PHP的变量的内部表示(深入理解PHP原理之变量(Variables inside PHP)),以及 ...
- 深入理解PHP原理之变量作用域
作者:laruence(http://www.laruence.com/) 地址: http://www.laruence.com/2008/08/26/463.html ...
- 深入理解 ProtoBuf 原理与工程实践(概述)
ProtoBuf 作为一种跨平台.语言无关.可扩展的序列化结构数据的方法,已广泛应用于网络数据交换及存储.随着互联网的发展,系统的异构性会愈发突出,跨语言的需求会愈加明显,同时 gRPC 也大有取代R ...
- 彻底理解Toast原理和解决小米MIUI系统上没法弹Toast的问题
彻底理解Toast原理和解决小米MIUI系统上没法弹Toast的问题 参考文章: (1)彻底理解Toast原理和解决小米MIUI系统上没法弹Toast的问题 (2)https://www.cnblog ...
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
本文主要讲解MyBatis非常棒的缓存机制的设计原理,给读者们介绍一下MyBatis的缓存机制的轮廓,然后会分别针对缓存机制中的方方面面展开讨论. MyBatis将数据缓存设计成两级结构,分为一级缓存 ...
- 深入理解FFM原理与实践
原文:http://tech.meituan.com/deep-understanding-of-ffm-principles-and-practices.html 深入理解FFM原理与实践 del2 ...
- 深入理解浏览器原理和架构|硬核
本文用47张图带你了解「浏览器的发展史」.「浏览器的架构」.「浏览器的基本原理」以及 「浏览器的其它小知识」 ???? 正文开始 浏览器的主要功能就是向服务器发出请求,在浏览器窗口中展示HTML文档. ...
最新文章
- Apache 基金会宣布 Apache Pulsar 毕业成为顶级项目
- R语言psych包的corr.test函数计算相关性并给出所有相关性的显著性(Correlation matrix and tests of significance via corr.test())
- 大数据+机器学习#x3D;天下无敌!
- android cmd 右键菜单不见了,为Windows右键菜单提供打开命令行选项
- 基于springboot实现高校学生健康档案管理系统
- 你的应用是如何被替换的,App劫持病毒剖析
- SDL 库安装、环境配置与使用
- 慕课python第四周测试卷_中国大学慕课用Python玩转数据期末考试查题公众号答案...
- Keras处理TIFF图像
- 第一次参加学校的ACM比赛所学及感想
- hpunix下11gRac的安装
- Magento: 在客户账户中添加自定义链接 My Account Add Link
- 线性查找算法(BFPRT)
- STM32F407 USB CDC调试与经验总结
- android刷机工具mac版,刷机精灵mac版
- MIMO系列之分集与复用
- 1068 万绿丛中一点红 (20 分)
- vue脚手架项目使用element-ui
- Cocos2dx lua 2.xpk 3.x偏Mac OS
- 记一次requestAnimationFrame之后页面崩溃、内存泄漏问题