summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-02-13 23:05:56 -0800
committerTakashi Kokubun <[email protected]>2023-03-05 23:28:59 -0800
commitbc50b0475a64dbae293c29bf3e6b72ba12424c99 (patch)
treedd6f18bc22ce6e31df27944a4671f8e5106ecb59 /lib
parent67cc53214cdb5900ccc75e195d8e9c85dea519f9 (diff)
Implement opt_and and opt_or
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/7448
Diffstat (limited to 'lib')
-rw-r--r--lib/ruby_vm/mjit/assembler.rb27
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb86
2 files changed, 108 insertions, 5 deletions
diff --git a/lib/ruby_vm/mjit/assembler.rb b/lib/ruby_vm/mjit/assembler.rb
index 5ea24266fc..bbc9691b56 100644
--- a/lib/ruby_vm/mjit/assembler.rb
+++ b/lib/ruby_vm/mjit/assembler.rb
@@ -121,6 +121,16 @@ module RubyVM::MJIT
mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg],
imm: imm8(src_imm),
)
+ # AND r64, r/m64 (Mod 01: [reg]+disp8)
+ in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_disp]] if r64?(dst_reg) && r64?(src_reg) && imm8?(src_disp)
+ # REX.W + 23 /r
+ # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
+ insn(
+ prefix: REX_W,
+ opcode: 0x23,
+ mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
+ disp: imm8(src_disp),
+ )
else
raise NotImplementedError, "and: not-implemented operands: #{dst.inspect}, #{src.inspect}"
end
@@ -545,6 +555,23 @@ module RubyVM::MJIT
end
end
+ def or(dst, src)
+ case [dst, src]
+ # OR r64, r/m64 (Mod 01: [reg]+disp8)
+ in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_disp]] if r64?(dst_reg) && r64?(src_reg) && imm8?(src_disp)
+ # REX.W + 0B /r
+ # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
+ insn(
+ prefix: REX_W,
+ opcode: 0x0b,
+ mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
+ disp: imm8(src_disp),
+ )
+ else
+ raise NotImplementedError, "or: not-implemented operands: #{dst.inspect}, #{src.inspect}"
+ end
+ end
+
def push(src)
case src
# PUSH r64
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb
index cc62a267ad..95d837b073 100644
--- a/lib/ruby_vm/mjit/insn_compiler.rb
+++ b/lib/ruby_vm/mjit/insn_compiler.rb
@@ -23,7 +23,7 @@ module RubyVM::MJIT
asm.incr_counter(:mjit_insns_count)
asm.comment("Insn: #{insn.name}")
- # 36/101
+ # 38/101
case insn.name
when :nop then nop(jit, ctx, asm)
# getlocal
@@ -105,8 +105,8 @@ module RubyVM::MJIT
when :opt_gt then opt_gt(jit, ctx, asm)
when :opt_ge then opt_ge(jit, ctx, asm)
when :opt_ltlt then opt_ltlt(jit, ctx, asm)
- # opt_and
- # opt_or
+ when :opt_and then opt_and(jit, ctx, asm)
+ when :opt_or then opt_or(jit, ctx, asm)
when :opt_aref then opt_aref(jit, ctx, asm)
# opt_aset
# opt_aset_with
@@ -648,8 +648,84 @@ module RubyVM::MJIT
opt_send_without_block(jit, ctx, asm)
end
- # opt_and
- # opt_or
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_and(jit, ctx, asm)
+ unless jit.at_current_insn?
+ defer_compilation(jit, ctx, asm)
+ return EndBlock
+ end
+
+ if two_fixnums_on_stack?(jit)
+ # Create a side-exit to fall back to the interpreter
+ # Note: we generate the side-exit before popping operands from the stack
+ side_exit = side_exit(jit, ctx)
+
+ unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_AND)
+ return CantCompile
+ end
+
+ # Check that both operands are fixnums
+ guard_two_fixnums(jit, ctx, asm, side_exit)
+
+ # Get the operands and destination from the stack
+ arg1 = ctx.stack_pop(1)
+ arg0 = ctx.stack_pop(1)
+
+ asm.comment('bitwise and')
+ asm.mov(:rax, arg0)
+ asm.and(:rax, arg1)
+
+ # Push the return value onto the stack
+ dst = ctx.stack_push
+ asm.mov(dst, :rax)
+
+ KeepCompiling
+ else
+ opt_send_without_block(jit, ctx, asm)
+ end
+ end
+
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_or(jit, ctx, asm)
+ unless jit.at_current_insn?
+ defer_compilation(jit, ctx, asm)
+ return EndBlock
+ end
+
+ if two_fixnums_on_stack?(jit)
+ # Create a side-exit to fall back to the interpreter
+ # Note: we generate the side-exit before popping operands from the stack
+ side_exit = side_exit(jit, ctx)
+
+ unless Invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_OR)
+ return CantCompile
+ end
+
+ # Check that both operands are fixnums
+ guard_two_fixnums(jit, ctx, asm, side_exit)
+
+ # Get the operands and destination from the stack
+ asm.comment('bitwise or')
+ arg1 = ctx.stack_pop(1)
+ arg0 = ctx.stack_pop(1)
+
+ # Do the bitwise or arg0 | arg1
+ asm.mov(:rax, arg0)
+ asm.or(:rax, arg1)
+
+ # Push the return value onto the stack
+ dst = ctx.stack_push
+ asm.mov(dst, :rax)
+
+ KeepCompiling
+ else
+ opt_send_without_block(jit, ctx, asm)
+ end
+ end
# @param jit [RubyVM::MJIT::JITState]
# @param ctx [RubyVM::MJIT::Context]