php のソースコードを眺めていたときの雑多な流れ

前記事 「php 5.4 リポジトリに舞い戻ってきたクロージャの $this サポート - do_akiの徒然想記」 を書くきっかけとなった経緯とか、その周辺の調べたことを、備忘録的に書き記しておく。

乱文だし、尻切れトンボな感じだけど、せっかく調べたならオープンなところに置いといた方が良いかなと思って。

restore $this support for closures to its former glory

phpリポジトリを覗いていて、ふと目にとまった Revision.298187 *1
クロージャの中で $this を使えるようにする修正。

Author:	stas
Date:	Mon Apr 19 19:45:03 2010 UTC (15 months, 1 week ago)
Changed paths:	23
Log Message:	restore $this support for closures to its former glory

このdiffの中で、従来の クロージャ生成文法 function(){} に加えて、 static function(){} という文法が加わっていた *2 ので、これは何だ? と思い調査してみることにした。

従来のクロージャ と static付きのクロージャ

二つの違いは、zend_do_begin_lambda_function_declaration の第4引数が 0 か 1 かというだけ。
zend_do_begin_lambda_function_declaration は、 Zend/zend_compile.c で定義され、やはり同コミットで変更が加えられていた。*3

違いは、 その第4引数 is_static が 真ならば CG(active_op_array)->fn_flags |= ZEND_ACC_STATIC; をしていると言うことだけ。


CG は、 Zend/zend_globals_macros.h に定義された compiler_globals のメンバを取り出すためのマクロ。
active_op_array (struct _zend_op_array)が何なのかは厳密には分からないが、 おそらく現在読み込み中のスコープに属するオペコード群を格納しておく変数だと思う。


現在のスコープ = 現在の関数 ということだと思うので、 fn_flags は名前の通り関数自身の属性フラグということであり、どうやら、Zend/zend_compile.h に定義された ZEND_ACC_XXX が入るらしい。


つまり、 static function(){} は、 function(){} に static 属性をつけただけと言うことになる。


ところで、 php で static な function というのは、 クラス内メソッドでしか定義できない。
とすると、これが生きてくるのはクラス内で定義された クロージャだと想像できる。 (もともと $this を使えるようにするコミットに含まれているんだから当然だぁね)



そんなこんなで、色々調べてみたけど、結局 static なクロージャ の存在意義は$this の分のメモリを省略できるということくらいのよう。

https://wiki.php.net/rfc/closures の Interaction with OOP の最後の方にも書かれているし。

なんか、いろいろ調べたけど、分かったのがこんだけってのはちと悔しかったりする。