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:
parent
6883aeda77
commit
3996e0ab07
3 changed files with 66 additions and 3 deletions
|
@ -1238,3 +1238,60 @@ assert_equal '[:A, [:A, :B]]', %q{
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -2995,7 +2995,8 @@ gen_send(jitstate_t *jit, ctx_t *ctx)
|
|||
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
|
||||
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);
|
||||
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)) {
|
||||
return YJIT_CANT_COMPILE;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// Remember that a block assumes that rb_callable_method_entry(receiver_klass, mid) == cme and that
|
||||
// cme is vald.
|
||||
// Remember that a block assumes that
|
||||
// `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
|
||||
// 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(cme_validity_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_objspace_garbage_object_p(receiver_klass));
|
||||
|
||||
|
|
Loading…
Reference in a new issue