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

ruby-changes:69051

From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:39 +0900 (JST)
Subject: [ruby-changes:69051] 812597676b (master): Avoid immediate side exits in checktype

https://git.ruby-lang.org/ruby.git/commit/?id=812597676b

From 812597676ba2b1e3c41c50e9da624441e0c40a6b Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Thu, 26 Aug 2021 11:45:05 -0700
Subject: Avoid immediate side exits in checktype

Previously checktype only supported heap objects, however it's not
uncommon to receive an immediate, for example when string interpolating
a Symbol or Integer.
---
 test/ruby/test_yjit.rb | 10 ++++++++++
 yjit_codegen.c         | 22 +++++++++++-----------
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 1f5f99f9a8..04502f925c 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -152,6 +152,16 @@ class TestYJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_yjit.rb#L152
     RUBY
   end
 
+  def test_string_interpolation_cast
+    assert_compiles(<<~'RUBY', insns: %i[checktype concatstrings tostring], result: "123")
+      def make_str(foo, bar)
+        "#{foo}#{bar}"
+      end
+
+      make_str(1, 23)
+    RUBY
+  end
+
   def test_fib_recursion
     assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34)
       def fib(n)
diff --git a/yjit_codegen.c b/yjit_codegen.c
index db0694523e..0e2bbf2fa3 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -1758,9 +1758,6 @@ gen_defined(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1758
 static codegen_status_t
 gen_checktype(jitstate_t* jit, ctx_t* ctx)
 {
-    // TODO: could we specialize on the type we detect
-    uint8_t* side_exit = yjit_side_exit(jit, ctx);
-
     enum ruby_value_type type_val = (enum ruby_value_type)jit_get_arg(jit, 0);
     // Only three types are emitted by compile.c
     if (type_val == T_STRING || type_val == T_ARRAY || type_val == T_HASH) {
@@ -1785,16 +1782,17 @@ gen_checktype(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1782
         }
 
         mov(cb, REG0, val);
+        mov(cb, REG1, imm_opnd(Qfalse));
+
+        uint32_t ret = cb_new_label(cb, "ret");
 
         if (!val_type.is_heap) {
             // if (SPECIAL_CONST_P(val)) {
-            // Bail if receiver is not a heap object
+            // Return Qfalse via REG1 if not on heap
             test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
-            jnz_ptr(cb, side_exit);
-            cmp(cb, REG0, imm_opnd(Qfalse));
-            je_ptr(cb, side_exit);
+            jnz_label(cb, ret);
             cmp(cb, REG0, imm_opnd(Qnil));
-            je_ptr(cb, side_exit);
+            jbe_label(cb, ret);
         }
 
         // Check type on object
@@ -1802,11 +1800,13 @@ gen_checktype(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1800
         and(cb, REG0, imm_opnd(RUBY_T_MASK));
         cmp(cb, REG0, imm_opnd(type_val));
         mov(cb, REG0, imm_opnd(Qtrue));
-        mov(cb, REG1, imm_opnd(Qfalse));
-        cmovne(cb, REG0, REG1);
+        // REG1 contains Qfalse from above
+        cmove(cb, REG1, REG0);
 
+        cb_write_label(cb, ret);
         stack_ret = ctx_stack_push(ctx, TYPE_IMM);
-        mov(cb, stack_ret, REG0);
+        mov(cb, stack_ret, REG1);
+        cb_link_labels(cb);
 
         return YJIT_KEEP_COMPILING;
     } else {
-- 
cgit v1.2.1


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

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