From 06499a611175fa4b075cbfa0db3ef0ab15c88d25 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 14 Jul 2017 12:45:32 +0800 Subject: [PATCH 01/43] change dir --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0192d2d..06bca77 100644 --- a/README.md +++ b/README.md @@ -85,11 +85,11 @@ * [7.7.6 数组操作](7/var.md) * [7.8 常量](7/constant.md) * 7.9 面向对象 - 7.9.1 内部类注册 - 7.9.2 定义成员属性 - 7.9.3 定义成员方法 - 7.9.4 定义常量 - 7.9.5 类的实例化 + * 7.9.1 内部类注册 + * 7.9.2 定义成员属性 + * 7.9.3 定义成员方法 + * 7.9.4 定义常量 + * 7.9.5 类的实例化 * 7.10 资源类型 * 7.11 经典扩展解析 * 7.8.1 Yaf @@ -106,5 +106,5 @@ ## 附录 * [附录1:break/continue按标签中断语法实现](try/break.md) - * [附录2:defer推迟函数调用语法的实现](try/defer.md) + * 附录2:defer推迟函数调用语法的实现 From 9a4d814fe5f5e69dae9f1a6b24cc91c13ed189b4 Mon Sep 17 00:00:00 2001 From: "byter.hu" Date: Sat, 15 Jul 2017 05:27:41 +0800 Subject: [PATCH 02/43] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=94=99=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复错字 --- 3/function_implement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/function_implement.md b/3/function_implement.md index d3c0fe6..ef4bcb5 100644 --- a/3/function_implement.md +++ b/3/function_implement.md @@ -287,7 +287,7 @@ $greet = function($name) $greet('World'); $greet('PHP'); ``` -这里提函数函数只是想说明编译函数时那个use的用法: +这里提匿名函数只是想说明编译函数时那个use的用法: __匿名函数可以从父作用域中继承变量。 任何此类变量都应该用 use 语言结构传递进去。__ From 6e5b9f43b587b57993e4c1fd6982bdec27166303 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 17 Jul 2017 14:42:25 +0800 Subject: [PATCH 03/43] update --- 7/func.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/7/func.md b/7/func.md index e04228a..5c1101a 100644 --- a/7/func.md +++ b/7/func.md @@ -497,7 +497,7 @@ echo $a; ### 7.6.4 函数返回值 调用内部函数时其返回值指针作为参数传入,这个参数为`zval *return_value`,如果函数有返回值直接设置此指针即可,需要特别注意的是设置返回值时需要增加其引用计数,举个例子来看: - ```c +```c PHP_FUNCTION(my_func_1) { zval *arr; @@ -510,8 +510,6 @@ PHP_FUNCTION(my_func_1) Z_ADDREF_P(arr); //设置返回值为数组: - //return_value->u1.type = IS_ARRAY; - //return_value->value->arr = arr->value->arr; ZVAL_ARR(return_value, Z_ARR_P(arr)); } ``` From db02aafbbd43d58f29c406b07a7334eb49608bc4 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 17 Jul 2017 16:52:17 +0800 Subject: [PATCH 04/43] fix error --- 7/func.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/func.md b/7/func.md index 5c1101a..1ce3f35 100644 --- a/7/func.md +++ b/7/func.md @@ -123,7 +123,7 @@ PHP_FUNCTION(my_func_1) ![](../img/internal_func_param.png) -注意:解析时除了整形、浮点型、布尔型是直接硬拷贝value外,其它解析到的变量只能是指针,arr为zend_execute_data上param_1的地址,即:`zval *arr = ¶m_1`,所以图中arr、param_1之间用的不是箭头指向,也就是说参数始终存储在zend_execute_data上,解析获取的是这些参数的地址。`zend_parse_parameters()`调用了`zend_parse_va_args()`进行处理,简单看下解析过程: +注意:解析时除了整形、浮点型、布尔型是直接硬拷贝value外,其它解析到的变量只能是指针,arr为zend_execute_data上param_1的地址,即:`zval *arr = ¶m_1`,也就是说参数始终存储在zend_execute_data上,解析获取的是这些参数的地址。`zend_parse_parameters()`调用了`zend_parse_va_args()`进行处理,简单看下解析过程: ```c //va就是定义的要解析到的各个变量的地址 static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, int flags) From 95ec461b4eaa0bbcb6992c62d9d5f7eca3498f20 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 17 Jul 2017 17:57:06 +0800 Subject: [PATCH 05/43] fix error --- 7/func.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/func.md b/7/func.md index 1ce3f35..e492812 100644 --- a/7/func.md +++ b/7/func.md @@ -229,7 +229,7 @@ static zend_always_inline int zend_parse_arg_long(zval *arg, zend_long *dest, ze return 1; } ``` -> __Note:__ "l"与"L"的区别在于,当传参不是整形且转为整形后超过了整形的大小范围时,"L"将值调整为整形的最大或最小值,而"l"将报错,比如传的参数是字符串"9223372036854775808",转整形后超过了unsigned int64的最大值:0xFFFFFFFFFFFFFFFF,"L"将解析为0xFFFFFFFFFFFFFFFF。 +> __Note:__ "l"与"L"的区别在于,当传参不是整形且转为整形后超过了整形的大小范围时,"L"将值调整为整形的最大或最小值,而"l"将报错,比如传的参数是字符串"9223372036854775808"(0x7FFFFFFFFFFFFFFF + 1),转整形后超过了有符号int64的最大值:0x7FFFFFFFFFFFFFFF,所以如果是"L"将解析为0x7FFFFFFFFFFFFFFF。 #### 7.6.2.2 布尔型:b 通过"b"标识符表示将传入的参数解析为布尔型,解析到的变量必须是zend_bool: From 56163b40731c1735f6b75c9a8bcd904c4e21fe2f Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 13:18:43 +0800 Subject: [PATCH 06/43] add global register variables --- 3/zend_global_register.md | 28 ++++++++++++++++++++++++++++ img/executor.png | Bin 0 -> 13778 bytes 2 files changed, 28 insertions(+) create mode 100644 3/zend_global_register.md create mode 100644 img/executor.png diff --git a/3/zend_global_register.md b/3/zend_global_register.md new file mode 100644 index 0000000..44f5c9a --- /dev/null +++ b/3/zend_global_register.md @@ -0,0 +1,28 @@ +### 3.3.4 全局execute_data和opline +Zend执行器在opcode的执行过程中,会频繁的用到execute_data和opline两个变量,execute_data为zend_execute_data结构,opline为当前执行的指令。普通的处理方式在执行每条opcode指令的handler时,会把execute_data地址作为参数传给handler使用,使用时先从当前栈上获取execute_data地址,然后再从堆上获取变量的数据,这种方式下Zend执行器展开后是下面这样: +```c +ZEND_API void execute_ex(zend_execute_data *ex) +{ + zend_execute_data *execute_data = ex; + + while (1) { + int ret; + + if (UNEXPECTED((ret = ((opcode_handler_t)execute_data->opline->handler)(execute_data)) != 0)) { + if (EXPECTED(ret > 0)) { + execute_data = EG(current_execute_data); + } else { + return; + } + } + } +} +``` +执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行,如下图。 + +![](../img/executor.png) + + + + +全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量类型,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。 diff --git a/img/executor.png b/img/executor.png new file mode 100644 index 0000000000000000000000000000000000000000..f2cdbe77ec115b8d3b226118461723c45a9d91c7 GIT binary patch literal 13778 zcmb80Wmr^Q*zZx0jv=IL=x(Gt6(kjhREAXPknS3~OG-cyWI&psYv>N?4(XPzvw5!f z!#Q8x>pEW;n7uc9?X}lkzx%(!wKP=luqm-oP*Ct*sw(QBpgchWzyHQW2Y#ASl?tGs z(4)LmlzZczxu1nKoosgBozrzG2%{YB5$_SG2nGM>;n6WFz%^q}hv!lfjQ>hCQN_?v^k>ph910qo$q39e8lH&nm2uhPkd#jTuVBKE03Wzmd4Io&(nz^vFM+#Gns*-ez07Kw4r{CopTBA3gB8ZpJd> zM~&3|<=Uu*#6F3z-Mpyhdc2BF%M06CMH+FJLY=N8cHO+x_r5bJnxZSg)?qYXdTywX zwtwa*Gb%@wZH#NmNZCp)c^x)w<%ZE#Y#6zIi@Fp8?#UA$0_hs~D%>CZc^=_7da}{K z-{f<1&Js8@lBKi`Zwtbh6NexiOkIY=HYa-RS%N_nFJTowZ0Bmi zX{9{h=yzL9hTT-z%m~Dj)KAp&7}tM4*Kc$$w{1C_G}N8j9Lz|CRDXI~Jw$lWQO73e z8>5}C{Np@b(nCN2eYVbjKL{P~*9-wL*Uw~0q3MCoL~LiPw$>9hODnR6;chqtUq$R` ztL+xV&nQxV8ag1f!BstFm?G03f*OYcijykZeMHGNU07a!H9wR%Y^>DJY;;&*QR4I5 zub#3oEY>R-s7Kmz1cN$d`H=$5AKPXm+KE%8M0ORix=dk?v2+1^dgR6-&qaeS5#i>+^k1VBt(~I;E$u!zdU8ZKlgO zc3+ybwPOnkIevuVi9^f|#+dR+cB9v*6|vl`r8irfD3`*VLtYAp(RyxCZuX#AoF6Pm zShN8H@B!nLN7db)^ylkph%sNUM)Kx0T`bNCC|V6?(?ruqe2MmHa66=RJ(!;nkfihZ zH)?%*d0ay)w>$PjO~_%nb*rRyvBK3R-==26Ic8i#f}4`>gFiPg=MymmX0W93e3jS< zvFR{R^&Dv_3*icaGc&4kWR2~dUbq)dK4a-_7C{x$!8(hp4JD3JLFP=Ik1_w(?_3E2O5x{42^O#qRSWc_RJ}W{?f03;ujn zfqz2}GtrnP8yznH&=y!|)*Z9+1sq)H#sqsFg99zS%mT>^xsWLQXHcCW&TPAddL=`< zI*amRV7V~I8WsF!m8nG_c}!DPPzYeas)1~P9g`C&0w*ve{Aa?U|CuoCKNAiH|7XGs z(Qgt{1cxOBJs<8aB8~C1S!`PF&PR>i7T)fC!UTT`N8`tXt*rMZ{&$SpWkjyCG!T@B zq6(@kbJ-r-x;bp&{UWSL(fYmb^Y5lF6L9@X=sP7$Z3QNnzAWzA={;6Fekrk{Hl}v- z%_aMz<^#6b)G1Jds!!WfuSS`MQlXM$8-L_fBcTQ`oG*wow`~YV1vKQ z560AZqZj|j{0+>S=$zZJSQRDq$`q2F+V?dwUfAa0(}=%m(AbV?*sqz(OXhs1Y-n5k z*5#y^)yi0tVl&6jx2g@D>iapBl&4FT^=O{(&e`Q!tO~G9v>%Q8`+1gtMMTrP+5>sa zcszZWMSFV)PJTS2%B%o%s~=oxIaqNf<@v9$V)5c^e`x99{-V&h;fu#bjsi^d-rn!V zF!?O$xQohOvBaRd!beoI<}8WdezB3GyOL&f9`J#16HIno8gZfejTA$5zN|-2XCjZO zt!fTV;j{a5chT|?ts%b6HKa-`v|7!oO-}tnt!+4i@yadX8fmS)mn^%az_|Jt*ed9*@Uib z`XLsXk%OGepSSOnfJcpWzhHuXIKSS5pw_v7heEyhO zKIb!|h1&T8Zz)dpYnKXATCR6Ei3^>Fr9{38T50^d+RXWh6ei|vzRatWnyay;lDa+W z82$CO*hY$B9&ou^{k$zgV8vj+%M}b_%Sm3tnt`1GPerbH)oI6xyAU!HSZVY1r<(y^ zoA;kfs`K98u96jrLxmZ>K6=s%gFY`ROlg4XV0n zy%cZuYjgDVZJc+DfG9y4)^PPVWB*e9cIRD7#V8esj!T*h;j%o2Jj3dy^K0xpFU0xX zaM&#IpRbX+m>0a>lzE^iX*j4K4W+Upk0$4DpF9Lk`1{mCYIU+un~`(#(Z{&yig?m!v$K8_4uu#pV<+mb$=;|%b%d4f1hN`o-*+&NnW%2a5-r2n`qEAW|s4CyD4Ky z*j+LQ*vU|{;IUfD2Fr7KlCOCX*wlMJAASwPFCUWQz2%`;cFJ%mE;uL{&2ja)K@fsJ zR^mXkavC(M4k9yuFWVzu`>AJdrgHxdh|(`aSSMF~E*9Q(hJ;@dDR{4jv;M-I)mEXg z;8zUhH&HQxaoaRs{ng%`EE#m_Jd3~)hD$I=_*}bGS}yDZAu1$~E%0(caF}GR$^v6j ztJZE|fP>Lj#O+|7%Zh9v#W@vZmysou`5XuO&}mS=f%V}Y|qLIpS?az*@$mFaRb z?sRm1CX+DH6&|HD5bh-L`^UtCV`$TTFBTv2$;V$-O?Mve~3$6Qf^;)%+9iwbL{AZ{gRNLf;kJW|`NN7&YVLRhZUT$6~ z!MTYE4BBYoE?ZhrZDzNObLQ05 z?(deGVQe$@WVFa)nku#*bf&`M%(%LuVB(dZH$31Oj498)Jup$ z49y+8xTWTcOlz@gyjm1fURs8`A>2wE4#d^s+WNrFWPy=?8uUMuaKCS!-|3I6M@gaH zEtho+ssEh1Cb^b``{wY|%2MKfwphQ@WfmJMXOh_~Jl~%{OjtDPJ8V3SDPbHxpK7^x zjsMJ|__hb{=+<8+_(;`U62(n5K!hD&j6-6D)MN)bB1uZ3N#0E+1xoQE{ITp2) z?iPc6F4!A&u`s_jj!>%D_{d|2)IQ0zliN5A=BgcI; zd{U~rg){#m61rYT3WgIs5M0JKW;{PLYk1%>UAVO0>NkQ>Xfwg`upyr5*Nj9L zYGh_4@lxOCDb>3XzIl>z_O;KP!#b*y-uNSXkw1_+A?fi~U6bN52WQqEFD-kw>y zBz=<{vMdxiS!d_L#t@1u*e(s8R?ie2P4T#FV1qvAM}i6TSLYOnZH;23f-A7?_y&JdD{HwkoYd#I+DAltbVktP-8(r2efG;tc|PvhRBGwchZ-E zU8pAWAlaskHKF7T2_t0OORmx&>J7_j^3IXD+tv)fzq^?`UmvtR?%ql8E@MrAT9xzo zG1JB9HT&6(eGkvdpXj}iwgDm>1G`<(FcP`y$X`>Lqrk-}843~FRgR{#$gyua)4QSW zD%2-?%NUwQ!Z_!5vff+d>P^;nCU7h0C~RU%(}WM6;5AC+VcB$zN!{FSUt7yLEpcmJ z$|C>KQCnogZewi zkiS+0d1Kl(BC6X@4t*~gs=C+Y^PbZNHsGpZa<-Q!ajDk-{_v6SudP_nE^aL)X?D=t zfDPiIJ^4_3@1%U7pnFlhSL&PNXfgKv<+)cF*nh;SKg=q}XR_k^IG%FsSxg3r8YT|5 z2+O3dXaS$A|B=^+kL7fFe5CySVRXLk$ra-v+}Os4-u;*h6X`LhhpU%~yi9A+1WTz09fWQK*)vWMOogaBySVE~SwW68{tBPxj{^<@ydjSr4`->3f?O zASn~3<={pjfS<=L2gIP14M+pdOp`+&18lJ+5yr#@HILFu!kYhuyQpQIYU?A18_A>XeY+l!<&NZr}Z|Kf@Mx^=s5!hJDj1J0n&09}Tlb ztWC#3v}0XpJFUvueQwCNe@>H1(MRcQsu67^Ppeuh23^xWQnfkPl5~_(u7pq}e3WYM z<6Q9Q7-E(etuS<+zm4vB&PF}ljFSD*;C{3^ryo>Gbm z5U0OZ+*Y^BJ6z5DP(EV{&VDI@ES;Irz0?bg6v4s2{FDYw4KEMUdmYBGT<@pfNJ&AI3TJ9lul;uEfPv z+TV0O%ekSqR)4mCCA*g39CxNlK^^;6hbA)8J!P1V@`XBEkk^ZY6D5>#(z-B&RUs;FE=5iYTR3pxC65@c zxDw=m9WQCvx-Y^bv#^UppdIlt=W0_m6JjUa0WFBs`zuZ(rNPM?`>ddR-lT>YLj==O0mPbs;c@c<}PB84&A_nQe^ zmv6jmq>SrsEknpPG=WEVXGtSij&6Xv9WK@kL=jdMrWy1a7ulGl$6KU{M`VDFq0jU% z@|WprfNCxyIi!$(keDKQUKQ=iF_LcwkD)7CWh5so*$^g~G#%^T=+>@e?$M)V73(G@ zy{r5~KipNRzKvq%^b#7U2@l6GF9j>DJOom$V0+&aSUe*$m!-f43iJojOj zFx->!U39-nj~RY*xFg%t0WrVz((<*g{&|zV-R##mFCWd#DF;W9#0S;>vep)OLrF?b zvoq7h_i3eBT9UFoNmcNN4q|8%x=!9_L6sFyJMW}ssG`hB_7_M|K0Q^2N&4O>{wng(Tva7`GUdr?-(!M;d_$HcO0cR*zTbf%+#h9VfkxG#DJqg zd55vg^9+jn&rE?WL+B$E3lpJLjsWp12h;bW26X6j?E8xr5F%j}3>rEAcYM1#fk;_bowd$~BW?RnU#TmB9GDEDoJ=s&fmaQd zQ+BTz&>QyURsjeEiXKJ#U#QY<^1YOKv1uLH2tj7VSH7sK{K0R&2tnr%7CO@Yx|Z6v z>nYN;&%>cu2mM$zr$3I06?qd;{c*gjp5a3sLxeQiy8^geJXNTfvxo=gfeR7UDh-_G zZ{ha`4rj<1AJJ8O@4^hIr`y=L#++uiAZBF5HY6^<@MM2MZ; zlThLvfit3Aib?EZo`u#0Q+0vtv+bOY)8+dp!wmJm{hauE-wCEAph(yRN(Vw$aL^Mh z&|#l;2q#5AdL5W@(LaYF(M{aRw)PGe(ZG~MkFi3X&&Uk+wR;c5RiSzpav4{8P)ZAp zXdY~k_HR%mkO|u~r8xv+{vP%s?^Ysrqp@4yn^Ac~V9EPog2L$A%(ooM zHJL864^i&P#7~sn^2}xw6W*dOICf1Pei}BSpU*Ag%r8~FB`qIOMMc8ISFMqFqIrpD>vCd zFCCv%$5sy&m}F4!G36GJG~#C!Bh8ZrD%PiMP3e(3&$Dz&-YGoW1<4@|%#B`yIViC5 zKn$EnQbNV+nl6km(!7L6hU_Fy^t_TEW&He&)n80--?PV)>>Y9i1PJpWG2_Zu@p!;D zc?NL-uZ##IkMAy)c)z#?vpo_l#p)T~oBh`y`}%Db<~dk|9J|lQZ)Wb^zOrC}QLRl| zbCcI-gr-QJU*%d#b&PWAsQEwmRD}f%!V+z<<6}bS-Sd_>166aBkjL#fyj)+BgA4hI zkX(Fdl!Br-@i?W4q4Qx0X$+OwBLO+VR5>$>FsHng#Ws)DBdZFKk~H5xYTA&{f%0zJ z&q1M#FiggN*WPri?4s|q@qvgJsN+-UkK_KZ2V};ihREoMKdL|Pfx?Zc3XDd=;PS}X zNJxfdH2Y7eK0^US7I>v9A30E#Z;K;yV?qF-khzKFs4p5NT8M6RjH5dA> zXpvmfy{u`6n34vdTM?fBwzSIx*kgH=@t2AcC`ABbOK9Y66tz+e(A665=0*GFQsaiw zQ5Bv>F$z;A$(XyJ>gfrUJjZM88NsAQIaB@rPOqKn>rt{A=Bhti@yh6N&-Vqwb+042 z^(&B+-M^d84a$q(IMVB=(0Z5)+07%YyJ_62Zngoc$9?HxIh0AkZPJKX-XO)nf>Jnc z|498RdgOU`Hf2kbm77&=)?H9j$?JW8wW$q&Z7$!$7y$7Zj0Mq!p`7jf;rxl&8H;oA zQ)w1Bk;CHp%T6LzFajtlM+Zfgs2|x^Om3!pjf2uh|LQG4OG%(YWr;$PwcH#uK;M;U z$QAB%K99R}RRP`MDFX%t;U9q{D^;Gf{Y8@_VjVdZ2QW z>$BZ=d!Le+jJy%qTWC!W_cwDPy_dzUPM6om-E{dtUt|gS7g$7U`=a z@TLBZYys?gXm@43`|9&_nQ2XS*aCsfE$Fd)?X#J!D#8od+_dnyl~{0Ji`L#8%F3TC zF;rRdK79>z8Y&76YwaeV`T&FlE~%|=Q~gJeR9BHaocGJ&;zA>Vee;!N(LTSg{>^NB6C5(0fd-xfEGJ&IEjd$~P27HsDfbOu@na-$zRc|k z!RVpigBKO@15osQ(R8FEU8TOKT2@w~zZ0Fjas=N>H%lL|b3A`lL$?aBpAuKbNwfg> z^BJqbS4Mt!XC-D%`O47)Qu4oU>UT>sDln%EK9_6(K=OrY9Wd8|F@OEF1U`2FoRm7t zv5TTcMvq=TYmE`P3kX1QM7@x`3I%-qm1uAd5ptl0O(C7>PgWx#W{#EK{N z5%<@eN|hp3v58j!hN1NOt5CT{4Yxs6+2L%#YpUX$LP?M^rH5osImtp(_lK1^+uE$b zHcX~XhiEcNzvXdE0;syjx?@Gis4nR`b3iqcY_Y>8lebr=wlw-hw}n-cq4+ePZcg~5 zk6KZ6U01p{<(mMUyywi^o#g;F@x9vkGU{`+k$Ubg3#x1jdbS(61S%%X9YEi3Jf&CX zvA&XJwLu#yky9L&n|Jy{+zg;u36YzyZYKrC6xU-}F1JOW3uCV|s6~0>;EOrP$*VAY znmhngXEB^C+b_UP;~k8~?HZ4WCH<9Akw};FJAUvg4BbF8vH( z)YGmngKQ4w>n0&Vi%nj0%|hxFQ7HUBz^XyCpTk4x9-d87E+!dW&_=(@{yabD?M8{6 znTX#0{^9!F97gVj+qcF<4e?&0q_W!=K>JXb@;6LqSe3GXy5s7-`%1`!*b!1oMn>h~ z{;o1RXl=aBzV*RrLR;lW%$&z&)_&F+=pE&Z zd8q(WxZit4TOHWd&XQq6l;wTW`=!zcV97fBi?P<4y%j%_noZ`)F^ceJw`xwOH8gh9%PkiU*(8+Lvb z=k1m@@T^JS9=doOg}M8bS&uRhH^fR`_bj$tuHqPW`)#geR17ExqFvNKTp(T(rpLtpx_ z3Hd`4iWo=mj~Gc^NqE8m^(}tg(HdLqsq@mwLU}2*GqG5#oi+SWw8h-~G2&`~f1ElF{ zX)A)!)kgGaW?fO`id3zg!>3)HeBa{&xA0!a`Y_Vo8?LUb=0@|0I;#DV0`s7>RyXwX zG^8zqUbR|$eU1Ahw;e=(aF|V3`ml6=UaQ9gUE?u!^V88B$|*UHfHXj^#UxdNP90)^ zuE1>Hz?T?xQYdxI>1IMKci+XPm$vej81^Y;#A}08b`Fi=9xREmM27%oWloM9v-uF_ zTU1{Zl;_cpS^z!6`A;8v;#{60-XjVT;JTH0+o-og(XZ5E%&FXX!yM#J;@V!hASim| z^Ce?8z-qgAQ_3|n%WK{7e`br~&;{a9@+G*YNSUUyKZ`DOMatJmKVQKW58lTuK$ zcqqZG3rKU*ZTV}#lgK%d9CC&ScGotkKA#w>L~#ch&md4N6)E{5d3NXR=AX9V0D2uw zN_t;>`^L$0YDc!4ihiER7Yi=BpXWbtkF|a~&M1!8$^lkdm8H9X-JAfv2&G=$d-AHn z3YsADRrH<^L;v(|7Q4rCVR~dfHk8;*nGR1z^V-GN-8P?TN?(1ild+z8lp_40RDr=d zt_Ope1DG{&qV@O=)MzCo(GV*H(w86R2;!Ymg9a=O zG3|^yOc$H#Y=4q|gH84#nuL;z3GK=+i8HiED%gJ!fWV_b`b@W9x0zjp&O0UJy4ENp z>!@;?!}zI=^7rmC<)t7dCC0ZGI!x@L;lt85T;)I_Jn^|R;yI8| zX8QzK+;g&ejL%-2x;A#lzOGr_Yl&z{kWb}cU2yEp=&ND2r=LryV%qDh`R+c;&lOh2 z1E;%j<~qBu*fEMQuQy>)Pm5Ds{8uCOv5D+o=1VnVKjW?`phs-=+hs0+;PjYEQMQtMMP7LHsSm(DR3O9vPFukYVIn0T|cq@IdlxUM?a zFVWw_u?}s4?=1cL&aB?pvLnwbLPNGnFs|VUPPB{EwKgvg{h@2orG8rrB&E*@5YrNGKm90NmEvXMF>5W>Q-?SODpLF1mklT41 zF(G+4#9p$#mp8>;DHxhiDF?4i;oxCHdAE@fBTru{g!n%pRW*5q0ab+rxf?Z_RVi@A zU-IzF${s<^akY@)q67@ExT!9hulT`agh=79w%JId3sZ$=O)U12X?TCAqEBXi9LcKZ z=(zeia?Q=rdjBQp0fQlN@KZ;nb|JjyabfOXdm}-xD_V!vCq)pNz<2K*B}$p0F_M{* zCJUeynVzKQeNxHAhxX0K?Xy~Rn{2}Wgowr1nNyXE0y*Oq$qtE#f5wqA@Msc&<$KtM zRB%@S+cnch_H@QE@el+Fy>SQ#E$!XW$!ZgLbw&L{S^F!BEB{V?p-&6kD81Pg%ZF^2 zv8lO~zEs&$df{15W7OK66V8*OBhyBhyTnX8e)$)Z^w8N~#m%spIPwUmZ)}08bmZC) z5Xo5jXH+|xBlfhN40S=LBw|cPGpDYQ@)2EX8n=1JqK*7m>Df@RbtOLmzs?3@6sSQ@ zbKDg@KgmX*QNi=4cPWy^ak!+OSg&U4t@a3eNmT`2bA6y5bQ9?sQNEH&K1n~5DDQQDg?*Ww%CSrXH zJK$T~^N8eb91s=V34Sd{J|4duXVzth?a*Vpwen+}joecVU0!}PvJ@%C`QY?`%%C%K zW&wP2HYe$JAMaLlqe|&XTTDGXM#!bZyJT6msO&%bg-(P@wL7N)o)Z_cOGZ{kRIY@T z>-E8*X%-wi=vdHa{;fc)f`s7`ckxn>*JT30YocB4Q?zd0j_Oue zASwt}DPs6^=p1}Te)8{i8<9EOB{|>flcdbLrve;BR@9#9=^7Nap%P}O7@JbxT?Oh; zz!yVaX91E9pYsTUT=aiZOj6Y48}4vTxY|&+0y+P>ByN@eTi^oZB_Nl00X_%cls2Bc z+Wj{0MhF)z)*?cwzuaZ0>F?LiHZsGX)&hrw3_}aCAK0^+9Mw)*E*WQ_^NBLk76nG+AIlO1qi2EP<-ej2RiA2yL=3pJ`eL$-Z_?W}ZW#?r zZ!3R4)_(9wzjJ>86ezac(BwEw1-ch>`GneLw+6@om4WWTS3aA01|q}O9h&-1s2is=-@rtawerT3JqDk50jGRpc(R}L^{`=59WxAd2x+ctk*Z&y**&SJ7c?FK6eEch);>*|XzI7xdeAGm z#<=Fts4xyiF$Os}sE1zBT(txvXE_x@cc8xLmIt9ZGMMXt>=?@Hk;Pw%1pbEZQCbaHZON=;C89c%cX!ezc z@P+gGPan4@D-8@8C-b~$tfb{=Kuge$lGM^&e(O=HSj34=GpCu4l`yLh$t^ zu}S_11x?kBSSU&l%e6ZnzJZClY&wdXRbAGYe?7|KV4wIc2gse{cXBy79=RfeeYW5I zm33R-Ggs*kwSWi`kjM2ziY$2xeie0u{`y@EN`92b#S_z&8JZte1vNOiilPFXU9PM?~@y{#Tg=nhZ zj?;3HT0%^ZP>*E5i2utT1o#(mkHR_hAo-SmV`?vyKeC%A>V&$VWLeN`r>8_7D+3PZ;t>o{lr(49)%Px{eWd)!n(f}cm^{z26DdxH1dvv{ z<=D`({LSKy-ymTOaN|)sj&0r+K$hl&3?j*RYt9@1rC0h<7Lc= zsl$G(ukBson)r(hr`+q}V6^$>z_9b~7$}g_FvlW(M52m(l5S@Yh7cc=JFa!joB*1q zd_Xlhdjf!q`~Xx8Wk6T?B3BaN1^LHo-6}viTeuL!G@R+VQ}o3zg#*yK0rFu*)ZC$G zgz;;Cy#ax*4lzVt)U_9jH4_L`d7&Sk)RW`WNzWhD0=0ZwaQp=z5|jKY^iij;&vUQ5 zTOBRDC{D8SkDlT4%4_)~+%rosLntKJ(IK(I7*pFv8t7>j0)3{U;dv_nenp`Z(AwnO zob6gYoyk**HL?7ydK3OQok4g7en_EI zZi7(p0STYYG@lnigTcDE9xU`#6E@VExeplI`Cjdk?_23a{Z|!Hv3-u0D`9gIcLB~c zoQeuR7g?P;IMywbUD*`(XI!U@i@me?OywskEc&<3rrwJ*mEPVtJUixjf}i7Ke0y`YHzQb0*WL9Kf*s3kk?rv}JSVX zkR5!P?DcK+fAaQx&F$Yqz!LXDX0}U@Rg^9mIc)84NW|prf9#OoLLNl*+o*2L;11C) z4_N{fh1Odmxo<15WFBsvz1{;N>|`eZSQ7ydwm$|(1-B0^3qe7ZSpRQ-Zfb~-cl@{> z{04E@UhnB6K+CY(4tzkvAW0d}L7D4ZC9(XOg5KPGy zR<6>4fA-GA!$Qb$6&XeG(-B7V$PfSgiUi?3!GdB5dY$iW0k|^?An($|!M~fY`zC*z zG>KQ^aseJ7`e$y2>&n^n9X~mwpJw=A6Y00kcnpzE`HAu2471qhs) z^`jw5xkp~g7VPT!Xt^NqE99;K7Cox{I9m@(VHC!|^1_s{oAIPGeegRY$B;Vp5YXFr z`V>CEO*&8Hs}Ou1Wh9EG6t0*ai32OB!^q<(Oh4$M!ue@ktg>A7CVpzt5oe2rE4DBG zCr?e%)hL(CA>)F8Y=OS*D8Ot}%W0iAhlB~K1TCZRMq>Qy>E8pGHKloY znEV#KC7j^>ZR&~@yxIF1AO6#BztKA9%`Lziq%^@M!lmdXj8T;jYEPiS+rcB?C!uwicOjq2i{tGGn@d56ODyoOShR9Qu$~)0 z2WAD1#ksiu9BQo~z7C+r3s48J9GLSU`C1ZZ2vs zpO>n^rCOhLSIL`@_4Tln)-B%{I}Zwzt|?wRY_ER8+f`81zF;yFy**OIj`pKd}0P>KF+dz1Pezu>;#W#Ioil+V(wx7Ds{frjuDa zz)G#k`Jq0-;ZtC^pw$q(0{1^J4`0Ynr65^ep21>PS z7-I~?>;_OxzX>(~9yJIM+P3yF;45{}7oEZwR<}rLcse`qB?h2j=B7}o(7O?TeSFFE zXKF+au0(DUfD{vMbaY9L>{rE@WSS}cXUkYXk@C{`F;K%NbFCuBZ2dj13o&@Ko6V@X zyu&SU{^J&TtiE!M4lo1+44XQ&bgzZa`akcVIqbxi165~1<1^qTzQ6$Am8fF1(N)dXifqPg|^B|ik97iSiCjm`BS$&<5oo)gPjR6$(ourD(_Hxv# zj#9xmA{;625qNU#N;`pDaWoOu<@kj80}hlt!K~5|;l$XPIC!-(599^gdEdVhJ^PIHBqGS+ zXjz3s9zX@;3YC@#y}&T_*K&_)Fn8OJR&z$jm9Iy!m|$F^>r#uoKf%l(M}i*sjzb{_ z3#`bmRg3e#Z&Ls=xc}ds4TE3eNiBUokh*|RN?Rc9w>+ z5xX>DYA^Q44?L}GKaC@1phK7hgEk_${@XO6qZ9qV-n8ohm4|}mZNr$$6|h$e<)xB_ KVyXOx!2bhw6w<%| literal 0 HcmV?d00001 From 67ea35249f73e94634f3242e227410eb992c0221 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 14:25:34 +0800 Subject: [PATCH 07/43] update --- 3/zend_global_register.md | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 44f5c9a..898ad6c 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -18,11 +18,44 @@ ZEND_API void execute_ex(zend_execute_data *ex) } } ``` -执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行,如下图。 +执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行。opcode执行完后以后指向下一条指令的操作是在当前handler中完成,也就是说每条执行执行完以后会主动更新opline,这里会有下面几个不同的动作: +```c +ZEND_VM_CONTINUE() +ZEND_VM_ENTER() +ZEND_VM_LEAVE() +ZEND_VM_RETURN() +``` +ZEND_VM_CONTINUE()表示继续执行下一条opcode;ZEND_VM_ENTER()/ZEND_VM_LEAVE()是调用函数时的动作,普通模式下ZEND_VM_ENTER()实际就是return 1,然后execute_ex()中会将execute_data切换到被调函数的结构上,对应的,在函数调用完成后ZEND_VM_LEAVE()会return 2,再将execute_data切换至原来的结构;ZEND_VM_RETURN()表示执行完成,比如exit,这时候execute_ex()将退出执行。下面看一个具体的例子: +```php +$a = "hi~"; +echo $a; +``` +执行过程如下图所示: ![](../img/executor.png) +以ZEND_ASSIGN这条赋值指令为例,其handler展开前如下: +```c +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + ... + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} +``` +所有opcode的handler定义格式都是相同的,其参数列表通过ZEND_OPCODE_HANDLER_ARGS宏定义,展开后实际只有一个execute_data;ZEND_FASTCALL这个宏是用于指定C语言函数调用方式的,这里指定的是fastcall方式,GNU C下就是__attribute__((fastcall))。去掉一些非关键操作展开后: +```c +static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_execute_data *execute_data) +{ + //USE_OPLINE + const zend_op *opline = execute_data->opline; + ... + //ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() + execute_data->opline = execute_data->opline + 1; + return 0; +} +``` +从这个例子可以很清楚的看到,执行完以后会将execute_data->opline加1,也就是指向下一条opcode,然后返回0给execute_ex(),接着执行器在下一次循环时执行下一条opcode,依次类推,直至所有的opcode执行完成。 - -全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量类型,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。 +全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。寄存器变量 From 34a9e6fbe17c5aa9d400e78247f888723cadaf69 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 14:26:15 +0800 Subject: [PATCH 08/43] update --- img/executor.png | Bin 13778 -> 23846 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/img/executor.png b/img/executor.png index f2cdbe77ec115b8d3b226118461723c45a9d91c7..dfbb4618cf57977f68391c9919fc5d7f01f13a4c 100644 GIT binary patch literal 23846 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 literal 13778 zcmb80Wmr^Q*zZx0jv=IL=x(Gt6(kjhREAXPknS3~OG-cyWI&psYv>N?4(XPzvw5!f z!#Q8x>pEW;n7uc9?X}lkzx%(!wKP=luqm-oP*Ct*sw(QBpgchWzyHQW2Y#ASl?tGs z(4)LmlzZczxu1nKoosgBozrzG2%{YB5$_SG2nGM>;n6WFz%^q}hv!lfjQ>hCQN_?v^k>ph910qo$q39e8lH&nm2uhPkd#jTuVBKE03Wzmd4Io&(nz^vFM+#Gns*-ez07Kw4r{CopTBA3gB8ZpJd> zM~&3|<=Uu*#6F3z-Mpyhdc2BF%M06CMH+FJLY=N8cHO+x_r5bJnxZSg)?qYXdTywX zwtwa*Gb%@wZH#NmNZCp)c^x)w<%ZE#Y#6zIi@Fp8?#UA$0_hs~D%>CZc^=_7da}{K z-{f<1&Js8@lBKi`Zwtbh6NexiOkIY=HYa-RS%N_nFJTowZ0Bmi zX{9{h=yzL9hTT-z%m~Dj)KAp&7}tM4*Kc$$w{1C_G}N8j9Lz|CRDXI~Jw$lWQO73e z8>5}C{Np@b(nCN2eYVbjKL{P~*9-wL*Uw~0q3MCoL~LiPw$>9hODnR6;chqtUq$R` ztL+xV&nQxV8ag1f!BstFm?G03f*OYcijykZeMHGNU07a!H9wR%Y^>DJY;;&*QR4I5 zub#3oEY>R-s7Kmz1cN$d`H=$5AKPXm+KE%8M0ORix=dk?v2+1^dgR6-&qaeS5#i>+^k1VBt(~I;E$u!zdU8ZKlgO zc3+ybwPOnkIevuVi9^f|#+dR+cB9v*6|vl`r8irfD3`*VLtYAp(RyxCZuX#AoF6Pm zShN8H@B!nLN7db)^ylkph%sNUM)Kx0T`bNCC|V6?(?ruqe2MmHa66=RJ(!;nkfihZ zH)?%*d0ay)w>$PjO~_%nb*rRyvBK3R-==26Ic8i#f}4`>gFiPg=MymmX0W93e3jS< zvFR{R^&Dv_3*icaGc&4kWR2~dUbq)dK4a-_7C{x$!8(hp4JD3JLFP=Ik1_w(?_3E2O5x{42^O#qRSWc_RJ}W{?f03;ujn zfqz2}GtrnP8yznH&=y!|)*Z9+1sq)H#sqsFg99zS%mT>^xsWLQXHcCW&TPAddL=`< zI*amRV7V~I8WsF!m8nG_c}!DPPzYeas)1~P9g`C&0w*ve{Aa?U|CuoCKNAiH|7XGs z(Qgt{1cxOBJs<8aB8~C1S!`PF&PR>i7T)fC!UTT`N8`tXt*rMZ{&$SpWkjyCG!T@B zq6(@kbJ-r-x;bp&{UWSL(fYmb^Y5lF6L9@X=sP7$Z3QNnzAWzA={;6Fekrk{Hl}v- z%_aMz<^#6b)G1Jds!!WfuSS`MQlXM$8-L_fBcTQ`oG*wow`~YV1vKQ z560AZqZj|j{0+>S=$zZJSQRDq$`q2F+V?dwUfAa0(}=%m(AbV?*sqz(OXhs1Y-n5k z*5#y^)yi0tVl&6jx2g@D>iapBl&4FT^=O{(&e`Q!tO~G9v>%Q8`+1gtMMTrP+5>sa zcszZWMSFV)PJTS2%B%o%s~=oxIaqNf<@v9$V)5c^e`x99{-V&h;fu#bjsi^d-rn!V zF!?O$xQohOvBaRd!beoI<}8WdezB3GyOL&f9`J#16HIno8gZfejTA$5zN|-2XCjZO zt!fTV;j{a5chT|?ts%b6HKa-`v|7!oO-}tnt!+4i@yadX8fmS)mn^%az_|Jt*ed9*@Uib z`XLsXk%OGepSSOnfJcpWzhHuXIKSS5pw_v7heEyhO zKIb!|h1&T8Zz)dpYnKXATCR6Ei3^>Fr9{38T50^d+RXWh6ei|vzRatWnyay;lDa+W z82$CO*hY$B9&ou^{k$zgV8vj+%M}b_%Sm3tnt`1GPerbH)oI6xyAU!HSZVY1r<(y^ zoA;kfs`K98u96jrLxmZ>K6=s%gFY`ROlg4XV0n zy%cZuYjgDVZJc+DfG9y4)^PPVWB*e9cIRD7#V8esj!T*h;j%o2Jj3dy^K0xpFU0xX zaM&#IpRbX+m>0a>lzE^iX*j4K4W+Upk0$4DpF9Lk`1{mCYIU+un~`(#(Z{&yig?m!v$K8_4uu#pV<+mb$=;|%b%d4f1hN`o-*+&NnW%2a5-r2n`qEAW|s4CyD4Ky z*j+LQ*vU|{;IUfD2Fr7KlCOCX*wlMJAASwPFCUWQz2%`;cFJ%mE;uL{&2ja)K@fsJ zR^mXkavC(M4k9yuFWVzu`>AJdrgHxdh|(`aSSMF~E*9Q(hJ;@dDR{4jv;M-I)mEXg z;8zUhH&HQxaoaRs{ng%`EE#m_Jd3~)hD$I=_*}bGS}yDZAu1$~E%0(caF}GR$^v6j ztJZE|fP>Lj#O+|7%Zh9v#W@vZmysou`5XuO&}mS=f%V}Y|qLIpS?az*@$mFaRb z?sRm1CX+DH6&|HD5bh-L`^UtCV`$TTFBTv2$;V$-O?Mve~3$6Qf^;)%+9iwbL{AZ{gRNLf;kJW|`NN7&YVLRhZUT$6~ z!MTYE4BBYoE?ZhrZDzNObLQ05 z?(deGVQe$@WVFa)nku#*bf&`M%(%LuVB(dZH$31Oj498)Jup$ z49y+8xTWTcOlz@gyjm1fURs8`A>2wE4#d^s+WNrFWPy=?8uUMuaKCS!-|3I6M@gaH zEtho+ssEh1Cb^b``{wY|%2MKfwphQ@WfmJMXOh_~Jl~%{OjtDPJ8V3SDPbHxpK7^x zjsMJ|__hb{=+<8+_(;`U62(n5K!hD&j6-6D)MN)bB1uZ3N#0E+1xoQE{ITp2) z?iPc6F4!A&u`s_jj!>%D_{d|2)IQ0zliN5A=BgcI; zd{U~rg){#m61rYT3WgIs5M0JKW;{PLYk1%>UAVO0>NkQ>Xfwg`upyr5*Nj9L zYGh_4@lxOCDb>3XzIl>z_O;KP!#b*y-uNSXkw1_+A?fi~U6bN52WQqEFD-kw>y zBz=<{vMdxiS!d_L#t@1u*e(s8R?ie2P4T#FV1qvAM}i6TSLYOnZH;23f-A7?_y&JdD{HwkoYd#I+DAltbVktP-8(r2efG;tc|PvhRBGwchZ-E zU8pAWAlaskHKF7T2_t0OORmx&>J7_j^3IXD+tv)fzq^?`UmvtR?%ql8E@MrAT9xzo zG1JB9HT&6(eGkvdpXj}iwgDm>1G`<(FcP`y$X`>Lqrk-}843~FRgR{#$gyua)4QSW zD%2-?%NUwQ!Z_!5vff+d>P^;nCU7h0C~RU%(}WM6;5AC+VcB$zN!{FSUt7yLEpcmJ z$|C>KQCnogZewi zkiS+0d1Kl(BC6X@4t*~gs=C+Y^PbZNHsGpZa<-Q!ajDk-{_v6SudP_nE^aL)X?D=t zfDPiIJ^4_3@1%U7pnFlhSL&PNXfgKv<+)cF*nh;SKg=q}XR_k^IG%FsSxg3r8YT|5 z2+O3dXaS$A|B=^+kL7fFe5CySVRXLk$ra-v+}Os4-u;*h6X`LhhpU%~yi9A+1WTz09fWQK*)vWMOogaBySVE~SwW68{tBPxj{^<@ydjSr4`->3f?O zASn~3<={pjfS<=L2gIP14M+pdOp`+&18lJ+5yr#@HILFu!kYhuyQpQIYU?A18_A>XeY+l!<&NZr}Z|Kf@Mx^=s5!hJDj1J0n&09}Tlb ztWC#3v}0XpJFUvueQwCNe@>H1(MRcQsu67^Ppeuh23^xWQnfkPl5~_(u7pq}e3WYM z<6Q9Q7-E(etuS<+zm4vB&PF}ljFSD*;C{3^ryo>Gbm z5U0OZ+*Y^BJ6z5DP(EV{&VDI@ES;Irz0?bg6v4s2{FDYw4KEMUdmYBGT<@pfNJ&AI3TJ9lul;uEfPv z+TV0O%ekSqR)4mCCA*g39CxNlK^^;6hbA)8J!P1V@`XBEkk^ZY6D5>#(z-B&RUs;FE=5iYTR3pxC65@c zxDw=m9WQCvx-Y^bv#^UppdIlt=W0_m6JjUa0WFBs`zuZ(rNPM?`>ddR-lT>YLj==O0mPbs;c@c<}PB84&A_nQe^ zmv6jmq>SrsEknpPG=WEVXGtSij&6Xv9WK@kL=jdMrWy1a7ulGl$6KU{M`VDFq0jU% z@|WprfNCxyIi!$(keDKQUKQ=iF_LcwkD)7CWh5so*$^g~G#%^T=+>@e?$M)V73(G@ zy{r5~KipNRzKvq%^b#7U2@l6GF9j>DJOom$V0+&aSUe*$m!-f43iJojOj zFx->!U39-nj~RY*xFg%t0WrVz((<*g{&|zV-R##mFCWd#DF;W9#0S;>vep)OLrF?b zvoq7h_i3eBT9UFoNmcNN4q|8%x=!9_L6sFyJMW}ssG`hB_7_M|K0Q^2N&4O>{wng(Tva7`GUdr?-(!M;d_$HcO0cR*zTbf%+#h9VfkxG#DJqg zd55vg^9+jn&rE?WL+B$E3lpJLjsWp12h;bW26X6j?E8xr5F%j}3>rEAcYM1#fk;_bowd$~BW?RnU#TmB9GDEDoJ=s&fmaQd zQ+BTz&>QyURsjeEiXKJ#U#QY<^1YOKv1uLH2tj7VSH7sK{K0R&2tnr%7CO@Yx|Z6v z>nYN;&%>cu2mM$zr$3I06?qd;{c*gjp5a3sLxeQiy8^geJXNTfvxo=gfeR7UDh-_G zZ{ha`4rj<1AJJ8O@4^hIr`y=L#++uiAZBF5HY6^<@MM2MZ; zlThLvfit3Aib?EZo`u#0Q+0vtv+bOY)8+dp!wmJm{hauE-wCEAph(yRN(Vw$aL^Mh z&|#l;2q#5AdL5W@(LaYF(M{aRw)PGe(ZG~MkFi3X&&Uk+wR;c5RiSzpav4{8P)ZAp zXdY~k_HR%mkO|u~r8xv+{vP%s?^Ysrqp@4yn^Ac~V9EPog2L$A%(ooM zHJL864^i&P#7~sn^2}xw6W*dOICf1Pei}BSpU*Ag%r8~FB`qIOMMc8ISFMqFqIrpD>vCd zFCCv%$5sy&m}F4!G36GJG~#C!Bh8ZrD%PiMP3e(3&$Dz&-YGoW1<4@|%#B`yIViC5 zKn$EnQbNV+nl6km(!7L6hU_Fy^t_TEW&He&)n80--?PV)>>Y9i1PJpWG2_Zu@p!;D zc?NL-uZ##IkMAy)c)z#?vpo_l#p)T~oBh`y`}%Db<~dk|9J|lQZ)Wb^zOrC}QLRl| zbCcI-gr-QJU*%d#b&PWAsQEwmRD}f%!V+z<<6}bS-Sd_>166aBkjL#fyj)+BgA4hI zkX(Fdl!Br-@i?W4q4Qx0X$+OwBLO+VR5>$>FsHng#Ws)DBdZFKk~H5xYTA&{f%0zJ z&q1M#FiggN*WPri?4s|q@qvgJsN+-UkK_KZ2V};ihREoMKdL|Pfx?Zc3XDd=;PS}X zNJxfdH2Y7eK0^US7I>v9A30E#Z;K;yV?qF-khzKFs4p5NT8M6RjH5dA> zXpvmfy{u`6n34vdTM?fBwzSIx*kgH=@t2AcC`ABbOK9Y66tz+e(A665=0*GFQsaiw zQ5Bv>F$z;A$(XyJ>gfrUJjZM88NsAQIaB@rPOqKn>rt{A=Bhti@yh6N&-Vqwb+042 z^(&B+-M^d84a$q(IMVB=(0Z5)+07%YyJ_62Zngoc$9?HxIh0AkZPJKX-XO)nf>Jnc z|498RdgOU`Hf2kbm77&=)?H9j$?JW8wW$q&Z7$!$7y$7Zj0Mq!p`7jf;rxl&8H;oA zQ)w1Bk;CHp%T6LzFajtlM+Zfgs2|x^Om3!pjf2uh|LQG4OG%(YWr;$PwcH#uK;M;U z$QAB%K99R}RRP`MDFX%t;U9q{D^;Gf{Y8@_VjVdZ2QW z>$BZ=d!Le+jJy%qTWC!W_cwDPy_dzUPM6om-E{dtUt|gS7g$7U`=a z@TLBZYys?gXm@43`|9&_nQ2XS*aCsfE$Fd)?X#J!D#8od+_dnyl~{0Ji`L#8%F3TC zF;rRdK79>z8Y&76YwaeV`T&FlE~%|=Q~gJeR9BHaocGJ&;zA>Vee;!N(LTSg{>^NB6C5(0fd-xfEGJ&IEjd$~P27HsDfbOu@na-$zRc|k z!RVpigBKO@15osQ(R8FEU8TOKT2@w~zZ0Fjas=N>H%lL|b3A`lL$?aBpAuKbNwfg> z^BJqbS4Mt!XC-D%`O47)Qu4oU>UT>sDln%EK9_6(K=OrY9Wd8|F@OEF1U`2FoRm7t zv5TTcMvq=TYmE`P3kX1QM7@x`3I%-qm1uAd5ptl0O(C7>PgWx#W{#EK{N z5%<@eN|hp3v58j!hN1NOt5CT{4Yxs6+2L%#YpUX$LP?M^rH5osImtp(_lK1^+uE$b zHcX~XhiEcNzvXdE0;syjx?@Gis4nR`b3iqcY_Y>8lebr=wlw-hw}n-cq4+ePZcg~5 zk6KZ6U01p{<(mMUyywi^o#g;F@x9vkGU{`+k$Ubg3#x1jdbS(61S%%X9YEi3Jf&CX zvA&XJwLu#yky9L&n|Jy{+zg;u36YzyZYKrC6xU-}F1JOW3uCV|s6~0>;EOrP$*VAY znmhngXEB^C+b_UP;~k8~?HZ4WCH<9Akw};FJAUvg4BbF8vH( z)YGmngKQ4w>n0&Vi%nj0%|hxFQ7HUBz^XyCpTk4x9-d87E+!dW&_=(@{yabD?M8{6 znTX#0{^9!F97gVj+qcF<4e?&0q_W!=K>JXb@;6LqSe3GXy5s7-`%1`!*b!1oMn>h~ z{;o1RXl=aBzV*RrLR;lW%$&z&)_&F+=pE&Z zd8q(WxZit4TOHWd&XQq6l;wTW`=!zcV97fBi?P<4y%j%_noZ`)F^ceJw`xwOH8gh9%PkiU*(8+Lvb z=k1m@@T^JS9=doOg}M8bS&uRhH^fR`_bj$tuHqPW`)#geR17ExqFvNKTp(T(rpLtpx_ z3Hd`4iWo=mj~Gc^NqE8m^(}tg(HdLqsq@mwLU}2*GqG5#oi+SWw8h-~G2&`~f1ElF{ zX)A)!)kgGaW?fO`id3zg!>3)HeBa{&xA0!a`Y_Vo8?LUb=0@|0I;#DV0`s7>RyXwX zG^8zqUbR|$eU1Ahw;e=(aF|V3`ml6=UaQ9gUE?u!^V88B$|*UHfHXj^#UxdNP90)^ zuE1>Hz?T?xQYdxI>1IMKci+XPm$vej81^Y;#A}08b`Fi=9xREmM27%oWloM9v-uF_ zTU1{Zl;_cpS^z!6`A;8v;#{60-XjVT;JTH0+o-og(XZ5E%&FXX!yM#J;@V!hASim| z^Ce?8z-qgAQ_3|n%WK{7e`br~&;{a9@+G*YNSUUyKZ`DOMatJmKVQKW58lTuK$ zcqqZG3rKU*ZTV}#lgK%d9CC&ScGotkKA#w>L~#ch&md4N6)E{5d3NXR=AX9V0D2uw zN_t;>`^L$0YDc!4ihiER7Yi=BpXWbtkF|a~&M1!8$^lkdm8H9X-JAfv2&G=$d-AHn z3YsADRrH<^L;v(|7Q4rCVR~dfHk8;*nGR1z^V-GN-8P?TN?(1ild+z8lp_40RDr=d zt_Ope1DG{&qV@O=)MzCo(GV*H(w86R2;!Ymg9a=O zG3|^yOc$H#Y=4q|gH84#nuL;z3GK=+i8HiED%gJ!fWV_b`b@W9x0zjp&O0UJy4ENp z>!@;?!}zI=^7rmC<)t7dCC0ZGI!x@L;lt85T;)I_Jn^|R;yI8| zX8QzK+;g&ejL%-2x;A#lzOGr_Yl&z{kWb}cU2yEp=&ND2r=LryV%qDh`R+c;&lOh2 z1E;%j<~qBu*fEMQuQy>)Pm5Ds{8uCOv5D+o=1VnVKjW?`phs-=+hs0+;PjYEQMQtMMP7LHsSm(DR3O9vPFukYVIn0T|cq@IdlxUM?a zFVWw_u?}s4?=1cL&aB?pvLnwbLPNGnFs|VUPPB{EwKgvg{h@2orG8rrB&E*@5YrNGKm90NmEvXMF>5W>Q-?SODpLF1mklT41 zF(G+4#9p$#mp8>;DHxhiDF?4i;oxCHdAE@fBTru{g!n%pRW*5q0ab+rxf?Z_RVi@A zU-IzF${s<^akY@)q67@ExT!9hulT`agh=79w%JId3sZ$=O)U12X?TCAqEBXi9LcKZ z=(zeia?Q=rdjBQp0fQlN@KZ;nb|JjyabfOXdm}-xD_V!vCq)pNz<2K*B}$p0F_M{* zCJUeynVzKQeNxHAhxX0K?Xy~Rn{2}Wgowr1nNyXE0y*Oq$qtE#f5wqA@Msc&<$KtM zRB%@S+cnch_H@QE@el+Fy>SQ#E$!XW$!ZgLbw&L{S^F!BEB{V?p-&6kD81Pg%ZF^2 zv8lO~zEs&$df{15W7OK66V8*OBhyBhyTnX8e)$)Z^w8N~#m%spIPwUmZ)}08bmZC) z5Xo5jXH+|xBlfhN40S=LBw|cPGpDYQ@)2EX8n=1JqK*7m>Df@RbtOLmzs?3@6sSQ@ zbKDg@KgmX*QNi=4cPWy^ak!+OSg&U4t@a3eNmT`2bA6y5bQ9?sQNEH&K1n~5DDQQDg?*Ww%CSrXH zJK$T~^N8eb91s=V34Sd{J|4duXVzth?a*Vpwen+}joecVU0!}PvJ@%C`QY?`%%C%K zW&wP2HYe$JAMaLlqe|&XTTDGXM#!bZyJT6msO&%bg-(P@wL7N)o)Z_cOGZ{kRIY@T z>-E8*X%-wi=vdHa{;fc)f`s7`ckxn>*JT30YocB4Q?zd0j_Oue zASwt}DPs6^=p1}Te)8{i8<9EOB{|>flcdbLrve;BR@9#9=^7Nap%P}O7@JbxT?Oh; zz!yVaX91E9pYsTUT=aiZOj6Y48}4vTxY|&+0y+P>ByN@eTi^oZB_Nl00X_%cls2Bc z+Wj{0MhF)z)*?cwzuaZ0>F?LiHZsGX)&hrw3_}aCAK0^+9Mw)*E*WQ_^NBLk76nG+AIlO1qi2EP<-ej2RiA2yL=3pJ`eL$-Z_?W}ZW#?r zZ!3R4)_(9wzjJ>86ezac(BwEw1-ch>`GneLw+6@om4WWTS3aA01|q}O9h&-1s2is=-@rtawerT3JqDk50jGRpc(R}L^{`=59WxAd2x+ctk*Z&y**&SJ7c?FK6eEch);>*|XzI7xdeAGm z#<=Fts4xyiF$Os}sE1zBT(txvXE_x@cc8xLmIt9ZGMMXt>=?@Hk;Pw%1pbEZQCbaHZON=;C89c%cX!ezc z@P+gGPan4@D-8@8C-b~$tfb{=Kuge$lGM^&e(O=HSj34=GpCu4l`yLh$t^ zu}S_11x?kBSSU&l%e6ZnzJZClY&wdXRbAGYe?7|KV4wIc2gse{cXBy79=RfeeYW5I zm33R-Ggs*kwSWi`kjM2ziY$2xeie0u{`y@EN`92b#S_z&8JZte1vNOiilPFXU9PM?~@y{#Tg=nhZ zj?;3HT0%^ZP>*E5i2utT1o#(mkHR_hAo-SmV`?vyKeC%A>V&$VWLeN`r>8_7D+3PZ;t>o{lr(49)%Px{eWd)!n(f}cm^{z26DdxH1dvv{ z<=D`({LSKy-ymTOaN|)sj&0r+K$hl&3?j*RYt9@1rC0h<7Lc= zsl$G(ukBson)r(hr`+q}V6^$>z_9b~7$}g_FvlW(M52m(l5S@Yh7cc=JFa!joB*1q zd_Xlhdjf!q`~Xx8Wk6T?B3BaN1^LHo-6}viTeuL!G@R+VQ}o3zg#*yK0rFu*)ZC$G zgz;;Cy#ax*4lzVt)U_9jH4_L`d7&Sk)RW`WNzWhD0=0ZwaQp=z5|jKY^iij;&vUQ5 zTOBRDC{D8SkDlT4%4_)~+%rosLntKJ(IK(I7*pFv8t7>j0)3{U;dv_nenp`Z(AwnO zob6gYoyk**HL?7ydK3OQok4g7en_EI zZi7(p0STYYG@lnigTcDE9xU`#6E@VExeplI`Cjdk?_23a{Z|!Hv3-u0D`9gIcLB~c zoQeuR7g?P;IMywbUD*`(XI!U@i@me?OywskEc&<3rrwJ*mEPVtJUixjf}i7Ke0y`YHzQb0*WL9Kf*s3kk?rv}JSVX zkR5!P?DcK+fAaQx&F$Yqz!LXDX0}U@Rg^9mIc)84NW|prf9#OoLLNl*+o*2L;11C) z4_N{fh1Odmxo<15WFBsvz1{;N>|`eZSQ7ydwm$|(1-B0^3qe7ZSpRQ-Zfb~-cl@{> z{04E@UhnB6K+CY(4tzkvAW0d}L7D4ZC9(XOg5KPGy zR<6>4fA-GA!$Qb$6&XeG(-B7V$PfSgiUi?3!GdB5dY$iW0k|^?An($|!M~fY`zC*z zG>KQ^aseJ7`e$y2>&n^n9X~mwpJw=A6Y00kcnpzE`HAu2471qhs) z^`jw5xkp~g7VPT!Xt^NqE99;K7Cox{I9m@(VHC!|^1_s{oAIPGeegRY$B;Vp5YXFr z`V>CEO*&8Hs}Ou1Wh9EG6t0*ai32OB!^q<(Oh4$M!ue@ktg>A7CVpzt5oe2rE4DBG zCr?e%)hL(CA>)F8Y=OS*D8Ot}%W0iAhlB~K1TCZRMq>Qy>E8pGHKloY znEV#KC7j^>ZR&~@yxIF1AO6#BztKA9%`Lziq%^@M!lmdXj8T;jYEPiS+rcB?C!uwicOjq2i{tGGn@d56ODyoOShR9Qu$~)0 z2WAD1#ksiu9BQo~z7C+r3s48J9GLSU`C1ZZ2vs zpO>n^rCOhLSIL`@_4Tln)-B%{I}Zwzt|?wRY_ER8+f`81zF;yFy**OIj`pKd}0P>KF+dz1Pezu>;#W#Ioil+V(wx7Ds{frjuDa zz)G#k`Jq0-;ZtC^pw$q(0{1^J4`0Ynr65^ep21>PS z7-I~?>;_OxzX>(~9yJIM+P3yF;45{}7oEZwR<}rLcse`qB?h2j=B7}o(7O?TeSFFE zXKF+au0(DUfD{vMbaY9L>{rE@WSS}cXUkYXk@C{`F;K%NbFCuBZ2dj13o&@Ko6V@X zyu&SU{^J&TtiE!M4lo1+44XQ&bgzZa`akcVIqbxi165~1<1^qTzQ6$Am8fF1(N)dXifqPg|^B|ik97iSiCjm`BS$&<5oo)gPjR6$(ourD(_Hxv# zj#9xmA{;625qNU#N;`pDaWoOu<@kj80}hlt!K~5|;l$XPIC!-(599^gdEdVhJ^PIHBqGS+ zXjz3s9zX@;3YC@#y}&T_*K&_)Fn8OJR&z$jm9Iy!m|$F^>r#uoKf%l(M}i*sjzb{_ z3#`bmRg3e#Z&Ls=xc}ds4TE3eNiBUokh*|RN?Rc9w>+ z5xX>DYA^Q44?L}GKaC@1phK7hgEk_${@XO6qZ9qV-n8ohm4|}mZNr$$6|h$e<)xB_ KVyXOx!2bhw6w<%| From ddfbddd0dd901d3ce0e233cb3ba7dbd365e09ac2 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 15:25:34 +0800 Subject: [PATCH 09/43] update --- 3/zend_global_register.md | 57 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 898ad6c..6d9b24e 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -56,6 +56,59 @@ static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_exe return 0; } ``` -从这个例子可以很清楚的看到,执行完以后会将execute_data->opline加1,也就是指向下一条opcode,然后返回0给execute_ex(),接着执行器在下一次循环时执行下一条opcode,依次类推,直至所有的opcode执行完成。 +从这个例子可以很清楚的看到,执行完以后会将execute_data->opline加1,也就是指向下一条opcode,然后返回0给execute_ex(),接着执行器在下一次循环时执行下一条opcode,依次类推,直至所有的opcode执行完成。这个处理过程比较简单,并没有不好理解的地方,而且整个过程看起来也都那么顺理成章。PHP7针对execute_data、opline两个变量的存储位置进行了优化,那就是使用全局寄存器保存这两个变量的地址,以实现更高效率的读取。这种方式下execute_data、opline直接从寄存器读取地址,在性能上大概有5%的提升(官方说法)。在分析PHP7的优化之前,我们先简单介绍下什么是寄存器变量。 + +寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其>次是内存,最慢的是内存。C语言中使用关键字register来声明局部变量为寄存器变量,需要注意的是,只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。而且,一个计算机中寄存器数量是有限的,一般为2到3个,因此寄存器变量的数量不能太多。对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量。 受硬件寄存器长度的限制,寄存器变量只能是char、int或指针型,而不能使其他复杂数据类型。由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。 + +GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量,也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: +```c +register int *foo asm ("r12"); //r12、%r12 +``` +或者: +```c +register int *foo __asm__ ("r12"); //r12、%r12 +``` +这里r12就是指定使用的寄存器,它必须是运行平台上有效的寄存器,这样就可以像使用普通的变量一样使用foo,但是foo同样没有地址,也就是无法通过&获取它的地址,在gdb调试时也无法使用foo符号,只能使用对应的寄存器获取数据。举个例子来看: +```c +//main.c +#include + +typedef struct _execute_data { + int ip; +}zend_execute_data; + + +register zend_execute_data* execute_data __asm__ ("%r14"); + +int main(void) +{ + execute_data = (zend_execute_data *)malloc(sizeof(zend_execute_data)); + execute_data->ip = 9999; + + return 0; +} +``` +编译:`$ gcc -o main -g main.c`,然后通过gdb看下: +```sh +$ gdb main +(gdb) break main +(gdb) r +Starting program: /home/qinpeng/c/php/main + +Breakpoint 1, main () at main.c:12 +12 execute_data = (zend_execute_data *)malloc(sizeof(zend_execute_data)); +(gdb) n +13 execute_data->ip = 9999; +(gdb) n +15 return 0; +``` +这时我们就无法再像普通变量那样直接使用execute_data访问数据,只能通过r14寄存器读取: +```sh +(gdb) p execute_data +Missing ELF symbol "execute_data". +(gdb) info register r14 +r14 0x601010 6295568 +(gdb) p ((zend_execute_data *)$r14)->ip +$3 = 9999 +``` -全局寄存器变量(Global Register Variables)是数据保存在寄存器中的一种变量,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是内存。寄存器变量 From 8b3d976818c26364056596c23e77484769e2ab9d Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 17:43:39 +0800 Subject: [PATCH 10/43] update --- 3/zend_global_register.md | 67 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 6d9b24e..18e15d8 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -20,12 +20,12 @@ ZEND_API void execute_ex(zend_execute_data *ex) ``` 执行器实际是一个大循环,从第一条opcode开始执行,execute_data->opline指向当前执行的指令,执行完以后指向下一条指令,opline类似eip(或rip)寄存器的作用。通过这个循环,ZendVM完成opcode指令的执行。opcode执行完后以后指向下一条指令的操作是在当前handler中完成,也就是说每条执行执行完以后会主动更新opline,这里会有下面几个不同的动作: ```c -ZEND_VM_CONTINUE() -ZEND_VM_ENTER() -ZEND_VM_LEAVE() -ZEND_VM_RETURN() +#define ZEND_VM_CONTINUE() return 0 +#define ZEND_VM_ENTER() return 1 +#define ZEND_VM_LEAVE() return 2 +#define ZEND_VM_RETURN() return -1 ``` -ZEND_VM_CONTINUE()表示继续执行下一条opcode;ZEND_VM_ENTER()/ZEND_VM_LEAVE()是调用函数时的动作,普通模式下ZEND_VM_ENTER()实际就是return 1,然后execute_ex()中会将execute_data切换到被调函数的结构上,对应的,在函数调用完成后ZEND_VM_LEAVE()会return 2,再将execute_data切换至原来的结构;ZEND_VM_RETURN()表示执行完成,比如exit,这时候execute_ex()将退出执行。下面看一个具体的例子: +ZEND_VM_CONTINUE()表示继续执行下一条opcode;ZEND_VM_ENTER()/ZEND_VM_LEAVE()是调用函数时的动作,普通模式下ZEND_VM_ENTER()实际就是return 1,然后execute_ex()中会将execute_data切换到被调函数的结构上,对应的,在函数调用完成后ZEND_VM_LEAVE()会return 2,再将execute_data切换至原来的结构;ZEND_VM_RETURN()表示执行完成,返回-1给execute_ex(),比如exit,这时候execute_ex()将退出执行。下面看一个具体的例子: ```php $a = "hi~"; echo $a; @@ -111,4 +111,61 @@ r14 0x601010 6295568 (gdb) p ((zend_execute_data *)$r14)->ip $3 = 9999 ``` +了解完全局寄存器变量,接下来我们再回头看下PHP7中的用法,处理也比较简单,就是在execute_ex()执行各opcode指令的过程中,不再将execute_data作为参数传给handler,而是通过寄存器保存execute_data及opline的地址,handler使用时直接从全局变量(寄存器)读取,执行完再把下一条指令更新到全局变量。 +该功能需要GCC 4.8+支持,默认开启,可以通过 --disable-gcc-global-regs 编译参数关闭。以x86_64为例,execute_data使用r14寄存器,opline使用r15寄存器: +```c +//file: zend_execute.c line: 2631 +# define ZEND_VM_FP_GLOBAL_REG "%r14" +# define ZEND_VM_IP_GLOBAL_REG "%r15" + +//file: zend_vm_execute.h line: 315 +register zend_execute_data* volatile execute_data __asm__(ZEND_VM_FP_GLOBAL_REG); +register const zend_op* volatile opline __asm__(ZEND_VM_IP_GLOBAL_REG); +``` +execute_data、opline定义为全局变量,下面看下execute_ex()的变化,展开后: +```c +ZEND_API void execute_ex(zend_execute_data *ex) +{ + const zend_op *orig_opline = opline; + zend_execute_data *orig_execute_data = execute_data; + + //将当前execute_data、opline保存到全局变量 + execute_data = ex; + opline = execute_data->opline + + while (1) { + ((opcode_handler_t)opline->handler)(); + + if (UNEXPECTED(!opline)) { + execute_data = orig_execute_data; + opline = orig_opline; + + return; + } + } +} +``` +这个时候调用各opcode指令的handler时就不再传入execute_data的参数了,handler使用时直接从全局变量读取,仍以上面的赋值ZEND_ASSIGN指令为例,handler展开后: +```c +static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(void) +{ + ... + + //ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION() + opline = execute_data->opline + 1; + return; +} +``` +当调用函数时,会把execute_data、opline更新为被调函数的,然后回到execute_ex()开始执行被调函数的指令: +```c +# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_CONTINUE() +``` +展开后: +```c +//ZEND_VM_ENTER() +execute_data = execute_data->current_execute_data; +opline = execute_data->opline; +return; +``` +这两种处理方式并没有本质上的差异,只是通过全局寄存器变量提升了一些性能。 From ac29cb0d9821778a692c18d63407699500526a3e Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 17:48:30 +0800 Subject: [PATCH 11/43] update dir --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 06bca77..ccdf4aa 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ * 3.3.1 基本结构 * 3.3.2 执行流程 * 3.3.3 函数的执行流程 + * [3.3.4 全局execute_data和opline](3/zend_global_register.md) * 3.4 面向对象实现 * [3.4.1 类](3/zend_class.md) * [3.4.2 对象](3/zend_object.md) From ac38e217dea0823f5502c783464a6dd8bb0ef3f4 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 17:57:34 +0800 Subject: [PATCH 12/43] update --- 3/zend_global_register.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 18e15d8..66d7c41 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -169,3 +169,5 @@ opline = execute_data->opline; return; ``` 这两种处理方式并没有本质上的差异,只是通过全局寄存器变量提升了一些性能。 + +> __Note:__ automake编译时的命令是cc,而不是gcc,如果更新gcc后发现PHP仍然没有支持这个特性,请检查下cc是否指向了新的gcc From 5461dedcc55da125508199a97104e7dbc74f3e71 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 18:02:14 +0800 Subject: [PATCH 13/43] update --- 3/zend_global_register.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 66d7c41..f091eda 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -60,7 +60,7 @@ static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_exe 寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其>次是内存,最慢的是内存。C语言中使用关键字register来声明局部变量为寄存器变量,需要注意的是,只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。而且,一个计算机中寄存器数量是有限的,一般为2到3个,因此寄存器变量的数量不能太多。对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量。 受硬件寄存器长度的限制,寄存器变量只能是char、int或指针型,而不能使其他复杂数据类型。由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。 -GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量,也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: +GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量(Global Register Variables,参考:https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Global-Register-Variables.html),也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: ```c register int *foo asm ("r12"); //r12、%r12 ``` From c0de5f804b3184582e8e3d7af1dc13f1e585e921 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 18:03:20 +0800 Subject: [PATCH 14/43] update --- 3/zend_global_register.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index f091eda..93a52ea 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -60,7 +60,7 @@ static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_exe 寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其>次是内存,最慢的是内存。C语言中使用关键字register来声明局部变量为寄存器变量,需要注意的是,只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。而且,一个计算机中寄存器数量是有限的,一般为2到3个,因此寄存器变量的数量不能太多。对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量。 受硬件寄存器长度的限制,寄存器变量只能是char、int或指针型,而不能使其他复杂数据类型。由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。 -GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量(Global Register Variables,参考:https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Global-Register-Variables.html),也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: +GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量(Global Register Variables,[详细介绍](https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Global-Register-Variables.html)),也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: ```c register int *foo asm ("r12"); //r12、%r12 ``` From ed96756cb3cf3bed4c07591665dac3efee2764ff Mon Sep 17 00:00:00 2001 From: qinpeng Date: Thu, 20 Jul 2017 10:12:35 +0800 Subject: [PATCH 15/43] update --- 3/zend_global_register.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 93a52ea..51cd81f 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -58,7 +58,7 @@ static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_exe ``` 从这个例子可以很清楚的看到,执行完以后会将execute_data->opline加1,也就是指向下一条opcode,然后返回0给execute_ex(),接着执行器在下一次循环时执行下一条opcode,依次类推,直至所有的opcode执行完成。这个处理过程比较简单,并没有不好理解的地方,而且整个过程看起来也都那么顺理成章。PHP7针对execute_data、opline两个变量的存储位置进行了优化,那就是使用全局寄存器保存这两个变量的地址,以实现更高效率的读取。这种方式下execute_data、opline直接从寄存器读取地址,在性能上大概有5%的提升(官方说法)。在分析PHP7的优化之前,我们先简单介绍下什么是寄存器变量。 -寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其>次是内存,最慢的是内存。C语言中使用关键字register来声明局部变量为寄存器变量,需要注意的是,只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。而且,一个计算机中寄存器数量是有限的,一般为2到3个,因此寄存器变量的数量不能太多。对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量。 受硬件寄存器长度的限制,寄存器变量只能是char、int或指针型,而不能使其他复杂数据类型。由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。 +寄存器变量存放在CPU的寄存器中,使用时,不需要访问内存直接从寄存器中读写,与存储在内存中的变量相比,寄存器变量具有更快的访问速度,在计算机的存储层次中,寄存器的速度最快,其次是内存,最慢的是硬盘。C语言中使用关键字register来声明局部变量为寄存器变量,需要注意的是,只有局部自动变量和形式参数才能够被定义为寄存器变量,全局变量和局部静态变量都不能被定义为寄存器变量。而且,一个计算机中寄存器数量是有限的,一般为2到3个,因此寄存器变量的数量不能太多。对于在一个函数中说明的多于2到3个的寄存器变量,C编译程序会自动地将寄存器变量变为自动变量。 受硬件寄存器长度的限制,寄存器变量只能是char、int或指针型,而不能使其他复杂数据类型。由于register变量使用的是硬件CPU中的寄存器,寄存器变量无地址,所以不能使用取地址运算符"&"求寄存器变量的地址。 GCC从4.8.0版本开始支持了另外一项特性:全局寄存器变量(Global Register Variables,[详细介绍](https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/Global-Register-Variables.html)),也就是可以把全局变量定义为寄存器变量,从而可以实现函数间共享数据。可以通过下面的语法告诉编译器使用寄存器来保存数据: ```c From ee2e98fb01d7b734dad19f33bb2054ce7b78c111 Mon Sep 17 00:00:00 2001 From: "byter.hu" Date: Sat, 22 Jul 2017 02:13:06 +0800 Subject: [PATCH 16/43] Update func.md fix error --- 7/func.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/func.md b/7/func.md index e04228a..a1fd5e9 100644 --- a/7/func.md +++ b/7/func.md @@ -67,7 +67,7 @@ const zend_function_entry mytest_functions[] = { #define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags }, #define ZEND_FN(name) zif_##name ``` -最后将`zend_module_entry->functions`设置为`timeout_functions`即可: +最后将`zend_module_entry->functions`设置为`mytest_functions`即可: ```c zend_module_entry mytest_module_entry = { STANDARD_MODULE_HEADER, From 3e09906791e3f375bb9a85bbfd5c3533a125ebe3 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 24 Jul 2017 17:17:29 +0800 Subject: [PATCH 17/43] fix error --- 3/zend_global_register.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/3/zend_global_register.md b/3/zend_global_register.md index 51cd81f..9c9462e 100644 --- a/3/zend_global_register.md +++ b/3/zend_global_register.md @@ -43,9 +43,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(Z ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } ``` -所有opcode的handler定义格式都是相同的,其参数列表通过ZEND_OPCODE_HANDLER_ARGS宏定义,展开后实际只有一个execute_data;ZEND_FASTCALL这个宏是用于指定C语言函数调用方式的,这里指定的是fastcall方式,GNU C下就是__attribute__((fastcall))。去掉一些非关键操作展开后: +所有opcode的handler定义格式都是相同的,其参数列表通过ZEND_OPCODE_HANDLER_ARGS宏定义,展开后实际只有一个execute_data,展开后: ```c -static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_execute_data *execute_data) +static int ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(zend_execute_data *execute_data) { //USE_OPLINE const zend_op *opline = execute_data->opline; @@ -148,7 +148,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) ``` 这个时候调用各opcode指令的handler时就不再传入execute_data的参数了,handler使用时直接从全局变量读取,仍以上面的赋值ZEND_ASSIGN指令为例,handler展开后: ```c -static int __attribute__((fastcall)) ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(void) +static int ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(void) { ... From bfdd8fd5bfb4a3a5b7a3ec68e2fa4b9b4b525ae8 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Tue, 25 Jul 2017 11:08:08 +0800 Subject: [PATCH 18/43] update --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index ccdf4aa..dbec699 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ * [3.4.5 魔术方法](3/zend_magic_method.md) * [3.4.6 类的自动加载](3/zend_autoload.md) * [3.5 运行时缓存](3/zend_runtime_cache.md) + * 3.6 Opcache + * 3.6.1 opcode缓存 + * 3.6.2 opcode优化 + * 3.6.3 JIT * 第4章 PHP基础语法实现 * [4.1 类型转换](4/type.md) * [4.2 选择结构](4/if.md) From 163db8b5856f3f9f5ad76344fbb63fa2713c744d Mon Sep 17 00:00:00 2001 From: qinpeng Date: Tue, 25 Jul 2017 15:03:13 +0800 Subject: [PATCH 19/43] fix error --- 2/zend_constant.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2/zend_constant.md b/2/zend_constant.md index fad305c..eca3f65 100644 --- a/2/zend_constant.md +++ b/2/zend_constant.md @@ -8,7 +8,7 @@ PHP中的常量通过`define()`函数定义: define('CONST_VAR_1', 1234); ``` ### 2.5.1 常量的存储 -在内核中常量存储在`EG(zend_constant)`哈希表中,访问时也是根据常量名直接到哈希表中查找,其实现比较简单。 +在内核中常量存储在`EG(zend_constants)`哈希表中,访问时也是根据常量名直接到哈希表中查找,其实现比较简单。 常量的数据结构: ```c From 337ab9c385d669d64a2554ea60867c5297c52170 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Tue, 25 Jul 2017 21:13:09 +0800 Subject: [PATCH 20/43] update --- 2/global_var.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/2/global_var.md b/2/global_var.md index a6e90fc..5537b51 100644 --- a/2/global_var.md +++ b/2/global_var.md @@ -1,7 +1,5 @@ ## 2.4 全局变量 -PHP中在函数、类之外直接定义的变量可以在函数、类成员方法中通过global关键词引入使用,这些变量称为:全局变量。 - -这些直接在PHP中定义的变量(包括include、require文件中的)相对于函数、类方法而言它们是全局变量,但是对自身执行域zend_execute_data而言它们是普通的局部变量,自身执行时它们与普通变量的读写方式完全相同。 +PHP中把定义在函数、类之外的变量称之为全局变量,也就是定义在主脚本中的变量,这些变量可以在函数、成员方法中通过global关键字引入使用。 ```php function test() { From cec1807fe0c946e146565ebfa1cbdef5311ba47c Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 26 Jul 2017 16:38:28 +0800 Subject: [PATCH 21/43] update --- 2/global_var.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2/global_var.md b/2/global_var.md index 5537b51..e9515d4 100644 --- a/2/global_var.md +++ b/2/global_var.md @@ -62,7 +62,7 @@ global $id; // 相当于:$id = & EG(symbol_table)["id"]; ![](../img/zend_global_ref.png) ### 2.4.3 超全局变量 -全部变量除了通过global引入外还有一类特殊的类型,它们不需要使用global引入而可以直接使用,这些全局变量称为:超全局变量。 +全局变量除了通过global引入外还有一类特殊的类型,它们不需要使用global引入而可以直接使用,这些全局变量称为:超全局变量。 超全局变量实际是PHP内核定义的一些全局变量:$GLOBALS、$_SERVER、$_REQUEST、$_POST、$_GET、$_FILES、$_ENV、$_COOKIE、$_SESSION、argv、argc。 From a6eec9f8121a4bf35664e57524bd39b4fa96f8ba Mon Sep 17 00:00:00 2001 From: qinpeng Date: Thu, 27 Jul 2017 20:38:56 +0800 Subject: [PATCH 22/43] fix error --- 8/namespace.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8/namespace.md b/8/namespace.md index b9b7c6d..d59d086 100644 --- a/8/namespace.md +++ b/8/namespace.md @@ -259,7 +259,7 @@ typedef struct _zend_file_context { ``` 简单总结下use的几种不同用法: * __a.导入命名空间:__ 导入的名称保存在FC(imports)中,编译使用的语句时搜索此符号表进行补全 -* __b.导入类:__ 导入的名称保存在FC(imports)中,与a不同的时如果不会根据"\"切割后的最后一节检索,而是直接使用类名查找 +* __b.导入类:__ 导入的名称保存在FC(imports)中,与a不同的是不会根据"\"切割后的最后一节检索,而是直接使用类名查找 * __c.导入函数:__ 通过`use function`导入到FC(imports_function),补全时先查找FC(imports_function),如果没有找到则继续按照a的情况处理 * __d.导入常量:__ 通过`use const`导入到FC(imports_const),不全是先查找FC(imports_const),如果没有找到则继续按照a的情况处理 From fb2385c368209a0d48f3e050bccce499f118102e Mon Sep 17 00:00:00 2001 From: qinpeng Date: Thu, 27 Jul 2017 20:40:29 +0800 Subject: [PATCH 23/43] fix error --- 8/namespace.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8/namespace.md b/8/namespace.md index d59d086..dc5ac2b 100644 --- a/8/namespace.md +++ b/8/namespace.md @@ -261,7 +261,7 @@ typedef struct _zend_file_context { * __a.导入命名空间:__ 导入的名称保存在FC(imports)中,编译使用的语句时搜索此符号表进行补全 * __b.导入类:__ 导入的名称保存在FC(imports)中,与a不同的是不会根据"\"切割后的最后一节检索,而是直接使用类名查找 * __c.导入函数:__ 通过`use function`导入到FC(imports_function),补全时先查找FC(imports_function),如果没有找到则继续按照a的情况处理 -* __d.导入常量:__ 通过`use const`导入到FC(imports_const),不全是先查找FC(imports_const),如果没有找到则继续按照a的情况处理 +* __d.导入常量:__ 通过`use const`导入到FC(imports_const),补全时先查找FC(imports_const),如果没有找到则继续按照a的情况处理 ```php use aa\bb; //导入namespace From 3edb26dc0af49be9adead33e9045678493508e7b Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 28 Jul 2017 14:25:39 +0800 Subject: [PATCH 24/43] fix error --- 8/namespace.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/8/namespace.md b/8/namespace.md index dc5ac2b..58ac9fe 100644 --- a/8/namespace.md +++ b/8/namespace.md @@ -427,7 +427,7 @@ zend_string *zend_resolve_non_class_name( return zend_prefix_with_ns(name); } ``` -可以看到,函数与常量的的补全逻辑只是优先用原始名称去FC(imports_function)或FC(imports_const)查找,如果没有找到再去FC(imports)中匹配。如果我们这样导入了一个函数:`use aa\bb\my_func;`,编译`my_func()`会在FC(imports_function)中根据"my_func"找到"aa\bb\my_func",从而使用完整的这个名称。 +可以看到,函数与常量的的补全逻辑只是优先用原始名称去FC(imports_function)或FC(imports_const)查找,如果没有找到再去FC(imports)中匹配。如果我们这样导入了一个函数:`use function aa\bb\my_func;`,编译`my_func()`会在FC(imports_function)中根据"my_func"找到"aa\bb\my_func",从而使用完整的这个名称。 ### 8.3.3 动态用法 前面介绍的这些命名空间的使用都是名称为CONST类型的情况,所有的处理都是在编译环节完成的,PHP是动态语言,能否动态使用命名空间呢?举个例子: From c84843bd92c33080dd344b1582d193c29aaa13e8 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Tue, 1 Aug 2017 17:53:26 +0800 Subject: [PATCH 25/43] fix error --- 4/loop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/4/loop.md b/4/loop.md index 19ce394..f698d0e 100644 --- a/4/loop.md +++ b/4/loop.md @@ -241,7 +241,7 @@ foreach($arr as $k=>$v){ 了解了foreach的实现、运行机制我们再回头看下其编译过程: -* __(1)__ 编译"拷贝"数组/对象操作的opcode:`ZEND_FE_RESET_R`,如果value是引用则是`ZEND_FE_RESET_RW`,执行时如果发现数组或对象属性为空则直接跳出遍历,所以这条opcode还需要知道跳出的位置,这个位置需要编译完foreach以后才能确定; +* __(1)__ 编译拷贝数组、对象操作的指令:ZEND_FE_RESET_R,如果value是引用则是ZEND_FE_RESET_RW。执行时如果发现遍历的变量不是数组、对象,则抛出一个warning,然后跳出循环,所以这条指令还需要知道跳出的位置,这个位置需要编译完foreach以后才能确定; * __(2)__ 编译fetch数组/对象当前单元key、value的opcode:`ZEND_FE_FETCH_R`,如果是引用则是`ZEND_FE_FETCH_RW`,此opcode还需要知道当遍历已经到达数组末尾时跳出遍历的位置,与步骤(1)的opcode相同,另外还有一个关键操作,前面已经说过遍历的key、value实际就是普通的局部变量,它们的内存存储位置正是在这一步分配确定的,分配过程与普通局部变量的过程完全相同,如果value不是一个CV变量(比如:foreach($arr as $v["xx"]){...})则还会编译其它操作的opcode; * __(3)__ 如果foreach定义了key则编译一条赋值opcode,此操作是对key进行赋值; * __(4)__ 编译循环体statement; From c9275007b354068318fc35322cc197481faec8c3 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 4 Aug 2017 14:35:12 +0800 Subject: [PATCH 26/43] fix error --- 3/zend_class.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/zend_class.md b/3/zend_class.md index e0bc8f5..b7099af 100644 --- a/3/zend_class.md +++ b/3/zend_class.md @@ -416,7 +416,7 @@ void zend_compile_class_const_decl(zend_ast *ast) zend_class_entry *ce = CG(active_class_entry); uint32_t i; - for (i = 0; i < list->children; ++i) { //不清楚这个地方为什么要用list,试了几个例子这个节点都只有一个child,即for只循环一次 + for (i = 0; i < list->children; ++i) { //const声明了多个常量,遍历编译每个子节点 zend_ast *const_ast = list->child[i]; zend_ast *name_ast = const_ast->child[0]; //常量名节点 zend_ast *value_ast = const_ast->child[1];//常量值节点 From 42c82f65cedbf7a08d0d4d67476a9a60b28a2da3 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 4 Aug 2017 14:46:28 +0800 Subject: [PATCH 27/43] fix error --- 3/zend_class.md | 1 - 1 file changed, 1 deletion(-) diff --git a/3/zend_class.md b/3/zend_class.md index b7099af..f67783b 100644 --- a/3/zend_class.md +++ b/3/zend_class.md @@ -446,7 +446,6 @@ void zend_compile_prop_decl(zend_ast *ast) zend_class_entry *ce = CG(active_class_entry); uint32_t i, children = list->children; - //也不清楚这里为啥用循环,测试的情况child只有一个 for (i = 0; i < children; ++i) { zend_ast *prop_ast = list->child[i]; //这个节点类型为:ZEND_AST_PROP_ELEM zend_ast *name_ast = prop_ast->child[0]; //属性名节点 From eb2f96fc2aa72515a3d1fb4f87e387b650775ac3 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 7 Aug 2017 17:26:13 +0800 Subject: [PATCH 28/43] fix error --- 7/func.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/7/func.md b/7/func.md index 74ae72a..4c4a47c 100644 --- a/7/func.md +++ b/7/func.md @@ -376,8 +376,25 @@ my_func_1(array($object, 'method')); #### 7.6.2.11 其它标识符 除了上面介绍的这些解析符号以外,还有几个有特殊用法的标识符:"|"、"+"、"*",它们并不是用来表示某种数据类型的。 -* __|:__ 表示此后的参数为可选参数,可以不传,比如解析规则为:"al|b",则可以传2个或3个参数,如果是:"alb",则必须传3个,否则将报错; -* __+/*:__ 用于可变参数,注意这里与PHP函数...的用法不太一样,PHP中可以把函数最后一个参数前加...,表示调用时可以传多个参数,这些参数都会插入...参数的数组中,"*/+"也表示这个参数是可变的,但内核中只能接收一个值,即使传了多个后面那些也解析不到,"*"、"+"的区别在于"*"表示可以不传可变参数,而"+"表示可变参数至少有一个。 +* __|:__ 表示此后的参数为可选参数,可以不传,比如解析规则为:"al|b",则可以传2个或3个参数,如果是:"alb",则必须传3个,否则将报错 +* __+、* :__ 用于可变参数,`+、*`的区别在于 * 表示可以不传可变参数,而 + 表示可变参数至少有一个。可变参数将被解析到zval数组,可以通过一个整形参数,用于获取具体的数量,例如: +```c +PHP_FUNCTION(my_func_1) +{ + zval *args; + int argc; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "+", &args, &argc) == FAILURE) { + return; + } + //... +} +``` +argc获取的就是可变参数的数量,args为参数数组,指向第一个参数,可以通过args[i]获取其它参数,比如这样传参: +```php +my_func_1(array(), 1, false, "ddd"); +``` +那么传入的4个参数就可以在解析后通过args[0]、args[1]、args[2]、args[3]获取。 ### 7.6.3 引用传参 上一节介绍了如何在内部函数中解析参数,这里还有一种情况没有讲到,那就是引用传参: From b7dbd3deebd3fff05fde871ec0e4331361dfe89e Mon Sep 17 00:00:00 2001 From: jianzhiyao <739319867@qq.com> Date: Tue, 29 Aug 2017 16:58:59 +0800 Subject: [PATCH 29/43] =?UTF-8?q?=E6=8B=BC=E5=86=99=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E9=94=99=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 7/implement.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/implement.md b/7/implement.md index bebf3d4..7c84d1c 100644 --- a/7/implement.md +++ b/7/implement.md @@ -1,5 +1,5 @@ ## 7.2 扩展的实现原理 -PHP中扩展通过`zend_module_entry`这个结构来表示,此结构定义了扩展的全部信息:扩展名、扩展版本、扩展提供的函数列表以及PHP四个执行阶段的hook函数等,每一个扩展都需要定义一个此结构的变量,而且这个变量的名称格式必须是:`{mudule_name}_module_entry`,内核正是通过这个结构获取到扩展提供的功能的。 +PHP中扩展通过`zend_module_entry`这个结构来表示,此结构定义了扩展的全部信息:扩展名、扩展版本、扩展提供的函数列表以及PHP四个执行阶段的hook函数等,每一个扩展都需要定义一个此结构的变量,而且这个变量的名称格式必须是:`{module_name}_module_entry`,内核正是通过这个结构获取到扩展提供的功能的。 扩展可以在编译PHP时一起编译(静态编译),也可以单独编译为动态库,动态库需要加入到php.ini配置中去,然后在`php_module_startup()`阶段把这些动态库加载到PHP中: ```c From 386016c4e23bd83003039bef2d5e2855b9d2281b Mon Sep 17 00:00:00 2001 From: qinpeng Date: Mon, 13 Nov 2017 19:49:28 +0800 Subject: [PATCH 30/43] update --- README.md | 5 ++++- img/book.jpg | Bin 0 -> 75288 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 img/book.jpg diff --git a/README.md b/README.md index dbec699..5dddd92 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,10 @@ ## 反馈 [交流&吐槽](https://github.com/pangudashu/php7-internal/issues/3) [错误反馈](https://github.com/pangudashu/php7-internal/issues/2) -![](img/my_wx2.png) +## 纸质版 +
+ +
## 目录: * 第1章 PHP基本架构 diff --git a/img/book.jpg b/img/book.jpg new file mode 100644 index 0000000000000000000000000000000000000000..89fc991f3db944b2f9540e7f491fe28831e57e7a GIT binary patch literal 75288 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ⓈubSvbsX|0)3%Vj`+dSGujJ5T^R<<1qh(K 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 Date: Mon, 13 Nov 2017 19:52:12 +0800 Subject: [PATCH 31/43] update --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 5dddd92..57dfd71 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ ## 纸质版
+ + (coming soon)
## 目录: From d5ec26aab7785a00065893226fb4bb36af26878f Mon Sep 17 00:00:00 2001 From: glowdan Date: Wed, 15 Nov 2017 21:12:30 +0800 Subject: [PATCH 32/43] add gitbook support --- SUMMARY.md | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++ book.json | 7 ++++ 2 files changed, 115 insertions(+) create mode 100644 SUMMARY.md create mode 100644 book.json diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..d26efd0 --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,108 @@ +# PHP7-internal + +## 目录 + +* 第1章 PHP基本架构 + * 1.1 PHP简介 + * 1.2 PHP7的改进 + * [1.3 FPM](1/fpm.md) + * [1.3.1 概述](1/fpm.md) + * [1.3.2 基本实现](1/fpm.md) + * [1.3.3 FPM的初始化](1/fpm.md) + * [1.3.4 请求处理](1/fpm.md) + * [1.3.5 进程管理](1/fpm.md) + * [1.4 PHP执行的几个阶段](1/base_process.md) +* 第2章 变量 + * [2.1 变量的内部实现](2/zval.md) + * [2.2 数组](2/zend_ht.md) + * [2.3 静态变量](2/static_var.md) + * [2.4 全局变量](2/global_var.md) + * [2.5 常量](2/zend_constant.md) +* 第3章 Zend虚拟机 + * [3.1 PHP代码的编译](3/zend_compile.md) + * [3.1.1 词法解析、语法解析](3/zend_compile_parse.md) + * [3.1.2 抽象语法树编译流程](3/zend_compile_opcode.md) + * [3.2 函数实现](3/function_implement.md) + * [3.2.1 内部函数](3/function_implement.md) + * 3.2.2 用户函数的实现 + * [3.3 Zend引擎执行流程](3/zend_executor.md) + * 3.3.1 基本结构 + * 3.3.2 执行流程 + * 3.3.3 函数的执行流程 + * [3.3.4 全局execute_data和opline](3/zend_global_register.md) + * 3.4 面向对象实现 + * [3.4.1 类](3/zend_class.md) + * [3.4.2 对象](3/zend_object.md) + * [3.4.3 继承](3/zend_extends.md) + * [3.4.4 动态属性](3/zend_prop.md) + * [3.4.5 魔术方法](3/zend_magic_method.md) + * [3.4.6 类的自动加载](3/zend_autoload.md) + * [3.5 运行时缓存](3/zend_runtime_cache.md) + * 3.6 Opcache + * 3.6.1 opcode缓存 + * 3.6.2 opcode优化 + * 3.6.3 JIT +* 第4章 PHP基础语法实现 + * [4.1 类型转换](4/type.md) + * [4.2 选择结构](4/if.md) + * [4.3 循环结构](4/loop.md) + * [4.4 中断及跳转](4/break.md) + * [4.5 include/require](4/include.md) + * [4.6 异常处理](4/exception.md) +* 第5章 内存管理 + * [5.1 Zend内存池](5/zend_alloc.md) + * [5.2 垃圾回收](5/gc.md) +* 第6章 线程安全 + * [6.1 什么是线程安全](6/ts.md) + * [6.2 线程安全资源管理器](6/ts.md) +* 第7章 扩展开发 + * [7.1 概述](7/intro.md) + * [7.2 扩展的实现原理](7/implement.md) + * [7.3 扩展的构成及编译](7/extension_intro.md) + * [7.3.1 扩展的构成](7/extension_intro.md) + * [7.3.2 编译工具](7/extension_intro.md) + * [7.3.3 编写扩展的基本步骤](7/extension_intro.md) + * [7.3.4 config.m4](7/extension_intro.md) + * [7.4 钩子函数](7/hook.md) + * [7.5 运行时配置](7/conf.md) + * [7.5.1 全局变量](7/conf.md) + * [7.5.2 ini配置](7/conf.md) + * [7.6 函数](7/func.md) + * 7.6.1 内部函数注册 + * 7.6.2 函数参数解析 + * 7.6.3 引用传参 + * 7.6.4 函数返回值 + * 7.6.5 函数调用 + * [7.7 zval的操作](7/var.md) + * [7.7.1 新生成各类型zval](7/var.md) + * [7.7.2 获取zval的值及类型](7/var.md) + * [7.7.3 类型转换](7/var.md) + * [7.7.4 引用计数](7/var.md) + * [7.7.5 字符串操作](7/var.md) + * [7.7.6 数组操作](7/var.md) + * [7.8 常量](7/constant.md) + * 7.9 面向对象 + * 7.9.1 内部类注册 + * 7.9.2 定义成员属性 + * 7.9.3 定义成员方法 + * 7.9.4 定义常量 + * 7.9.5 类的实例化 + * 7.10 资源类型 + * 7.11 经典扩展解析 + * 7.8.1 Yaf + * 7.8.2 Redis +* 第8章 命名空间 + * [8.1 概述](8/namespace.md) + * [8.2 命名空间的定义](8/namespace.md) + * [8.2.1 定义语法](8/namespace.md) + * [8.2.2 内部实现](8/namespace.md) + * [8.3 命名空间的使用](8/namespace.md) + * [8.3.1 基本用法](8/namespace.md) + * [8.3.2 use导入](8/namespace.md) + * [8.3.3 动态用法](8/namespace.md) + +---- + +## 附录 + * [附录1:break/continue按标签中断语法实现](try/break.md) + * 附录2:defer推迟函数调用语法的实现 \ No newline at end of file diff --git a/book.json b/book.json new file mode 100644 index 0000000..d167834 --- /dev/null +++ b/book.json @@ -0,0 +1,7 @@ +{ + "title" : "PHP7内核剖析", + "author" : "pangudashu", + "description" : "PHP7", + "language" : "zh-hans", + "gitbook" : ">=3.0.0" +} \ No newline at end of file From 3c0ba793950105f929a2d9f597a2ccc8137d2df8 Mon Sep 17 00:00:00 2001 From: glowdan Date: Wed, 15 Nov 2017 21:17:24 +0800 Subject: [PATCH 33/43] edit description --- book.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book.json b/book.json index d167834..26f051e 100644 --- a/book.json +++ b/book.json @@ -1,7 +1,7 @@ { "title" : "PHP7内核剖析", "author" : "pangudashu", - "description" : "PHP7", + "description" : "PHP7内核剖析,基于PHP版本:php-7.0.12", "language" : "zh-hans", "gitbook" : ">=3.0.0" } \ No newline at end of file From bf67ee7d1cc994f2282e06ae1dafbd088ed4f9cc Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 1 Dec 2017 10:13:27 +0800 Subject: [PATCH 34/43] update --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 57dfd71..7458bfa 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ ## 纸质版
- - (coming soon) + [京东](https://item.jd.com/12267210.html) + [当当](http://product.dangdang.com/25185400.html)
## 目录: From f89a9abc25b94fd0d7aa950dcc6a47a49f701a4b Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 1 Dec 2017 10:16:25 +0800 Subject: [PATCH 35/43] add url --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7458bfa..6ae92fe 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,9 @@ ## 纸质版
+ [京东](https://item.jd.com/12267210.html) + [当当](http://product.dangdang.com/25185400.html)
From 254c7b87aa865b50535e9d09354fcd014a19c70d Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 1 Dec 2017 10:18:20 +0800 Subject: [PATCH 36/43] add url --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6ae92fe..dacb5fc 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,8 @@
- [京东](https://item.jd.com/12267210.html) - - [当当](http://product.dangdang.com/25185400.html) + [京东] + [当当]
## 目录: From 9e273d42af08960642989a32bc605d3122cde55b Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 1 Dec 2017 10:18:55 +0800 Subject: [PATCH 37/43] add url --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dacb5fc..90ebdf2 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ ## 纸质版
+
[京东] [当当] - ## 目录: * 第1章 PHP基本架构 From 6c469f14f222c0a922aa194b56c972747697f331 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 1 Dec 2017 10:19:55 +0800 Subject: [PATCH 38/43] add url --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 90ebdf2..95dcbb4 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@
- - [京东] - [当当] + +[京东](https://item.jd.com/12267210.html) +[当当](http://product.dangdang.com/25185400.html) ## 目录: * 第1章 PHP基本架构 From 6c34d2e2036c4d06be089283e3e6b4b3e7cc5b1d Mon Sep 17 00:00:00 2001 From: xmc Date: Mon, 19 Mar 2018 17:01:54 +0800 Subject: [PATCH 39/43] =?UTF-8?q?fix=20=E8=AF=8D=E8=AF=AD=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2/zval.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2/zval.md b/2/zval.md index 6f96b7e..dd82bc0 100644 --- a/2/zval.md +++ b/2/zval.md @@ -278,7 +278,7 @@ $b[] = 3; ![zval_sep](../img/zval_sep.png) -不是所有类型都可以copy的,比如对象、资源,实时上只有string、array两种支持,与引用计数相同,也是通过`zval.u1.type_flag`标识value是否可复制的: +不是所有类型都可以copy的,比如对象、资源,事实上只有string、array两种支持,与引用计数相同,也是通过`zval.u1.type_flag`标识value是否可复制的: ```c #define IS_TYPE_COPYABLE (1<<4) ``` From 66505547ac5a3ff13c0399d62e64dd51750682fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?mc=C2=B2?= Date: Mon, 26 Mar 2018 17:53:21 +0800 Subject: [PATCH 40/43] =?UTF-8?q?=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复 严格的将 => 严格的说 --- 2/static_var.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2/static_var.md b/2/static_var.md index d382cb4..c134cf2 100644 --- a/2/static_var.md +++ b/2/static_var.md @@ -87,7 +87,7 @@ if (by_ref) { * __ZEND_FETCH_W:__ 这条opcode对应的操作是创建一个IS_INDIRECT类型的zval,指向static_variables中对应静态变量的zval * __ZEND_ASSIGN_REF:__ 它的操作是引用赋值,即将一个引用赋值给CV变量 -通过上面两条opcode可以确定静态变量的读写过程:首先根据变量名在static_variables中取出对应的zval,然后将它修改为引用类型并赋值给局部变量,也就是说`static $count = 4;`包含了两个操作,严格的将`$count`并不是真正的静态变量,它只是一个指向静态变量的局部变量,执行时实际操作是:`$count = & static_variables["count"];`。上面例子$count与static_variables["count"]间的关系如图所示。 +通过上面两条opcode可以确定静态变量的读写过程:首先根据变量名在static_variables中取出对应的zval,然后将它修改为引用类型并赋值给局部变量,也就是说`static $count = 4;`包含了两个操作,严格的说`$count`并不是真正的静态变量,它只是一个指向静态变量的局部变量,执行时实际操作是:`$count = & static_variables["count"];`。上面例子$count与static_variables["count"]间的关系如图所示。 ![](../img/zend_static_ref.png) From 217ea91e703df8cbfacb872ad7a6259e07d4aa89 Mon Sep 17 00:00:00 2001 From: smalleyes Date: Wed, 25 Apr 2018 18:04:16 +0800 Subject: [PATCH 41/43] =?UTF-8?q?=E6=A0=A1=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3/zend_class.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/3/zend_class.md b/3/zend_class.md index f67783b..62eea77 100644 --- a/3/zend_class.md +++ b/3/zend_class.md @@ -1,7 +1,7 @@ ### 3.4.1 类 类是现实世界或思维世界中的实体在计算机中的反映,它将某些具有关联关系的数据以及这些数据上的操作封装在一起。在面向对象中类是对象的抽象,对象是类的具体实例。 -在PHP中类编译阶段的产物,而对象是运行时产生的,它们归属于不同阶段。 +在PHP中类是编译阶段的产物,而对象是运行时产生的,它们归属于不同阶段。 PHP中我们这样定义一个类: ```php From 124d6bc9bbf5abc5a3671bfc005b46bcec099252 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Tue, 10 Jul 2018 17:34:12 +0800 Subject: [PATCH 42/43] update doc --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 95dcbb4..566fac0 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,10 @@ * [8.3.2 use导入](8/namespace.md) * [8.3.3 动态用法](8/namespace.md) -## 附录 - * [附录1:break/continue按标签中断语法实现](try/break.md) - * 附录2:defer推迟函数调用语法的实现 +## 实现PHP新特性 + * [1、break/continue按标签中断语法实现](try/break.md) + * 2、defer语法 + * 3、协程 + * 3.1 协程的原理 + * 3.2 上下文切换 From 860410be29627212b5dbd485664ace2d4e6188b3 Mon Sep 17 00:00:00 2001 From: Ching-Ping Sun <252880+tomjpsun@users.noreply.github.com> Date: Fri, 18 Jan 2019 17:29:42 +0800 Subject: [PATCH 43/43] fix example typo --- 7/extension_intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/extension_intro.md b/7/extension_intro.md index f6aafc8..020a179 100644 --- a/7/extension_intro.md +++ b/7/extension_intro.md @@ -270,7 +270,7 @@ __(5)PHP_ADD_INCLUDE(path):__ 添加include路径,即:`gcc -Iinclude_dir`, __(6)PHP_CHECK_LIBRARY(library, function [, action-found [, action-not-found [, extra-libs]]]):__ 检查依赖的库中是否存在需要的function,action-found为存在时执行的动作,action-not-found为不存在时执行的动作,比如扩展里使用到线程pthread,检查pthread_create(),如果没找到则终止./configure执行: ```sh -PHP_ADD_INCLUDE(pthread, pthread_create, [], [ +PHP_CHECK_LIBRARY(pthread, pthread_create, [], [ AC_MSG_ERROR([not find pthread_create() in lib pthread]) ]) ```