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
Родитель 0d492003b0
Коммит 14a3499c4f
2 изменённых файлов: 19 добавлений и 10 удалений

Просмотреть файл

@ -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
BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */
if (body->parent_iseq != NULL) {
pos = 0;
while (pos < body->iseq_size) {
pos = 0;
while (pos < body->iseq_size) {
#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
insn = (int)body->iseq_encoded[pos];
insn = (int)body->iseq_encoded[pos];
#endif
if (insn == BIN(throw)) {
struct rb_iseq_constant_body *parent_body = body->parent_iseq->body;
set_catch_except_p(parent_body);
}
pos += insn_len(insn);
if (insn == BIN(throw)) {
set_catch_except_p(body);
break;
}
pos += insn_len(insn);
}
if (ct == NULL)

Просмотреть файл

@ -574,6 +574,17 @@ class TestJIT < Test::Unit::TestCase
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
# The shortest way to test one proc