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
|
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);
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue