YJIT: Support invokesuper in a block (#7264)
Support invokesuper in a block on YJIT invokesuper previously side exited when it is in a block. To make sure we're compiling the correct method in super, we now use the local environment pointer (LEP) to get the method, which will work in a block. Co-authored-by: John Hawthorn <john@hawthorn.email>
This commit is contained in:
parent
0601ba6a1b
commit
381bdee118
Notes:
git
2023-02-09 15:41:50 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -1940,6 +1940,38 @@ assert_equal '[:A, :Btwo]', %q{
|
||||
ins.foo
|
||||
}
|
||||
|
||||
# invokesuper with a block
|
||||
assert_equal 'true', %q{
|
||||
class A
|
||||
def foo = block_given?
|
||||
end
|
||||
|
||||
class B < A
|
||||
def foo = super()
|
||||
end
|
||||
|
||||
B.new.foo { }
|
||||
B.new.foo { }
|
||||
}
|
||||
|
||||
# invokesuper in a block
|
||||
assert_equal '[0, 2]', %q{
|
||||
class A
|
||||
def foo(x) = x * 2
|
||||
end
|
||||
|
||||
class B < A
|
||||
def foo
|
||||
2.times.map do |x|
|
||||
super(x)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
B.new.foo
|
||||
B.new.foo
|
||||
}
|
||||
|
||||
# Call to fixnum
|
||||
assert_equal '[true, false]', %q{
|
||||
def is_odd(obj)
|
||||
|
@ -6623,22 +6623,15 @@ fn gen_invokesuper(
|
||||
// Guard that the receiver has the same class as the one from compile time
|
||||
let side_exit = get_side_exit(jit, ocb, ctx);
|
||||
|
||||
let cfp = unsafe { get_ec_cfp(jit.ec.unwrap()) };
|
||||
let ep = unsafe { get_cfp_ep(cfp) };
|
||||
let cref_me = unsafe { *ep.offset(VM_ENV_DATA_INDEX_ME_CREF.try_into().unwrap()) };
|
||||
let me_as_value = VALUE(me as usize);
|
||||
if cref_me != me_as_value {
|
||||
// This will be the case for super within a block
|
||||
return CantCompile;
|
||||
}
|
||||
|
||||
asm.comment("guard known me");
|
||||
let ep_opnd = asm.load(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP));
|
||||
let lep_opnd = gen_get_lep(jit, asm);
|
||||
let ep_me_opnd = Opnd::mem(
|
||||
64,
|
||||
ep_opnd,
|
||||
lep_opnd,
|
||||
SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_ME_CREF,
|
||||
);
|
||||
|
||||
let me_as_value = VALUE(me as usize);
|
||||
asm.cmp(ep_me_opnd, me_as_value.into());
|
||||
asm.jne(counted_exit!(ocb, side_exit, invokesuper_me_changed));
|
||||
|
||||
@ -6650,11 +6643,9 @@ fn gen_invokesuper(
|
||||
// TODO: this could properly forward the current block handler, but
|
||||
// would require changes to gen_send_*
|
||||
asm.comment("guard no block given");
|
||||
// EP is in REG0 from above
|
||||
let ep_opnd = asm.load(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP));
|
||||
let ep_specval_opnd = Opnd::mem(
|
||||
64,
|
||||
ep_opnd,
|
||||
lep_opnd,
|
||||
SIZEOF_VALUE_I32 * VM_ENV_DATA_INDEX_SPECVAL,
|
||||
);
|
||||
asm.cmp(ep_specval_opnd, VM_BLOCK_HANDLER_NONE.into());
|
||||
|
Loading…
x
Reference in New Issue
Block a user