summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2024-11-14 09:04:48 -0800
committerGitHub <[email protected]>2024-11-14 12:04:48 -0500
commit7e2f9eaccd008e1ef91411145112f5820a05580b (patch)
treef9b63c53eac720b643300b18d2d180ba03e9638d
parentfd4b27472ead7294d1e6bdab1d29cd3a28786da6 (diff)
YJIT: Specialize Integer#pred (#12082)
Notes
Notes: Merged-By: maximecb <[email protected]>
-rw-r--r--bootstraptest/test_yjit.rb5
-rw-r--r--yjit/src/codegen.rs30
-rw-r--r--yjit/src/stats.rs2
3 files changed, 37 insertions, 0 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 40f1db2ec5..b8e8e11eec 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -4594,6 +4594,11 @@ assert_equal '[2, 4611686018427387904]', %q{
[1.succ, 4611686018427387903.succ]
}
+# Integer pred and overflow
+assert_equal '[0, -4611686018427387905]', %q{
+ [1.pred, -4611686018427387904.pred]
+}
+
# Integer right shift
assert_equal '[0, 1, -4]', %q{
[0 >> 1, 2 >> 1, -7 >> 1]
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index d810a9f0dd..7d0a7a66d5 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -5277,6 +5277,35 @@ fn jit_rb_int_succ(
true
}
+fn jit_rb_int_pred(
+ _jit: &mut JITState,
+ asm: &mut Assembler,
+ _ci: *const rb_callinfo,
+ _cme: *const rb_callable_method_entry_t,
+ _block: Option<BlockHandler>,
+ _argc: i32,
+ _known_recv_class: Option<VALUE>,
+) -> bool {
+ // Guard the receiver is fixnum
+ let recv_type = asm.ctx.get_opnd_type(StackOpnd(0));
+ let recv = asm.stack_pop(1);
+ if recv_type != Type::Fixnum {
+ asm_comment!(asm, "guard object is fixnum");
+ asm.test(recv, Opnd::Imm(RUBY_FIXNUM_FLAG as i64));
+ asm.jz(Target::side_exit(Counter::send_pred_not_fixnum));
+ }
+
+ asm_comment!(asm, "Integer#pred");
+ let out_val = asm.sub(recv, Opnd::Imm(2)); // 2 is untagged Fixnum 1
+ asm.jo(Target::side_exit(Counter::send_pred_underflow));
+
+ // Push the output onto the stack
+ let dst = asm.stack_push(Type::Fixnum);
+ asm.mov(dst, out_val);
+
+ true
+}
+
fn jit_rb_int_div(
jit: &mut JITState,
asm: &mut Assembler,
@@ -10525,6 +10554,7 @@ pub fn yjit_reg_method_codegen_fns() {
reg_method_codegen(rb_cInteger, "===", jit_rb_int_equal);
reg_method_codegen(rb_cInteger, "succ", jit_rb_int_succ);
+ reg_method_codegen(rb_cInteger, "pred", jit_rb_int_pred);
reg_method_codegen(rb_cInteger, "/", jit_rb_int_div);
reg_method_codegen(rb_cInteger, "<<", jit_rb_int_lshift);
reg_method_codegen(rb_cInteger, ">>", jit_rb_int_rshift);
diff --git a/yjit/src/stats.rs b/yjit/src/stats.rs
index c2c9bc7e21..325d64487c 100644
--- a/yjit/src/stats.rs
+++ b/yjit/src/stats.rs
@@ -420,6 +420,8 @@ make_counters! {
send_bmethod_ractor,
send_bmethod_block_arg,
send_optimized_block_arg,
+ send_pred_not_fixnum,
+ send_pred_underflow,
invokesuper_defined_class_mismatch,
invokesuper_forwarding,