Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
2016/12/11
第七回闇PHP勉強会
do_aki
1
updated 2016-12-13
このスライドは
• PHPカンファレンス2016で発表した
「PHP AST 徹底解説」 において説明し
きれなかった部分を補足した際に用いた
もの
• AST に関する部分については、元のスラ
イドにマージ済みなので
http://www.s...
@do_aki
@do_aki
http://do-aki.net/
PHPカンファレンス2016で
話したこと
PHP
Compiler in PHP
PHP Script
Opcode
Request
Output
Compiler
Lexing
Parsing
Compilation
VM
Execution
INCLUDE_OR_EVAL
php5 (1 pass / 151構文(5.6))
字句解析 + 構文解析 + Opcode生成
php7 (2 pass / 127構文(7.0))
字句解析+構文解析 Opcode生成
最適化の余地
PHP の
抽象構文木
<?php
1/(2+3);
種別
付属情報
子ノード
子ノード
token_get_all の話
token_get_all 関数
• PHP スクリプトを トークン分解して配列
にする関数
• nikic/PHP-Parser で利用されてる
• tokenizer 拡張 (デフォルトで有効)
7.0 からの変更
• 7.0 から第2引数に TOKEN_PARSE を指定で
きるようになった
– 指定なし: 字句解析のみ / 5.6 まで同様
– 指定あり: 構文解析もする / ast は破棄
• TOKEN_PARSE 指定でも O...
7.0.12 での実行例
token_name(319) => T_STRING
コンパイル と
token_get_all の関係
字句解析 構文解析 Opcode生成
狭義のコンパイルAST を生成トークンに分解
従来からの
token_get_all
TOKEN_PARSE 付きの
token_get_all
文字列結合 Opcode の話
ソースコード(php スクリプト)
<?php
function hello ( $name ) {
echo “HELLO $name“ ;
}
hello ( “php“ ) ;
Opcode (vld)
line #* E I O op fetch ext return operands
----------------------------------------------------------------
2...
Opcode (vld without xdebug)
line #* E I O op fetch ext return operands
---------------------------------------------------...
FAST_CONCAT
• encaps_list (変数を含む文字列) において、
要素が2つの時(変数の前後どちらかに文字列を加える時)
に FAST_CONCAT になる
(at zend_compile_encaps_list)
• 5...
"{$a} lines"
5.6
7.0
#* E I O op fetch ext return operands
------------------------------------------------------
0 E > AD...
"{$a} / {$b} lines"
5.6
7.0
#* E I O op fetch ext return operands
------------------------------------------------------
0...
parse しつつ opcode 生成し
ていた時に、これを導入するの
は困難だったはず
AST により、容易に導入できる
ようになった例かなと
strlen 静的展開の話
静的関数展開(定数化)
• 関数呼び出しコストの削減
• 定数畳み込みとの組み合わせも有効
ex: strlen(A::HOGE) + 1 -> 5
strlen(’hoge’) -> 4
ord(’A’) -> 65 / 7.1~
chr(6...
mbstring.func_overload
• strlen コールが mb_strlen に置き換わ
る
• EG(function_table) を操作して、上書
き
• コンパイル時に strlen が定数になって
しまうと機能しないの...
静的関数展開の無効化
• CG(compiler_options) に
ZEND_COMPILE_NO_BUILTINS ビットをセッ
トすることで静的関数展開を無効にできる
• CG(compiler_options) に
ZEND_COMP...
問題なかった
• mbstring 拡張の初期化(RINIT)時
func_overload が有効ならば
ZEND_COMPILE_NO_BUILTIN_STRLEN を
指定している
• func_overload は問題なく機能する
• ...
同じコードから異なるOpcodeが
生成される話
定数の畳み込み
$sec_in_day = 60 * 60 * 24;
$sec_in_day = 86400;
※実は OpCache でも行われている
class A { const HOGE = ‘hoge‘; }
echo A::HOG...
コンパイルタイミングによって
Opcode が変化する例
class A { const X = 1; }
a.php
require_once 'a.php';
echo A::X;
echo.php
require_once 'a.php'...
line #* E I O op fetch ext return operands
-----------------------------------------------------------
2 0 E > INCLUDE_OR_...
HHVM の話
HHVM におけるコンパイル
• 2つのLexer (yylex)
Compiler5lex/Compiler7lex
• 2つのParser (yyparse)
HPHP::Compiler::Parser::parseImpl5
HPHP:...
HHVM における AST
• AST ノードの基底クラスである
HPHP::Construct があり、Statement
と Expression に分かれる
• HPHP::Compiler::Parser::parseImpl
が、pa...
HPHP::Statement
• 構造を表すノードの
基本クラス
• HPHP::StatementList が
ZEND_STATEMENT_LIST に
相当
HPHP::Expression
• 評価式や値を表す
ノードの基本クラス
• AwaitExpression
あたりは hhvm なら
では
ast 操作拡張の話
php-ast
• https://github.com/nikic/php-ast
• astparse_file あるいは
astparse_code で AST 構築
• astNode をベースクラスとした astDecl
• リスト型...
astkit
• https://github.com/sgolemon/astkit
• AstKit::parseString あるいは
AstKit::parseFile で AST構築
• AstKit をベースクラスとした AstKi...
astparse_code('<?php 1 + 2;')
全ノードをphp スクリプトで扱える構造に変換 (CG(ast) は破棄)
C言語 (CG(ast))
array
astnode
kind: 520
flags: 1
lineno:...
Astkit::parseString('1+2;')
先頭のノードのみ生成。操作により子の AstKit が生成される
C language (CG(ast) =
astkit_tree->tree)
AstKitList
AST_ZVAL
...
それぞれの特徴
• php-ast
– php スクリプトから扱いやすい
– 初期のコストが大きめ
– 異なるバージョンでの変換処理を拡張側で頑張っ
てる部分もある
• astkit
– C の ast そのままのメモリを操作
– 利用する箇所...
おしまい
(blank)
PHP AST 徹底解説(補遺)
Upcoming SlideShare
Loading in …5
×

PHP AST 徹底解説(補遺)

4,253 views

Published on

第七回闇PHP勉強会

Published in: Technology
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/2F90ZZC ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Dating for everyone is here: ❤❤❤ http://bit.ly/2F90ZZC ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • DOWNLOAD FULL eBOOK INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc eBook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, CookeBOOK Crime, eeBOOK Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

PHP AST 徹底解説(補遺)

  1. 1. 2016/12/11 第七回闇PHP勉強会 do_aki 1 updated 2016-12-13
  2. 2. このスライドは • PHPカンファレンス2016で発表した 「PHP AST 徹底解説」 において説明し きれなかった部分を補足した際に用いた もの • AST に関する部分については、元のスラ イドにマージ済みなので http://www.slideshare.net/do_aki/p hp-ast を参照してください
  3. 3. @do_aki @do_aki http://do-aki.net/
  4. 4. PHPカンファレンス2016で 話したこと
  5. 5. PHP Compiler in PHP PHP Script Opcode Request Output Compiler Lexing Parsing Compilation VM Execution INCLUDE_OR_EVAL
  6. 6. php5 (1 pass / 151構文(5.6)) 字句解析 + 構文解析 + Opcode生成 php7 (2 pass / 127構文(7.0)) 字句解析+構文解析 Opcode生成 最適化の余地
  7. 7. PHP の 抽象構文木 <?php 1/(2+3); 種別 付属情報 子ノード 子ノード
  8. 8. token_get_all の話
  9. 9. token_get_all 関数 • PHP スクリプトを トークン分解して配列 にする関数 • nikic/PHP-Parser で利用されてる • tokenizer 拡張 (デフォルトで有効)
  10. 10. 7.0 からの変更 • 7.0 から第2引数に TOKEN_PARSE を指定で きるようになった – 指定なし: 字句解析のみ / 5.6 まで同様 – 指定あり: 構文解析もする / ast は破棄 • TOKEN_PARSE 指定でも Opcode 生成は省略 – zendparse を呼ぶが、 zend_compile_top_stmt は呼ばない – Syntax Error (例外) は発生するがCompile Error (Fatal) は発生しない – const A = f(); のようなコードも受け入れる
  11. 11. 7.0.12 での実行例 token_name(319) => T_STRING
  12. 12. コンパイル と token_get_all の関係 字句解析 構文解析 Opcode生成 狭義のコンパイルAST を生成トークンに分解 従来からの token_get_all TOKEN_PARSE 付きの token_get_all
  13. 13. 文字列結合 Opcode の話
  14. 14. ソースコード(php スクリプト) <?php function hello ( $name ) { echo “HELLO $name“ ; } hello ( “php“ ) ;
  15. 15. Opcode (vld) line #* E I O op fetch ext return operands ---------------------------------------------------------------- 2 0 E > EXT_NOP 1 RECV !0 3 2 EXT_STMT 3 NOP 4 FAST_CONCAT ~1 'Hello+', !0 5 ECHO ~1 4 6 EXT_STMT 7 > RETURN null line #* E I O op fetch ext return operands ---------------------------------------------------------------- 2 0 E > EXT_STMT 1 NOP 6 2 EXT_STMT 3 INIT_FCALL 'hello' 4 EXT_FCALL_BEGIN 5 SEND_VAL 'php' 6 DO_FCALL 0 7 EXT_FCALL_END 8 > RETURN 1 function hello() call hello()
  16. 16. Opcode (vld without xdebug) line #* E I O op fetch ext return operands ---------------------------------------------------------------- 2 0 E > RECV !0 3 1 NOP 2 FAST_CONCAT ~1 'HELLO+', !0 3 ECHO ~1 4 4 > RETURN null line #* E I O op fetch ext return operands ---------------------------------------------------------------- 2 0 E > NOP 6 1 INIT_FCALL 'hello' 2 SEND_VAL 'php' 3 DO_FCALL 0 4 > RETURN 1 function hello() call hello()
  17. 17. FAST_CONCAT • encaps_list (変数を含む文字列) において、 要素が2つの時(変数の前後どちらかに文字列を加える時) に FAST_CONCAT になる (at zend_compile_encaps_list) • 5.6 までは ADD_VAR + ADD_STRING • ちなみに 3要素以上ならば ROPE_INIT, ROPE_ADD, [ROPE_ADD,] ROPE_END
  18. 18. "{$a} lines" 5.6 7.0 #* E I O op fetch ext return operands ------------------------------------------------------ 0 E > ADD_VAR ~0 !0 1 ADD_STRING ~0 ~0, '+lines' #* E I O op fetch ext return operands ------------------------------------------------------ 0 E > NOP 1 FAST_CONCAT ~1 !0, '+lines'
  19. 19. "{$a} / {$b} lines" 5.6 7.0 #* E I O op fetch ext return operands ------------------------------------------------------ 0 E > ADD_VAR ~0 !0 1 ADD_STRING ~0 ~0, '+%2F+' 2 ADD_VAR ~0 ~0, !1 3 ADD_STRING ~0 ~0, '+lines' #* E I O op fetch ext return operands ------------------------------------------------------ 0 E > ROPE_INIT 4 ~3 !0 1 ROPE_ADD 1 ~3 ~3, '+%2F+' 2 ROPE_ADD 2 ~3 ~3, !1 3 ROPE_END 3 ~2 ~3, '+lines'
  20. 20. parse しつつ opcode 生成し ていた時に、これを導入するの は困難だったはず AST により、容易に導入できる ようになった例かなと
  21. 21. strlen 静的展開の話
  22. 22. 静的関数展開(定数化) • 関数呼び出しコストの削減 • 定数畳み込みとの組み合わせも有効 ex: strlen(A::HOGE) + 1 -> 5 strlen(’hoge’) -> 4 ord(’A’) -> 65 / 7.1~ chr(65) -> ‘A‘ / 7.1~
  23. 23. mbstring.func_overload • strlen コールが mb_strlen に置き換わ る • EG(function_table) を操作して、上書 き • コンパイル時に strlen が定数になって しまうと機能しないのでは? という疑問
  24. 24. 静的関数展開の無効化 • CG(compiler_options) に ZEND_COMPILE_NO_BUILTINS ビットをセッ トすることで静的関数展開を無効にできる • CG(compiler_options) に ZEND_COMPILE_NO_BUILTIN_STRLENビット をセットすることで strlen の展開のみを 無効にできる • 拡張ならば、 CG(compiler_options) を制 御可能
  25. 25. 問題なかった • mbstring 拡張の初期化(RINIT)時 func_overload が有効ならば ZEND_COMPILE_NO_BUILTIN_STRLEN を 指定している • func_overload は問題なく機能する • func_overload が有効だと、 strlen 展開による恩恵を受けられない
  26. 26. 同じコードから異なるOpcodeが 生成される話
  27. 27. 定数の畳み込み $sec_in_day = 60 * 60 * 24; $sec_in_day = 86400; ※実は OpCache でも行われている class A { const HOGE = ‘hoge‘; } echo A::HOGE; echo ‘hoge‘; コンパイル時点で定義済みの定数に対してのみ有効 (autoload より pre include のほうが効きやすい)
  28. 28. コンパイルタイミングによって Opcode が変化する例 class A { const X = 1; } a.php require_once 'a.php'; echo A::X; echo.php require_once 'a.php'; require_once 'echo.php'; require.php > php echo.php echo.php をコンパイルする時点 では a.php はコンパイルされて いない > php require.php echo.php をコンパイルする時点 で a.php はコンパイル済み
  29. 29. line #* E I O op fetch ext return operands ----------------------------------------------------------- 2 0 E > INCLUDE_OR_EVAL 'a.php', REQUIRE_ONCE 3 1 FETCH_CONSTANT ~1 'A', 'X' 2 ECHO ~1 3 > RETURN 1 line #* E I O op fetch ext return operands ----------------------------------------------------------- 0 E > INCLUDE_OR_EVAL 'a.php', REQUIRE_ONCE 3 1 ECHO 1 2 > RETURN 1 > php echo.php > php require.php (の時の echo.php)
  30. 30. HHVM の話
  31. 31. HHVM におけるコンパイル • 2つのLexer (yylex) Compiler5lex/Compiler7lex • 2つのParser (yyparse) HPHP::Compiler::Parser::parseImpl5 HPHP::Compiler::Parser::parseImpl7 • どちらも AST を生成する
  32. 32. HHVM における AST • AST ノードの基底クラスである HPHP::Construct があり、Statement と Expression に分かれる • HPHP::Compiler::Parser::parseImpl が、parseImpl7 あるいは parseImpl5 を呼び出し、 HPHP::Compiler::Parser::m_tree に StatementList が作られる
  33. 33. HPHP::Statement • 構造を表すノードの 基本クラス • HPHP::StatementList が ZEND_STATEMENT_LIST に 相当
  34. 34. HPHP::Expression • 評価式や値を表す ノードの基本クラス • AwaitExpression あたりは hhvm なら では
  35. 35. ast 操作拡張の話
  36. 36. php-ast • https://github.com/nikic/php-ast • astparse_file あるいは astparse_code で AST 構築 • astNode をベースクラスとした astDecl • リスト型のノード は Node に統合 • Zval型のノードは Node の exprプロパティ • STMT_LIST(A) の子要素に STMT_LIST(B) が含 まれる場合は、B の子を A の子として併合
  37. 37. astkit • https://github.com/sgolemon/astkit • AstKit::parseString あるいは AstKit::parseFile で AST構築 • AstKit をベースクラスとした AstKitList, AstKitDecl, AstKitZval にマッピングさ れる • $AstKit->export でコードに変換
  38. 38. astparse_code('<?php 1 + 2;') 全ノードをphp スクリプトで扱える構造に変換 (CG(ast) は破棄) C言語 (CG(ast)) array astnode kind: 520 flags: 1 lineno: 1 left: 1 right: 2 astNode kind: 133 flags:0 lineno: 0 children: AST_ZVAL 1 AST_ZVAL 2 AST_BINA RY_OP + AST_STMT _LIST ast_to_zval php スクリプト (zval)
  39. 39. Astkit::parseString('1+2;') 先頭のノードのみ生成。操作により子の AstKit が生成される C language (CG(ast) = astkit_tree->tree) AstKitList AST_ZVAL 1 AST_ZVAL 2 AST_BINA RY_OP + AST_STMT _LIST php script (zval) AstKit AstKitZval getChild(0) で生成 getChild(0,false) で生成 getChild(0) ならば int(1)
  40. 40. それぞれの特徴 • php-ast – php スクリプトから扱いやすい – 初期のコストが大きめ – 異なるバージョンでの変換処理を拡張側で頑張っ てる部分もある • astkit – C の ast そのままのメモリを操作 – 利用する箇所が部分的ならば低コストか – ast 構造の変化によって php 側での操作が大き く変わる
  41. 41. おしまい
  42. 42. (blank)

×