Ruby1.9/YARVコードへのコンパイルを読む
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
#contents
*はじめに [#kc039f01]
ここでは[[スクリプト解析>Ruby1.9/スクリプト解析を読む]]で...
*ruby_exec_node(eval.c) [#i1d8df00]
スクリプトの解析が終わると解析したNODEツリーを引数にruby_...
*rb_iseq_new(iseq.c) [#ffb39234]
rb_iseq_new関数は最終的にrb_iseq_new_with_bopt_and_opt関...
VALUE iseq = rb_iseq_new(n, rb_str_new2("<main>"),
rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP);
rb_iseq_new(NODE *node, VALUE name, VALUE filename,
VALUE parent, VALUE type)
{
return rb_iseq_new_with_opt(node, name, filename, pa...
&COMPILE_OPTION_DEFAULT);
}
static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimizat...
OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimizat...
OPT_SPECIALISED_INSTRUCTION, /* int specialized_inst...
OPT_OPERANDS_UNIFICATION, /* int operands_unificatio...
OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_un...
OPT_STACK_CACHING, /* int stack_caching; */
OPT_TRACE_INSTRUCTION, /* int trace_instruction */
};
vm_opts.h
#define OPT_INLINE_CONST_CACHE 1
#define OPT_PEEPHOLE_OPTIMIZATION 1
#define OPT_TAILCALL_OPTIMIZATION 0
#define OPT_SPECIALISED_INSTRUCTION 1
#define OPT_OPERANDS_UNIFICATION 0
#define OPT_INSTRUCTIONS_UNIFICATION 0
#define OPT_STACK_CACHING 0
#define OPT_TRACE_INSTRUCTION 0
rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filen...
VALUE parent, VALUE type,
const rb_compile_option_t *option)
{
return rb_iseq_new_with_bopt_and_opt(node, name, fil...
Qfalse, option);
}
rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VA...
VALUE parent, VALUE type, VALUE bopt,
const rb_compile_option_t *option)
{
*iseq_compile(compile.c) [#a2784d0f]
コンパイル処理のエントリーポイントとなる関数はiseq_compil...
**iseq_compile_each(compile.c) [#y62a3f9b]
コンパイルのメイン処理です。NODEのタイプに応じてYARVコー...
**new_child_iseq(compile.c) [#mb2cf0c6]
NODE_CLASSやNODE_DEFNに行き当たるとマクロ経由でnew_child_...
**LINK_ELEMENT(compile.c) [#ye41f82b]
compile.cを読んでいるとNODEを変換した結果のYARVコードやラ...
**ADD_INSNファミリー(compile.h) [#hc7287bf]
YARVコードを追加するのにはADD_INSNマクロファミリーが使わ...
ADD_INSN1(ret, nd_line(node), setlocal, INT2FIX(idx));
#define ADD_INSN1(seq, line, insn, op1) \
ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, lin...
iseqは関数の引数で渡されたrb_iseq_t*
new_insn_body関数はargc引数で指定された数の追加引数を受け...
new_insn_core関数はcompile_data_alloc_insn関数(compile_d...
|VALUE||idx|
|int|link.type|ISEQ_ELEMENT_INSN|
|LINK_ELEMENT*|link.prev|一つ前の要素|
|LINK_ELEMENT*|link.next|0(自分がリストの最後)|
|int|insn_id|setlocal|
|int|line_no|line_no|
|int|operand_size|1|
|int|sc_state|0|
|VALUE*|operands|引数領域へのポインタ|
**ADD_SEND_R(compile.h) [#h10c86c8]
メソッド呼び出しにはADD_SEND_Rマクロが使われています。
#define ADD_SEND_R(seq, line, id, argc, block, flag) \
ADD_ELEM(seq, (LINK_ELEMENT *) \
new_insn_send(iseq, line, \
(VALUE)id, (VALUE)argc, (VALUE)...
new_insn_send関数は引数を指定してnew_insn_core関数を呼びs...
メソッドのシンボル表現
引数の数
ブロックを示すInstructionSequenceオブジェクト
フラグ
0
*iseq_setup(compile.c) [#w38e2974]
iseq_compile関数の最後でiseq_setup関数が呼ばれています。...
**iseq_optimize(compile.c) [#v50a320f]
この関数はコンパイルオプションに応じてYARVコードの最適化...
***iseq_peephole_optimize(compile.c) [#yfce3178]
この関数ではjump命令のすぐ次にあるラベルに飛ぶ意味のないj...
***iseq_specialized_instruction(compile.c) [#r333969a]
この関数では演算子メソッドなどのよく出現するsend命令を専...
***insn_operands_unification(optinsn.inc) [#d74e5b72]
この関数は・・・何もやってない?おそらくvm_opts.hのコンパ...
***iseq_insns_unification(compile.c) [#v0f88a40]
実際にはこの関数はiseq_optimize関数から呼び出されていませ...
***iseq_set_sequence_stackcache(compile.c) [#y8413dc6]
この関数も同様にiseq_optimize関数からではなくiseq_setup関...
**iseq_set_sequence(compile.c) [#t80f2ed5]
この関数で作業領域に置かれていたYARVコードがrb_iseq_t構造...
まずLINK_ELEMENTをスキャンして各命令の命令長と命令の数を...
次にもう一度LINK_ELEMENTをスキャンし確保したメモリに命令...
**iseq_set_exception_table(compile.c) [#j86d4e5e]
この関数ではコンパイル時にADD_CATCH_ENTRYマクロで追加され...
**iseq_set_optargs_table(compile.c) [#y80d323c]
この関数ではデフォルト値付き引数の設定情報をrb_iseq_t構造...
* def foo(a, b=expr1, c=expr2)
* =>
* b:
* expr1
* c:
* expr2
つまり、b引数が設定されていなかったらbラベルに飛んでexpr1...
**iseq_translate_threaded_code(compile.c) [#v9cf13b5]
この関数では設定した命令コードをより実行に適した形に変換...
ところでvm_eval関数は2引数なのですがcompile.cからは1引数...
*VM::InstructionSequence [#tc43a103]
手動コンパイルした結果が合っているか調べるには実際にコン...
puts VM::InstructionSequence.compile_file(file).disasm
とするとfileで指定したスクリプトがコンパイルされ、YARVコ...
なお、デフォルトでは最適化されたものが出てくるので最適化...
VM::InstructionSequence.compile_option = false
とすると最適化が行われません。なお、inline_const_cacheは...
VM::InstructionSequence.compile_option = {:inline_const_...
とするとinline_const_cacheを有効にできます。
*コンパイルしてみる [#pc4f900c]
実際にNODEをコンパイルしてみると動きがよくわかるでしょう...
**NODE_SCOPE [#kd7e932a]
NODEツリーの頂点はNODE_SCOPEです。というわけでiseq_compil...
local_table = ID("n"), ID("pi")
local_table_size = 2
local_size = 2 + 1
次にiseq_set_arguments関数が呼ばれますが引数はないのでels...
arg_simple = 1
次のswitch文ではISEQ_TYPE_TOPなので単純にCOMPILEマクロが...
どのような引数が渡されるのか見てみましょう。
COMPILE(ret, "scoped node", node->nd_body);
#define COMPILE(anchor, desc, node) iseq_compile_each(is...
iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NOD...
一連のコンパイルが終わると最後にleaveが追加されます。
**NODE_BLOCK [#m681f07e]
NODE_BLOCKのそれぞれの要素に対してCOMPILE_マクロ(先ほど...
**NODE_CLASS [#q86755b4]
ブロックの一番初めはNODE_CLASSなのでNODE_CLASSの処理に移...
#define NEW_CHILD_ISEQVAL(node, name, type) new_child_is...
node = NODE_SCOPE
name = "<class:MonteCarlo>"
type = ISEQ_TYPE_CLASS
次にcompile_cpath関数が呼ばれています。cpathはNODE_COLON2...
次にnode->nd_superが指定してCOMPILEマクロが呼ばれますがnd...
その後、defineclass("MonteCarlo", iseqval, 0)が追加されま...
最後にpopedが1なのでpopが追加されます。
**NODE_DEFN [#r77970eb]
new_child_iseq関数が呼ばれることでrb_iseq_new_with_opt → ...
#define NEW_ISEQVAL(node, name, type) new_child_iseq(ise...
node = NODE_SCOPE
name = "pi"
type = ISEQ_TYPE_METHOD
次にputnilが追加されます。
次にdefinemethod("pi", iseqval, 0)が追加されます。
最後にpopedが0なのでputnilが追加されます。
***iseq_set_arguments [#a9095fa8]
というわけでまた再帰呼び出しされてiseq_compile関数に来ま...
argc = 1
arg_opts = 0
arg_simple = 1
arg_size = 1
**NODE_LASGN [#n345a649]
それではNODE_DEFN以下のコンパイルに進みましょう。まずNODE...
get_local_var_idx関数を実行することで変数のIDがlocal_tabl...
次にrhsを指定してCOMPILEマクロが実行されます。NODE_LITな...
最後にsetlocal(3 - 1)が追加されます。
**NODE_ITER [#w5300eff]
NODE_BLOCKの次の要素はNODE_ITERです。まずブロックの先頭に...
次にブロックのNODEツリーを引数にNEW_CHILD_ISEQVALマクロが...
node = NODE_SCOPE
name = "block in pi"
type = ISEQ_TYPE_BLOCK
次にメソッド呼び出しの部分((1..n).each)がCOMPILEマクロ...
次にブロックを抜けるためのラベルが追加されます。
次にpopedが1なのでpopが追加されます。
最後にADD_CATCH_ENTRYマクロを使用してcompile_data->catch_...
**NODE_DASGN_CURR [#kd7e632c]
ブロックの初めのNODE_BLOCKはNODE_DASGN_CURR(x = rand)です...
変数のIDからインデックスを取得するのにget_dyna_var_idx関...
最後にsetdynamic(2 - 0, 0)が追加されます。
**NODE_VCALL [#c9ccf2e8]
rhsはNODE_VCALLです。SUPPORT_JOKEは飛ばして:-)、まずレシ...
次に引数の設定ですがNODE_VCALLなので何も追加されません。
その後、flagにVM_CALL_VCALL_BITとVM_CALL_FCALL_BIT(コメ...
**NODE_IF [#j5021ec2]
まずnode->nd_condがコンパイルされます。NODE_CALLなのでそ...
次にbranchunless(elseラベル)とjump(thenラベル)が追加され...
次にthenラベルが追加され、thenの部分をコンパイル、jump(en...
次にelseラベルが追加され、elseの部分がコンパイルされます。
最後にendラベルが追加されます。
**NODE_CALL [#a4029ca5]
条件部はNODE_CALL(x * x + y * y <= 1)です。NODE_VCALLに似...
まずレシーバがCOMPILEマクロにかけられます。レシーバ(x * x...
次にsetup_args関数が呼ばれて引数が追加されます。引数はNOD...
その後、ADD_SEND_Rマクロが呼ばれてsendが追加されます。
**NODE_DVAR [#s7a45d64]
次にレシーバ部を何回か再帰してNODE_DVAR(x)に行き着きます...
**NODE_DOT2 [#c8ed3128]
始点(1)と終点(n)がCOMPILEマクロにかけられ、その後にnewran...
**NODE_CALL(poped = 0) [#leee1b74]
メソッド定義の最後のNODE_BLOCKはNODE_CALLです。popedが0な...
**NODE_CONST [#h78d78a7]
しばらくは既存の知識でどうにかなるとして、NODE_CONST(Mont...
:開始ラベル
getinlinecache(0, 終了ラベル)
getconstant(:MonteCarlo)
setinlinecache(開始ラベル)
:終了ラベル
見てわかるようにキャッシュされてたらgetconstantがバイパス...
**NODE_DSTR [#c449b184]
最後にNODE_DSTR("pi = #{pi}")です。compile_dstr関数が呼ば...
compile_dstr関数ではまずputobject("pi = ")が追加されます...
**コンパイル結果 [#h12893f3]
というわけでNODEからYARVコードへのコンパイルが完了しまし...
>>>>>>>> 識別名(他から参照される名前)
rb_iseq_tの変数値
**** code
YARV擬似コード
引数あり命令(引数1, 引数2, ...)
:ラベルはこう書かれている
<<<<<<<< 識別名
&ref(montecarlo.yarv.txt);
&ref(montecarlo.yarv.opt.txt);
*おわりに [#xf5bf5db]
今回はNODEツリーからYARVコードへのコンパイルを見てきまし...
それでは[[コードの実行>Ruby1.9/YARVコードの実行を読む]]へ...
終了行:
#contents
*はじめに [#kc039f01]
ここでは[[スクリプト解析>Ruby1.9/スクリプト解析を読む]]で...
*ruby_exec_node(eval.c) [#i1d8df00]
スクリプトの解析が終わると解析したNODEツリーを引数にruby_...
*rb_iseq_new(iseq.c) [#ffb39234]
rb_iseq_new関数は最終的にrb_iseq_new_with_bopt_and_opt関...
VALUE iseq = rb_iseq_new(n, rb_str_new2("<main>"),
rb_str_new2(file), Qfalse, ISEQ_TYPE_TOP);
rb_iseq_new(NODE *node, VALUE name, VALUE filename,
VALUE parent, VALUE type)
{
return rb_iseq_new_with_opt(node, name, filename, pa...
&COMPILE_OPTION_DEFAULT);
}
static rb_compile_option_t COMPILE_OPTION_DEFAULT = {
OPT_INLINE_CONST_CACHE, /* int inline_const_cache; */
OPT_PEEPHOLE_OPTIMIZATION, /* int peephole_optimizat...
OPT_TAILCALL_OPTIMIZATION, /* int tailcall_optimizat...
OPT_SPECIALISED_INSTRUCTION, /* int specialized_inst...
OPT_OPERANDS_UNIFICATION, /* int operands_unificatio...
OPT_INSTRUCTIONS_UNIFICATION, /* int instructions_un...
OPT_STACK_CACHING, /* int stack_caching; */
OPT_TRACE_INSTRUCTION, /* int trace_instruction */
};
vm_opts.h
#define OPT_INLINE_CONST_CACHE 1
#define OPT_PEEPHOLE_OPTIMIZATION 1
#define OPT_TAILCALL_OPTIMIZATION 0
#define OPT_SPECIALISED_INSTRUCTION 1
#define OPT_OPERANDS_UNIFICATION 0
#define OPT_INSTRUCTIONS_UNIFICATION 0
#define OPT_STACK_CACHING 0
#define OPT_TRACE_INSTRUCTION 0
rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE filen...
VALUE parent, VALUE type,
const rb_compile_option_t *option)
{
return rb_iseq_new_with_bopt_and_opt(node, name, fil...
Qfalse, option);
}
rb_iseq_new_with_bopt_and_opt(NODE *node, VALUE name, VA...
VALUE parent, VALUE type, VALUE bopt,
const rb_compile_option_t *option)
{
*iseq_compile(compile.c) [#a2784d0f]
コンパイル処理のエントリーポイントとなる関数はiseq_compil...
**iseq_compile_each(compile.c) [#y62a3f9b]
コンパイルのメイン処理です。NODEのタイプに応じてYARVコー...
**new_child_iseq(compile.c) [#mb2cf0c6]
NODE_CLASSやNODE_DEFNに行き当たるとマクロ経由でnew_child_...
**LINK_ELEMENT(compile.c) [#ye41f82b]
compile.cを読んでいるとNODEを変換した結果のYARVコードやラ...
**ADD_INSNファミリー(compile.h) [#hc7287bf]
YARVコードを追加するのにはADD_INSNマクロファミリーが使わ...
ADD_INSN1(ret, nd_line(node), setlocal, INT2FIX(idx));
#define ADD_INSN1(seq, line, insn, op1) \
ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, lin...
iseqは関数の引数で渡されたrb_iseq_t*
new_insn_body関数はargc引数で指定された数の追加引数を受け...
new_insn_core関数はcompile_data_alloc_insn関数(compile_d...
|VALUE||idx|
|int|link.type|ISEQ_ELEMENT_INSN|
|LINK_ELEMENT*|link.prev|一つ前の要素|
|LINK_ELEMENT*|link.next|0(自分がリストの最後)|
|int|insn_id|setlocal|
|int|line_no|line_no|
|int|operand_size|1|
|int|sc_state|0|
|VALUE*|operands|引数領域へのポインタ|
**ADD_SEND_R(compile.h) [#h10c86c8]
メソッド呼び出しにはADD_SEND_Rマクロが使われています。
#define ADD_SEND_R(seq, line, id, argc, block, flag) \
ADD_ELEM(seq, (LINK_ELEMENT *) \
new_insn_send(iseq, line, \
(VALUE)id, (VALUE)argc, (VALUE)...
new_insn_send関数は引数を指定してnew_insn_core関数を呼びs...
メソッドのシンボル表現
引数の数
ブロックを示すInstructionSequenceオブジェクト
フラグ
0
*iseq_setup(compile.c) [#w38e2974]
iseq_compile関数の最後でiseq_setup関数が呼ばれています。...
**iseq_optimize(compile.c) [#v50a320f]
この関数はコンパイルオプションに応じてYARVコードの最適化...
***iseq_peephole_optimize(compile.c) [#yfce3178]
この関数ではjump命令のすぐ次にあるラベルに飛ぶ意味のないj...
***iseq_specialized_instruction(compile.c) [#r333969a]
この関数では演算子メソッドなどのよく出現するsend命令を専...
***insn_operands_unification(optinsn.inc) [#d74e5b72]
この関数は・・・何もやってない?おそらくvm_opts.hのコンパ...
***iseq_insns_unification(compile.c) [#v0f88a40]
実際にはこの関数はiseq_optimize関数から呼び出されていませ...
***iseq_set_sequence_stackcache(compile.c) [#y8413dc6]
この関数も同様にiseq_optimize関数からではなくiseq_setup関...
**iseq_set_sequence(compile.c) [#t80f2ed5]
この関数で作業領域に置かれていたYARVコードがrb_iseq_t構造...
まずLINK_ELEMENTをスキャンして各命令の命令長と命令の数を...
次にもう一度LINK_ELEMENTをスキャンし確保したメモリに命令...
**iseq_set_exception_table(compile.c) [#j86d4e5e]
この関数ではコンパイル時にADD_CATCH_ENTRYマクロで追加され...
**iseq_set_optargs_table(compile.c) [#y80d323c]
この関数ではデフォルト値付き引数の設定情報をrb_iseq_t構造...
* def foo(a, b=expr1, c=expr2)
* =>
* b:
* expr1
* c:
* expr2
つまり、b引数が設定されていなかったらbラベルに飛んでexpr1...
**iseq_translate_threaded_code(compile.c) [#v9cf13b5]
この関数では設定した命令コードをより実行に適した形に変換...
ところでvm_eval関数は2引数なのですがcompile.cからは1引数...
*VM::InstructionSequence [#tc43a103]
手動コンパイルした結果が合っているか調べるには実際にコン...
puts VM::InstructionSequence.compile_file(file).disasm
とするとfileで指定したスクリプトがコンパイルされ、YARVコ...
なお、デフォルトでは最適化されたものが出てくるので最適化...
VM::InstructionSequence.compile_option = false
とすると最適化が行われません。なお、inline_const_cacheは...
VM::InstructionSequence.compile_option = {:inline_const_...
とするとinline_const_cacheを有効にできます。
*コンパイルしてみる [#pc4f900c]
実際にNODEをコンパイルしてみると動きがよくわかるでしょう...
**NODE_SCOPE [#kd7e932a]
NODEツリーの頂点はNODE_SCOPEです。というわけでiseq_compil...
local_table = ID("n"), ID("pi")
local_table_size = 2
local_size = 2 + 1
次にiseq_set_arguments関数が呼ばれますが引数はないのでels...
arg_simple = 1
次のswitch文ではISEQ_TYPE_TOPなので単純にCOMPILEマクロが...
どのような引数が渡されるのか見てみましょう。
COMPILE(ret, "scoped node", node->nd_body);
#define COMPILE(anchor, desc, node) iseq_compile_each(is...
iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NOD...
一連のコンパイルが終わると最後にleaveが追加されます。
**NODE_BLOCK [#m681f07e]
NODE_BLOCKのそれぞれの要素に対してCOMPILE_マクロ(先ほど...
**NODE_CLASS [#q86755b4]
ブロックの一番初めはNODE_CLASSなのでNODE_CLASSの処理に移...
#define NEW_CHILD_ISEQVAL(node, name, type) new_child_is...
node = NODE_SCOPE
name = "<class:MonteCarlo>"
type = ISEQ_TYPE_CLASS
次にcompile_cpath関数が呼ばれています。cpathはNODE_COLON2...
次にnode->nd_superが指定してCOMPILEマクロが呼ばれますがnd...
その後、defineclass("MonteCarlo", iseqval, 0)が追加されま...
最後にpopedが1なのでpopが追加されます。
**NODE_DEFN [#r77970eb]
new_child_iseq関数が呼ばれることでrb_iseq_new_with_opt → ...
#define NEW_ISEQVAL(node, name, type) new_child_iseq(ise...
node = NODE_SCOPE
name = "pi"
type = ISEQ_TYPE_METHOD
次にputnilが追加されます。
次にdefinemethod("pi", iseqval, 0)が追加されます。
最後にpopedが0なのでputnilが追加されます。
***iseq_set_arguments [#a9095fa8]
というわけでまた再帰呼び出しされてiseq_compile関数に来ま...
argc = 1
arg_opts = 0
arg_simple = 1
arg_size = 1
**NODE_LASGN [#n345a649]
それではNODE_DEFN以下のコンパイルに進みましょう。まずNODE...
get_local_var_idx関数を実行することで変数のIDがlocal_tabl...
次にrhsを指定してCOMPILEマクロが実行されます。NODE_LITな...
最後にsetlocal(3 - 1)が追加されます。
**NODE_ITER [#w5300eff]
NODE_BLOCKの次の要素はNODE_ITERです。まずブロックの先頭に...
次にブロックのNODEツリーを引数にNEW_CHILD_ISEQVALマクロが...
node = NODE_SCOPE
name = "block in pi"
type = ISEQ_TYPE_BLOCK
次にメソッド呼び出しの部分((1..n).each)がCOMPILEマクロ...
次にブロックを抜けるためのラベルが追加されます。
次にpopedが1なのでpopが追加されます。
最後にADD_CATCH_ENTRYマクロを使用してcompile_data->catch_...
**NODE_DASGN_CURR [#kd7e632c]
ブロックの初めのNODE_BLOCKはNODE_DASGN_CURR(x = rand)です...
変数のIDからインデックスを取得するのにget_dyna_var_idx関...
最後にsetdynamic(2 - 0, 0)が追加されます。
**NODE_VCALL [#c9ccf2e8]
rhsはNODE_VCALLです。SUPPORT_JOKEは飛ばして:-)、まずレシ...
次に引数の設定ですがNODE_VCALLなので何も追加されません。
その後、flagにVM_CALL_VCALL_BITとVM_CALL_FCALL_BIT(コメ...
**NODE_IF [#j5021ec2]
まずnode->nd_condがコンパイルされます。NODE_CALLなのでそ...
次にbranchunless(elseラベル)とjump(thenラベル)が追加され...
次にthenラベルが追加され、thenの部分をコンパイル、jump(en...
次にelseラベルが追加され、elseの部分がコンパイルされます。
最後にendラベルが追加されます。
**NODE_CALL [#a4029ca5]
条件部はNODE_CALL(x * x + y * y <= 1)です。NODE_VCALLに似...
まずレシーバがCOMPILEマクロにかけられます。レシーバ(x * x...
次にsetup_args関数が呼ばれて引数が追加されます。引数はNOD...
その後、ADD_SEND_Rマクロが呼ばれてsendが追加されます。
**NODE_DVAR [#s7a45d64]
次にレシーバ部を何回か再帰してNODE_DVAR(x)に行き着きます...
**NODE_DOT2 [#c8ed3128]
始点(1)と終点(n)がCOMPILEマクロにかけられ、その後にnewran...
**NODE_CALL(poped = 0) [#leee1b74]
メソッド定義の最後のNODE_BLOCKはNODE_CALLです。popedが0な...
**NODE_CONST [#h78d78a7]
しばらくは既存の知識でどうにかなるとして、NODE_CONST(Mont...
:開始ラベル
getinlinecache(0, 終了ラベル)
getconstant(:MonteCarlo)
setinlinecache(開始ラベル)
:終了ラベル
見てわかるようにキャッシュされてたらgetconstantがバイパス...
**NODE_DSTR [#c449b184]
最後にNODE_DSTR("pi = #{pi}")です。compile_dstr関数が呼ば...
compile_dstr関数ではまずputobject("pi = ")が追加されます...
**コンパイル結果 [#h12893f3]
というわけでNODEからYARVコードへのコンパイルが完了しまし...
>>>>>>>> 識別名(他から参照される名前)
rb_iseq_tの変数値
**** code
YARV擬似コード
引数あり命令(引数1, 引数2, ...)
:ラベルはこう書かれている
<<<<<<<< 識別名
&ref(montecarlo.yarv.txt);
&ref(montecarlo.yarv.opt.txt);
*おわりに [#xf5bf5db]
今回はNODEツリーからYARVコードへのコンパイルを見てきまし...
それでは[[コードの実行>Ruby1.9/YARVコードの実行を読む]]へ...
ページ名: