1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Add tests, comments, and an assert for invokesuper

This commit is contained in:
Alan Wu 2021-06-23 20:28:42 -04:00
parent 6883aeda77
commit 3996e0ab07
3 changed files with 66 additions and 3 deletions

View file

@ -1238,3 +1238,60 @@ assert_equal '[:A, [:A, :B]]', %q{
C.new.bar C.new.bar
} }
# Same invokesuper bytecode, multiple destinations
assert_equal '[:Forward, :SecondTerminus]', %q{
module Terminus
def foo = :Terminus
end
module SecondTerminus
def foo = :SecondTerminus
end
module Forward
def foo = [:Forward, super]
end
class B
include SecondTerminus
end
class A < B
include Terminus
include Forward
end
A.new.foo
A.new.foo # compile
class B
include Forward
alias bar foo
end
# A.ancestors.take(5) == [A, Forward, Terminus, B, Forward, SecondTerminus]
A.new.bar
}
# invokesuper calling into itself
assert_equal '[:B, [:B, :m]]', %q{
module M
def foo = :m
end
class B
include M
def foo = [:B, super]
end
ins = B.new
ins.singleton_class # materialize the singleton class
ins.foo
ins.foo # compile
ins.singleton_class.define_method(:bar, B.instance_method(:foo))
ins.bar
}

View file

@ -2995,7 +2995,8 @@ gen_send(jitstate_t *jit, ctx_t *ctx)
return gen_send_general(jit, ctx, cd, block); return gen_send_general(jit, ctx, cd, block);
} }
RBIMPL_ATTR_MAYBE_UNUSED() // not in use as it has problems in some situations. // Not in use as it's incorrect in some situations. See comments.
RBIMPL_ATTR_MAYBE_UNUSED()
static codegen_status_t static codegen_status_t
gen_invokesuper(jitstate_t *jit, ctx_t *ctx) gen_invokesuper(jitstate_t *jit, ctx_t *ctx)
{ {
@ -3096,6 +3097,9 @@ gen_invokesuper(jitstate_t *jit, ctx_t *ctx)
insn_opnd_t recv_opnd = OPND_STACK(argc); insn_opnd_t recv_opnd = OPND_STACK(argc);
mov(cb, REG0, recv); mov(cb, REG0, recv);
// FIXME: This guard and the assume_method_lookup_stable() call below isn't
// always enough to correctly replicate the interpreter's behavior of
// searching at runtime for the callee through the method entry of the stack frame.
if (!jit_guard_known_klass(jit, ctx, comptime_recv_klass, recv_opnd, comptime_recv, SEND_MAX_DEPTH, side_exit)) { if (!jit_guard_known_klass(jit, ctx, comptime_recv_klass, recv_opnd, comptime_recv, SEND_MAX_DEPTH, side_exit)) {
return YJIT_CANT_COMPILE; return YJIT_CANT_COMPILE;
} }

View file

@ -218,8 +218,9 @@ add_lookup_dependency_i(st_data_t *key, st_data_t *value, st_data_t data, int ex
return ST_CONTINUE; return ST_CONTINUE;
} }
// Remember that a block assumes that rb_callable_method_entry(receiver_klass, mid) == cme and that // Remember that a block assumes that
// cme is vald. // `rb_callable_method_entry(receiver_klass, cme->called_id) == cme` and that
// `cme` is valid.
// When either of these assumptions becomes invalid, rb_yjit_method_lookup_change() or // When either of these assumptions becomes invalid, rb_yjit_method_lookup_change() or
// rb_yjit_cme_invalidate() invalidates the block. // rb_yjit_cme_invalidate() invalidates the block.
// //
@ -230,6 +231,7 @@ assume_method_lookup_stable(VALUE receiver_klass, const rb_callable_method_entry
RUBY_ASSERT(!block->receiver_klass && !block->callee_cme); RUBY_ASSERT(!block->receiver_klass && !block->callee_cme);
RUBY_ASSERT(cme_validity_dependency); RUBY_ASSERT(cme_validity_dependency);
RUBY_ASSERT(method_lookup_dependency); RUBY_ASSERT(method_lookup_dependency);
RUBY_ASSERT(rb_callable_method_entry(receiver_klass, cme->called_id) == cme);
RUBY_ASSERT_ALWAYS(RB_TYPE_P(receiver_klass, T_CLASS)); RUBY_ASSERT_ALWAYS(RB_TYPE_P(receiver_klass, T_CLASS));
RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(receiver_klass)); RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(receiver_klass));