summaryrefslogtreecommitdiff
path: root/yjit/src
diff options
context:
space:
mode:
authorAlan Wu <[email protected]>2024-12-13 10:41:04 -0500
committerGitHub <[email protected]>2024-12-13 10:41:04 -0500
commitf3a117605c86b44ef48f313dc921c7fb86ff3481 (patch)
tree7771f17e0abbb4301910f6e1d62097fbbfcbb5b1 /yjit/src
parent92dd9734a967c20e628c8f77c5ce700058dcd58c (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.rs28
-rw-r--r--yjit/src/stats.rs1
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,