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]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61618 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-01-05 14:23:23 +00:00
parent 665839ddda
commit 43c1eb440a
2 changed files with 14 additions and 0 deletions

View File

@ -2476,6 +2476,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
goto again; goto again;
} }
else if (IS_INSN_ID(diobj, leave)) { else if (IS_INSN_ID(diobj, leave)) {
INSN *pop;
/* /*
* jump LABEL * jump LABEL
* ... * ...
@ -2483,6 +2484,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* leave * leave
* => * =>
* leave * leave
* pop
* ... * ...
* LABEL: * LABEL:
* leave * leave
@ -2492,6 +2494,9 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
iobj->insn_id = BIN(leave); iobj->insn_id = BIN(leave);
iobj->operand_size = 0; iobj->operand_size = 0;
iobj->insn_info = diobj->insn_info; 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; goto again;
} }
else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 && else if ((piobj = (INSN *)get_prev_insn(iobj)) != 0 &&

View File

@ -1128,6 +1128,15 @@ eom
assert_equal(:begin, result) assert_equal(:begin, result)
end 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 private
def not_label(x) @result = x; @not_label ||= nil end def not_label(x) @result = x; @not_label ||= nil end