summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2024-01-08 09:34:57 -0800
committerGitHub <noreply@github.com>2024-01-08 17:34:57 +0000
commita0eecfb5bae66470ccf40e27b9193fbf5c76618f (patch)
tree7defc6d9403d6177deac2e69ec37ab94e416e25c
parent85a7da742a81d87322878a7f66c44b16c7cb9b0b (diff)
YJIT: Fallback Integer#<< if a shift amount varies (#9426)
* YJIT: Fallback Integer#<< if a shift amount varies * YJIT: Do not fallback lshift in the first chain
-rw-r--r--yjit.rb2
-rw-r--r--yjit/src/codegen.rs17
-rw-r--r--yjit/src/stats.rs2
3 files changed, 16 insertions, 5 deletions
diff --git a/yjit.rb b/yjit.rb
index a2286117a8..a96db9b641 100644
--- a/yjit.rb
+++ b/yjit.rb
@@ -288,7 +288,7 @@ module RubyVM::YJIT
].each do |insn|
print_counters(stats, out: out, prefix: "#{insn}_", prompt: "#{insn} exit reasons:", optional: true)
end
- print_counters(stats, out: out, prefix: 'lshift_', prompt: 'left shift (ltlt) exit reasons: ')
+ print_counters(stats, out: out, prefix: 'lshift_', prompt: 'left shift (opt_ltlt) exit reasons: ')
print_counters(stats, out: out, prefix: 'invalidate_', prompt: 'invalidation reasons: ')
end
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 6d85ca4266..7e44c3add0 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -4637,17 +4637,28 @@ fn jit_rb_int_lshift(
// Untag the fixnum shift amount
let shift_amt = comptime_shift.as_isize() >> 1;
-
if shift_amt > 63 || shift_amt < 0 {
return false;
}
+ // Fallback to a C call if the shift amount varies
+ if asm.ctx.get_chain_depth() > 1 {
+ return false;
+ }
+
let rhs = asm.stack_pop(1);
let lhs = asm.stack_pop(1);
- // Guard on the shift value we speculated on
+ // Guard on the shift amount we speculated on
asm.cmp(rhs, comptime_shift.into());
- asm.jne(Target::side_exit(Counter::lshift_amt_changed));
+ jit_chain_guard(
+ JCC_JNE,
+ jit,
+ asm,
+ ocb,
+ 2, // defer_compilation increments chain_depth
+ Counter::lshift_amount_changed,
+ );
let in_val = asm.sub(lhs, 1.into());
let shift_opnd = Opnd::UImm(shift_amt as u64);
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index ac247d2fa8..ba1479e152 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -447,7 +447,7 @@ make_counters! {
opt_mod_zero,
opt_div_zero,
- lshift_amt_changed,
+ lshift_amount_changed,
lshift_overflow,
opt_aref_argc_not_one,