ruby-changes:68652
From: Alan <ko1@a...>
Date: Thu, 21 Oct 2021 08:11:43 +0900 (JST)
Subject: [ruby-changes:68652] 11c1daea17 (master): Add to the MicroJIT scraper an example that passes ec
https://git.ruby-lang.org/ruby.git/commit/?id=11c1daea17 From 11c1daea172df21af30be24d645040d8de9d461d Mon Sep 17 00:00:00 2001 From: Alan Wu <XrXr@u...> Date: Mon, 19 Oct 2020 17:45:43 -0400 Subject: Add to the MicroJIT scraper an example that passes ec --- iseq.c | 7 +++++ iseq.h | 1 + tool/ruby_vm/models/micro_jit.rb | 35 +++++++++++++++++----- .../models/micro_jit/example_instructions.rb | 10 +++++-- tool/ruby_vm/views/ujit_examples.inc.erb | 7 +++-- tool/ruby_vm/views/vm.inc.erb | 2 +- 6 files changed, 47 insertions(+), 15 deletions(-) diff --git a/iseq.c b/iseq.c index 6b8f3d0e2c..d4d5261c3c 100644 --- a/iseq.c +++ b/iseq.c @@ -3495,6 +3495,13 @@ rb_ujit_empty_func(rb_control_frame_t *cfp) https://github.com/ruby/ruby/blob/trunk/iseq.c#L3495 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 rb_iseq_trace_set_all(rb_event_flag_t turnon_events) { diff --git a/iseq.h b/iseq.h index 9b5eb138ad..cd939a0684 100644 --- a/iseq.h +++ b/iseq.h @@ -316,6 +316,7 @@ VALUE rb_iseq_defined_string(enum defined_type type); https://github.com/ruby/ruby/blob/trunk/iseq.h#L316 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_with_ec(rb_control_frame_t *cfp, rb_execution_context_t *ec)); RUBY_SYMBOL_EXPORT_END diff --git a/tool/ruby_vm/models/micro_jit.rb b/tool/ruby_vm/models/micro_jit.rb index b2ce26cb3a..63815a85a0 100644 --- a/tool/ruby_vm/models/micro_jit.rb +++ b/tool/ruby_vm/models/micro_jit.rb @@ -128,20 +128,23 @@ module RubyVM::MicroJIT https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/micro_jit.rb#L128 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 "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 call_idx = handler_instructions.find_index { |_, mnemonic, _| mnemonic == 'call' } - @pre_call_bytes = [] - @post_call_bytes = [] + pre_call_bytes = [] + post_call_bytes = [] handler_instructions.take(call_idx).each do |bytes, mnemonic, _| - @pre_call_bytes += bytes.split + pre_call_bytes += bytes.split end handler_instructions[call_idx + 1, handler_instructions.size].each do |bytes, _, _| - @post_call_bytes += bytes.split + post_call_bytes += bytes.split end + + [pre_call_bytes, post_call_bytes] end def darwin_scrape(instruction_id) @@ -166,8 +169,19 @@ module RubyVM::MicroJIT https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/micro_jit.rb#L169 disassemble(handler_offset) end - def scrape - instruction_id = RubyVM::Instructions.find_index { |insn| insn.name == 'ujit_call_example' } + def make_result(success, pre_call, post_call, pre_call_with_ec, post_call_with_ec) + [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 when :darwin darwin_scrape(instruction_id) @@ -176,10 +190,15 @@ module RubyVM::MicroJIT https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/micro_jit.rb#L190 else raise 'Unkonwn platform. Only Mach-O on macOS and ELF on Linux are supported' 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 print_warning("scrape failed: #{e.message}") - [false, '0xcc', '0xcc'] + make_result(false, ['cc'], ['cc'], ['cc'], ['cc']) end def print_warning(text) diff --git a/tool/ruby_vm/models/micro_jit/example_instructions.rb b/tool/ruby_vm/models/micro_jit/example_instructions.rb index 5117d1c519..111346f6e9 100644 --- a/tool/ruby_vm/models/micro_jit/example_instructions.rb +++ b/tool/ruby_vm/models/micro_jit/example_instructions.rb @@ -13,10 +13,11 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/micro_jit/example_instructions.rb#L13 class RubyVM::MicroJIT::ExampleInstructions include RubyVM::CEscape - attr_reader :name + attr_reader :name, :call_line - def initialize name + def initialize(name, call_line) @name = name + @call_line = call_line end def pretty_name @@ -63,7 +64,10 @@ class RubyVM::MicroJIT::ExampleInstructions https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/models/micro_jit/example_instructions.rb#L64 false 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 @all_examples diff --git a/tool/ruby_vm/views/ujit_examples.inc.erb b/tool/ruby_vm/views/ujit_examples.inc.erb index 5fefcd4674..af0561f852 100644 --- a/tool/ruby_vm/views/ujit_examples.inc.erb +++ b/tool/ruby_vm/views/ujit_examples.inc.erb @@ -12,7 +12,8 @@ https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/ujit_examples.inc.erb#L12 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_pre_call_bytes[] = { <%= pre_call_bytes %> }; -static const uint8_t ujit_post_call_bytes[] = { <%= post_call_bytes %> }; +% byte_arrays.each do |(name, bytes)| +static const uint8_t <%= name %>[] = { <%= bytes %> }; +% end diff --git a/tool/ruby_vm/views/vm.inc.erb b/tool/ruby_vm/views/vm.inc.erb index 91e0b930c0..235eb30b11 100644 --- a/tool/ruby_vm/views/vm.inc.erb +++ b/tool/ruby_vm/views/vm.inc.erb @@ -32,7 +32,7 @@ INSN_ENTRY(<%= insn.name %>) https://github.com/ruby/ruby/blob/trunk/tool/ruby_vm/views/vm.inc.erb#L32 #if USE_MACHINE_REGS // assumes USE_MACHINE_REGS, aka reg_pc setup, // aka #define SET_PC(x) (reg_cfp->pc = reg_pc = (x)) - reg_pc = rb_ujit_empty_func(GET_CFP()); + <%= insn.call_line %> #endif END_INSN(<%= insn.name %>); } -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/