diff options
-rw-r--r-- | lib/mjit/insn_compiler.rb | 15 | ||||
-rw-r--r-- | lib/mjit/x86_assembler.rb | 26 | ||||
-rw-r--r-- | lib/ruby_vm/mjit/compiler.rb | 47 |
3 files changed, 58 insertions, 30 deletions
diff --git a/lib/mjit/insn_compiler.rb b/lib/mjit/insn_compiler.rb index c6f88b37fb..4dbb19a96e 100644 --- a/lib/mjit/insn_compiler.rb +++ b/lib/mjit/insn_compiler.rb @@ -1,14 +1,21 @@ module RubyVM::MJIT + # ec: rdi + # cfp: rsi + # sp: rbx + # scratch regs: rax class InsnCompiler - def putnil(_asm) - # TODO + # Ruby constants + Qnil = Fiddle::Qnil + + def putnil(asm) + asm.mov([:rbx], Qnil) KeepCompiling end def leave(asm) # pop the current frame (ec->cfp++) - asm.add(:rsi, C.rb_control_frame_t.size) - asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi) + asm.add(:rsi, C.rb_control_frame_t.size) # rsi = cfp + 1 + asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi) # ec->cfp = rsi # return a value asm.mov(:rax, 1001) diff --git a/lib/mjit/x86_assembler.rb b/lib/mjit/x86_assembler.rb index 934bf071c7..bc447e7808 100644 --- a/lib/mjit/x86_assembler.rb +++ b/lib/mjit/x86_assembler.rb @@ -43,14 +43,24 @@ module RubyVM::MJIT def mov(dst, src) case [dst, src] - # MOV r/m64, imm32 + # MOV r/m64, imm32 (Mod 00) + in [[Symbol => dst_reg], Integer => src_imm] if r_reg?(dst_reg) + # REX.W + C7 /0 id + # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64 + insn( + prefix: REX_W, + opcode: 0xc7, + mod_rm: mod_rm(mod: 0b00, rm: reg_code(dst_reg)), # Mod 00: [reg] + imm: imm32(src_imm), + ) + # MOV r/m64, imm32 (Mod 11) in [Symbol => dst_reg, Integer => src_imm] if r_reg?(dst_reg) # REX.W + C7 /0 id # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64 insn( prefix: REX_W, opcode: 0xc7, - mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)), + mod_rm: mod_rm(mod: 0b11, rm: reg_code(dst_reg)), # Mod 11: reg imm: imm32(src_imm), ) # MOV r/m64, r64 @@ -60,9 +70,19 @@ module RubyVM::MJIT insn( prefix: REX_W, opcode: 0x89, - mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # disp8 + mod_rm: mod_rm(mod: 0b01, reg: reg_code(src_reg), rm: reg_code(dst_reg)), # Mod 01: [reg]+disp8 disp: dst_offset, ) + # MOV r64, r/m64 + in [Symbol => dst_reg, [Symbol => src_reg, Integer => src_offset]] if r_reg?(dst_reg) && r_reg?(src_reg) && src_offset <= 0xff + # REX.W + 8B /r + # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r) + insn( + prefix: REX_W, + opcode: 0x8b, + mod_rm: mod_rm(mod: 0b01, reg: reg_code(dst_reg), rm: reg_code(src_reg)), # Mod 01: [reg]+disp8 + disp: src_offset, + ) else raise NotImplementedError, "mov: not-implemented input: #{dst.inspect}, #{src.inspect}" end diff --git a/lib/ruby_vm/mjit/compiler.rb b/lib/ruby_vm/mjit/compiler.rb index 75314501c1..9383c189b2 100644 --- a/lib/ruby_vm/mjit/compiler.rb +++ b/lib/ruby_vm/mjit/compiler.rb @@ -9,9 +9,6 @@ module RubyVM::MJIT EndBlock = :end_block class Compiler - # Ruby constants - Qundef = Fiddle::Qundef - attr_accessor :write_pos # @param mem_block [Integer] JIT buffer address @@ -24,7 +21,11 @@ module RubyVM::MJIT # @param iseq [RubyVM::MJIT::CPointer::Struct] def call(iseq) return if iseq.body.location.label == '<main>' - iseq.body.jit_func = compile_block(iseq) + + asm = X86Assembler.new + compile_prologue(asm) + compile_block(asm, iseq) + iseq.body.jit_func = compile(asm) rescue Exception => e $stderr.puts e.full_message # TODO: check verbose end @@ -35,25 +36,13 @@ module RubyVM::MJIT private - def compile(asm) - start_addr = write_addr - - C.mjit_mark_writable - @write_pos += asm.compile(start_addr) - C.mjit_mark_executable - - end_addr = write_addr - if C.mjit_opts.dump_disasm && start_addr < end_addr - dump_disasm(start_addr, end_addr) - end - start_addr + # ec: rdi + # cfp: rsi + def compile_prologue(asm) + asm.mov(:rbx, [:rsi, C.rb_control_frame_t.offsetof(:sp)]) # rbx = cfp->sp end - # ec -> RDI, cfp -> RSI - def compile_block(iseq) - addr = write_addr - asm = X86Assembler.new - + def compile_block(asm, iseq) index = 0 while index < iseq.body.iseq_size insn = decode_insn(iseq.body.iseq_encoded[index]) @@ -63,8 +52,6 @@ module RubyVM::MJIT end index += insn.len end - - compile(asm) end def compile_insn(asm, insn) @@ -75,6 +62,20 @@ module RubyVM::MJIT end end + def compile(asm) + start_addr = write_addr + + C.mjit_mark_writable + @write_pos += asm.compile(start_addr) + C.mjit_mark_executable + + end_addr = write_addr + if C.mjit_opts.dump_disasm && start_addr < end_addr + dump_disasm(start_addr, end_addr) + end + start_addr + end + def decode_insn(encoded) INSNS.fetch(C.rb_vm_insn_decode(encoded)) end |