diff options
-rw-r--r-- | bootstraptest/test_yjit.rb | 8 | ||||
-rw-r--r-- | yjit/src/codegen.rs | 28 |
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); |