blob: 9383c189b27a02757571e1841c5d0197a095fddb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
require 'mjit/insn_compiler'
require 'mjit/instruction'
require 'mjit/x86_assembler'
module RubyVM::MJIT
# Compilation status
KeepCompiling = :keep_compiling
CantCompile = :cant_compile
EndBlock = :end_block
class Compiler
attr_accessor :write_pos
# @param mem_block [Integer] JIT buffer address
def initialize(mem_block)
@mem_block = mem_block
@write_pos = 0
@insn_compiler = InsnCompiler.new
end
# @param iseq [RubyVM::MJIT::CPointer::Struct]
def call(iseq)
return if iseq.body.location.label == '<main>'
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
def write_addr
@mem_block + @write_pos
end
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)
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
def dump_disasm(from, to)
C.dump_disasm(from, to).each do |address, mnemonic, op_str|
puts " 0x#{"%p" % address}: #{mnemonic} #{op_str}"
end
end
end
end
|