compile.c: mark catch_except_p of iseq

which has throw insn, not only ancestor iseqs of it.
I think we should remove catch_except_p flag and try to simplify the
catch table itself, to prevent similar bugs in the future.

test_jit.rb: add test to prevent the bug

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@63320 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
k0kubun 2018-05-02 12:55:57 +00:00
parent 0d492003b0
commit 14a3499c4f
2 changed files with 19 additions and 10 deletions

View File

@ -1281,20 +1281,18 @@ update_catch_except_flags(struct rb_iseq_constant_body *body)
/* This assumes that a block has parent_iseq which may catch an exception from the block, and that /* This assumes that a block has parent_iseq which may catch an exception from the block, and that
BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */ BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */
if (body->parent_iseq != NULL) { pos = 0;
pos = 0; while (pos < body->iseq_size) {
while (pos < body->iseq_size) {
#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE #if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]); insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]);
#else #else
insn = (int)body->iseq_encoded[pos]; insn = (int)body->iseq_encoded[pos];
#endif #endif
if (insn == BIN(throw)) { if (insn == BIN(throw)) {
struct rb_iseq_constant_body *parent_body = body->parent_iseq->body; set_catch_except_p(body);
set_catch_except_p(parent_body); break;
}
pos += insn_len(insn);
} }
pos += insn_len(insn);
} }
if (ct == NULL) if (ct == NULL)

View File

@ -574,6 +574,17 @@ class TestJIT < Test::Unit::TestCase
end end
end end
def test_lambda_longjmp
assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1)
begin;
fib = lambda do |x|
return x if x == 0 || x == 1
fib.call(x-1) + fib.call(x-2)
end
print fib.call(5)
end;
end
private private
# The shortest way to test one proc # The shortest way to test one proc