[前][次][番号順一覧][スレッド一覧]

ruby-changes:68552

From: Alan <ko1@a...>
Date: Thu, 21 Oct 2021 08:08:13 +0900 (JST)
Subject: [ruby-changes:68552] 16c5ce863c (master): Yeah, this actually works!

https://git.ruby-lang.org/ruby.git/commit/?id=16c5ce863c

From 16c5ce863c06dd3ae5562f4ed86fb40ced670c69 Mon Sep 17 00:00:00 2001
From: Alan Wu <XrXr@u...>
Date: Thu, 3 Sep 2020 12:06:53 -0400
Subject: Yeah, this actually works!

---
 common.mk                     |   5 ++
 compile.c                     |   5 ++
 gen-ujit-example-header.rb    | 105 ----------------------------------------
 gen_ujit_examples.rb          | 108 ++++++++++++++++++++++++++++++++++++++++++
 iseq.c                        |  34 ++++++++++++-
 iseq.h                        |   2 +-
 tool/ruby_vm/views/vm.inc.erb |   2 +-
 7 files changed, 153 insertions(+), 108 deletions(-)
 delete mode 100644 gen-ujit-example-header.rb
 create mode 100644 gen_ujit_examples.rb

diff --git a/common.mk b/common.mk
index 872e6e0a10..45ebaab86a 100644
--- a/common.mk
+++ b/common.mk
@@ -1105,6 +1105,10 @@ incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \ https://github.com/ruby/ruby/blob/trunk/common.mk#L1105
 
 insns: $(INSNS)
 
+ujit_examples.h: gen_ujit_examples.rb vm.$(OBJEXT)
+	$(ECHO) generating $@
+	$(Q) $(BASERUBY) gen_ujit_examples.rb
+
 id.h: $(tooldir)/generic_erb.rb $(srcdir)/template/id.h.tmpl $(srcdir)/defs/id.def
 	$(ECHO) generating $@
 	$(Q) $(BASERUBY) $(tooldir)/generic_erb.rb --output=$@ \
@@ -7002,6 +7006,7 @@ iseq.$(OBJEXT): {$(VPATH)}util.h https://github.com/ruby/ruby/blob/trunk/common.mk#L7006
 iseq.$(OBJEXT): {$(VPATH)}vm_callinfo.h
 iseq.$(OBJEXT): {$(VPATH)}vm_core.h
 iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
+iseq.$(OBJEXT): {$(VPATH)}ujit_examples.h
 load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
 load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
 load.$(OBJEXT): $(CCAN_DIR)/list/list.h
diff --git a/compile.c b/compile.c
index 1e88dc242d..49263002e3 100644
--- a/compile.c
+++ b/compile.c
@@ -856,6 +856,8 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) https://github.com/ruby/ruby/blob/trunk/compile.c#L856
     return iseq_setup(iseq, ret);
 }
 
+extern uint8_t *native_pop_code; // TODO global hack
+
 static int
 rb_iseq_translate_threaded_code(rb_iseq_t *iseq)
 {
@@ -868,6 +870,9 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L870
 	int insn = (int)iseq->body->iseq_encoded[i];
 	int len = insn_len(insn);
 	encoded[i] = (VALUE)table[insn];
+
+        if (insn == BIN(pop)) encoded[i] = (VALUE)native_pop_code;
+
 	i += len;
     }
     FL_SET((VALUE)iseq, ISEQ_TRANSLATED);
