mirror of
https://github.com/ruby/ruby.git
synced 2025-08-25 22:14:37 +02:00
Compile putnil properly
This commit is contained in:
parent
8deb0438c4
commit
145c937f3f
3 changed files with 65 additions and 37 deletions
|
@ -1,14 +1,21 @@
|
||||||
module RubyVM::MJIT
|
module RubyVM::MJIT
|
||||||
|
# ec: rdi
|
||||||
|
# cfp: rsi
|
||||||
|
# sp: rbx
|
||||||
|
# scratch regs: rax
|
||||||
class InsnCompiler
|
class InsnCompiler
|
||||||
def putnil(_asm)
|
# Ruby constants
|
||||||
# TODO
|
Qnil = Fiddle::Qnil
|
||||||
|
|
||||||
|
def putnil(asm)
|
||||||
|
asm.mov([:rbx], Qnil)
|
||||||
KeepCompiling
|
KeepCompiling
|
||||||
end
|
end
|
||||||
|
|
||||||
def leave(asm)
|
def leave(asm)
|
||||||
# pop the current frame (ec->cfp++)
|
# pop the current frame (ec->cfp++)
|
||||||
asm.add(:rsi, C.rb_control_frame_t.size)
|
asm.add(:rsi, C.rb_control_frame_t.size) # rsi = cfp + 1
|
||||||
asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi)
|
asm.mov([:rdi, C.rb_execution_context_t.offsetof(:cfp)], :rsi) # ec->cfp = rsi
|
||||||
|
|
||||||
# return a value
|
# return a value
|
||||||
asm.mov(:rax, 1001)
|
asm.mov(:rax, 1001)
|
||||||
|
|
|
@ -43,14 +43,24 @@ module RubyVM::MJIT
|
||||||
|
|
||||||
def mov(dst, src)
|
def mov(dst, src)
|
||||||
case [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)
|
in [Symbol => dst_reg, Integer => src_imm] if r_reg?(dst_reg)
|
||||||
# REX.W + C7 /0 id
|
# REX.W + C7 /0 id
|
||||||
# MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
|
# MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
|
||||||
insn(
|
insn(
|
||||||
prefix: REX_W,
|
prefix: REX_W,
|
||||||
opcode: 0xc7,
|
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),
|
imm: imm32(src_imm),
|
||||||
)
|
)
|
||||||
# MOV r/m64, r64
|
# MOV r/m64, r64
|
||||||
|
@ -60,9 +70,19 @@ module RubyVM::MJIT
|
||||||
insn(
|
insn(
|
||||||
prefix: REX_W,
|
prefix: REX_W,
|
||||||
opcode: 0x89,
|
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,
|
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
|
else
|
||||||
raise NotImplementedError, "mov: not-implemented input: #{dst.inspect}, #{src.inspect}"
|
raise NotImplementedError, "mov: not-implemented input: #{dst.inspect}, #{src.inspect}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,9 +9,6 @@ module RubyVM::MJIT
|
||||||
EndBlock = :end_block
|
EndBlock = :end_block
|
||||||
|
|
||||||
class Compiler
|
class Compiler
|
||||||
# Ruby constants
|
|
||||||
Qundef = Fiddle::Qundef
|
|
||||||
|
|
||||||
attr_accessor :write_pos
|
attr_accessor :write_pos
|
||||||
|
|
||||||
# @param mem_block [Integer] JIT buffer address
|
# @param mem_block [Integer] JIT buffer address
|
||||||
|
@ -24,7 +21,11 @@ module RubyVM::MJIT
|
||||||
# @param iseq [RubyVM::MJIT::CPointer::Struct]
|
# @param iseq [RubyVM::MJIT::CPointer::Struct]
|
||||||
def call(iseq)
|
def call(iseq)
|
||||||
return if iseq.body.location.label == '<main>'
|
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
|
rescue Exception => e
|
||||||
$stderr.puts e.full_message # TODO: check verbose
|
$stderr.puts e.full_message # TODO: check verbose
|
||||||
end
|
end
|
||||||
|
@ -35,6 +36,32 @@ module RubyVM::MJIT
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
# ec: rdi
|
||||||
|
# cfp: rsi
|
||||||
|
def compile_prologue(asm)
|
||||||
|
asm.mov(:rbx, [:rsi, C.rb_control_frame_t.offsetof(:sp)]) # rbx = cfp->sp
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile_block(asm, iseq)
|
||||||
|
index = 0
|
||||||
|
while index < iseq.body.iseq_size
|
||||||
|
insn = decode_insn(iseq.body.iseq_encoded[index])
|
||||||
|
status = compile_insn(asm, insn)
|
||||||
|
if status == EndBlock
|
||||||
|
break
|
||||||
|
end
|
||||||
|
index += insn.len
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile_insn(asm, insn)
|
||||||
|
case insn.name
|
||||||
|
when :putnil then @insn_compiler.putnil(asm)
|
||||||
|
when :leave then @insn_compiler.leave(asm)
|
||||||
|
else raise NotImplementedError, "insn '#{insn.name}' is not supported yet"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def compile(asm)
|
def compile(asm)
|
||||||
start_addr = write_addr
|
start_addr = write_addr
|
||||||
|
|
||||||
|
@ -49,32 +76,6 @@ module RubyVM::MJIT
|
||||||
start_addr
|
start_addr
|
||||||
end
|
end
|
||||||
|
|
||||||
# ec -> RDI, cfp -> RSI
|
|
||||||
def compile_block(iseq)
|
|
||||||
addr = write_addr
|
|
||||||
asm = X86Assembler.new
|
|
||||||
|
|
||||||
index = 0
|
|
||||||
while index < iseq.body.iseq_size
|
|
||||||
insn = decode_insn(iseq.body.iseq_encoded[index])
|
|
||||||
status = compile_insn(asm, insn)
|
|
||||||
if status == EndBlock
|
|
||||||
break
|
|
||||||
end
|
|
||||||
index += insn.len
|
|
||||||
end
|
|
||||||
|
|
||||||
compile(asm)
|
|
||||||
end
|
|
||||||
|
|
||||||
def compile_insn(asm, insn)
|
|
||||||
case insn.name
|
|
||||||
when :putnil then @insn_compiler.putnil(asm)
|
|
||||||
when :leave then @insn_compiler.leave(asm)
|
|
||||||
else raise NotImplementedError, "insn '#{insn.name}' is not supported yet"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def decode_insn(encoded)
|
def decode_insn(encoded)
|
||||||
INSNS.fetch(C.rb_vm_insn_decode(encoded))
|
INSNS.fetch(C.rb_vm_insn_decode(encoded))
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue