зеркало из https://github.com/github/ruby.git
Implement a no-op JIT compiler
This commit is contained in:
Родитель
baa120ee80
Коммит
fd04e1b4db
|
@ -0,0 +1,35 @@
|
||||||
|
class RubyVM::MJIT::Assembler
|
||||||
|
ByteWriter = RubyVM::MJIT::CType::Immediate.parse('char')
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@bytes = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def compile(compiler)
|
||||||
|
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 mov(_reg, val)
|
||||||
|
@bytes.push(0xb8, val, 0x00, 0x00, 0x00)
|
||||||
|
end
|
||||||
|
|
||||||
|
def ret
|
||||||
|
@bytes.push(0xc3)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
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
|
|
@ -1,6 +1,14 @@
|
||||||
|
require 'mjit/x86_64/assembler'
|
||||||
|
|
||||||
class RubyVM::MJIT::Compiler
|
class RubyVM::MJIT::Compiler
|
||||||
C = RubyVM::MJIT.const_get(:C, false)
|
# MJIT internals
|
||||||
INSNS = RubyVM::MJIT.const_get(:INSNS, false)
|
Assembler = RubyVM::MJIT::Assembler
|
||||||
|
C = RubyVM::MJIT::C
|
||||||
|
|
||||||
|
# Ruby constants
|
||||||
|
Qundef = Fiddle::Qundef
|
||||||
|
|
||||||
|
attr_accessor :write_pos
|
||||||
|
|
||||||
# @param mem_block [Integer] JIT buffer address
|
# @param mem_block [Integer] JIT buffer address
|
||||||
def initialize(mem_block)
|
def initialize(mem_block)
|
||||||
|
@ -10,6 +18,16 @@ class RubyVM::MJIT::Compiler
|
||||||
|
|
||||||
# @param iseq [RubyVM::MJIT::CPointer::Struct]
|
# @param iseq [RubyVM::MJIT::CPointer::Struct]
|
||||||
def compile(iseq)
|
def compile(iseq)
|
||||||
# TODO: implement
|
return if iseq.body.location.label == '<main>'
|
||||||
|
|
||||||
|
iseq.body.jit_func = write_addr
|
||||||
|
asm = Assembler.new
|
||||||
|
asm.mov(:eax, Qundef)
|
||||||
|
asm.ret
|
||||||
|
asm.compile(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_addr
|
||||||
|
@mem_block + @write_pos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
8
mjit.c
8
mjit.c
|
@ -371,8 +371,8 @@ mjit_compile(FILE *f, const rb_iseq_t *iseq, const char *funcname, int id)
|
||||||
// New stuff from here
|
// New stuff from here
|
||||||
//
|
//
|
||||||
|
|
||||||
// TODO: Make it configurable
|
// JIT buffer
|
||||||
#define MJIT_CODE_SIZE 16 * 1024 * 1024
|
uint8_t *rb_mjit_mem_block = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_mjit_compile(const rb_iseq_t *iseq)
|
rb_mjit_compile(const rb_iseq_t *iseq)
|
||||||
|
@ -393,7 +393,7 @@ mjit_init(const struct mjit_options *opts)
|
||||||
mjit_opts = *opts;
|
mjit_opts = *opts;
|
||||||
|
|
||||||
extern uint8_t* rb_yjit_reserve_addr_space(uint32_t mem_size);
|
extern uint8_t* rb_yjit_reserve_addr_space(uint32_t mem_size);
|
||||||
uint8_t *mem_block = rb_yjit_reserve_addr_space(MJIT_CODE_SIZE);
|
rb_mjit_mem_block = rb_yjit_reserve_addr_space(MJIT_CODE_SIZE);
|
||||||
|
|
||||||
// MJIT doesn't support miniruby, but it might reach here by MJIT_FORCE_ENABLE.
|
// MJIT doesn't support miniruby, but it might reach here by MJIT_FORCE_ENABLE.
|
||||||
rb_mMJIT = rb_const_get(rb_cRubyVM, rb_intern("MJIT"));
|
rb_mMJIT = rb_const_get(rb_cRubyVM, rb_intern("MJIT"));
|
||||||
|
@ -404,7 +404,7 @@ mjit_init(const struct mjit_options *opts)
|
||||||
}
|
}
|
||||||
rb_mMJITC = rb_const_get(rb_mMJIT, rb_intern("C"));
|
rb_mMJITC = rb_const_get(rb_mMJIT, rb_intern("C"));
|
||||||
VALUE rb_cMJITCompiler = rb_const_get(rb_mMJIT, rb_intern("Compiler"));
|
VALUE rb_cMJITCompiler = rb_const_get(rb_mMJIT, rb_intern("Compiler"));
|
||||||
rb_MJITCompiler = rb_funcall(rb_cMJITCompiler, rb_intern("new"), 1, SIZET2NUM((size_t)mem_block));
|
rb_MJITCompiler = rb_funcall(rb_cMJITCompiler, rb_intern("new"), 1, SIZET2NUM((size_t)rb_mjit_mem_block));
|
||||||
rb_cMJITIseqPtr = rb_funcall(rb_mMJITC, rb_intern("rb_iseq_t"), 0);
|
rb_cMJITIseqPtr = rb_funcall(rb_mMJITC, rb_intern("rb_iseq_t"), 0);
|
||||||
|
|
||||||
mjit_call_p = true;
|
mjit_call_p = true;
|
||||||
|
|
14
mjit.rb
14
mjit.rb
|
@ -23,15 +23,7 @@ if RubyVM::MJIT.enabled?
|
||||||
return # miniruby doesn't support MJIT
|
return # miniruby doesn't support MJIT
|
||||||
end
|
end
|
||||||
|
|
||||||
# forward declaration for ruby_vm/mjit/compiler
|
RubyVM::MJIT::C = Object.new # forward declaration for mjit/compiler
|
||||||
RubyVM::MJIT::C = Object.new # :nodoc:
|
require 'mjit/c_type'
|
||||||
|
require 'mjit/compiler'
|
||||||
require 'ruby_vm/mjit/c_type'
|
|
||||||
require 'ruby_vm/mjit/instruction'
|
|
||||||
require 'ruby_vm/mjit/compiler'
|
|
||||||
require 'ruby_vm/mjit/hooks'
|
|
||||||
|
|
||||||
module RubyVM::MJIT
|
|
||||||
private_constant(*constants)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
10
mjit_c.h
10
mjit_c.h
|
@ -94,4 +94,14 @@ struct compile_status {
|
||||||
struct inlined_call_context inline_context;
|
struct inlined_call_context inline_context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//================================================================================
|
||||||
|
//
|
||||||
|
// New stuff from here
|
||||||
|
//
|
||||||
|
|
||||||
|
// TODO: Make it configurable
|
||||||
|
#define MJIT_CODE_SIZE 16 * 1024 * 1024
|
||||||
|
|
||||||
|
extern uint8_t *rb_mjit_mem_block;
|
||||||
|
|
||||||
#endif /* MJIT_C_H */
|
#endif /* MJIT_C_H */
|
||||||
|
|
24
mjit_c.rb
24
mjit_c.rb
|
@ -5,6 +5,30 @@ module RubyVM::MJIT # :nodoc: all
|
||||||
# This `class << C` section is for calling C functions. For importing variables
|
# This `class << C` section is for calling C functions. For importing variables
|
||||||
# or macros as is, please consider using tool/mjit/bindgen.rb instead.
|
# or macros as is, please consider using tool/mjit/bindgen.rb instead.
|
||||||
class << C
|
class << C
|
||||||
|
#========================================================================================
|
||||||
|
#
|
||||||
|
# New stuff
|
||||||
|
#
|
||||||
|
def mjit_mark_writable
|
||||||
|
Primitive.cstmt! %{
|
||||||
|
extern bool rb_yjit_mark_writable(void *mem_block, uint32_t mem_size);
|
||||||
|
rb_yjit_mark_writable(rb_mjit_mem_block, MJIT_CODE_SIZE);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def mjit_mark_executable
|
||||||
|
Primitive.cstmt! %{
|
||||||
|
extern bool rb_yjit_mark_executable(void *mem_block, uint32_t mem_size);
|
||||||
|
rb_yjit_mark_executable(rb_mjit_mem_block, MJIT_CODE_SIZE);
|
||||||
|
return Qnil;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
#========================================================================================
|
||||||
|
#
|
||||||
|
# Old stuff
|
||||||
|
#
|
||||||
def rb_hash_values(cdhash_addr)
|
def rb_hash_values(cdhash_addr)
|
||||||
Primitive.cexpr! 'rb_hash_values((VALUE)NUM2PTR(cdhash_addr))'
|
Primitive.cexpr! 'rb_hash_values((VALUE)NUM2PTR(cdhash_addr))'
|
||||||
end
|
end
|
||||||
|
|
Загрузка…
Ссылка в новой задаче