зеркало из https://github.com/github/ruby.git
Add to the MicroJIT scraper an example that passes ec
This commit is contained in:
Родитель
008551decb
Коммит
11c1daea17
7
iseq.c
7
iseq.c
|
@ -3495,6 +3495,13 @@ rb_ujit_empty_func(rb_control_frame_t *cfp)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE *
|
||||||
|
rb_ujit_empty_func_with_ec(rb_control_frame_t *cfp, rb_execution_context_t *ec)
|
||||||
|
{
|
||||||
|
// see rb_ujit_empty_func
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_iseq_trace_set_all(rb_event_flag_t turnon_events)
|
rb_iseq_trace_set_all(rb_event_flag_t turnon_events)
|
||||||
{
|
{
|
||||||
|
|
1
iseq.h
1
iseq.h
|
@ -316,6 +316,7 @@ VALUE rb_iseq_defined_string(enum defined_type type);
|
||||||
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq);
|
VALUE rb_iseq_local_variables(const rb_iseq_t *iseq);
|
||||||
|
|
||||||
NOINLINE(VALUE *rb_ujit_empty_func(rb_control_frame_t *cfp));
|
NOINLINE(VALUE *rb_ujit_empty_func(rb_control_frame_t *cfp));
|
||||||
|
NOINLINE(VALUE *rb_ujit_empty_func_with_ec(rb_control_frame_t *cfp, rb_execution_context_t *ec));
|
||||||
|
|
||||||
|
|
||||||
RUBY_SYMBOL_EXPORT_END
|
RUBY_SYMBOL_EXPORT_END
|
||||||
|
|
|
@ -128,20 +128,23 @@ module RubyVM::MicroJIT
|
||||||
raise "found an unrecognized \"#{unrecognized[1]}\" instruction in the example. List of recognized instructions: #{acceptable_mnemonics.join(', ')}" if unrecognized
|
raise "found an unrecognized \"#{unrecognized[1]}\" instruction in the example. List of recognized instructions: #{acceptable_mnemonics.join(', ')}" if unrecognized
|
||||||
raise 'found multiple jmp instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'jmp' } > 1
|
raise 'found multiple jmp instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'jmp' } > 1
|
||||||
raise "the jmp instruction seems to be relative which isn't copiable" if instructions[jmp_idx][0].split.size > 4
|
raise "the jmp instruction seems to be relative which isn't copiable" if instructions[jmp_idx][0].split.size > 4
|
||||||
|
raise 'no call instructions found' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'call' } == 0
|
||||||
raise 'found multiple call instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'call' } > 1
|
raise 'found multiple call instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'call' } > 1
|
||||||
call_idx = handler_instructions.find_index { |_, mnemonic, _| mnemonic == 'call' }
|
call_idx = handler_instructions.find_index { |_, mnemonic, _| mnemonic == 'call' }
|
||||||
|
|
||||||
|
|
||||||
@pre_call_bytes = []
|
pre_call_bytes = []
|
||||||
@post_call_bytes = []
|
post_call_bytes = []
|
||||||
|
|
||||||
handler_instructions.take(call_idx).each do |bytes, mnemonic, _|
|
handler_instructions.take(call_idx).each do |bytes, mnemonic, _|
|
||||||
@pre_call_bytes += bytes.split
|
pre_call_bytes += bytes.split
|
||||||
end
|
end
|
||||||
|
|
||||||
handler_instructions[call_idx + 1, handler_instructions.size].each do |bytes, _, _|
|
handler_instructions[call_idx + 1, handler_instructions.size].each do |bytes, _, _|
|
||||||
@post_call_bytes += bytes.split
|
post_call_bytes += bytes.split
|
||||||
end
|
end
|
||||||
|
|
||||||
|
[pre_call_bytes, post_call_bytes]
|
||||||
end
|
end
|
||||||
|
|
||||||
def darwin_scrape(instruction_id)
|
def darwin_scrape(instruction_id)
|
||||||
|
@ -166,8 +169,19 @@ module RubyVM::MicroJIT
|
||||||
disassemble(handler_offset)
|
disassemble(handler_offset)
|
||||||
end
|
end
|
||||||
|
|
||||||
def scrape
|
def make_result(success, pre_call, post_call, pre_call_with_ec, post_call_with_ec)
|
||||||
instruction_id = RubyVM::Instructions.find_index { |insn| insn.name == 'ujit_call_example' }
|
[success ? 1 : 0,
|
||||||
|
[
|
||||||
|
['ujit_pre_call_bytes', comma_separated_hex_string(pre_call)],
|
||||||
|
['ujit_post_call_bytes', comma_separated_hex_string(post_call)],
|
||||||
|
['ujit_pre_call_with_ec_bytes', comma_separated_hex_string(pre_call_with_ec)],
|
||||||
|
['ujit_post_call_with_ec_bytes', comma_separated_hex_string(post_call_with_ec)]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def scrape_instruction(instruction_id)
|
||||||
|
raise unless instruction_id.is_a?(Integer)
|
||||||
case target_platform
|
case target_platform
|
||||||
when :darwin
|
when :darwin
|
||||||
darwin_scrape(instruction_id)
|
darwin_scrape(instruction_id)
|
||||||
|
@ -176,10 +190,15 @@ module RubyVM::MicroJIT
|
||||||
else
|
else
|
||||||
raise 'Unkonwn platform. Only Mach-O on macOS and ELF on Linux are supported'
|
raise 'Unkonwn platform. Only Mach-O on macOS and ELF on Linux are supported'
|
||||||
end
|
end
|
||||||
[true, comma_separated_hex_string(@pre_call_bytes), comma_separated_hex_string(@post_call_bytes)]
|
end
|
||||||
|
|
||||||
|
def scrape
|
||||||
|
pre, post = scrape_instruction(RubyVM::Instructions.find_index { |insn| insn.name == 'ujit_call_example' })
|
||||||
|
pre_with_ec, post_with_ec = scrape_instruction(RubyVM::Instructions.find_index { |insn| insn.name == 'ujit_call_example_with_ec' })
|
||||||
|
make_result(true, pre, post, pre_with_ec, post_with_ec)
|
||||||
rescue => e
|
rescue => e
|
||||||
print_warning("scrape failed: #{e.message}")
|
print_warning("scrape failed: #{e.message}")
|
||||||
[false, '0xcc', '0xcc']
|
make_result(false, ['cc'], ['cc'], ['cc'], ['cc'])
|
||||||
end
|
end
|
||||||
|
|
||||||
def print_warning(text)
|
def print_warning(text)
|
||||||
|
|
|
@ -13,10 +13,11 @@
|
||||||
class RubyVM::MicroJIT::ExampleInstructions
|
class RubyVM::MicroJIT::ExampleInstructions
|
||||||
include RubyVM::CEscape
|
include RubyVM::CEscape
|
||||||
|
|
||||||
attr_reader :name
|
attr_reader :name, :call_line
|
||||||
|
|
||||||
def initialize name
|
def initialize(name, call_line)
|
||||||
@name = name
|
@name = name
|
||||||
|
@call_line = call_line
|
||||||
end
|
end
|
||||||
|
|
||||||
def pretty_name
|
def pretty_name
|
||||||
|
@ -63,7 +64,10 @@ class RubyVM::MicroJIT::ExampleInstructions
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
@all_examples = [new('ujit_call_example')]
|
@all_examples = [
|
||||||
|
new('ujit_call_example', 'reg_pc = rb_ujit_empty_func(GET_CFP());'),
|
||||||
|
new('ujit_call_example_with_ec', 'reg_pc = rb_ujit_empty_func_with_ec(GET_CFP(), ec);')
|
||||||
|
]
|
||||||
|
|
||||||
def self.to_a
|
def self.to_a
|
||||||
@all_examples
|
@all_examples
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
edit: __FILE__,
|
edit: __FILE__,
|
||||||
} -%>
|
} -%>
|
||||||
|
|
||||||
% success, pre_call_bytes, post_call_bytes = RubyVM::MicroJIT.scrape
|
% success, byte_arrays = RubyVM::MicroJIT.scrape
|
||||||
static const uint8_t ujit_scrape_successful = <%= success %>;
|
static const uint8_t ujit_scrape_successful = <%= success %>;
|
||||||
static const uint8_t ujit_pre_call_bytes[] = { <%= pre_call_bytes %> };
|
% byte_arrays.each do |(name, bytes)|
|
||||||
static const uint8_t ujit_post_call_bytes[] = { <%= post_call_bytes %> };
|
static const uint8_t <%= name %>[] = { <%= bytes %> };
|
||||||
|
% end
|
||||||
|
|
|
@ -32,7 +32,7 @@ INSN_ENTRY(<%= insn.name %>)
|
||||||
#if USE_MACHINE_REGS
|
#if USE_MACHINE_REGS
|
||||||
// assumes USE_MACHINE_REGS, aka reg_pc setup,
|
// assumes USE_MACHINE_REGS, aka reg_pc setup,
|
||||||
// aka #define SET_PC(x) (reg_cfp->pc = reg_pc = (x))
|
// aka #define SET_PC(x) (reg_cfp->pc = reg_pc = (x))
|
||||||
reg_pc = rb_ujit_empty_func(GET_CFP());
|
<%= insn.call_line %>
|
||||||
#endif
|
#endif
|
||||||
END_INSN(<%= insn.name %>);
|
END_INSN(<%= insn.name %>);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче