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

ruby-changes:69046

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:38 +0900 (JST)
Subject: [ruby-changes:69046] e5f8b41786 (master): Implement send with alias method (#23)

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

From e5f8b417862cf7a7d03c82067b9870151cd6ce28 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maximechevalierb@g...>
Date: Wed, 5 May 2021 16:06:19 -0400
Subject: Implement send with alias method (#23)

* Implement send with alias method

* Add alias_method tests
---
 bootstraptest/test_yjit.rb | 46 ++++++++++++++++++++++
 vm_insnhelper.c            |  6 +++
 yjit_codegen.c             | 98 +++++++++++++++++++++++++---------------------
 3 files changed, 106 insertions(+), 44 deletions(-)

diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index b8ae5a989c..0b469ff5fa 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -130,6 +130,52 @@ assert_normal_exit %q{ https://github.com/ruby/ruby/blob/trunk/bootstraptest/test_yjit.rb#L130
   foo()
 }
 
+# Method aliasing
+assert_equal '42', %q{
+  class Foo
+    def method_a
+      42
+    end
+
+    alias method_b method_a
+
+    def method_a
+        :somethingelse
+    end
+  end
+
+  @obj = Foo.new
+
+  def test
+    @obj.method_b
+  end
+
+  test
+  test
+}
+
+# Method aliasing with method from parent class
+assert_equal '777', %q{
+  class A
+    def method_a
+      777
+    end
+  end
+
+  class B < A
+    alias method_b method_a
+  end
+
+  @obj = B.new
+
+  def test
+    @obj.method_b
+  end
+
+  test
+  test
+}
+
 # The hash method is a C function and uses the self argument
 assert_equal 'true', %q{
     def lehashself
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 124de73afb..772fa76ffd 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -3126,6 +3126,12 @@ aliased_callable_method_entry(const rb_callable_method_entry_t *me) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3126
     return cme;
 }
 
+const rb_callable_method_entry_t *
+rb_aliased_callable_method_entry(const rb_callable_method_entry_t *me)
+{
+    return aliased_callable_method_entry(me);
+}
+
 static VALUE
 vm_call_alias(rb_execution_context_t *ec, rb_control_frame_t *cfp, struct rb_calling_info *calling)
 {
diff --git a/yjit_codegen.c b/yjit_codegen.c
index dfcf198978..ba332687b4 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -2093,6 +2093,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#L2093
     return true;
 }
 
+const rb_callable_method_entry_t *
+rb_aliased_callable_method_entry(const rb_callable_method_entry_t *me);
+
 static codegen_status_t
 gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t *block)
 {
@@ -2177,54 +2180,61 @@ gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2180
     // Method calls may corrupt types
     ctx_clear_local_types(ctx);
 
-    switch (cme->def->type) {
-    case VM_METHOD_TYPE_ISEQ:
-        return gen_send_iseq(jit, ctx, ci, cme, block, argc);
-    case VM_METHOD_TYPE_CFUNC:
-        return gen_send_cfunc(jit, ctx, ci, cme, block, argc);
-    case VM_METHOD_TYPE_IVAR:
-        if (argc != 0) {
-            // Argument count mismatch. Getters take no arguments.
-            GEN_COUNTER_INC(cb, send_getter_arity);
+    // To handle the aliased method case (VM_METHOD_TYPE_ALIAS)
+    while (true) {
+        // switch on the method type
+        switch (cme->def->type) {
+        case VM_METHOD_TYPE_ISEQ:
+            return gen_send_iseq(jit, ctx, ci, cme, block, argc);
+        case VM_METHOD_TYPE_CFUNC:
+            return gen_send_cfunc(jit, ctx, ci, cme, block, argc);
+        case VM_METHOD_TYPE_IVAR:
+            if (argc != 0) {
+                // Argument count mismatch. Getters take no arguments.
+                GEN_COUNTER_INC(cb, send_getter_arity);
+                return YJIT_CANT_COMPILE;
+            }
+            else {
+                mov(cb, REG0, recv);
+
+                ID ivar_name = cme->def->body.attr.id;
+                return gen_get_ivar(jit, ctx, SEND_MAX_DEPTH, comptime_recv, ivar_name, recv_opnd, side_exit);
+            }
+        case VM_METHOD_TYPE_ATTRSET:
+            GEN_COUNTER_INC(cb, send_ivar_set_method);
             return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_BMETHOD:
+            GEN_COUNTER_INC(cb, send_bmethod);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_ZSUPER:
+            GEN_COUNTER_INC(cb, send_zsuper_method);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_ALIAS: {
+            // Retrieve the alised method and re-enter the switch
+            cme = rb_aliased_callable_method_entry(cme);
+            continue;
         }
-        else {
-            mov(cb, REG0, recv);
-
-            ID ivar_name = cme->def->body.attr.id;
-            return gen_get_ivar(jit, ctx, SEND_MAX_DEPTH, comptime_recv, ivar_name, recv_opnd, side_exit);
+        case VM_METHOD_TYPE_UNDEF:
+            GEN_COUNTER_INC(cb, send_undef_method);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_NOTIMPLEMENTED:
+            GEN_COUNTER_INC(cb, send_not_implemented_method);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_OPTIMIZED:
+            GEN_COUNTER_INC(cb, send_optimized_method);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_MISSING:
+            GEN_COUNTER_INC(cb, send_missing_method);
+            return YJIT_CANT_COMPILE;
+        case VM_METHOD_TYPE_REFINED:
+            GEN_COUNTER_INC(cb, send_refined_method);
+            return YJIT_CANT_COMPILE;
+        // no default case so compiler issues a warning if this is not exhaustive
         }
-    case VM_METHOD_TYPE_ATTRSET:
-        GEN_COUNTER_INC(cb, send_ivar_set_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_BMETHOD:
-        GEN_COUNTER_INC(cb, send_bmethod);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_ZSUPER:
-        GEN_COUNTER_INC(cb, send_zsuper_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_ALIAS:
-        GEN_COUNTER_INC(cb, send_alias_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_UNDEF:
-        GEN_COUNTER_INC(cb, send_undef_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_NOTIMPLEMENTED:
-        GEN_COUNTER_INC(cb, send_not_implemented_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_OPTIMIZED:
-        GEN_COUNTER_INC(cb, send_optimized_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_MISSING:
-        GEN_COUNTER_INC(cb, send_missing_method);
-        return YJIT_CANT_COMPILE;
-    case VM_METHOD_TYPE_REFINED:
-        GEN_COUNTER_INC(cb, send_refined_method);
-        return YJIT_CANT_COMPILE;
-    // no default case so compiler issues a warning if this is not exhaustive
-    }
 
-    return YJIT_CANT_COMPILE;
+        // Unreachable
+        RUBY_ASSERT(false);
+    }
 }
 
 static codegen_status_t
-- 
cgit v1.2.1


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

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