■Perl5 フレキシビリティ
Perl5 は全体的に hack ready な構造になっている。
PL_check で、コンパイルされた後の OP tree を変更可能だ。これにより任意の op tree 操作を挿入することができる。これにより autobox などの、syntax 的には正しいが op tree の解釈が違う、というような hack をすることができる。これ以外にも、任意の最適化を行うことができる。
PL_ppaddr をさしかえれば、任意の perl opcode の実行ルーチンをさしかえ可能だ。PL_ppaddr は opcode 番号をキーにした function pointer の配列である。Sys::Protect では、PL_ppaddr の中身をさしかえて安全性を担保している。Devel::SafeEval では pp_unpack をさしかえて、引数チェックを行い、'p' を防ぐことによって、peek を防いでいる。
PL_runops をさしかえれば、perl5 vm のメインループをさしかえ可能だ。PL_runops には関数ポインタがはいっている。デフォルトでは run.c にかいてある Perl_runops_standard() が入っているが、これは自由にさしかえられる。実際、dump.c の中には代替実装がはいっている。これはデバッグ用のトレーサが含まれた runops になっている。メインループが一回まわるたびになにかの処理をしたい、なんて場合にはここをフックすればいいだろう。
このように、様々なレベルで perl5 vmの挙動はフック可能だ。なかなかおもしろい。
だが、実際に色々な hack の対象になっているのはやはり PL_check だ。PL_check は autobox でその価値が認められ、Shibuya.pm の XS Nite で、それを利用した hack の有効性が国内外に広く認められるようになったというような経緯がある。
Perl5 の文法は強力だが、非常にナイーブなので、文法をいじらずに挙動を変えられるようというのは非常に魅力的なのだ。。。
PL_runops をつかったハックは、それよりは、より大局的であって、「This hack is cool!」と叫びたくなるような感じのものにはならないかもしれないけれど、なかなか楽しそうではある。
最後に、PL_runops を hack するコードのサンプルをのせておく。単純に、現在実行している PL_op の名前を表示するだけの簡単なものである。
Devel::BindPP をつかうと、こういう類のコードも楽にかけてよい。
#include "bindpp.h"
// see run.c in perl source
int my_runops (pTHX) {
while ((PL_op = CALL_FPTR(PL_op->op_ppaddr)(aTHX))) {
pl::IO::printf(pl::IO::stderr(), "%s\n", OP_NAME(PL_op));
if (PL_sig_pending) {
despatch_signals();
}
}
PL_tainted = FALSE;
return 0;
}
XS(boot_OreOre__VM) {
pl::BootstrapCtx bc;
PL_runops = my_runops; // PL_runops をさしかえる
}


