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/