summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <ko1@atdot.net>2021-05-18 17:11:39 +0900
committerKoichi Sasada <ko1@atdot.net>2021-05-21 18:12:14 +0900
commit817764bd82513e2a0a672f5958f65854ea172c08 (patch)
tree005bfd5847e2e62c10ba823a7f1ec8b37acd1fa7
parent59b327aa58d3f514030b0afb767f11ab6ca0a76d (diff)
simple rescue+while+break should not use `throw`
609de71f043e8ba34f22b9993e444e2e5bb05709 fixes the issue by using `throw` insn if `ensure` is used. However, that patch introduce additional `throw` even if it is not needed. This patch solves the issue. This issue is pointed by @mame.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/4507
-rw-r--r--compile.c12
-rw-r--r--test/ruby/test_exception.rb11
2 files changed, 18 insertions, 5 deletions
diff --git a/compile.c b/compile.c
index e8bb023b78..d2de521ec8 100644
--- a/compile.c
+++ b/compile.c
@@ -5409,12 +5409,14 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange,
static bool
can_add_ensure_iseq(const rb_iseq_t *iseq)
{
- if (ISEQ_COMPILE_DATA(iseq)->in_rescue && ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) {
- return false;
- }
- else {
- return true;
+ struct iseq_compile_data_ensure_node_stack *e;
+ if (ISEQ_COMPILE_DATA(iseq)->in_rescue && (e = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack) != NULL) {
+ while (e) {
+ if (e->ensure_node) return false;
+ e = e->prev;
+ }
}
+ return true;
}
static void
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index af29163ce3..8c4e6889ab 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -104,6 +104,17 @@ class TestException < Test::Unit::TestCase
end
end
end
+
+ iseq = RubyVM::InstructionSequence.compile(<<-RUBY)
+ begin
+ while true
+ break
+ end
+ rescue
+ end
+ RUBY
+
+ assert_equal false, iseq.to_a[13].any?{|(e,_)| e == :throw}
end
def test_exception_in_ensure_with_redo