ext_skel の 雛形ファイルは php7 でどう変わったか

この記事は 闇PHP Advent Calendar 2015 9日目 です



先日の 闇PHP勉強会で、 ext_skel スクリプトで生成される雛形って、ほとんど更新されてないのでは 的な話をしたので、気になって調べてみました。

上は php-5.6.16 と php-7.0.0 の skelton.c の diff です。

大きく分けて3種類の変更が入っています。


1. PHP_FUNCTION(confirm_extname_compiled) の処理
2. TLS キャッシュ の処理
3. コメント行の行末空白の除去


3は見ればわかるので、 1 と 2 について少し詳しく見ていきましょう。

PHP_FUNCTION(confirm_extname_compiled)

まず、ZTS 絡みではありますが zend_parse_parameters の引数から TSRMLS_CC が消えました。(13行目)
これは、雛形ファイルに限らず、 php-7.0.0 への変更において最も多くの diff を作った変更の一つでしょう。


文字列の結合処理が spprintf から strpprintf へ変更されています。(19行目)
ともに main/spprintf.c で定義されている関数ですが、 strpprintf は 7.0.0 で新たに追加されたものです。

spprintf が、 第一引数で渡した char* にヒープを割り当てて文字列を格納するのに対し、
strpprintf は 生成した zend_string へのポインタを返すようになっています。


従来は RETURN_STRINGL を duplicate 0 (第三引数) で呼ぶことで、zval.str.val に char* を zval.str.len にその長さを割り当てていたところが、RETURN_STR になって 生成された zend_string を zval.str に割り当てるようになりました。(21行目)

ちなみにこの RETURN_STRINGL マクロは php 5.6系までは 4つの引数を取る関数マクロでしたが、 php 7 では 3つの引数に変更されていて、この変更が拡張開発者の頭を悩ませる要因の一つになっています。

zend_string が char 配列 へのポインタを保持するのではなく、zend_string (可変長)構造体に文字列のメモリを確保するため、メモリコピーを発生させずに zval を作ることができないからではないかと推測しますが、それでも、同じ関数(マクロ)名でインターフェースを変えるのはさすがにどうかと思う。。。

TLS キャッシュ

TLS とは Thread Local Storage のことで、 ここでは ZEND_TSRMLS_CACHE_DEFINE() (57行目) と ZEND_TSRMLS_CACHE_UPDATE() (47行目) が新たに呼ばれるようになりました。

ZEND_TSRMLS_CACHE は ZEND の TSRM (Thread Safe Resource Manager) の LS (Local Storage) の キャッシュという意味で、php7 における TLS 関連の変更については https://wiki.php.net/rfc/native-tls を参照してください。

php 処理系に含まれるコードのほとんどから TSRMLS_* マクロが消えたのは この変更によるものです。


1. TLS を利用するためのキーとなる変数を、従来はすべての関数の引数で受け渡ししていたのを、キーを必要な時だけ取得するようにした。
2. ただしそれだどリソースにアクセスする頻度が上がるほどパフォーマンスが落ちるので、取得したキーをキャッシュするようにした


という認識ですけど、ちゃんとは追ってないので推測の域を出ません。(詳しい方いたら解説お願いしたいです)

まとめ

skelton.c の変更から php-7.0.0 における変更点を確認しました。

zend_string にしても、 TLS にしても、php 全体に関わる変更を行っていて、php 開発陣には頭の下がる思いですね。