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

ruby-changes:70681

From: John <ko1@a...>
Date: Sat, 1 Jan 2022 10:31:14 +0900 (JST)
Subject: [ruby-changes:70681] 5414de4b6e (master): YJIT: Fix SP index with optarg and unordered kwarg

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

From 5414de4b6e4372af832e338f8eb7a9fe8de17c84 Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Thu, 30 Dec 2021 11:13:37 -0800
Subject: YJIT: Fix SP index with optarg and unordered kwarg

Previously when we were calling a method with an optional argument and
multiple keywords arguments which weren't in the order the receiver
expected we would use the wrong SP index to rearrange them.

Fixes Bug #18453
---
 bootstraptest/test_yjit.rb | 16 ++++++++++++++++
 yjit_codegen.c             |  7 +++++--
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 05947c48ed2..30298a820d6 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -2280,6 +2280,22 @@ assert_equal '[[1, 2, 3]]', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L2280
   5.times.map { opt_and_kwargs(1, 2, c: 3) }.uniq
 }
 
+# Bug #18453
+assert_equal '[[1, nil, 2]]', %q{
+  def opt_and_kwargs(a = {}, b: nil, c: nil)
+    [a, b, c]
+  end
+
+  5.times.map { opt_and_kwargs(1, c: 2) }.uniq
+}
+
+assert_equal '[[{}, nil, 1]]', %q{
+  def opt_and_kwargs(a = {}, b: nil, c: nil)
+    [a, b, c]
+  end
+
+  5.times.map { opt_and_kwargs(c: 1) }.uniq
+}
 
 # leading and keyword arguments are swapped into the right order
 assert_equal '[[1, 2, 3, 4, 5, 6]]', %q{
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 8a547d2ef60..21e4813c193 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -3671,7 +3671,10 @@ 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#L3671
     if (doing_kw_call) {
         // Here we're calling a method with keyword arguments and specifying
         // keyword arguments at this call site.
-        const int lead_num = iseq->body->param.lead_num;
+
+        // Number of positional arguments the callee expects before the first
+        // keyword argument
+        const int args_before_kw = required_num + opt_num;
 
         // This struct represents the metadata about the caller-specified
         // keyword arguments.
@@ -3761,7 +3764,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#L3764
                 if (callee_kwarg == caller_kwargs[swap_idx]) {
                     // First we're going to generate the code that is going
                     // to perform the actual swapping at runtime.
-                    stack_swap(ctx, cb, argc - 1 - swap_idx - lead_num, argc - 1 - kwarg_idx - lead_num, REG1, REG0);
+                    stack_swap(ctx, cb, argc - 1 - swap_idx - args_before_kw, argc - 1 - kwarg_idx - args_before_kw, REG1, REG0);
 
                     // Next we're going to do some bookkeeping on our end so
                     // that we know the order that the arguments are
-- 
cgit v1.2.1


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

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