diff --git a/gen-ujit-example-header.rb b/gen-ujit-example-header.rb
deleted file mode 100644
index 5ad0c65f02..0000000000
--- a/gen-ujit-example-header.rb
+++ /dev/null
@@ -1,105 +0,0 @@ https://github.com/ruby/ruby/blob/trunk/compile.c#L0
-def get_example_instruction_id
-  # TODO we could get this from the script that generates vm.inc instead of dothings this song and dance
-  `dwarfdump --name='YARVINSN_ujit_call_example' vm.o`.each_line do |line|
-    if (id = line[/DW_AT_const_value\s\((\d+\))/, 1])
-      p [__method__, line]
-      return id.to_i
-    end
-  end
-  raise
-end
-
-def get_fileoff
-  # use the load command to figure out the offset to the start of the content of vm.o
-  `otool -l vm.o`.each_line do |line|
-    if (fileoff = line[/fileoff (\d+)/, 1])
-      p [__method__, line]
-      return fileoff.to_i
-    end
-  end
-  raise
-end
-
-def get_symbol_offset(symbol)
-  `nm vm.o`.each_line do |line|
-    if (offset = line[Regexp.compile('(\h+).+' + Regexp.escape(symbol) + '\Z'), 1])
-      p [__method__, line]
-      return Integer(offset, 16)
-    end
-  end
-  raise
-end
-
-def readint8b(offset)
-  bytes = IO.binread('vm.o', 8, offset)
-  bytes.unpack('q').first #  this is native endian but we want little endian. it's fine if the host moachine is x86
-end
-
-
-def disassemble(offset)
-  command = "objdump --x86-asm-syntax=intel --start-address=#{offset} --stop-address=#{offset+50} -d vm.o"
-  puts "Running: #{command}"
-  puts "feel free to verify with --reloc"
-  disassembly = `#{command}`
-  instructions = []
-  puts disassembly
-  disassembly.each_line do |line|
-    line = line.strip
-    match = /\h+: ((?:\h\h\s?)+)\s+(\w+)/.match(line) do |match_data|
-      bytes = match_data[1]
-      mnemonic = match_data[2]
-      instructions << [bytes, mnemonic, line]
-    end
-    if !match && !instructions.empty?
-      p line
-      raise "expected a continuous sequence of disassembly lines"
-    end
-  end
-
-  jmp_idx = instructions.find_index { |_, mnemonic, _| mnemonic == 'jmp' }
-  raise 'failed to find jmp' unless jmp_idx
-  raise 'generated code for example too long' unless jmp_idx < 10
-  handler_instructions = instructions[(0..jmp_idx)]
-  raise 'rip reference in example makes copying unsafe' if handler_instructions.any? { |_, _, full_line| full_line.downcase.include?('rip') }
-  acceptable_mnemonics = %w(mov jmp lea call)
-  unrecognized = nil
-  handler_instructions.each { |i| unrecognized = i unless acceptable_mnemonics.include?(i[1]) }
-  raise "found a 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 call instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'call' } > 1
-  call_idx = handler_instructions.find_index { |_, mnemonic, _| mnemonic == 'call' }
-
-
-  puts "\n\nDisassembly for the handler:"
-  puts handler_instructions.map{|_,_,line|line}
-
-  pre_call_bytes = []
-  post_call_bytes = []
-  handler_instructions.take(call_idx).each do |bytes, mnemonic, _|
-    pre_call_bytes += bytes.split
-  end
-  handler_instructions[((call_idx+1)...)].each do |bytes, _, _|
-    post_call_bytes += bytes.split
-  end
-
-  File.write("ujit_examples.h", <<-EOF)
-static const uint8_t ujit_precall_bytes[] = { #{pre_call_bytes.map{ |byte| '0x'+byte}.join(', ')} };
-static const uint8_t ujit_postall_bytes[] = { #{post_call_bytes.map{ |byte| '0x'+byte}.join(', ')} };
-  EOF
-  puts "file:"
-  puts File.binread("ujit_examples.h")
-end
-
-instruction_id = get_example_instruction_id
-fileoff = get_fileoff
-tc_table_offset = get_symbol_offset('vm_exec_core.insns_address_table')
-vm_exec_core_offset = get_symbol_offset('vm_exec_core')
-p instruction_id
-p fileoff
-p tc_table_offset.to_s(16)
-offset_to_insn_in_tc_table = fileoff + tc_table_offset + 8 * instruction_id
-p offset_to_insn_in_tc_table
-offset_to_handler_code_from_vm_exec_core = readint8b(offset_to_insn_in_tc_table)
-p offset_to_handler_code_from_vm_exec_core
-disassemble(vm_exec_core_offset + offset_to_handler_code_from_vm_exec_core)
-
diff --git a/gen_ujit_examples.rb b/gen_ujit_examples.rb
new file mode 100644
index 0000000000..eaacd988b8
--- /dev/null
+++ b/gen_ujit_examples.rb
@@ -0,0 +1,108 @@ https://github.com/ruby/ruby/blob/trunk/gen_ujit_examples.rb#L1
+def get_example_instruction_id
+  # TODO we could get this from the script that generates vm.inc instead of dothings this song and dance
+  `dwarfdump --name='YARVINSN_ujit_call_example' vm.o`.each_line do |line|
+    if (id = line[/DW_AT_const_value\s\((\d+\))/, 1])
+      p [__method__, line] if $DEBUG
+      return id.to_i
+    end
+  end
+  raise
+end
+
+def get_fileoff
+  # use the load command to figure out the offset to the start of the content of vm.o
+  `otool -l vm.o`.each_line do |line|
+    if (fileoff = line[/fileoff (\d+)/, 1])
+      p [__method__, line] if $DEBUG
+      return fileoff.to_i
+    end
+  end
+  raise
+end
+
+def get_symbol_offset(symbol)
+  `nm vm.o`.each_line do |line|
+    if (offset = line[Regexp.compile('(\h+).+' + Regexp.escape(symbol) + '\Z'), 1])
+      p [__method__, line] if $DEBUG
+      return Integer(offset, 16)
+    end
+  end
+  raise
+end
+
+def readint8b(offset)
+  bytes = IO.binread('vm.o', 8, offset)
+  bytes.unpack('q').first #  this is native endian but we want little endian. it's fine if the host moachine is x86
+end
+
+
+def disassemble(offset)
+  command = "objdump --x86-asm-syntax=intel --start-address=#{offset} --stop-address=#{offset+50} -d vm.o"
+  puts "Running: #{command}"
+  puts "feel free to verify with --reloc"
+  disassembly = `#{command}`
+  instructions = []
+  puts disassembly if $DEBUG
+  disassembly.each_line do |line|
+    line = line.strip
+    match_data = /\h+: ((?:\h\h\s?)+)\s+(\w+)/.match(line)
+    if match_data
+      bytes = match_data[1]
+      mnemonic = match_data[2]
+      instructions << [bytes, mnemonic, line]
+      break if mnemonic == 'jmp'
+    elsif !instructions.empty?
+      p line
+      raise "expected a continuous sequence of disassembly lines"
+    end
+  end
+
+  jmp_idx = instructions.find_index { |_, mnemonic, _| mnemonic == 'jmp' }
+  raise 'failed to find jmp' unless jmp_idx
+  raise 'generated code for example too long' unless jmp_idx < 10
+  handler_instructions = instructions[(0..jmp_idx)]
+  raise 'rip reference in example makes copying unsafe' if handler_instructions.any? { |_, _, full_line| full_line.downcase.include?('rip') }
+  acceptable_mnemonics = %w(mov jmp lea call)
+  unrecognized = nil
+  handler_instructions.each { |i| unrecognized = i unless acceptable_mnemonics.include?(i[1]) }
+  raise "found a 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 call instructions' if handler_instructions.count { |_, mnemonic, _| mnemonic == 'call' } > 1
+  call_idx = handler_instructions.find_index { |_, mnemonic, _| mnemonic == 'call' }
+
+
+  puts "Disassembly for the example handler:"
+  puts handler_instructions.map{|_,_,line|line}
+
+  pre_call_bytes = []
+  post_call_bytes = []
+  handler_instructions.take(call_idx).each do |bytes, mnemonic, _|
+    pre_call_bytes += bytes.split
+   (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]