summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstraptest/test_yjit.rb8
-rw-r--r--yjit/src/codegen.rs28
2 files changed, 36 insertions, 0 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index a13a8d6295..a2c46b8fb9 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -1,3 +1,6 @@
+# To run the tests in this file only, with YJIT enabled:
+# make btest BTESTS=bootstraptest/test_yjit.rb RUN_OPTS="--yjit-call-threshold=1"
+
# regression test for popping before side exit
assert_equal "ok", %q{
def foo(a, *) = a
@@ -4451,6 +4454,11 @@ assert_equal '[0, 1, -4]', %q{
[0 >> 1, 2 >> 1, -7 >> 1]
}
+# Integer XOR
+assert_equal '[0, 0, 4]', %q{
+ [0 ^ 0, 1 ^ 1, 7 ^ 3]
+}
+
assert_equal '[nil, "yield"]', %q{
def defined_yield = defined?(yield)
[defined_yield, defined_yield {}]
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index cb979b247b..029e19b71b 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -4877,6 +4877,33 @@ fn jit_rb_int_rshift(
true
}
+fn jit_rb_int_xor(
+ jit: &mut JITState,
+ asm: &mut Assembler,
+ ocb: &mut OutlinedCb,
+ _ci: *const rb_callinfo,
+ _cme: *const rb_callable_method_entry_t,
+ _block: Option<BlockHandler>,
+ _argc: i32,
+ _known_recv_class: *const VALUE,
+) -> bool {
+ if asm.ctx.two_fixnums_on_stack(jit) != Some(true) {
+ return false;
+ }
+ guard_two_fixnums(jit, asm, ocb);
+
+ let rhs = asm.stack_pop(1);
+ let lhs = asm.stack_pop(1);
+
+ // XOR and then re-tag the resulting fixnum
+ let out_val = asm.xor(lhs, rhs);
+ let out_val = asm.or(out_val, 1.into());
+
+ let ret_opnd = asm.stack_push(Type::Fixnum);
+ asm.mov(ret_opnd, out_val);
+ true
+}
+
fn jit_rb_int_aref(
jit: &mut JITState,
asm: &mut Assembler,
@@ -9090,6 +9117,7 @@ pub fn yjit_reg_method_codegen_fns() {
yjit_reg_method(rb_cInteger, "/", jit_rb_int_div);
yjit_reg_method(rb_cInteger, "<<", jit_rb_int_lshift);
yjit_reg_method(rb_cInteger, ">>", jit_rb_int_rshift);
+ yjit_reg_method(rb_cInteger, "^", jit_rb_int_xor);
yjit_reg_method(rb_cInteger, "[]", jit_rb_int_aref);
yjit_reg_method(rb_cString, "empty?", jit_rb_str_empty_p);