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