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

ruby-changes:70218

From: Alan <ko1@a...>
Date: Wed, 15 Dec 2021 09:48:11 +0900 (JST)
Subject: [ruby-changes:70218] ac5d6faea8 (master): YJIT: Fix unexpected truncation when outputing VALUE

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

From ac5d6faea8e8d142df798572b0522f8a185c8fb6 Mon Sep 17 00:00:00 2001
From: Alan Wu <XrXr@u...>
Date: Tue, 14 Dec 2021 19:47:42 -0500
Subject: YJIT: Fix unexpected truncation when outputing VALUE

Previously, YJIT incorrectly discarded the upper 32 bits of the object
pointer when writing out VALUEs to setup default keyword arguments.

In addition to incorrectly truncating, the output pointers were not
properly tracked for handling GC compaction moving the referenced
objects.

YJIT previously attempted to encode a mov instruction with a memory
destination and a 64 bit immediate when there is no such encoding
possible in the ISA. Add an assert to mitigate not being able to
catch this at build time.
---
 bootstraptest/test_yjit.rb | 15 +++++++++++++++
 yjit_asm.c                 |  5 ++++-
 yjit_codegen.c             |  6 ++++--
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 2ac37df0a23..0b2b78ca4a9 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1,3 +1,18 @@ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L1
+assert_equal '18374962167983112447', %q{
+  # regression test for incorrectly discarding 32 bits of a pointer when it
+  # comes to default values.
+  def large_literal_default(n: 0xff00_fabcafe0_00ff)
+    n
+  end
+
+  def call_graph_root
+    large_literal_default
+  end
+
+  call_graph_root
+  call_graph_root
+}
+
 assert_normal_exit %q{
   # regression test for a leak caught by an asert on --yjit-call-threshold=2
   Foo = 1
diff --git a/yjit_asm.c b/yjit_asm.c
index 3a43c80ef08..64cbb163a21 100644
--- a/yjit_asm.c
+++ b/yjit_asm.c
@@ -1343,7 +1343,10 @@ void mov(codeblock_t *cb, x86opnd_t dst, x86opnd_t src) https://github.com/ruby/ruby/blob/trunk/yjit_asm.c#L1343
             else
                 cb_write_rm(cb, dst.num_bits == 16, dst.num_bits == 64, NO_OPND, dst, 0, 1, 0xC7);
 
-            cb_write_int(cb, src.as.imm, (dst.num_bits > 32)? 32:dst.num_bits);
+            const uint32_t output_num_bits = (dst.num_bits > 32u) ? 32u : dst.num_bits;
+            // assert that we can write whole immediate without loss of infomation
+            assert (sig_imm_size(src.as.imm) <= output_num_bits);
+            cb_write_int(cb, src.as.imm, output_num_bits);
         }
 
         else
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 3378f1500dd..38b830a0974 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -3698,7 +3698,7 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3698
 
         // This struct represents the metadata about the callee-specified
         // keyword parameters.
-        const struct rb_iseq_param_keyword *keyword = iseq->body->param.keyword;
+        const struct rb_iseq_param_keyword *const keyword = iseq->body->param.keyword;
 
         ADD_COMMENT(cb, "keyword args");
 
@@ -3748,7 +3748,9 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3748
                     default_value = Qnil;
                 }
 
-                mov(cb, default_arg, imm_opnd(default_value));
+                // GC might move default_value.
+                jit_mov_gc_ptr(jit, cb, REG0, default_value);
+                mov(cb, default_arg, REG0);
 
                 caller_kwargs[kwarg_idx++] = callee_kwarg;
             }
-- 
cgit v1.2.1


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

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