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

ruby-changes:69172

From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:21:07 +0900 (JST)
Subject: [ruby-changes:69172] 9951a9a8ec (master): Implement invokebuiltin

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

From 9951a9a8ece77ad8aa2a8871b009e2f1fb776987 Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Thu, 8 Jul 2021 23:33:55 -0700
Subject: Implement invokebuiltin

---
 bootstraptest/test_yjit.rb | 12 ++++++++++++
 test/ruby/test_yjit.rb     | 13 +++++++++++++
 yjit_codegen.c             | 36 +++++++++++++++++++++++++++++++++++-
 3 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 8cb4432b6a..6d507e17d7 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1210,6 +1210,18 @@ assert_equal 'foo123', %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L1210
   make_str("foo", 123)
 }
 
+# test invokebuiltin as used in struct assignment
+assert_equal '123', %q{
+  def foo(obj)
+    obj.foo = 123
+  end
+
+  struct = Struct.new(:foo)
+  obj = struct.new
+  foo(obj)
+  foo(obj)
+}
+
 # test invokebuiltin_delegate as used inside Dir.open
 assert_equal '.', %q{
   def foo(path)
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
index 4672e83c9c..ed83bd681a 100644
--- a/test/ruby/test_yjit.rb
+++ b/test/ruby/test_yjit.rb
@@ -310,6 +310,19 @@ class TestYJIT < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_yjit.rb#L310
     RUBY
   end
 
+  def test_invokebuiltin
+    assert_compiles(<<~RUBY)
+      def foo(obj)
+        obj.foo = 123
+        obj.bar = 123
+      end
+
+      Foo = Struct.new(:foo, :bar)
+      foo(Foo.new(123))
+      foo(Foo.new(123))
+    RUBY
+  end
+
   def test_super_iseq
     assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
       class A
diff --git a/yjit_codegen.c b/yjit_codegen.c
index 9f0029712d..c056b1c216 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -4136,6 +4136,39 @@ gen_getblockparamproxy(jitstate_t *jit, ctx_t *ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4136
     return YJIT_KEEP_COMPILING;
 }
 
+static codegen_status_t
+gen_invokebuiltin(jitstate_t *jit, ctx_t *ctx)
+{
+    const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0);
+
+    if (bf->argc + 2 > NUM_C_ARG_REGS) {
+        return YJIT_CANT_COMPILE;
+    }
+
+    // If the calls don't allocate, do they need up to date PC, SP?
+    jit_prepare_routine_call(jit, ctx, REG0);
+
+    // Call the builtin func (ec, recv, arg1, arg2, ...)
+    mov(cb, C_ARG_REGS[0], REG_EC);
+    mov(cb, C_ARG_REGS[1], member_opnd(REG_CFP, rb_control_frame_t, self));
+
+    // Copy arguments from locals
+    for (int32_t i = 0; i < bf->argc; i++) {
+        x86opnd_t stack_opnd = ctx_stack_opnd(ctx, bf->argc - i - 1);
+        x86opnd_t c_arg_reg = C_ARG_REGS[2 + i];
+        mov(cb, c_arg_reg, stack_opnd);
+    }
+
+    call_ptr(cb, REG0, (void *)bf->func_ptr);
+
+    // Push the return value
+    ctx_stack_pop(ctx, bf->argc);
+    x86opnd_t stack_ret = ctx_stack_push(ctx, TYPE_UNKNOWN);
+    mov(cb, stack_ret, RAX);
+
+    return YJIT_KEEP_COMPILING;
+}
+
 // opt_invokebuiltin_delegate calls a builtin function, like
 // invokebuiltin does, but instead of taking arguments from the top of the
 // stack uses the argument locals (and self) from the current method.
@@ -4145,7 +4178,7 @@ gen_opt_invokebuiltin_delegate(jitstate_t *jit, ctx_t *ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4178
     const struct rb_builtin_function *bf = (struct rb_builtin_function *)jit_get_arg(jit, 0);
     int32_t start_index = (int32_t)jit_get_arg(jit, 1);
 
-    if (bf->argc + 2 >= NUM_C_ARG_REGS) {
+    if (bf->argc + 2 > NUM_C_ARG_REGS) {
         return YJIT_CANT_COMPILE;
     }
 
@@ -4387,6 +4420,7 @@ yjit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4420
     yjit_reg_op(BIN(opt_length), gen_opt_length);
     yjit_reg_op(BIN(opt_regexpmatch2), gen_opt_regexpmatch2);
     yjit_reg_op(BIN(opt_getinlinecache), gen_opt_getinlinecache);
+    yjit_reg_op(BIN(invokebuiltin), gen_invokebuiltin);
     yjit_reg_op(BIN(opt_invokebuiltin_delegate), gen_opt_invokebuiltin_delegate);
     yjit_reg_op(BIN(opt_invokebuiltin_delegate_leave), gen_opt_invokebuiltin_delegate);
     yjit_reg_op(BIN(opt_case_dispatch), gen_opt_case_dispatch);
-- 
cgit v1.2.1


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

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