summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2022-12-17 13:39:35 -0800
committerTakashi Kokubun <takashikkbn@gmail.com>2023-03-05 22:11:20 -0800
commitd9c2eb6f4288e5a0b03222854b4ad62c2047cd2b (patch)
tree2c17f14c8b6230dec9a5a2b58dc9ccf2f672d23d
parent6fc336fedcbf58cceedd272ecf1ac2f725662f73 (diff)
downloadruby-d9c2eb6f4288e5a0b03222854b4ad62c2047cd2b.tar.gz
Move modules around
-rw-r--r--lib/mjit/insn_compiler.rb19
-rw-r--r--lib/mjit/x86_64/assembler.rb60
-rw-r--r--lib/mjit/x86_assembler.rb62
-rw-r--r--lib/ruby_vm/mjit/compiler.rb91
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb2
5 files changed, 138 insertions, 96 deletions
diff --git a/lib/mjit/insn_compiler.rb b/lib/mjit/insn_compiler.rb
new file mode 100644
index 0000000000..c32dd808db
--- /dev/null
+++ b/lib/mjit/insn_compiler.rb
@@ -0,0 +1,19 @@
+module RubyVM::MJIT
+ class InsnCompiler
+ def compile_putnil(_asm)
+ # TODO
+ KeepCompiling
+ end
+
+ def compile_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)
+
+ # return a value
+ asm.mov(:rax, 7)
+ asm.ret
+ EndBlock
+ end
+ end
+end
diff --git a/lib/mjit/x86_64/assembler.rb b/lib/mjit/x86_64/assembler.rb
deleted file mode 100644
index be6480bba7..0000000000
--- a/lib/mjit/x86_64/assembler.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-class RubyVM::MJIT::Assembler
- ByteWriter = RubyVM::MJIT::CType::Immediate.parse('char')
-
- def initialize
- @bytes = []
- end
-
- def compile(compiler) = with_dump_disasm(compiler) do
- RubyVM::MJIT::C.mjit_mark_writable
- write_bytes(compiler.write_addr, @bytes)
- RubyVM::MJIT::C.mjit_mark_executable
-
- compiler.write_pos += @bytes.size
- @bytes.clear
- end
-
- def add(_reg, imm)
- # REX.W [83] RSI ib
- @bytes.push(0x48, 0x83, 0xc6, imm)
- end
-
- def mov(reg, val)
- case reg
- when :rax
- # REX.W [C7] RAX imm32
- @bytes.push(0x48, 0xc7, 0xc0, val, 0x00, 0x00, 0x00)
- else
- # REX.W [89] [rdi+val],rsi
- @bytes.push(0x48, 0x89, 0x77, reg.last)
- end
- end
-
- def ret
- # Near return
- # [C3]
- @bytes.push(0xc3)
- end
-
- private
-
- def with_dump_disasm(compiler)
- from = compiler.write_addr
- yield
- to = compiler.write_addr
- if RubyVM::MJIT::C.mjit_opts.dump_disasm && from < to
- RubyVM::MJIT::C.dump_disasm(from, to).each do |address, mnemonic, op_str|
- puts " 0x#{"%p" % address}: #{mnemonic} #{op_str}"
- end
- end
- end
-
- def write_bytes(addr, bytes)
- writer = ByteWriter.new(addr)
- # If you pack bytes containing \x00, Ruby fails to recognize bytes after \x00.
- # So writing byte by byte to avoid hitting that situation.
- bytes.each_with_index do |byte, index|
- writer[index] = byte
- end
- end
-end
diff --git a/lib/mjit/x86_assembler.rb b/lib/mjit/x86_assembler.rb
new file mode 100644
index 0000000000..b89438f552
--- /dev/null
+++ b/lib/mjit/x86_assembler.rb
@@ -0,0 +1,62 @@
+module RubyVM::MJIT
+ class X86Assembler
+ ByteWriter = CType::Immediate.parse('char')
+
+ def initialize
+ @bytes = []
+ end
+
+ def compile(compiler) = with_dump_disasm(compiler) do
+ C.mjit_mark_writable
+ write_bytes(compiler.write_addr, @bytes)
+ C.mjit_mark_executable
+
+ compiler.write_pos += @bytes.size
+ @bytes.clear
+ end
+
+ def add(_reg, imm)
+ # REX.W [83] RSI ib
+ @bytes.push(0x48, 0x83, 0xc6, imm)
+ end
+
+ def mov(reg, val)
+ case reg
+ when :rax
+ # REX.W [C7] RAX imm32
+ @bytes.push(0x48, 0xc7, 0xc0, val, 0x00, 0x00, 0x00)
+ else
+ # REX.W [89] [rdi+val],rsi
+ @bytes.push(0x48, 0x89, 0x77, reg.last)
+ end
+ end
+
+ def ret
+ # Near return
+ # [C3]
+ @bytes.push(0xc3)
+ end
+
+ private
+
+ def with_dump_disasm(compiler)
+ from = compiler.write_addr
+ yield
+ to = compiler.write_addr
+ if C.mjit_opts.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
+
+ def write_bytes(addr, bytes)
+ writer = ByteWriter.new(addr)
+ # If you pack bytes containing \x00, Ruby fails to recognize bytes after \x00.
+ # So writing byte by byte to avoid hitting that situation.
+ bytes.each_with_index do |byte, index|
+ writer[index] = byte
+ end
+ end
+ end
+end
diff --git a/lib/ruby_vm/mjit/compiler.rb b/lib/ruby_vm/mjit/compiler.rb
index 4b980c1400..1dfa3a3592 100644
--- a/lib/ruby_vm/mjit/compiler.rb
+++ b/lib/ruby_vm/mjit/compiler.rb
@@ -1,47 +1,70 @@
-require 'mjit/x86_64/assembler'
+require 'mjit/insn_compiler'
+require 'mjit/instruction'
+require 'mjit/x86_assembler'
-class RubyVM::MJIT::Compiler
- # MJIT internals
- Assembler = RubyVM::MJIT::Assembler
- C = RubyVM::MJIT::C
+module RubyVM::MJIT
+ # Compilation status
+ KeepCompiling = :keep_compiling
+ CantCompile = :cant_compile
+ EndBlock = :end_block
- # Ruby constants
- Qundef = Fiddle::Qundef
+ class Compiler
+ # Ruby constants
+ Qundef = Fiddle::Qundef
- attr_accessor :write_pos
+ attr_accessor :write_pos
- # @param mem_block [Integer] JIT buffer address
- def initialize(mem_block)
- @mem_block = mem_block
- @write_pos = 0
- end
+ # @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 compile(iseq)
- return if iseq.body.location.label == '<main>'
- iseq.body.jit_func = compile_iseq(iseq)
- end
+ # @param iseq [RubyVM::MJIT::CPointer::Struct]
+ def compile(iseq)
+ return if iseq.body.location.label == '<main>'
+ iseq.body.jit_func = compile_iseq(iseq)
+ rescue Exception => e
+ # TODO: check --mjit-verbose
+ $stderr.puts e.full_message
+ end
- def write_addr
- @mem_block + @write_pos
- end
+ def write_addr
+ @mem_block + @write_pos
+ end
+
+ private
- private
+ # ec -> RDI, cfp -> RSI
+ def compile_iseq(iseq)
+ addr = write_addr
+ asm = X86Assembler.new
- # ec -> RDI, cfp -> RSI
- def compile_iseq(iseq)
- addr = write_addr
- asm = Assembler.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
- # 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.compile(self)
+ addr
+ end
- # return a value
- asm.mov(:rax, 7)
- asm.ret
+ def compile_insn(asm, insn)
+ case insn.name
+ when :putnil then @insn_compiler.compile_putnil(asm)
+ when :leave then @insn_compiler.compile_leave(asm)
+ else raise NotImplementedError, "insn '#{insn.name}' is not supported yet"
+ end
+ end
- asm.compile(self)
- addr
+ def decode_insn(encoded)
+ INSNS.fetch(C.rb_vm_insn_decode(encoded))
+ end
end
end
diff --git a/tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb b/tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb
index 4b20e896a2..38b9c1f92e 100644
--- a/tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb
+++ b/tool/ruby_vm/views/lib/ruby_vm/mjit/instruction.rb.erb
@@ -35,6 +35,4 @@ module RubyVM::MJIT # :nodoc: all
),
% end
}
-
- private_constant(*constants)
end