From 59056dfaf0c13453278730b98f769bec69e599b1 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Thu, 6 Jul 2017 09:25:35 +0800 Subject: [PATCH 01/52] fix error --- 4/break.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/4/break.md b/4/break.md index 5bfc256..47ec5b8 100644 --- a/4/break.md +++ b/4/break.md @@ -19,7 +19,15 @@ typedef struct _zend_brk_cont_element { ``` cont记录的是当前循环判断条件opcode起始位置,brk记录的是当前循环结束的位置,parent记录的是父层循环`zend_brk_cont_element`结构的存储位置,也就是说多层嵌套循环会生成一个`zend_brk_cont_element`的链表,每层循环编译结束时更新自己的`zend_brk_cont_element`结构,所以break、continue的处理过程实际就是根据跳出的层级索引到那一层的`zend_brk_cont_element`结构,然后得到它的cont、brk进行相应的opcode跳转。 -各循环的`zend_brk_cont_element`结构保存在`zend_op_array->brk_cont_array`数组中,实际这个数组在编译前就已经分配好了,编译各循环时依次申请一个`zend_brk_cont_element`,`zend_op_array->last_brk_cont`记录此数组第一个可用位置,每申请一个元素last_brk_cont就相应的增加1,parent记录的就是父层循环在`zend_op_array->brk_cont_array`中的位置。 +各循环的`zend_brk_cont_element`结构保存在`zend_op_array->brk_cont_array`数组中,编译各循环时依次申请一个`zend_brk_cont_element`,`zend_op_array->last_brk_cont`记录此数组第一个可用位置,每申请一个元素last_brk_cont就相应的增加1,然后将数组扩容,parent记录的就是父层循环结构在该数组中的存储位置。 +```c +zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) +{ + op_array->last_brk_cont++; + op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont); + return &op_array->brk_cont_array[op_array->last_brk_cont-1]; +} +``` 示例: ```php From 70108cd0868d0e44c20455e73fd58f349d4436b0 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 7 Jul 2017 16:10:45 +0800 Subject: [PATCH 02/52] fix error --- 7/func.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/7/func.md b/7/func.md index 0807f69..e04228a 100644 --- a/7/func.md +++ b/7/func.md @@ -355,7 +355,7 @@ callable指函数或成员方法,如果参数是函数名称字符串、array( zend_fcall_info callable; //注意,这两个结构不能是指针 zend_fcall_info_cache call_cache; -if(zend_parse_parameters( +if(zend_parse_parameters(ZEND_NUM_ARGS(), "f", &callable, &call_cache) == FAILURE){ RETURN_FALSE; } ``` From c6983b641bc2285c5c0e0014affa7b47591697f7 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 7 Jul 2017 18:36:26 +0800 Subject: [PATCH 03/52] add defer --- img/defer.png | Bin 0 -> 20196 bytes try/break.md | 2 +- try/defer.md | 23 +++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 img/defer.png create mode 100644 try/defer.md diff --git a/img/defer.png b/img/defer.png new file mode 100644 index 0000000000000000000000000000000000000000..08c48e5a9c3be0704bdb22734f3e075fcc779964 GIT binary patch literal 20196 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 BFvchild[0]; zend_ast *cond_ast = ast->child[1]; diff --git a/try/defer.md b/try/defer.md new file mode 100644 index 0000000..66e35ee --- /dev/null +++ b/try/defer.md @@ -0,0 +1,23 @@ +# 附录2:defer推迟执行语法的实现 + +使用过Go语言的应该都知道defer这个语法,它用来推迟一个函数的执行,在函数执行返回前首先检查当前函数内是否有推迟执行的函数,如果有则执行,然后再返回。defer是一个非常有用的语法,这个功能可以很方便的在函数结束前执行一些清理工作,比如关闭打开的文件、关闭连接、释放资源、解锁等等。这样延迟一个函数有以下两个好处: + + * (1) 靠近使用位置,避免漏掉清理工作,同时比放在函数结尾要清晰 + * (2) 如果有多处返回的地方可以避免代码重复,比如函数中有很多处return + +在一个函数中可以使用多个defer,其执行顺序与栈类似:后进先出,先定义的defer后执行。另外,在返回之后定义的defer将不会被执行,只有返回前定义的才会执行,通过exit退出程序的情况也不会执行任何defer。 + +在PHP中并没有实现类似的语法,接下来我们介绍下如何在PHP中实现类似Go语言中defer的功能。此功能的实现需要对PHP的语法解析、抽象语法树/opcode的编译、opcode指令的执行等环节进行改造,涉及的地方比较多,但是改动点比较简单,可以很好的帮助大家完整的理解PHP编译、执行两个核心阶段的实现。整体实现思路: + + * (1) 语法解析:defer本质上还是函数调用,只是将调用时机移到了函数的最后,所以编译时可以复用调用函数的规则,但是需要与普通的调用区分开,所以我们新增一个AST节点类型,其子节点为为正常函数调用编译的AST,语法我们定义为:`defer function_name()`; + * (2) AST编译为opcode:编译opcode时也复用调用函数的编译逻辑,不同的地方在于把defer放在最后编译,另外需要在编译return前新增一条opcode,用于执行return前跳转到defer开始的位置,在defer的最后也需要新增一条opcode,用于执行完defer后跳回return的位置; + * (3) 执行阶段:执行时如果发现是return前新增的opcode则跳转到defer开始的位置,同时把return的位置记录下来,执行完defer后再跳回return。 + +编译后的opcode指令如下图所示: + +![](../img/defer.png) + +1、修改词法解析文件,将defer解析为token:T_DEFER +2、修改语法解析文件,支持语法:T_DEFER function_call,解析为AST:ZEND_AST_DEFER_CALL +3、编译ZEND_AST_DEFER_CALL时加入defer栈 +4、编译结束时继续编译defer栈中的function_call,最后编译一条ZEND_JMP,用于跳回return/exit/die的位置 From 1a059c238eb688f21bfe6fc99e7e97aed67d9fc7 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 7 Jul 2017 18:39:54 +0800 Subject: [PATCH 04/52] update --- try/defer.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/try/defer.md b/try/defer.md index 66e35ee..7f61355 100644 --- a/try/defer.md +++ b/try/defer.md @@ -2,16 +2,16 @@ 使用过Go语言的应该都知道defer这个语法,它用来推迟一个函数的执行,在函数执行返回前首先检查当前函数内是否有推迟执行的函数,如果有则执行,然后再返回。defer是一个非常有用的语法,这个功能可以很方便的在函数结束前执行一些清理工作,比如关闭打开的文件、关闭连接、释放资源、解锁等等。这样延迟一个函数有以下两个好处: - * (1) 靠近使用位置,避免漏掉清理工作,同时比放在函数结尾要清晰 - * (2) 如果有多处返回的地方可以避免代码重复,比如函数中有很多处return +* (1) 靠近使用位置,避免漏掉清理工作,同时比放在函数结尾要清晰 +* (2) 如果有多处返回的地方可以避免代码重复,比如函数中有很多处return 在一个函数中可以使用多个defer,其执行顺序与栈类似:后进先出,先定义的defer后执行。另外,在返回之后定义的defer将不会被执行,只有返回前定义的才会执行,通过exit退出程序的情况也不会执行任何defer。 在PHP中并没有实现类似的语法,接下来我们介绍下如何在PHP中实现类似Go语言中defer的功能。此功能的实现需要对PHP的语法解析、抽象语法树/opcode的编译、opcode指令的执行等环节进行改造,涉及的地方比较多,但是改动点比较简单,可以很好的帮助大家完整的理解PHP编译、执行两个核心阶段的实现。整体实现思路: - * (1) 语法解析:defer本质上还是函数调用,只是将调用时机移到了函数的最后,所以编译时可以复用调用函数的规则,但是需要与普通的调用区分开,所以我们新增一个AST节点类型,其子节点为为正常函数调用编译的AST,语法我们定义为:`defer function_name()`; - * (2) AST编译为opcode:编译opcode时也复用调用函数的编译逻辑,不同的地方在于把defer放在最后编译,另外需要在编译return前新增一条opcode,用于执行return前跳转到defer开始的位置,在defer的最后也需要新增一条opcode,用于执行完defer后跳回return的位置; - * (3) 执行阶段:执行时如果发现是return前新增的opcode则跳转到defer开始的位置,同时把return的位置记录下来,执行完defer后再跳回return。 +* (1) 语法解析:defer本质上还是函数调用,只是将调用时机移到了函数的最后,所以编译时可以复用调用函数的规则,但是需要与普通的调用区分开,所以我们新增一个AST节点类型,其子节点为为正常函数调用编译的AST,语法我们定义为:`defer function_name()`; +* (2) AST编译为opcode:编译opcode时也复用调用函数的编译逻辑,不同的地方在于把defer放在最后编译,另外需要在编译return前新增一条opcode,用于执行return前跳转到defer开始的位置,在defer的最后也需要新增一条opcode,用于执行完defer后跳回return的位置; +* (3) 执行阶段:执行时如果发现是return前新增的opcode则跳转到defer开始的位置,同时把return的位置记录下来,执行完defer后再跳回return。 编译后的opcode指令如下图所示: From 8552cec11643625189b02e144f4feaed66e876ad Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 7 Jul 2017 19:55:39 +0800 Subject: [PATCH 05/52] add ast --- img/defer_ast.png | Bin 0 -> 14606 bytes try/defer.md | 50 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 img/defer_ast.png diff --git a/img/defer_ast.png b/img/defer_ast.png new file mode 100644 index 0000000000000000000000000000000000000000..db1da709f4a931e719031c1fb100409571a85b60 GIT binary patch literal 14606 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"defer" { + RETURN_TOKEN(T_DEFER); +} +``` +完成词法解析规则的修改后接着需要定义语法解析规则,这是非常关键的一步,语法解析器会根据配置的语法规则将PHP代码解析为抽象语法树(AST)。普通函数调用会被解析为ZEND_AST_CALL类型的AST节点,我们新增一种节点类型:ZEND_AST_DEFER_CALL,抽象语法树的节点类型为enum,定义在zend_ast.h中,同时此节点只需要一个子节点,这个子节点用于保存ZEND_AST_CALL节点,因此zend_ast.h的修改如下: +```c +enum _zend_ast_kind { + ... + /* 1 child node */ + ... + ZEND_AST_DEFER_CALL + .... +} +``` +定义完AST节点后就可以在配置语法解析规则了,把defer语法解析为ZEND_AST_DEFER_CALL节点,我们把这条语法规则定义在"statement:"节点下,if、echo、for等语法都定义在此节点下,语法解析规则文件为zend_language_parser.y: +```c +statement: + '{' inner_statement_list '}' { $$ = $2; } + ... + | T_DEFER function_call ';' { $$ = zend_ast_create(ZEND_AST_DEFER_CALL, $2); } +; +``` +修改完这两个文件后需要分别调用re2c、yacc生成对应的C文件,具体的生成命令可以在Makefile.frag中看到: +```c +$ re2c --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l +$ yacc -p ini_ -v -d Zend/zend_language_parser.y -oZend/zend_language_parser.c +``` +执行完以后将在Zend目录下重新生成zend_language_scanner.c、zend_language_parser.c两个文件。到这一步已经完成生成抽象语法树的工作了,重新编译PHP后已经能够解析defer语法了,将会生成以下节点: + +![](../img/defer_ast.png) + + From e09183e09b877548f593da43ebd49d9202040edb Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 7 Jul 2017 21:16:52 +0800 Subject: [PATCH 06/52] update --- img/defer_call.png | Bin 0 -> 26242 bytes try/defer.md | 147 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+) create mode 100644 img/defer_call.png diff --git a/img/defer_call.png b/img/defer_call.png new file mode 100644 index 0000000000000000000000000000000000000000..37c76328f39501a1308c158dde4504b4b27a7efd GIT binary patch literal 26242 zcmbsRcRZHwA3qMCw(Ml@P$b!VC&>z-va+&wHrYaU60#GL?5t!Hl1(-t*?Vt(uj~E! zegC@uxbMgJzTS`C_29bB>pYM1I9{*kI?gb4)dz%lGEq^_lT>i-`4 z(@xw{&{cwu@#$YPfowL(N7fHBq{(;z?~?!EXmxp){C*pe=b}8w>f= z&~J&L2gsa}2UZZuFp*T^zQx8wH%3?qaWR__1sW3ES7>hpm`HFjn5^K}*fInDGE4;i z*=PYWREQ!5dH@gd|JMiPY-o+Vo)qcp7#cd*-6nAhX=u2dZ3!*33nt{n&B?59$M+?Q4Oj}PEJOU z?d|Q3jt+0BhWz||L&1@up(twpo1C1S0s`-P7oSs^qdQ+J-M!mXZZ)_!2!~Em`BYq7 ztibBEUNK^AZB0W%^S!3#p*_;Z~y#xRz?Qn*=LQscS<)9CN?%4sk6=c zQ?8&Ub}p`Zmt|7K==5NnyLPL2ZLCa?CQ6k-o8!if`5$4|o;`b(B4pRBH&*%_C#F6B z^XH?j7UF5Y%kwxkHEb-b?o`oh2oq`8!R9nEf6L#+-i*+jcbfgNS@Zp@^XhMANRBG<&LwmgO|y; zWdUA<6gOB{p05rUBL08>nylNqxw!15iMs~|1u;r`30U;dtutF!&>%878itZSU_t&L854SIW_tU3PVK&61CLtCWKYtAj~SPEPCb$_~G ze{Z22^L5h8UGAcO%O57Zh*3|fD2z!~zong>9h+LZe!cf`62FDxOIFe_b@q1(tg5Q2 zl0MuxI5_A5Gb=0O!^7B`9ufv}a+o2;tfW_vnT-vDCr{)v)lK=RqvZJ)9U^(C6=*nd z_UM27`0>+}FH>E_`ZqgQ;>6I9>+0|wM8?IXTq$S3Qeb_3T`faueQoWxFY)EUgah`j zr9kpf{?nFFIz$F_PsuONR+-|JZjs^DKH-SpqGzC_WTS}4(a0++<40szNhQ6H-gKCv zBS+p+0Wu#3m+^vSSxK9&M@qp}!|P-jMqUpWPGLoG^eU_>e{IfB{gz~St^NJ6s<{}* zdzFPhbuY!m#bHKX!Iah3)^>NVf~n-_2vy9fI#uQ7>Cw^BV!x$;M@4#ix)@vH^?w3OO1Tx=|x}Q|gS5@`p-B5MFjh+!QRupm{1OZxO`5 zW%gT5jV3$U5$Y!XqiGBF|U z@>Hq3tr6F7F)1l28DerZ@^CSs2^>(KoEl9x_%XUyxVgD`d3x^Wi!`q=S(VU1d24EF zy8Wc!y_l=Dvon8UXYevC`)S|P^)HX}n_F7aQd5fz8|sZ)uqh(2ULL*4QBL$do=-gS z^jas9`8zjvjg<7W7Duc?K|z5)x@T)R`GaUWMKv`>Q72Pn<<9rK&&wC3%4Z!#a@8_I z;)=!H)<_~+8GZJyB1|G8-(W#-aS@r{zI}UeyO7zIQQ)5Oqn>oh8q5BVU%q_#{P}Zp zbMyTOil#p=6%{*_x$9iE|F*)i_c_^HzI*pBE9osB9uhH{>)5*m&uWC2m>P}rA}H=8 z^O@n*M#sc7ILJA5owY`1i7{<&DDMAzV=}A60 zUa)Rq$oYCv5!cdp7Sb@jq)0htxcR}d*GX`+1FilHK>#NC} zve(n2)sI2!;yUO1TKk5FGjd!-Z@G8C2-`^kF0JNg%dLQxI zxAU{J$xw@Q1y%?=u9DC{-8XB7X$<;TNl|pK2 zYM%wiM}%-s%KFjvX-Mj>QBYuC&~?s)IaTX(C0+}Yd-`-F9S=qzOs?682daddAExms z^z%J(v9zM;b^)opu>6qN)_1rQn2H!5i}%WZlJc_OrI+~s4g`2`bF*+UWo>N>Dhg#r zsVzklh=SB%FS&kfVS0!CT8m@eQDnFh-B`_0gs!{*-=gn=M1Y16&hu3wy=&h*}!-X`ej>9G}}_5I!3GVAzCHd7T(AAj=qZ_L}FX4_s&JV9H7Qo4Gatz7#N^W+_-ULqRL@$+r!ZJ z7>b>Q*B*PULaML>LtFl`D$M$~7(3e!PcOl*9791kC#nxKu=q4p{X ziTcy0IQTbNS=YuZR?B*&;DFf3%!r}iLj?r@ASHieLU<&T?>vbO$Oc^xD3 z%eR~QF388Hk*N-a9o9e8p+dkP`T46* zb~!1O*~zR0Xo6*DH#hzER~|>nx0sYZDbUW;$op;Ws-^V~pqoR(IaKUQhiL|C>M&!f zE=?`1?0!ovjv)X%e_n1%YI|yFX=!T4$z~ocq&S?NpBpc%PgMEsbg+?zW!Kfww~dz_ z5u5X^o%FWReJ}{JLp$BFva;H&J4`Pw<_?hYN6Uigt6P|$z=|N;+{LGdo0r?|jBqD7 z;_wNE3q&$ zM>9xrklNXDka(e`{;74AZx7-vFw%x3xjd4-O8#f{D%? zyR^1Oa3iS6sL`Vg`ZRPs>k8c*4N+0iJBIZVqM|x^TGkhll335}#6?8QeL@_`Nz6ciLD_faV)aM`+I97-k3$HBq4-o^YOYtpcPfBz0lP1%)Q zFS&|=0p|xu_;l#0p``Db$3j<9mHiYRF)ocWwZd_MRLwHlyXvKqWgnJ4|6LL_k0QK`aGypFX8Tn1qF^zJI4d0G#}q+rBuO zi`m)PsjwOOGGu-BI3p$Hbmkyn=@nzbFMIkUOb`0 zv`DvN1*$XR{}%NkB@HwEH~9mfl54WwM~{;tW#N>?7Mqo@^1g@15iG7T+k;R>-=pKj zjE1dde5#Q3KXo-lMfR}b=!n=PC4E+Y=M8>(IPu-p#>>k~U7f_cZgZ-p3K|PPe_YEf zFbacOkL{EF)hk!7bSB(^j`^G~i2!@9mD13~%`Jqm`uq34zGxN}i!(Du9?!J2FcIyq zrX8uG&P0q-5^ihS*g?EzzsQ1;gzYD(=;+QaPB$~eTz|c7AZz61qfz)#fK9jOClGyB}G$;8|YlMA%#Uv^=ReQivI_^aH6 z&sXagW$0w815ANZ#~f?fU~!u$P?~ly(2KAVH%SG?889Y%er$~TVDXv0{yQZznD`ob zE>2F&aX?QD*~!F2MQ4dwgPMQ=OifJzyMTFLQ`0%`B$Y8eHU>q2PTi82gpQ7`oY9;) z7I(LCv7xLCW@<#M$$P`aj&}Yy1y;OZW{QaZ5)&TdVjAgh0csVh%wci^=~#W~H-9_} zL6G%8Ip#+V04FKe3C8y=Erv5fvNiHbFg|AJ)TsWLL7{QOZxV!9xz$w<_?(RjjwY9x__pURMTkSnh(|F}59<(+lxWJZKZQz$vJOG4X>J8?q z`5n!M`uh3~3$>pR=vo05{XF8oB#y%R930g!EQ?_ilT zX-koAP>}CXx|MFl>)ca^_ zzB94VF2WVX#DR1enOaypefpG9%6oLYQX36;yIjnhj(=TUDq?B%b`wG#@(X=vK-By3 z9qNzGO-=u)YvQ2Zw5gIICCSI<)SE6jEcC+(#qLjj0Q1AZzzB^NBN)G-RvDzgI^N*d z;1-^rk6IRh`5r!uQe_Tp5%oC{K#X9)@X&v%J>94wz`j@W8s4O#p;6rV-O0(x=mQ?& zpOG;=kfS_X;k#O9-W~XGHRU_7W;@V60EYJQQoT)0?J_T`NP!XvaIswzL6(=7+w3ZJ z0M^DZqDb=g@84QB6DGa|eVc|T}7_ixJ`R9y6hg#qRkGQe1F&$B8%j{&0JF(Q8-NoMa=Uof) z^HVkMo6ruAkB{+!(c7}kOSMOe4ION4e;47z*jR%F$E!jURxEsifoN!IW-4A> zTmYFK>1mmF5_b4QP0t@Bw z+FQzc5aZ_VPU}!tR#sM5mxdy1KshsdL)B_jSJ49yzY8pMv~(gyTPXH`vBjY7*q1;T zx|yd1ym<(y=ELyt@MH;3Ct&=Zp4FASM^x=?x45}`J34f#oy^S5ZxUePc64=hb#@N+ zZ`{S+5!A*d4SScAG}hPWc(A4;mc~U9VXXBH=5M^x{L+%gzn@ou`n24u+is)H$;p9> z!>8c%cltn_rs@ah4a{!HdLK@^Et2{<>nkmQV|I3TT=3-X-#4bh&L6U(A6I0KZOph@ zy5u4jCBM4Qi4h>6H5t@dEhL0bk z2(X=KXHU;?&%K**WnaI-Qcj4AeS!!#)Z^DE2A11f6y?yJ>o%jw@z~+TdXuU(K^*17^`4I$eHYJz7 z$9()#IF9R1 z#cQXnt*w3i%D0|=m6e^{av)n#EDUM}Ok32@H~7}&5R|i9${1e(#q4l>0>^#7$)nQa z-7okQyvOjni`CKAEY#;s7EbMwnfXLRE)bifI04l{odRwb_exhkt6kk9UA?+E0Fa0W%w@HBKiMlAWCm@+Q4lHhtM3_7!4cVXA&% z35iLgi=(5X=;-Ky0S*2MGx|3I+JSp}E?kKz$;luC0VDcp`t_iZ9QmNd0TUk3BZE|d zUKJ7Y21<%%1q`}Am#~NkRsB|!#OSq~DnEbyqTx4J0Wf>-UXYuk-TH8pGDb{$5ar?K zG!8;QD@4#Rzpx+#6$PN3bG5#R#q8Qz%gTZEFNd`^Z7_4a#T zB*6q$yU)kZua+vp%U

g%&&pEPAmgEr{i~P_OEX76%(!Zb1R3$6;3zzW_~?Y^H~& zXHIUe4Y9tV&;AeyDb9;MXb2BM3!}OAKPVT{XImH%t>e|sY%X*f>|}EZoX@_yz;w&- zIiS`z{4njMhNY>g36m)`AwlSQ8-Z9FobC&xFYfhD~4`y$XZ7g)e-yK%K;k4h=JgpK#9@|l#b!N~f zj!vg9drV3{?4loP?)?ZSzYU1(S7#@nYv^80!)Qn!&-%#4r-vzG;^NRz@Y$4fIERI& zz4={Nw3aj*32&0%f<^{~66TF|g*ABr-ktu3DJUTYyL0#u`{KR?j( zZkcZi!okPG17Vn&oIL*R+m9?H(0N_ZnwqBJS*+UN38b6-_HB@JM~}AW&=5d3R3X*X)u1p~@+7H*{J|Ve z&CO*?Qn9zOVIjfgp%)@V8lA_9PW*%(KYk2j%Nz?F3Ku1fav9d2wGd02nwx`OYL!SH zCI`I^+IgwZ?5gS?v>5|;YqrwrtqOu03 z%WjIjS|tc%Q#Dm2Ha>o6baZKPvE7IVW(kaEdVD-NDJdYCKtFNppi+|9Be9tvbO0bx@c$v~ZxVFK1LDN7nA0JExA_}{;OuhcxhS65s0`ZUvc z(Vvdu0-c6I=|AA}^6-FPd!MdXB_$<+Sk&&5P-f9v?=-IjBdehBIzCd6*HVVpqt8+R zd-2bbi&ruJHIno5vb@5=DR^Tb7QT6JI-%yu>gpjt8jIfarczwIhXzCpTcQf|Ub<>w z9uy$%08sgopTFJ0a(;du6c~tyhgV?pK2K(V#{-CrK}esDTNn@dmdCf16>EJWn2Mf2 zo}#0PR%y&hQI<%roVob|4ArbIF<(-xQBz=Tt%MD&8Tx;}!<&>x8@etfRbO82LgGS) z`q@n+{nQ0e&E3HlDD3t=2H1+@QCy{%5dwNy&aE*k4(HJP$XWA$lag9y& zRY=JA%XSouGghJ^kbm-I7^Jhgzkfjqes1TC-NTf+4J!;d1WIJF*z@}NY#Iy%5CSiu zML<<8uhJc*{7;zK@6%_G@}N*T6$2`hS6tlSvOECrVJrUkLF@mARCBF}?xCt`z3=%6 zEajl=rpo^p+EUsI)l^rHy(0HL+is7bZ z2?Z>>6hO(AVJd0Q!vpB~iu!t72b9O|&d#zL&D>ZRngz3_KrEUldA5uA^&kMjJls;gAf2M90ltSnBRf09jRNmaVz|lIy)x9 zLq*{3?hagOXlST7d18DVlu$GT1`!%ZwW*OiYXbW48*0{U5mSb7eGMGk_enJJDeM65rCTs2?^^QXVKH8 z9RAc&^P8tizI5yVc;BIJ{|VeiC8b{=lWTJhZ%owycmnYUZoMn`tstjTa2rTKAEmb% zt@Y%O>rhcp&;}3$>VIMm5L3fjMK}3!WDsMDgcs zkwETfFE#Lj1C?^Xe2SzMRt4^Ta(;G}t#ON>T->53_17;Y^Z+nD9_}lTv+&?W*S*S@ z888wRp;Luk3$039d-PZQZ2$$2D|8F{Embq5x=s0vKdbJNGi3GwiNWpJ>wD*zOzd?X273h#BR2^5e_bsz-GE@B812gescpM{0p zgM-(kbpKN(em6A*$Y*uTJMksi^2E6P)HpBM0}o7UqAnyON1YvTCiqOUnee@+X$p|S zBTceZ9vodzU~NF`P3aEluiB=n1;tK0nJc{J3W7^a%+1YBjEARN>+u38vbT3_cRE@y zHdz9O+YaCt5W<6HZ*g*BB5xG3x3(M^Vn)WsU}=DbbqwA_Z(`^CcwNXX%}-QaLDHpS zXvMCtU%&RrS|s{ESpWbK{v$ZV48ME*DcMMH|K~%&#i;v#pdFYAdZwdO4GS0MZcFj- z(9r!%buiE3Iyi6NZYh%l8Jdad!>06aCUal|p!%UBP?{T~gDUQUcdGai;a!d%vDVju+otK?&^1r@<_ccFA_4fw&qJ7=hch(Bo9_a8h!X{vd7d0bpv2$(AV;_e$WV=F5w zviI(tnk;@`V`u+dT6)#X6WsM8{c01t2rqg5C2-FHx4;SlZGs0l9efCskL$G*5v_%V zg)~tMAnn4>YTee8E9ZgogAhW1z59D;$Vwm?5Fa>w({I$-e>lL2u8&vbfBcC41b-s9 z6@Wf3!8N>KkE>Dgn!38*oflQ#! zZ>i1s1axbCuJ(r4geIlZDPS^FP*60l0}(& zXp5pc;F+<%K2w%>P})On5>|Ox8^=f!A3lG{#{AwmU3QD zada&CF9*Oko7a8N`Rd9w064P&vA1sB8XFq}f;24j3t7teg$E@U^jmfI*K!{L!fv#= z!x%d`0WtXx95=h1H7hWPrTvK$j*!oqt@;lXi>EgC*(a*z&c)HdqES19V(sDr$PVC% z_i|3+s2`SnY-7Zd!~xvvM6PFWENCsLfB_=Im1yG^dmUdY_zJRhczC$I-6TCuF}zXv zo`IH8o#2+Po*vk57Zrpi9nvY~NYQy*D&e zk;@Dt!W;|N5GIFiq0w!do{N^Sx>KiP0r~pGj>0K;OW$ZEBqRXU z*;-RvLm@US_&0!v3QgN?>M#H|CFsD*p}QT8Ya%kBHHR4Q@9#e;S4wGGHi(Xjs;Inz zE5|M49(2I542gkD$XWmbuKM^`1XM*CZ5)6oZEf=F@1Xo9CM1l%=67;Dph1Z)DJeca zK81F;&GseUYR(W+0XF$t6{Zr~9)6pBIApy{K;OG>dvZe39q{^%&Vtiqy~fuN2aHE@f-^_7fi9&ECG|*Upe~&1Z$4)&#<%sf)!DPSiB7IkZLciKk>Df&b zL@Dy9e-pwrB_vRs3#!7YqDH33E*}*!D!D1?N_P|Pf`Ng(=SxQvh#t;nvw9sF`CI3< zl`;5mXaEVv_4cq++y9Y)I!sBa_pSeK8<-lPhknjrfLWoZXVZF4_QZhj);r_-sqG`8 zQL@#w0o(`@dEnywN&Qplxye{oYMv0yt>4Y5Vy+y_%;;_L-U$*n7ZVMA(GXzr+F$$c zhGb-9+>K#LQb~v6Xl1p$w>)^qfxP6SfPm{2;`qs1-|}m^1GwL!BjF-3(&)l(4e|8J z_usNTw`>)>#m+ujVFRuQGqVX)7eF==3=Ysyporxc*9Vpw8?iqFD+^c(IB*Q6iJ1o3_1dB8Avg9#vf>AU@&Pnt6PQ$>B9_=qRKiNO|NZ$9;tyv5r~ZnkT{Fb^24H#5cHHfY~^`d|J{ednZbdYS{zy9cs^|b6CvZX+HGm+cyidlyiZ!|-@MCm&w_}-m+C@)uFB^8OLlJs(csw$fa zIiA;5Rl?r0+Nn^M~-y2Zo;Svgv!6hI7 z74f&F003r4+&~B-JW(m<@9uHJ@k4A$bs8g{+w`c)5KzcDZu3p!bj#E;O7(9or4Dr& zGoShWSCM$&?)pUZnK zk=szp@8S&Hk8~NP#zndXPk?qXhH$>0RMTjvsgJ?DH#0S5Wo6y+kO2F(UM_122*=7$ z{@}m>1R`VKym8$5rwG4E?~%eIB9e07(6_Z+gTnCe>>j}lZ*T8Ni8HY#Th0)Si<`W{ zyG}bP-(Sh|rTU%j6P3Cg3sXk@^V}BQymkvz{=kW;^+Q_)qEKfD8Fgj>{H38M7 z=KFU8-(xeHsNu=U)Wk$ea&ked0al{Wxy40@nMq1Yf-if6v;)LCV~0y9M_{=_0*MG0 z*Iybdw8gk=?7uirVz!8L`6(Am}+Ly;WkZxQ7p8{Xc?7Hy3O}}!Qkzn5;{>h=^vHY(( zqqe9ZK&do%U@WZ53ffYaPrlioO2KDuV znHH~P1_cEbUIqsRzDG8bDXzm&UnX~O+ZiWJj@f|X z3H~lBL?$W>%UgK0%5V!L8Qbe`ZI@ zk9!wNN+>~g*qd(LdQ1$c<0$CMI)2}+97E!GrPgA4u!}bjw50!pyWJa4s#ujHKt^9| zZSzVf;!F`@TL^cD2EVJX?lcwm;~9GMK3j(1R^&@&SCd6uY<$HQ^$DB+nY{>uDZ+$| z?2nvoM*6`*AK*@x=z`14*zXKFd*7Su0mo`8(msZ-oWrrRIj__mA zCyKG2C$c|Rv3Rzqhg)jVjya12SFfqPJ+ys}y2HrRJt#OkK*c4}EQZfxHLB!8@rBUl z&w*-RhN9~%KJ_OPwU;_PWw~A^80o@^VYsjMd89rd!%KqN_KWl4yt9cmj4KX--;Tr& z52bZaH87Hv-qY|N2^%tpFx4pm&4u}R=gu9;hmOf~or*zhL6xQ&Tcw6B;`d2aUNq#? zaSL)Lkwuz|kp#Up$U#F$$jGz+=I~mTEa6o?e#A{Us>!qMISv0x8fL(3mS2hxpo$E% zkmB@uho7``bR4L2iw*CjCWG03`B)m?JT@%ar$dE_1T1PCQznxoll|a7jze*=ssRlR z4cl{z5fKp(MFZpkjsb`?GXWpK`F#n77q%l+WR9BWj%nY{6V`ga1?%Z5*&kmY_y{;y zGpZ%pTat^CbliW6x9+}pqnShd+||UpPylJ1o^Hs^A%y1L4X&Dw+Lbv3keeR}iGbHH zkJ_aT;L!CG&x5b!q~-m?z_;-8JH6QcYCT8GEJ0oFZqhv0UiPxEOz+D#-6<`v4B_TM zm~S|!;15x5;&ZF3xT#MKJcCbLaRodij1nh6KDzEK05t9bF>w+~@Z?8%L1M2{3Ocy;78s86LRSFo?h7M{Sa8N+(SZQX z5JO2%Uzj!v{t3vz?i-WK6`Mx$OOHi*w03?ho*usCuI{Zl{@}X&o0mmmxo%OOX)Oc5 z)Y_UYBBQLVY+~~9?z6^w;Q%82Ahm`{lPW6@_8dS>h2i`7k$KK;Y&GSeeL^iojCHfU z!QTaqR|Lw!QKp_`Kzmt7PY>8ur3ZI_(?S$xJuVN_18Bq$U)x{3#l;0prgpn>O@n5~ zK?r<&`Dpnd+#eq@x$Cj{lGf(tG<9^2AyTt6=>$NnRNIG`66LigD1c}k9UlW+bQimK1wlev#_C=QN6O*_*dL|4*}>RQ$2i$r47_Q)Y@$Rs0SK%4Vxi+f{i($_lzlbYu;7m6;i*aR#GW}A_!GLx> zsP^SYUnkfOA)NL8 zTH9}s(ZKP%bwQrKJVLkA$YUbUe(RQ%jm@A=rxD5AY0bI}P0c4uOV1((K5)ULz0FufEP$RVsr!Ua2W#JGKF2=y&hPJd^>izNz$x1zvJr zP7aJVh`OYTyZ0QmHG#MSk{(|0S5UU0TaAXRt|I;r1q3*80pwbr%N=YKz*_!K@`kJd zd(ExN-fAKYDcXUq4Tme#t@!f&`*%<^YHDcfC$%{fbPIa`jK;*ku7-ddFg&-lCthEe zct`EVvOMq~{=)YDZG60$BigqYRwes~JcjJW-aj$~jYZCm-f`Po3hF4}PjnmV#Xec(}NI3{A%;C#q>;6}eH@Atu5<5MFpl({pja z>ibv0o1M2g&cG?-P#Q}xy@!k#J9vKeZ_@`4F-`4yuHlNZr$AQgPdCIVB3!p-?jBJ= zVig?$-|PxMgg##d2j68IgcKzNF2OvOx;%51c%MeZQ#l1cgUaJDT`vg^rUYg>5!?}w zuq7CZGc&LA^1c884-m4tnTu}dh~wdPTgu9TRUK?Yzw`ap2+E0x2@njxOt^RSlqhBN z+l#s4hKpoi>#*&l*wFTK{{vxGlo-4MKD}5Nlzq65U=@s(TU|>R0YidipURNYY;d5F z@>j-A>urk*GbVcapS9<&d+jzB@aHEN>?PK+GVaps45x4953-|0!fb zf)#UJM;}l%Ql1rGo)p7oD9|MVFK>YQvpkSv$~V^3g!borCWsiA7g*hsnrc-2+yn20OQnC4RiTIFro^mu^{}&n3Dg@bx04+~{AcJ=nhUyi_|y z*a3PR>>q(B)8bDOs;Fd`#gDN6LBbh+>$se9@SYKTi5&<*J67x0viM7fV*~A0k&$Tx zGZr?eJj@-eXvg(f^}w{Fhpj@;ex4foU`aDbc#t3@l$5z~cKa(sh(A~rkjGo^CxobL zrLE4rd-ouUeL;D5j}kkm$-K;!!8TSw%L+GWa00AID2D=n!q*RItTXW57YV2>Hbj=^ zyeHjg{S-%!rMoyBM|VXzH~I>#c-LR^15mNhQhoHxEn}5(oPeykxcsEnL1-Q;dc*nwNoRbvzr&Nc7=4N4ytI5`&;-X7< zTmHllbJd=g|GV%zi0b?KqsqM0ZulA`|MnoTje&r{sFVY;_!c!VOGrr*g&2dy|6dFS z4S`7u#nw$Ig^&$P*lzqEY(kox{Ewf^gIBxIoq`hqahW>?wWHuDF~=HF!5$34=$qwf z_^1$Wy-$rk*He!8&Dz~)-_sg>YzUjt>K0r|bb8eRcwI(hR8NKZgxhX+y)8dLn5EvwCTY7^Qy>EmF zlB6;WaaxNIdg}jj!5`GwAt<)}0ycLf$}zwAPrnD1`F}x_LU38-=_>v2oQ=uQp1gI2 zNDl0ah>D511k)B0LB$PM2bo|`AS%$r_V5rjvA^HIqhupBWS2JhVRrm|L))Y=SgJX$ z-sz^EMW1mBTu@N45(HW@HfCo0)r?VDZkiBdb##~T#)^BO{qY|$H0H7z-(8CIPiSn# z!qyuR($=&8Uz!GT+ZX7NMSAyGU&|_BW3W)6SEE3Uw4Z^+f(aztAZM=f z@ZoyrqtfxwCFjSxn>}uswH12b-RwU!g7JJv#25g4JCs7 zT#36ZCoTyWZ_s=0uH>>jqw-!Vw(0xCZO~>=Drz-zB|Fz%=|{Lbc<+{AOwwFAqdS z<{B9`nym(&5k|=nJb{F1+Mk%8SI%{r1rgi(G#|Judqs{;MMkRjxIYM?^SV%x)`f&T zd34c@otE_T!&UnVH7t3h>m)&75%(A0|LC}#a=cbrFQC9{cF`U3TRWkL^~PY-f}C6V zbdVm&YhOqo%+AjCAD;Py#U68N`-Lzcwq=QC_EPKjQ;9}C^?v!#AXsBZ(QuG_l{ZTwlP-$RB!`P>#oIYGrQ^n@WbQ>l!e^ z?~30;dqx1`C0IWyDm0onF?s%uyYjv9>+2Ef?B#zI`Ol~F{}ex*#Avi0aQw8U*o80U zGbTXIDD`z_xZ#cwsmbfCI*h3U>eRZBT<>ko`s|qg+d=Z*c&9Ay3ktdaWkENVJ*lBV z*)~oN61rlpD$~2|p)qGs6Ft`yx-Cf2ji2?&TB)~L(atVs`*3L%zoEO*X>uMzK6G1a zsqYcyU+MQ1b4C#6`20KAJ-sdTbiayeFiI#%P^EntV9Y}c8pr^>ADV)MtCrPC3`$SwQFx@iafhQPg9S zLoSQp2h)d!2pXoK+!1x)+DY^KoVk@v&hyR=5`p)^PSt8W&~GJ=%Z-X-#9^12h@wuZ z;l;#9^bEmr>L?X`(YUmibF+1Asv_UmzgP{&IETuNUcIMFvmv!XHNP&w!yQBfH8e-F z-Pd{UYP!=J%}7zqE07rQ&TlIxaH1h}VlE2OrSz(sHl*>ILh*U4BMgL+XIe46s?Dj3kENh)wqWp zm~^o9BSp}LqQDU}etj;=r#Q8R&CRkN=WEifePG6zA*F%cUZ$W7p@|WlRwOie*j4L3 z!&aDYIp9-GQCz9w0{vm{;9xi=q^KL34OHJ6hiR#~$EbWK91>hpzIvfH1v?N&AmY#* z6&AgA19$oVWC5c8fZ_`7iz~<8_V(CUGi5uw!WS<|B>Tt4MEwm~jNV{hbEE#k=)P9t zGCfo9Bk3#KLHz*ipuYgup>2Bi4agH8Dk}D2yK-9@*zy<%piP`76L3T@kv|#ELOAwi z1xdeq$dbQo_^s-P&*ol=yvsC%H50yB5xM2U_l;XQ{FbxB`xiJhSPE)t8RG6--e*h= z7bmx+V0%_^`{1(63HaT{3Z!!$FJB%ew=39reActu>Qh7y_yD&xJNsXpnpBdwyL~a? zbpn&10i&=ieK=w4C>MUk?7aRzkrmEC<(fybo}mgwK6hU%4;I~_#jG!vKK^%Y{Rh}_ zI&7*}dmtXtaI%sQdN6nxyJLErc|sBfl|o!xmto4j07qe`o#)G!fPp%Xm~f3>UFRSK z{{1}gw5ltA6R3(2ap3-P6~H2c>Ou#$Fo2GYVdat$lQ>~ zUt58U>){k>+Bh6O4$@}u(kU}Yj&qVBUPv79J_YhE?&i;ryW3yw9{N;&->Ilb$GBJ#h@zI>sIjgxiQ0?8%xu#q12 zK)8}ZrZ@ltr@(|5-NH!udUup(&a7g}k|%eKXsEMenf;X5dAzfmi_!|yCrBerJT_%{ z|CEMC_kQf0m!U&Y2`XYgEQDtK{^Z1K*Yg@qBz4V+hDrxi%nAqe0IC83A)%Aw{Zj=w z=jZZPGXkzY2>erEvnB z4&>fQNl6Jd5_tpbzF+r5zcmAaWcsIc8odsXrVKS=K1=S{q{nd!uETw1Ev7rXR!Eu-?4MrCYuPrAo_s zQ*z@%et3i1JQn-bC#}x{H?N5DBCs6{xK2iImC`D%_zl?Q@y`_xGjMct6eQMjJ+MI` z45SJIqN23x%5N|>BErMH9^=%!3!w<;YVZCPjSYq2NtX8e*S<_-cwusJl2`eXIAKrE z14Y?15zww+FE}=SLVP^%g(Fbl+E%MN(Sq-&sKG8Xy%FS<&vvoj`E5bLq5s8E zA#{T6P+e0~rd^PpjfOa0oE^tVoh)U=NbzY%!vhfBQj0IZH3&!sQ2m7#xHeVuRJ!il zH>#EUva*5OG?1c)C1%HB(Xr!Ed*#|qiIk)^o=$@Mp$Z#KJQ12W0VVkG7BjxFvfm(k zMm}KUuPSch9O%2#q@UU)G8Zm0$_G*=+=E_&-aO6R$jJ&dt2Z14f|3C;+G+3*i?mjJ zj5)X+0QV%PDmovId1p=<&4^-}up>`pQffF(^$5eh6TH429h(<=u>;3Rwt$SV46a|0z-b&L14;!FkTMxoszlJ!&yI2BHZ8#|+I!tK{-y3B!)V#y~ZL`E} zGh7hR{~3IP2Z#(jp5W~bWg{gpL5o|B{o_K389@Ln(ka7!^7;^L%++nnDro6>U%mu( zH>HlFqGnLdP5$Mz)v&sVO--C$vJk`GC6o+!xwO7MRqTv|eFI!*!T0r$d$|szqp8 z8+pF?do(JWHg8NgXvX^g4G}59I6ya;4I(2YMK|p9@E(U21P@Eu`={TBO=J(^kXMvt ziTAP75f|(^83uh64GATp-#Iw=Q(}yAu|&VLFj#N!b37-*swMY_hMm) zpi%o=o*#bVw|3lt{o1gH0F`USV6TDUnG^r9u0cc6tDvNW7tt!_xxh(;T+owTTp$;As<-pX&Ge9dy+iu!BTQ0hN?W74 z5C~v;m-|7$b}k8wjj{1@4vL7`2P{QVP_0Dnf05kq9~sYKkoN5|DaAHAm3YC1kgBc6Ut}>_Dx43y&bG&}BrR4S~Lq zB49;&A;bl;y0x|LH^)r30abLHT9)7 zSS1DqM7y-5n(d`b0|GT9W+({?>-Ar;6!cI9q8_Uhc`X7R3!{DTK`Rpn((_(8k4Vqu`9 z9le!9eZ7m=v(x7a3JS%8*Cg}gA?XZ345DK283BN;sZw&@d;E9^l0fM`h1pmXf~dz) z`4DXM!>;NpsWZRZr>CX)_`YUmvx7+ucZJFvUl zSrNip>48^|n3o?=I_NJ7_zF0D;U}l34Wp8sQBF~LoO$qFu#8W}Y9=E4wwi%g*QGLD zv@t>MtL?R)r7U7MzD_d;`#jaj_o;fl`)&5s%+}lLbb|55_4`a~;o!(aqCs;A;^sUA zWsMwGJUqgzpS0@S7rsPu)zYl_nJ$AQ-d~h&COsnQ%YPOOzPDQL%=7x0Ap8-C#mpQq zlN`WV8n%RD?40Xv>Uo%5-+iVaJFv4gg*@bPhaO9NLBp)@q=q`NoKa}T_GY{T_byS5!vIq_R0)RN#^-sS_xt@iH4PMT&!QYG!IntbK!cBY zK`9+YL~19XVug8;qM%~`I440YcKzsPoZV>^{iF<5#lY4+JAZm1RV&QK_g4E2S~1AT zfE7DKRENfV$-mZ3Oc~6>kPtzS?^Ta%qFB{RXM(LN4-?e{+7YB8wrw+?4EJ1t7B04rDc?mLbvBCvP=sQNTk3p$sJqDVNDQ7`DHllDIXJ)w zcQ4_sH19tSBl&{>^XF%Vy3;vj`(1i_7kV)#i5+CJo;`DW?-CFV3)&R;`*!n6N#2gi zUU|v;Z=i$j_KaE57@SA$mUWw>e}l^tXL>E+m+bI)nt_2;ilUJa0)?k*_tlC^aJ)-y zm*jhjnh$+of`)DEsFB>v7ex_PA#Zuv(D3{KuLT+Xp&a+W6f!#t$GI$v*ng_GlSViE z_WnJY;(yFqN)=sp0g5F@M@MkdIz9L#L*wD;`F@@az+q&Dp-KGZYB>(@(cU7$ZGWj- zSPk~6`TiQi-UPuinAPd@biRxw)^el|*%zZFLic8S-}rnds)%>(G3tel#C_9SY9ps0 zy#|i(?^u;tOB|QL%Si8zQ#l)_SAR}?75u7qg!O(;{_F{-lBA+PXEv*B|Kjquo98Wi zu@){hf52QC1VcbTkx}j#vAwLV9V6s@-fv*X`R-Eh-+pUKh2Uci1`bQhUtAGR-DzM# z5gPH*;H!r+1^fel$0dm!BxocJz1`eK z;SmPeN=TW0_KIr8&VMiX)~_a{)Og~=Vc$m%67T--D=$~rgTIs0#Wv#|&DhY;+4mjV zG`m#U*OR1=w11G~ul$i&c!IyE$!ipZeJ*fu9}Q3KwabT;&>zsCS{4$7i=#9g!tP=& zEH0frbd3^m?uZ*#mTI6@h=@>;^TB<;M#eC5RdUv>tC2gz|8PHv$X4uH9n&+^BIScQr^2t^ z)vz#RXP>^M4hEs%devE32uB{1?=rg~$OB_H2>nK{I9GhAujd>}g2-iTng;lK6~9*U zzRHh&{c|Kv4T2N>{lrHmx6AEEr$AK3$})h87v+n(t*I`*y}b>#MVQ3o8|wv?xW|Bd zk<7inhS9!l_po}{@UVT*vAk#LjXKe`Do2LGkmUUI#$Kz`fOCb{=(~kj`ioJK>Krpe z+%3{|lW&cL>&+kYiRzDfRza8=I2y*Ug|!QlhbAW@;MM?h*z+NbnOQ1Yh~Jd24Ql8& zuV1g3o@I{iiRs(bDL8`h!!^k?OsPfDAP9}%;rX0Zp=mGA&cV)}&dG=h9|_;A?`ZPw zI{LG+b!fLfGroLOE5WTVSdd>{E(4L`SFaLlZNQSYMSmJee)@E5YRbFZ5;|()lmg?| zaJ^F0AxLu9LSP+NyKi+iehYUJvz9N@pW=N?Z%Pk1_hD-jrOg20q*rx&kHC-75g5%dGCsaMv;isUuNv5#wKd-w5<&@2FsRsJVPSAJ zwCL$D#BaQybgm-}Sc}K z<8dPv6GMzs=FmkxVWTC*C<>L(gM}x4*xYgypCSe`hz}d;RgjqK$!Nlsqh0K$6 z$dVi__1trvwwrl+3VaB_W`pJjJ#)pzzd$hauX&+!B2Ht>M!tQIZ1;C)plmGv7s% z5Hqqu_}EjzM%{ID+s=x4BsTx#CK@I1XSOQHW+MKX z@tZGIRakF?p3%B|`A*Bsah|eej!&IEo<4R<%g~U%h4feWrBb)VJNMvQL!^JA4X^hI z*p!$9TT)5s(@0{XbS?mYyiP{JvazxP=nGFVVq~(M48a%G*VF~JZ~lwX*F=pC-AZSJ z_@-gbJGQgGS609;bi?CR703G=!s9g@r*~$D%|rDaHE(g-n&cTqM&52Pe{>EmTV5&} z#I@c)Xo6{r<2V=+lO2PDM`o~P#y<&SH0kjpeVr~#6jrDh_7d~DfMxTl%3Ucmx+6`( zphiWu8Lvj6nMmy6j^lk69Yr~SH@x5Ol|n-krxqt1+JNCu*oS9b@?8amE5{OlM#RZiDbRv zL0m>T;iP3GW3ZUBhCk1~G#b*n13%)pEwA$UM{k`~tXWRr9f%^(Rsf+A@5EX$YKy_F zj$V>XgI*Wz)je6xX5w~V;I0i>T3DP{RQw+?26%uaRB>!zjbXYS$Iq7R#41axx3=N< zd{Ko}i{t$db+AFexPNnV*XpyRbS@E2%nia*f(#VX&do4dUiMeoXQq&wF1Q^u6_Vhk zRga(0jx}SW_LsSiJgc zyd>pHIdK2!Q})}MkR#p{5LkjLJDorTU;h0&=Uia&vu9qi8PYT`^@x3Y z2-C-i0P~_jSd)cPL=+YGK#CwjMm(!vSPcZiOmx9hrNq_LvXE!(OS7ts{T9hpZ(z{L{6&+ zK6Id77#c#9n5uR-YMNLwtq7(@#l`o$v|ibNmDkkLrszLG{`J)Oe!gF7yyKMcg7oB!293`Mb|W0)7EJTo7yj+}+K^%}svn>;-i3NfwsVinzEx z>@cwg=Qf!H(8~i{cYWvTB&nwOL>So&F`eBE}@}vA0kUMt_akFW_OVKdrF3O;-9C5hfFVmmk*b> z&g2q(K?n>PqvlSbmeRBz#Ec)fH%bNj`I-tSZD!o%RK&H)$pJ6}uVrosa3@GAn2q-sQpFSznI1)~~tqCT>KCb*i*H?3gmx&Ott9pvfN)>l+ z58n`^r`bbq>F^LJ6I$|2MFHywJ4;sP%#O2oIZ>k;FU!y97yabP69~ZiDoTu<7(#29 zI<>+VNzpzi%SVWtX+j&OX0X_edKRh?+l!hHNceuS0XxmdhrZ-BDo%eOij!P(cu7K@{E!x%v5mXU-%H#UA~LKT*KTDA!gCyX51PrI1C?G=0_PQ-D4qCy%IOPkX zw5DOg9m_{9qf-N*6j0yz`T1Q$+Fj*g9VmJIT142ooZ_#8Zp_XU0S;29u#ewzes9C- z#wZOveRXy9@bEDC6>gT9WH;SAIZbO@rthtzDXwzT>A;*9(wj^1r#rD7aA-qPVTwYb zQwzVj-<41h%gDhN@MC@b?q5lZvlJ7u;0Nm5zsJpe;29DnI?AICpbIGXrBXT-Zt8B{ zo6dp}?PH(W$cTTCA5LM-JyBWp7P>!X$I^gt&6HH=CBz+;RDcKye920ev!XV5x6A&XLTM zE&`u(Jfx*zph2TaIc(MN2pn_c~80L*Gj%xx?!mqfbtiSmtq4Czi* zynp}IUYb)mI9VNr-)}$$fLPZv1M;nEOYuKNuv9|%M$;nB()GT2PW4Y4uagwsy^={V zrU5g%Wz~mzFb7tpAO2PE-vc7kQ1xUnap}Tv zH#PW3)yXIyHob`q-1?U9_U}1h36N>?TzwhR4~*N<|3pTryf_fNMDitCe@pMFdcBe; z3*pdgr2r}QSb2Jfl^wechOKe;$pDRuU~@~UZnJ5 z7CzospJn;joiJE!cPDF5A5vGb%|_PNmjhA7=3-Y@X`j4Gm|s|c-tJ`MJ7K5wy>ObA zUx9T;?!f0}L9i=hXWdEd^}_xuIfN&e?7X)wfqR;{rwfmdDlI*BWFvTZqU8;ijjvQl zEz96WfiiC(6Ls#115j0V80XyD`{{jSf&rcpicR%{t<{LY(ey@7X(jsklYv%X? zTw)#uQ1Rn+RrTg>V*oX|v75)J?AXD|OQ6f!a#O)AQhiDu^$_r`tP!@2;fl73XG#Z8c>Kr?p#mFdrKLEykG)pl zt^g!0+?V#O-wgvoDnOpcodes。编译ZEND_AST_DEFER_CALL节点时不能立即进行编译,需要等到当前脚本或函数全部编译完以后再进行编译,所以在编译过程需要把ZEND_AST_DEFER_CALL节点先缓存下来,参考循环结构编译时生成的zend_brk_cont_element的存储位置,我们也把ZEND_AST_DEFER_CALL节点保存在zend_op_array中,通过数组进行存储,将ZEND_AST_DEFER_CALL节点依次存入该数组,zend_op_array中加入以下几个成员: + +* __last_defer:__ 整形,记录当前编译的defer数 +* __defer_start_op:__ 整形,用于记录defer编译生成opcode指令的起始位置 +* __defer_call_array:__ 保存ZEND_AST_DEFER_CALL节点的数组,用于保存ast节点的地址 + +```c +struct _zend_op_array { + ... + int last_defer; + uint32_t defer_start_op; + zend_ast **defer_call_array; +} +``` +修改完数据结构后接着对应修改zend_op_array初始化的过程: +```c +//zend_opcode.c +void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_size) +{ + ... + op_array->last_defer = 0; + op_array->defer_start_op = 0; + op_array->defer_call_array = NULL; + ... +} +``` +完成依赖的这些数据结构的改造后接下来开始编写具体的编译逻辑,也就是编译ZEND_AST_DEFER_CALL的处理。抽象语法树的编译入口函数为zend_compile_top_stmt(),然后根据不同节点的类型进行相应的编译,我们在zend_compile_stmt()函数中对ZEND_AST_DEFER_CALL节点进行编译: +```c +void zend_compile_stmt(zend_ast *ast) +{ + ... + switch (ast->kind) { + ... + case ZEND_AST_DEFER_CALL: + zend_compile_defer_call(ast); + break + ... + } +} +``` +编译过程只是将ZEND_AST_DEFER_CALL的子节点(即:ZEND_AST_CALL)保存到zend_op_array->defer_call_array数组中,注意这里defer_call_array数组还没有分配内存,参考循环结构的实现,这里我们定义了一个函数用于数组的分配: +```c +//zend_compile.c +void zend_compile_defer_call(zend_ast *ast) +{ + if(!ast){ + return; + } + + zend_ast **call_ast = NULL; + //将普通函数调用的ast节点保存到defer_call_array数组中 + call_ast = get_next_defer_call(CG(active_op_array)); + *call_ast = ast->child[0]; +} + +//zend_opcode.c +zend_ast **get_next_defer_call(zend_op_array *op_array) +{ + op_array->last_defer++; + op_array->defer_call_array = erealloc(op_array->defer_call_array, sizeof(zend_ast*)*op_array->last_defer); + return &op_array->defer_call_array[op_array->last_defer-1]; +} +``` +既然分配了defer_call_array数组的内存就需要在zend_op_array销毁时释放: +```c +//zend_opcode.c +ZEND_API void destroy_op_array(zend_op_array *op_array) +{ + ... + if (op_array->defer_call_array) { + efree(op_array->defer_call_array); + } + ... +} +``` +编译完整个脚本或函数后,最后还会编译一条ZEND_RETURN,也就是返回指令,相当于ret指令,注意:这条opcode并不是我们在脚本中定义的return语句的,而是PHP内核为我们加的一条指令,这就是为什么有些函数我们没有写return也能返回的原因,任何函数或脚本都会生成这样一条指令。我们缓存在zend_op_array->defer_call_array数组中defer就是要在这时进行编译,也就是把defer的指令编译在最后。内核最后编译返回的这条指令由zend_emit_final_return()方法完成,我们把defer的编译放在此方法的末尾: +```c +//zend_compile.c +void zend_emit_final_return(zval *zv) +{ + ... + ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL); + ret->extended_value = -1; + + //编译defer call + zend_emit_defer_call(); +} +``` +前面已经说过,defer本质上就是函数调用,所以编译的过程直接复用普通函数调用的即可。另外,在编译时把起始位置记录到zend_op_array->defer_start_op中,因为在执行return前需要知道跳转到什么位置,这个值就是在那时使用的,具体的用法稍后再作说明。编译时按照倒序的顺序进行编译: +```c +//zend_compile.c +void zend_emit_defer_call() +{ + if (!CG(active_op_array)->defer_call_array) { + return; + } + + zend_ast *call_ast; + zend_op *nop; + znode result; + uint32_t opnum = get_next_op_number(CG(active_op_array)); + int defer_num = CG(active_op_array)->last_defer; + + //记录推迟的函数调用指令开始位置 + CG(active_op_array)->defer_start_op = opnum; + + while(--defer_num >= 0){ + call_ast = CG(active_op_array)->defer_call_array[defer_num]; + if (call_ast == NULL) { + continue; + } + nop = zend_emit_op(NULL, ZEND_NOP, NULL, NULL); + nop->op1.var = -2; + //编译函数调用 + zend_compile_call(&result, call_ast, BP_VAR_R); + } + //compile ZEND_DEFER_CALL + zend_emit_op(NULL, ZEND_DEFER_CALL_END, NULL, NULL); +} +``` +编译完推迟的函数调用之后,编译一条ZEND_DEFER_CALL_END指令,该指令用于执行完推迟的函数后跳回return的位置进行返回,opcode定义在zend_vm_opcodes.h中: +```c +//zend_vm_opcodes.h +#define ZEND_DEFER_CALL_END 174 +``` +还有一个地方你可能已经注意到,在逐个编译defer的函数调用前都生成了一条ZEND_NOP的指令,这个的目的是什么呢?开始的时候已经介绍过defer语法的特点,函数中定义的defer并不是全部执行,在return之后定义的defer是不会执行的,比如: +```go +func main(){ + defer fmt.Println("A") + + if 1 == 1{ + return + } + + defer fmt.Println("B") +} +``` +这种情况下第2个defer就不会生效,因此在return前跳转的位置就不一定是zend_op_array->defer_start_op,有可能会跳过几个函数的调用,所以这里我们通过ZEND_NOP这条空指令对多个defer call进行隔离,同时为避免与其它ZEND_NOP指令混淆,增加一个判断条件:op1.var=-2。这样在return前跳转时就根据此前定义的defer数跳过部分函数的调用,如下图所示。 + +![](../img/defer_call.png) + +到这一步我们已经完成defer函数调用的编译,此时重新编译PHP后可以看到通过defer推迟的函数调用已经被编译在最后了,只不过这个时候它们不能被执行。 + +__(3)编译return__ + From 5acabed4f5818e7c598073889762cfc264c3eb9a Mon Sep 17 00:00:00 2001 From: qinpeng Date: Sat, 8 Jul 2017 00:10:24 +0800 Subject: [PATCH 07/52] add defer --- try/defer.md | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) diff --git a/try/defer.md b/try/defer.md index 467ff8b..e496056 100644 --- a/try/defer.md +++ b/try/defer.md @@ -48,7 +48,7 @@ statement: 修改完这两个文件后需要分别调用re2c、yacc生成对应的C文件,具体的生成命令可以在Makefile.frag中看到: ```c $ re2c --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l -$ yacc -p ini_ -v -d Zend/zend_language_parser.y -oZend/zend_language_parser.c +$ yacc -p zend -v -d Zend/zend_language_parser.y -oZend/zend_language_parser.c ``` 执行完以后将在Zend目录下重新生成zend_language_scanner.c、zend_language_parser.c两个文件。到这一步已经完成生成抽象语法树的工作了,重新编译PHP后已经能够解析defer语法了,将会生成以下节点: @@ -140,7 +140,7 @@ void zend_emit_final_return(zval *zv) ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL); ret->extended_value = -1; - //编译defer call + //编译推迟执行的函数调用 zend_emit_defer_call(); } ``` @@ -172,7 +172,7 @@ void zend_emit_defer_call() //编译函数调用 zend_compile_call(&result, call_ast, BP_VAR_R); } - //compile ZEND_DEFER_CALL + //compile ZEND_DEFER_CALL_END zend_emit_op(NULL, ZEND_DEFER_CALL_END, NULL, NULL); } ``` @@ -201,4 +201,97 @@ func main(){ __(3)编译return__ +编译return时需要插入一条指令用于跳转到推迟执行的函数调用指令处,因此这里需要再定义一条opcode:ZEND_DEFER_CALL,在编译过程中defer call还未编译,因此此时还无法知道具体的跳转值。 +```c +//zend_vm_opcodes.h +#define ZEND_DEFER_CALL 173 +#define ZEND_DEFER_CALL_END 174 +``` +PHP脚本中声明的return语句由zend_compile_return()方法完成编译,在编译生成ZEND_DEFER_CALL指令时还需要将当前已定义的defer数(即在return前声明的defer)记录下来,用于计算具体的跳转值。 +```c +void zend_compile_return(zend_ast *ast) +{ + ... + //在return前编译ZEND_DEFER_CALL:用于在执行retur前跳转到defer call + if (CG(active_op_array)->defer_call_array) { + defer_zn.op_type = IS_UNUSED; + defer_zn.u.op.num = CG(active_op_array)->last_defer; + zend_emit_op(NULL, ZEND_DEFER_CALL, NULL, &defer_zn); + } + + //编译正常返回的指令 + opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, + &expr_node, NULL); + ... +} +``` +除了这种return外还有一种我们上面已经提过的return,即PHP内核编译的return指令,当PHP脚本中没有声明return语句时将执行内核添加的那条指令,因此也需要在zend_emit_final_return()加上上面的逻辑。 +```c +void zend_emit_final_return(zval *zv) +{ + ... + //在return前编译ZEND_DEFER_CALL:用于在执行retur前跳转到defer call + if (CG(active_op_array)->defer_call_array) { + //当前return之前定义的defer数 + defer_zn.op_type = IS_UNUSED; + defer_zn.u.op.num = CG(active_op_array)->last_defer; + zend_emit_op(NULL, ZEND_DEFER_CALL, NULL, &defer_zn); + } + + //编译返回指令 + ret = zend_emit_op(NULL, returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN, &zn, NULL); + ret->extended_value = -1; + + //编译推迟执行的函数调用 + zend_emit_defer_call(); +} +``` +__(4)计算ZEND_DEFER_CALL指令的跳转位置__ + +前面我们已经完成了推迟调用函数以及return编译过程的改造,在编译完成后ZEND_DEFER_CALL指令已经能够知道具体的跳转位置了,因为推迟调用的函数已经编译完成了,所以下一步就是为全部的ZEND_DEFER_CALL指令计算跳转值。前面曾介绍过,在编译完成有一个pass_two()的环节,我们就在这里完成具体跳转位置的计算,并把跳转位置保存到ZEND_DEFER_CALL指令的操作数中,在执行阶段直接跳转到对应位置。 + +```c +ZEND_API int pass_two(zend_op_array *op_array) +{ + zend_op *opline, *end; + ... + //遍历opcode + opline = op_array->opcodes; + end = opline + op_array->last; + while (opline < end) { + switch (opline->opcode) { + ... + case ZEND_DEFER_CALL: //设置jmp + { + uint32_t defer_start = op_array->defer_start_op; + //skip_defer为当前return之后声明的defer数,也就是不需要执行的defer + uint32_t skip_defer = op_array->last_defer - opline->op2.num; + //defer_opline为推迟的函数调用起始位置 + zend_op *defer_opline = op_array->opcodes + defer_start; + uint32_t n = 0; + + while(n <= skip_defer){ + if (defer_opline->opcode == ZEND_NOP && defer_opline->op1.var == -2) { + n++; + } + defer_opline++; + defer_start++; + } + + //defer_start为opcode在op_array->opcodes数组中的位置 + opline->op1.opline_num = defer_start; + //将跳转位置保存到操作数op1中 + ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1); + } + break; + } + ... + } + ... +} +``` +这里我们并没有直接编译为ZEND_JMP跳转指令,虽然ZEND_JMP可以跳转到后面的指令位置,但是最后的那条跳回return位置的指令(即:ZEND_DEFER_CALL_END)由于可能存在多个return的原因无法在编译期间确定具体的跳转值,只能在运行期间执行ZEND_DEFER_CALL时才能确定,所以需要在ZEND_DEFER_CALL指令的handler中将return的位置记录下来,执行ZEND_DEFER_CALL_END时根据这个值跳回。 + +__(5)定义ZEND_DEFER_CALL、ZEND_DEFER_CALL_END指令的handler__ + From a5b413ba145a80ef02ba48dd5200ce16021b25b0 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Sat, 8 Jul 2017 11:57:38 +0800 Subject: [PATCH 08/52] finish defer --- try/defer.md | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/try/defer.md b/try/defer.md index e496056..0a3230e 100644 --- a/try/defer.md +++ b/try/defer.md @@ -46,7 +46,7 @@ statement: ; ``` 修改完这两个文件后需要分别调用re2c、yacc生成对应的C文件,具体的生成命令可以在Makefile.frag中看到: -```c +```sh $ re2c --no-generation-date --case-inverted -cbdFt Zend/zend_language_scanner_defs.h -oZend/zend_language_scanner.c Zend/zend_language_scanner.l $ yacc -p zend -v -d Zend/zend_language_parser.y -oZend/zend_language_parser.c ``` @@ -294,4 +294,62 @@ ZEND_API int pass_two(zend_op_array *op_array) __(5)定义ZEND_DEFER_CALL、ZEND_DEFER_CALL_END指令的handler__ +ZEND_DEFER_CALL指令执行时需要将return的位置保存下来,我们把这个值保存到zend_execute_data结构中: +```c +//zend_compile.h +struct _zend_execute_data { + ... + const zend_op *return_opline; + ... +} +``` +opcode的handler定义在zend_vm_def.h文件中,定义完成后需要执行`php zend_vm_gen.php`脚本生成具体的handler函数。 +```c +ZEND_VM_HANDLER(173, ZEND_DEFER_CALL, ANY, ANY) +{ + USE_OPLINE + + //1) 将return指令的位置保存到EX(return_opline) + EX(return_opline) = opline + 1; + + //2) 跳转 + ZEND_VM_SET_OPCODE(OP_JMP_ADDR(opline, opline->op1)); + ZEND_VM_CONTINUE(); +} + +ZEND_VM_HANDLER(174, ZEND_DEFER_CALL_END, ANY, ANY) +{ + USE_OPLINE + + ZEND_VM_SET_OPCODE(EX(return_opline)); + ZEND_VM_CONTINUE(); +} +``` +到目前为止我们已经完成了全部的修改,重新编译PHP后就可以使用defer语法了: +```php +function shutdown($a){ + echo $a."\n"; +} +function test(){ + $a = 1234; + defer shutdown($a); + + $a = 8888; + + if(1){ + return "mid end\n"; + } + defer shutdown("9999"); + return "last end\n"; +} + +echo test(); +``` +执行后将显示: +```sh +8888 +mid end +``` +这里我们只实现了普通函数调用的方式,关于成员方法、静态方法、匿名函数等调用方式并未实现,留给有兴趣的读者自己去实现。 +完整代码:[https://github.com/pangudashu/php-7.0.12](https://github.com/pangudashu/php-7.0.12) From 8418b469b9c6dbf5d82a9ee17d5b094b1b590d62 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Sat, 8 Jul 2017 11:59:19 +0800 Subject: [PATCH 09/52] finish defer --- README.md | 1 + try/defer.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fcbe4d..0192d2d 100644 --- a/README.md +++ b/README.md @@ -106,4 +106,5 @@ ## 附录 * [附录1:break/continue按标签中断语法实现](try/break.md) + * [附录2:defer推迟函数调用语法的实现](try/defer.md) diff --git a/try/defer.md b/try/defer.md index 0a3230e..761d149 100644 --- a/try/defer.md +++ b/try/defer.md @@ -1,4 +1,4 @@ -# 附录2:defer推迟执行语法的实现 +# 附录2:defer推迟函数调用语法的实现 使用过Go语言的应该都知道defer这个语法,它用来推迟一个函数的执行,在函数执行返回前首先检查当前函数内是否有推迟执行的函数,如果有则执行,然后再返回。defer是一个非常有用的语法,这个功能可以很方便的在函数结束前执行一些清理工作,比如关闭打开的文件、关闭连接、释放资源、解锁等等。这样延迟一个函数有以下两个好处: From 06499a611175fa4b075cbfa0db3ef0ab15c88d25 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Fri, 14 Jul 2017 12:45:32 +0800 Subject: [PATCH 10/52] 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 11/52] =?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 12/52] 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 13/52] 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 14/52] 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 15/52] 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 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 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 16/52] 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 17/52] 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 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 KVyXOx!2bhw6w<%| From ddfbddd0dd901d3ce0e233cb3ba7dbd365e09ac2 Mon Sep 17 00:00:00 2001 From: qinpeng Date: Wed, 19 Jul 2017 15:25:34 +0800 Subject: [PATCH 18/52] 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 19/52] 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 20/52] 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 21/52] 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 22/52] 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 23/52] 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 24/52] 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 25/52] 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 26/52] 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 27/52] 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 28/52] 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 29/52] 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 30/52] 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 31/52] 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 32/52] 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 33/52] 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 34/52] 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 35/52] 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 36/52] 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 37/52] 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 38/52] =?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 39/52] 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 40/52] 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 41/52] 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 42/52] 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 43/52] 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 44/52] 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 45/52] 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 46/52] 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 47/52] 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 48/52] =?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 49/52] =?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 50/52] =?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 51/52] 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 52/52] 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]) ]) ```