[前][次][番号順一覧][スレッド一覧]

ruby-changes:66286

From: Koichi <ko1@a...>
Date: Fri, 21 May 2021 18:12:33 +0900 (JST)
Subject: [ruby-changes:66286] 817764bd82 (master): simple rescue+while+break should not use `throw`

https://git.ruby-lang.org/ruby.git/commit/?id=817764bd82

From 817764bd82513e2a0a672f5958f65854ea172c08 Mon Sep 17 00:00:00 2001
From: Koichi Sasada <ko1@a...>
Date: Tue, 18 May 2021 17:11:39 +0900
Subject: 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.
---
 compile.c                   | 12 +++++++-----
 test/ruby/test_exception.rb | 11 +++++++++++
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/compile.c b/compile.c
index e8bb023..d2de521 100644
--- a/compile.c
+++ b/compile.c
@@ -5409,12 +5409,14 @@ add_ensure_range(rb_iseq_t *iseq, struct ensure_range *erange, https://github.com/ruby/ruby/blob/trunk/compile.c#L5409
 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 af29163..8c4e688 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -104,6 +104,17 @@ class TestException < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_exception.rb#L104
         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
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]