Opcodeのトレースを実装した
OpcodeのトレースにおいてAcme::Perl::VMで実装したOpcode traceを,普通のPerlでも実装した。これはperl(1)の-Dtsオプションを通常のPerlで実行できるようにし,さらに出力結果をより見やすくしたものと言える。
- Devel::Optrace - search.cpan.org
使用例:
$ perl -d:Optrace -e 'print "Hello, world!\n"' Entering RUNOPS (-e:1) () null SCALAR () const("Hello, world!\n") SCALAR ("Hello, world!\n") stringify SCALAR KIDS ("Hello, world!\n") Leaving RUNOPS (-e:1) Entering RUNOPS (-e:0) () enter () nextstate(main -e:1) VOID () pushmark SCALAR () const("Hello, world!\n") SCALAR ("Hello, world!\n") print VOID KIDS Hello, world! (YES) leave VOID KIDS PARENS () Leaving RUNOPS (-e:0)
perl(1)の-dオプションで指定すればコンパイルのタイミングからすべてトレースする。また,useしたあとDevel::Optrace->set(-all => 1)などとして実行時にトレース設定することもできる。出力はデフォルト(-all)だとRUNOPSの出入り(-runops),Opcodeトレース(-trace),引数スタック(-stack)のすべてを指定したのと同じになる。インデントはブロックの深さを表す。
なお,上記の例だとRUNOPS*1が二回行われていて,二度目のRUNOPSがメインプログラムの実行となっている。一度目のRUNOPS実行はおそらく定数畳み込みと関係がある。上記の例だと効果は不明だが,以下の例が分かりやすい。
$ perl -d:Optrace -e 'warn 1+2' Entering RUNOPS (-e:1) () const(1) SCALAR (1) const(2) SCALAR (1,2) add SCALAR KIDS (3) Leaving RUNOPS (-e:1) Entering RUNOPS (-e:0) () enter () nextstate(main -e:1) VOID () pushmark SCALAR () const(3) SCALAR (3) warn VOID KIDS 3 at -e line 1. (YES) leave VOID KIDS PARENS () Leaving RUNOPS (-e:0)
一度目のRUNOPSの実行はコンパイルフェーズに行われ,定数同士の加算を行う。二度目のRUNOPSの実行はメインプログラムの実行であり,引数スタックにプッシュするのは1+2の演算結果である3となっている。