YJIT: Speculate block arg for c_func_method(&nil) calls (#12326)

A good amount of call sites always pass nil as block argument, but the
nil doesn't show up in the context. Put a runtime guard for those
cases to handle it. Particular relevant for the `ruby-lsp` benchmark in
`yjit-bench`. Up to a 2% speedup across headline benchmarks.

Co-authored-by: Takashi Kokubun <takashikkbn@gmail.com>
Co-authored-by: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
Co-authored-by: Aaron Patterson <tenderlove@ruby-lang.org>
Co-authored-by: Kevin Menard <kevin@nirvdrum.com>
Co-authored-by: Randy Stauner <randy.stauner@shopify.com>
This commit is contained in:
Alan Wu 2024-12-13 10:41:04 -05:00 committed by GitHub
parent 92dd9734a9
commit f3a117605c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2024-12-13 15:41:23 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
2 changed files with 12 additions and 19 deletions

View File

@ -6949,7 +6949,7 @@ fn gen_send_cfunc(
return None;
}
let block_arg_type = if block_arg {
let mut block_arg_type = if block_arg {
Some(asm.ctx.get_opnd_type(StackOpnd(0)))
} else {
None
@ -6957,7 +6957,15 @@ fn gen_send_cfunc(
match block_arg_type {
Some(Type::Nil | Type::BlockParamProxy) => {
// We'll handle this later
// We don't need the actual stack value for these
asm.stack_pop(1);
}
Some(Type::Unknown | Type::UnknownImm) if jit.peek_at_stack(&asm.ctx, 0).nil_p() => {
// The sample blockarg is nil, so speculate that's the case.
asm.cmp(asm.stack_opnd(0), Qnil.into());
asm.jne(Target::side_exit(Counter::guard_send_cfunc_block_not_nil));
block_arg_type = Some(Type::Nil);
asm.stack_pop(1);
}
None => {
// Nothing to do
@ -6967,23 +6975,7 @@ fn gen_send_cfunc(
return None;
}
}
match block_arg_type {
Some(Type::Nil) => {
// We have a nil block arg, so let's pop it off the args
asm.stack_pop(1);
}
Some(Type::BlockParamProxy) => {
// We don't need the actual stack value
asm.stack_pop(1);
}
None => {
// Nothing to do
}
_ => {
assert!(false);
}
}
let block_arg_type = block_arg_type; // drop `mut`
// Pop the empty kw_splat hash
if kw_splat {

View File

@ -470,6 +470,7 @@ make_counters! {
guard_send_str_aref_not_fixnum,
guard_send_cfunc_bad_splat_vargs,
guard_send_cfunc_block_not_nil,
guard_invokesuper_me_changed,