Skip to content

Commit

Permalink
YJIT: Support invokesuper in a block (#7264)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
wildmaples and jhawthorn committed Feb 9, 2023
1 parent 0601ba6 commit 381bdee
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
32 changes: 32 additions & 0 deletions bootstraptest/test_yjit.rb
Expand Up @@ -1940,6 +1940,38 @@ def foo
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)
Expand Down
19 changes: 5 additions & 14 deletions yjit/src/codegen.rs
Expand Up @@ -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));

Expand All @@ -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());
Expand Down

0 comments on commit 381bdee

Please sign in to comment.