NODE_OPTBLOCK
YARVの最適化の一つとして、「ブロックのインライン化」があります。例えば
3.times { ブロックの中身 }
をブロックを作ったりyieldで呼んだりすると、スタック操作が無駄に発生してしまって効率がよくありません。あと、ブロックを使うとredoやnextが例外になってしまうのも避けたいところです。というわけで、こういう簡単なループがブロックで書かれているときは、while文に変換されます。
e = 0 while e < 3 do lredo: ブロックの中身 lnext: e = e + 1 end
「実はされません。とても微妙なバグがあるため、この機能はオフになっています。」だそうです。むむむー残念。
この最適化変換でwhileの中に移動されたブロックを表すノードが、OPTBLOCKです。
case NODE_OPTBLOCK:{ /* for optimize */ LABEL *redo_label = NEW_LABEL(0); LABEL *next_label = NEW_LABEL(0); iseq->compile_data->start_label = next_label; iseq->compile_data->redo_label = redo_label; ADD_LABEL(ret, redo_label); COMPILE_(ret, "optblock body", node->nd_head, 1 /* pop */ ); ADD_LABEL(ret, next_label); ADD_INSN(ret, 0, opt_checkenv); break; }