ひとり勉強会

ひとり楽しく勉強会

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することになります。