RHGの逆襲
自分用のメモ。YARVの実装の話
topにあるのとincludeの下の.hの差は? topにあるのは、外から使わせない。includeは使われることがある。 rb_vm_tってどこですか?最新版だとrb_vm_tが定義されている。 rb_vm_struct。 svn updateして自分のソースを最新版にする。 YARVはスタックマシンだ。 命令iseqでさしている $ ./ruby --dump=insn -e '1..3' == disasm: <RubyVM::InstructionSequence:<main>@-e>====================== 0000 trace 1 ( 1) 0002 putobject 1..3 0004 leave $ ./ruby --dump=insn -e '1..n' == disasm: <RubyVM::InstructionSequence:<main>@-e>====================== 0000 trace 1 ( 1) 0002 putobject 1 0004 putnil 0005 send :n, 0, nil, 24, <ic> 0011 newrange 0 0013 leave $ ./ruby --dump=insn -e 'n=3; 1..n' == disasm: <RubyVM::InstructionSequence:<main>@-e>====================== local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1) [ 2] n 0000 trace 1 ( 1) 0002 putobject 3 0004 setlocal n 0006 trace 1 0008 putobject 1 0010 getlocal n 0012 newrange 0 0014 leave vm.incを読む INSN_ENTRY(newrange){ { VALUE val; rb_num_t flag = (rb_num_t)GET_OPERAND(1); VALUE low = TOPN(1); VALUE high = TOPN(0); DEBUG_ENTER_INSN("newrange"); ADD_PC(1+1); PREFETCH(GET_PC()); POPN(2); #define CURRENT_INSN_newrange 1 #define INSN_IS_SC() 0 #define INSN_LABEL(lab) LABEL_newrange_##lab #define LABEL_IS_SC(lab) LABEL_##lab##_##t USAGE_ANALYSIS_INSN(BIN(newrange)); USAGE_ANALYSIS_OPERAND(BIN(newrange), 0, flag); { #line 608 "insns.def" val = rb_range_new(low, high, flag); #line 905 "vm.inc" PUSH(val); #undef CURRENT_INSN_newrange #undef INSN_IS_SC #undef INSN_LABEL #undef LABEL_IS_SC END_INSN(newrange);}}} answerの実装。 SUPPORT_JOKEを定義すればいい だめだ。というのは、id.hがvm_opts.hを#includeしていない。 $ svn diff id.h Index: id.h =================================================================== --- id.h (revision 20086) +++ id.h (working copy) @@ -27,6 +27,7 @@ #ifdef USE_PARSE_H #include "parse.h" #endif +#include "vm_opts.h" #define symIFUNC ID2SYM(idIFUNC) #define symCFUNC ID2SYM(idCFUNC) ということで、ruby 1.9 初パッチ $ ./ruby --dump=insn -e 'p the_answer_to_life_the_universe_and_everything' == disasm: <RubyVM::InstructionSequence:<main>@-e>====================== 0000 trace 1 ( 1) 0002 putnil 0003 answer 0004 send :p, 1, nil, 8, <ic> 0010 leave $ ./ruby -e 'p the_answer_to_life_the_universe_and_everything' 42