From: Yusuke ENDOH Date: 2007-12-29T05:29:38+09:00 Subject: [ruby-dev:32882] emptstack dumps core 遠藤と申します。 emptstack を使うとラベルの sp の計算が正しくできなくなります。 具体的には、以下の 3 つのプログラムがすべて落ちます。 # next が emptstack にコンパイルされる例 1.times do [ 1, 2, 3, 4, 5, 6, 7, 8, begin false ? next : p break while true end ] end # redo が emptstack にコンパイルされる例 1.times do [ 1, 2, 3, 4, 5, 6, 7, 8, begin false ? redo : p break while true end ] end # return が emptstack にコンパイルされる例 def foo [ 1, 2, 3, 4, 5, 6, 7, 8, begin false ? return : p break while true end ] end foo とりあえず emptstack の使用をあきらめる応急処置のパッチです。 ただし性能劣化はそれなりにある予感がします (調べてません) 。 Index: compile.c =================================================================== --- compile.c (revision 14778) +++ compile.c (working copy) @@ -2993,11 +2993,8 @@ } else if (iseq->compile_data->end_label) { debugs("next in block\n"); - ADD_INSN (ret, nd_line(node), emptstack); - COMPILE(ret, "next val", node->nd_stts); - add_ensure_iseq(ret, iseq); - ADD_INSNL(ret, nd_line(node), jump, - iseq->compile_data->end_label); + pop_after_throw = poped; + goto next_by_throw; } else if (iseq->type == ISEQ_TYPE_EVAL) { next_in_eval: @@ -3057,13 +3054,8 @@ COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); } else if (iseq->compile_data->start_label) { - ADD_INSN (ret, nd_line(node), emptstack); - add_ensure_iseq(ret, iseq); - ADD_INSNL(ret, nd_line(node), jump, - iseq->compile_data->start_label); - if (!poped) { /* for stack consistency */ - ADD_INSN(ret, nd_line(node), putnil); - } + pop_after_throw = poped; + goto redo_by_throw; } else { rb_iseq_t *ip; @@ -3808,22 +3800,12 @@ break; } else { - if (is->type == ISEQ_TYPE_METHOD) { - ADD_INSN(ret, nd_line(node), emptstack); - } - COMPILE(ret, "return nd_stts (return val)", node->nd_stts); - if (is->type == ISEQ_TYPE_METHOD) { - add_ensure_iseq(ret, iseq); - ADD_INSN(ret, nd_line(node), leave); + ADD_INSN1(ret, nd_line(node), throw, INT2FIX(0x01) /* TAG_RETURN */ ); + if (poped) { + ADD_INSN(ret, nd_line(node), pop); } - else { - ADD_INSN1(ret, nd_line(node), throw, INT2FIX(0x01) /* TAG_RETURN */ ); - if (poped) { - ADD_INSN(ret, nd_line(node), pop); - } - } break; } } -- Yusuke ENDOH