summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-01-07 14:06:38 -0800
committerTakashi Kokubun <[email protected]>2023-03-05 22:11:20 -0800
commit9ef04f56367453d9c3a374bb4dfda2b64ba57924 (patch)
tree42540fa5a6cba15d45273b45518df44ea7e4e125 /lib
parentee6d627b434c4bc977c059a0e1d885800de90b63 (diff)
Implement opt_minus
Diffstat (limited to 'lib')
-rw-r--r--lib/ruby_vm/mjit/assembler.rb29
-rw-r--r--lib/ruby_vm/mjit/insn_compiler.rb53
2 files changed, 76 insertions, 6 deletions
diff --git a/lib/ruby_vm/mjit/assembler.rb b/lib/ruby_vm/mjit/assembler.rb
index 32668ff3c8..adf7fd1821 100644
--- a/lib/ruby_vm/mjit/assembler.rb
+++ b/lib/ruby_vm/mjit/assembler.rb
@@ -163,6 +163,17 @@ module RubyVM::MJIT
end
end
+ def jo(dst)
+ case dst
+ # JO rel32
+ in Integer => dst_addr
+ # 0F 80 cd
+ insn(opcode: [0x0f, 0x80], imm: rel32(dst_addr))
+ else
+ raise NotImplementedError, "jo: not-implemented operands: #{dst.inspect}"
+ end
+ end
+
def jz(dst)
case dst
# JZ rel8
@@ -333,12 +344,28 @@ module RubyVM::MJIT
end
end
- # RET
def ret
+ # RET
# Near return: A return to a procedure within the current code segment
insn(opcode: 0xc3)
end
+ def sub(dst, src)
+ case [dst, src]
+ # SUB r/m64, r64 (Mod 11: reg)
+ in [Symbol => dst_reg, Symbol => src_reg] if r64?(dst_reg) && r64?(src_reg)
+ # REX.W + 29 /r
+ # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
+ insn(
+ prefix: REX_W,
+ opcode: 0x29,
+ mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
+ )
+ else
+ raise NotImplementedError, "sub: not-implemented operands: #{dst.inspect}, #{src.inspect}"
+ end
+ end
+
def test(left, right)
case [left, right]
# TEST r/m8*, imm8 (Mod 01: [reg]+disp8)
diff --git a/lib/ruby_vm/mjit/insn_compiler.rb b/lib/ruby_vm/mjit/insn_compiler.rb
index 3d349e611c..db2be20f4c 100644
--- a/lib/ruby_vm/mjit/insn_compiler.rb
+++ b/lib/ruby_vm/mjit/insn_compiler.rb
@@ -17,7 +17,7 @@ module RubyVM::MJIT
asm.incr_counter(:mjit_insns_count)
asm.comment("Insn: #{insn.name}")
- # 9/101
+ # 10/101
case insn.name
# nop
# getlocal
@@ -88,7 +88,7 @@ module RubyVM::MJIT
# once
# opt_case_dispatch
# opt_plus
- # opt_minus
+ when :opt_minus then opt_minus(jit, ctx, asm)
# opt_mult
# opt_div
# opt_mod
@@ -316,7 +316,50 @@ module RubyVM::MJIT
# once
# opt_case_dispatch
# opt_plus
- # opt_minus
+
+ # @param jit [RubyVM::MJIT::JITState]
+ # @param ctx [RubyVM::MJIT::Context]
+ # @param asm [RubyVM::MJIT::Assembler]
+ def opt_minus(jit, ctx, asm)
+ unless jit.at_current_insn?
+ defer_compilation(jit, ctx, asm)
+ return EndBlock
+ end
+
+ comptime_recv = jit.peek_at_stack(1)
+ comptime_obj = jit.peek_at_stack(0)
+
+ if fixnum?(comptime_recv) && fixnum?(comptime_obj)
+ unless @invariants.assume_bop_not_redefined(jit, C.INTEGER_REDEFINED_OP_FLAG, C.BOP_MINUS)
+ return CantCompile
+ end
+
+ raise 'sp_offset != stack_size' if ctx.sp_offset != ctx.stack_size # TODO: handle this
+ recv_index = ctx.stack_size - 2
+ obj_index = ctx.stack_size - 1
+
+ asm.comment('guard recv is fixnum') # TODO: skip this with type information
+ asm.test([SP, C.VALUE.size * recv_index], C.RUBY_FIXNUM_FLAG)
+ asm.jz(side_exit(jit, ctx))
+
+ asm.comment('guard obj is fixnum') # TODO: skip this with type information
+ asm.test([SP, C.VALUE.size * obj_index], C.RUBY_FIXNUM_FLAG)
+ asm.jz(side_exit(jit, ctx))
+
+ asm.mov(:rax, [SP, C.VALUE.size * recv_index])
+ asm.mov(:rcx, [SP, C.VALUE.size * obj_index])
+ asm.sub(:rax, :rcx)
+ asm.jo(side_exit(jit, ctx))
+ asm.add(:rax, 1)
+ asm.mov([SP, C.VALUE.size * recv_index], :rax)
+
+ ctx.stack_pop(1)
+ KeepCompiling
+ else
+ CantCompile # TODO: delegate to send
+ end
+ end
+
# opt_mult
# opt_div
# opt_mod
@@ -346,11 +389,11 @@ module RubyVM::MJIT
asm.comment('guard recv is fixnum') # TODO: skip this with type information
asm.test([SP, C.VALUE.size * recv_index], C.RUBY_FIXNUM_FLAG)
- asm.je(side_exit(jit, ctx))
+ asm.jz(side_exit(jit, ctx))
asm.comment('guard obj is fixnum') # TODO: skip this with type information
asm.test([SP, C.VALUE.size * obj_index], C.RUBY_FIXNUM_FLAG)
- asm.je(side_exit(jit, ctx))
+ asm.jz(side_exit(jit, ctx))
asm.mov(:rax, [SP, C.VALUE.size * obj_index])
asm.cmp([SP, C.VALUE.size * recv_index], :rax)