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

ruby-changes:70792

From: John <ko1@a...>
Date: Sun, 9 Jan 2022 04:41:16 +0900 (JST)
Subject: [ruby-changes:70792] 18b97eee5a (master): YJIT: Add support for ruby array cfuncs (argc=-2)

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

From 18b97eee5ace0fc70bf4e6d61092ad9fbade5f56 Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Wed, 5 Jan 2022 01:07:52 -0800
Subject: YJIT: Add support for ruby array cfuncs (argc=-2)

This adds support for cfuncs which take variable arguments using a Ruby
array. This is specified with the method entry's argc == -2.
---
 bootstraptest/test_yjit.rb | 20 ++++++++++++++++++++
 yjit.c                     |  1 -
 yjit_codegen.c             | 28 ++++++++++++++++++++++------
 3 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 47744efb735..a52ed8027d6 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -2766,3 +2766,23 @@ assert_equal 'ok', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L2766
   foo(s) rescue :ok
   foo(s) rescue :ok
 }
+
+# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
+assert_equal 'foo/bar', %q{
+  def foo
+    File.join("foo", "bar")
+  end
+
+  foo
+  foo
+}
+
+# File.join is a cfunc accepting variable arguments as a Ruby array (argc = -2)
+assert_equal '', %q{
+  def foo
+    File.join()
+  end
+
+  foo
+  foo
+}
diff --git a/yjit.c b/yjit.c
index e4fa84d510b..39ade5f1e23 100644
--- a/yjit.c
+++ b/yjit.c
@@ -69,7 +69,6 @@ YJIT_DECLARE_COUNTERS( https://github.com/ruby/ruby/blob/trunk/yjit.c#L69
     send_missing_method,
     send_bmethod,
     send_refined_method,
-    send_cfunc_ruby_array_varg,
     send_cfunc_argc_mismatch,
     send_cfunc_toomany_args,
     send_cfunc_tracing,
diff --git a/yjit_codegen.c b/yjit_codegen.c
index c9a44045507..c8de6307478 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -3244,12 +3244,6 @@ gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3244
 {
     const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc);
 
-    // If the function expects a Ruby array of arguments
-    if (cfunc->argc < 0 && cfunc->argc != -1) {
-        GEN_COUNTER_INC(cb, send_cfunc_ruby_array_varg);
-        return YJIT_CANT_COMPILE;
-    }
-
     // If the argument count doesn't match
     if (cfunc->argc >= 0 && cfunc->argc != argc) {
         GEN_COUNTER_INC(cb, send_cfunc_argc_mismatch);
@@ -3402,6 +3396,28 @@ gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3396
         lea(cb, C_ARG_REGS[1], ctx_stack_opnd(ctx, argc - 1));
         mov(cb, C_ARG_REGS[2], ctx_stack_opnd(ctx, argc));
     }
+    // Variadic method with Ruby array
+    if (cfunc->argc == -2) {
+        // Create a Ruby array from the arguments.
+        //
+        // This follows similar behaviour to vm_call_cfunc_with_frame() and
+        // call_cfunc_m2(). We use rb_ec_ary_new_from_values() instead of
+        // rb_ary_new4() since we have REG_EC available.
+        //
+        // Before getting here we will have set the new CFP in the EC, and the
+        // stack at CFP's SP will contain the values we are inserting into the
+        // Array, so they will be properly marked if we hit a GC.
+
+        // rb_ec_ary_new_from_values(rb_execution_context_t *ec, long n, const VLAUE *elts)
+        mov(cb, C_ARG_REGS[0], REG_EC);
+        mov(cb, C_ARG_REGS[1], imm_opnd(argc));
+        lea(cb, C_ARG_REGS[2], ctx_stack_opnd(ctx, argc - 1));
+        call_ptr(cb, REG0, (void *)rb_ec_ary_new_from_values);
+
+        // rb_file_s_join(VALUE recv, VALUE args)
+        mov(cb, C_ARG_REGS[0], ctx_stack_opnd(ctx, argc));
+        mov(cb, C_ARG_REGS[1], RAX);
+    }
 
     // Pop the C function arguments from the stack (in the caller)
     ctx_stack_pop(ctx, argc + 1);
-- 
cgit v1.2.1


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

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