ruby-changes:49503
From: nobu <ko1@a...>
Date: Fri, 5 Jan 2018 23:23:30 +0900 (JST)
Subject: [ruby-changes:49503] nobu:r61618 (trunk): compile.c: fix stack consistency error
nobu 2018-01-05 23:23:23 +0900 (Fri, 05 Jan 2018) New Revision: 61618 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61618 Log: compile.c: fix stack consistency error * compile.c (iseq_peephole_optimize): fix stack consistency error from return in loop, by adding extra `pop` when replacing `jump` with `leave`, which is never reached but needed to adjust sp calculation. [ruby-core:84589] [Bug #14273] Modified files: trunk/compile.c trunk/test/ruby/test_syntax.rb Index: compile.c =================================================================== --- compile.c (revision 61617) +++ compile.c (revision 61618) @@ -2476,6 +2476,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2476 goto again; } else if (IS_INSN_ID(diobj, leave)) { + INSN *pop; /* * jump LABEL * ... @@ -2483,6 +2484,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2484 * leave * => * leave + * pop * ... * LABEL: * leave @@ -2492,6 +2494,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, https://github.com/ruby/ruby/blob/trunk/compile.c#L2494 iobj->insn_id = BIN(leave); iobj->operand_size = 0; iobj->insn_info = diobj->insn_info; + /* adjust stack depth */ + pop = new_insn_body(iseq, diobj->insn_info.line_no, BIN(pop), 0); + ELEM_INSERT_NEXT(&iobj->link, &pop->link); goto again; } else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 && Index: test/ruby/test_syntax.rb =================================================================== --- test/ruby/test_syntax.rb (revision 61617) +++ test/ruby/test_syntax.rb (revision 61618) @@ -1128,6 +1128,15 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1128 assert_equal(:begin, result) end + def test_return_in_loop + obj = Object.new + def obj.test + x = nil + return until x unless x + end + assert_nil obj.test + end + private def not_label(x) @result = x; @not_label ||= nil end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/