From 14a3499c4f9dfc9ee102cbed5fe37481282f5f5a Mon Sep 17 00:00:00 2001 From: k0kubun Date: Wed, 2 May 2018 12:55:57 +0000 Subject: [PATCH] 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 --- compile.c | 18 ++++++++---------- test/ruby/test_jit.rb | 11 +++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/compile.c b/compile.c index 2fadf643ad..4fa3e473e2 100644 --- a/compile.c +++ b/compile.c @@ -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) diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb index 7542f8087e..040328533f 100644 --- a/test/ruby/test_jit.rb +++ b/test/ruby/test_jit.rb @@ -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