NODE_RESBODY
case NODE_RESBODY:{ NODE *resq = node; NODE *narg; LABEL *label_miss, *label_hit; while (resq) { ... resq = resq->nd_head; } break;
複数のrescue節がありうるので、一個一個順番にコンパイルしていきます。これは上にあるrescue節から順に命令列に変換して並べていくだけの処理です。YARVアーキテクチャに書いてあるイメージです。
具体的には各rescue節は、以下の命令列になります。
=== で比較 branchif label_hit jump label_miss label_hit: rescue の本体 leave label_miss:
例外をうまくrescueで捕まえたら、処理の本体を実行して、YARVのleave命令で抜けます。leaveで抜けると正常終了で、NODE_RESCUEのlcontに飛びます。
最後のlabel_missまで飛んでしまうと...
// iseq_compile 関数 if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) { ADD_INSN2(list_anchor, 0, getdynamic, INT2FIX(1), INT2FIX(0)); ADD_INSN1(list_anchor, 0, throw, INT2FIX(0) /* continue throw */ ); }
上位のiseq_compile関数で、その後ろにthrow命令が追加されるようになっていました。例外をrescueで捕まえられなかったので、再度throwすることになります。