diff options
author | Alan Wu <[email protected]> | 2024-12-13 10:41:04 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2024-12-13 10:41:04 -0500 |
commit | f3a117605c86b44ef48f313dc921c7fb86ff3481 (patch) | |
tree | 7771f17e0abbb4301910f6e1d62097fbbfcbb5b1 /yjit/src | |
parent | 92dd9734a967c20e628c8f77c5ce700058dcd58c (diff) |
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 <[email protected]>
Co-authored-by: Maxime Chevalier-Boisvert <[email protected]>
Co-authored-by: Aaron Patterson <[email protected]>
Co-authored-by: Kevin Menard <[email protected]>
Co-authored-by: Randy Stauner <[email protected]>
Notes
Notes:
Merged-By: maximecb <[email protected]>
Diffstat (limited to 'yjit/src')
-rw-r--r-- | yjit/src/codegen.rs | 28 | ||||
-rw-r--r-- | yjit/src/stats.rs | 1 |
2 files changed, 11 insertions, 18 deletions
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index e4283b786f..91d3aff532 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -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,33 +6957,25 @@ fn gen_send_cfunc( match block_arg_type { Some(Type::Nil | Type::BlockParamProxy) => { - // We'll handle this later - } - None => { - // Nothing to do - } - _ => { - gen_counter_incr(jit, asm, Counter::send_cfunc_block_arg); - return None; - } - } - - match block_arg_type { - Some(Type::Nil) => { - // We have a nil block arg, so let's pop it off the args + // We don't need the actual stack value for these asm.stack_pop(1); } - Some(Type::BlockParamProxy) => { - // We don't need the actual stack value + 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 } _ => { - assert!(false); + gen_counter_incr(jit, asm, Counter::send_cfunc_block_arg); + return None; } } + let block_arg_type = block_arg_type; // drop `mut` // Pop the empty kw_splat hash if kw_splat { diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs index 56ecfc5bc1..3a3965577b 100644 --- a/yjit/src/stats.rs +++ b/yjit/src/stats.rs @@ -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, |