summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2022-09-18 23:17:22 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2022-09-23 06:44:28 +0900
commit334b8bd4596cd2fff737f4ced2f2bdf1d7f82679 (patch)
tree9ccb099fce202972378512444632d4b3a28b6bb2
parent00c441ce7ac76dedd272acf9a9daec59d9d5d908 (diff)
Mix manual and auto-generated C APIs
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/6418
-rw-r--r--mjit_compiler.rb118
-rwxr-xr-xtool/mjit/bindgen.rb31
-rw-r--r--tool/ruby_vm/views/mjit_c.rb.erb124
3 files changed, 148 insertions, 125 deletions
diff --git a/mjit_compiler.rb b/mjit_compiler.rb
index 4996e773dc..0a558f67e4 100644
--- a/mjit_compiler.rb
+++ b/mjit_compiler.rb
@@ -14,124 +14,6 @@ if RubyVM::MJIT.enabled?
require 'mjit/c_32'
end
- class << RubyVM::MJIT::C
- def ROBJECT_EMBED_LEN_MAX
- Primitive.cexpr! 'INT2NUM(RBIMPL_EMBED_LEN_MAX_OF(VALUE))'
- end
-
- def cdhash_to_hash(cdhash_addr)
- Primitive.cdhash_to_hash(cdhash_addr)
- end
-
- def builtin_compiler(f, bf, index, stack_size, builtin_inline_p)
- Primitive.builtin_compile(f, bf.to_i, index, stack_size, builtin_inline_p)
- end
-
- def has_cache_for_send(cc, insn)
- Primitive.has_cache_for_send(cc.to_i, insn)
- end
-
- def rb_iseq_check(iseq)
- _iseq_addr = iseq.to_i
- iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseq_check((rb_iseq_t *)NUM2PTR(_iseq_addr)))'
- rb_iseq_t.new(iseq_addr)
- end
-
- def rb_iseq_path(iseq)
- _iseq_addr = iseq.to_i
- Primitive.cexpr! 'rb_iseq_path((rb_iseq_t *)NUM2PTR(_iseq_addr))'
- end
-
- def vm_ci_argc(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'UINT2NUM(vm_ci_argc((CALL_INFO)NUM2PTR(_ci_addr)))'
- end
-
- def vm_ci_flag(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'UINT2NUM(vm_ci_flag((CALL_INFO)NUM2PTR(_ci_addr)))'
- end
-
- def rb_splat_or_kwargs_p(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'RBOOL(rb_splat_or_kwargs_p((CALL_INFO)NUM2PTR(_ci_addr)))'
- end
-
- def fastpath_applied_iseq_p(ci, cc, iseq)
- _ci_addr = ci.to_i
- _cc_addr = cc.to_i
- _iseq_addr = iseq.to_i
- Primitive.cexpr! 'RBOOL(fastpath_applied_iseq_p((CALL_INFO)NUM2PTR(_ci_addr), (CALL_CACHE)NUM2PTR(_cc_addr), (rb_iseq_t *)NUM2PTR(_iseq_addr)))'
- end
-
- def mjit_opts
- addr = Primitive.cexpr! 'PTR2NUM((VALUE)&mjit_opts)'
- mjit_options.new(addr)
- end
-
- def mjit_call_attribute_sp_inc(insn, operands)
- _operands_addr = operands.to_i
- Primitive.cexpr! 'LONG2NUM(mjit_call_attribute_sp_inc(NUM2INT(insn), (VALUE *)NUM2PTR(_operands_addr)))'
- end
-
- def mjit_capture_cc_entries(compiled_body, captured_body)
- _compiled_body_addr = compiled_body.to_i
- _captured_body_addr = captured_body.to_i
- Primitive.cexpr! 'INT2NUM(mjit_capture_cc_entries((struct rb_iseq_constant_body *)NUM2PTR(_compiled_body_addr), (struct rb_iseq_constant_body *)NUM2PTR(_captured_body_addr)))'
- end
-
- #const struct rb_iseq_constant_body *body, union iseq_inline_storage_entry *is_entries
- def mjit_capture_is_entries(body, is_entries)
- _body_addr = body.to_i
- _is_entries_addr = is_entries.to_i
- Primitive.cstmt! %{
- mjit_capture_is_entries((struct rb_iseq_constant_body *)NUM2PTR(_body_addr), (union iseq_inline_storage_entry *)NUM2PTR(_is_entries_addr));
- return Qnil;
- }
- end
-
- # Convert encoded VM pointers to insn BINs.
- def rb_vm_insn_decode(encoded)
- Primitive.cexpr! 'INT2NUM(rb_vm_insn_decode(NUM2PTR(encoded)))'
- end
-
- # Convert insn BINs to encoded VM pointers. This one is not used by the compiler, but useful for debugging.
- def rb_vm_insn_encode(bin)
- Primitive.cexpr! 'PTR2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
- end
-
- def insn_may_depend_on_sp_or_pc(insn, opes)
- _opes_addr = opes.to_i
- Primitive.cexpr! 'RBOOL(insn_may_depend_on_sp_or_pc(NUM2INT(insn), (VALUE *)NUM2PTR(_opes_addr)))'
- end
-
- # Convert Integer VALUE to an actual Ruby object
- def to_ruby(value)
- Primitive.cexpr! '(VALUE)NUM2PTR(value)'
- end
-
- # Convert RubyVM::InstructionSequence to C.rb_iseq_t. Not used by the compiler, but useful for debugging.
- def rb_iseqw_to_iseq(iseqw)
- iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseqw_to_iseq(iseqw))'
- rb_iseq_t.new(iseq_addr)
- end
-
- # TODO: remove this after migration
- def fprintf(f, str)
- Primitive.cstmt! %{
- fprintf((FILE *)NUM2PTR(f), "%s", RSTRING_PTR(str));
- return Qnil;
- }
- end
-
- def rb_cFalseClass; Primitive.cexpr! 'PTR2NUM(rb_cFalseClass)' end
- def rb_cNilClass; Primitive.cexpr! 'PTR2NUM(rb_cNilClass)' end
- def rb_cTrueClass; Primitive.cexpr! 'PTR2NUM(rb_cTrueClass)' end
- def rb_cInteger; Primitive.cexpr! 'PTR2NUM(rb_cInteger)' end
- def rb_cSymbol; Primitive.cexpr! 'PTR2NUM(rb_cSymbol)' end
- def rb_cFloat; Primitive.cexpr! 'PTR2NUM(rb_cFloat)' end
- end
-
require "mjit/instruction"
require "mjit/compiler"
end
diff --git a/tool/mjit/bindgen.rb b/tool/mjit/bindgen.rb
index 32a487d4bb..8fa20fe64c 100755
--- a/tool/mjit/bindgen.rb
+++ b/tool/mjit/bindgen.rb
@@ -100,16 +100,20 @@ end
# Convert Node objects to a Ruby binding source.
class BindingGenerator
+ BINDGEN_BEG = '### MJIT bindgen begin ###'
+ BINDGEN_END = '### MJIT bindgen end ###'
DEFAULTS = { '_Bool' => 'CType::Bool.new' }
DEFAULTS.default_proc = proc { |_h, k| "CType::Stub.new(:#{k})" }
attr_reader :src
+ # @param src_path [String] Source path used for preamble/postamble
# @param macros [Array<String>] Imported macros
# @param enums [Hash{ Symbol => Array<String> }] Imported enum values
# @param types [Array<String>] Imported types
# @param ruby_fields [Hash{ Symbol => Array<String> }] Struct VALUE fields that are considered Ruby objects
- def initialize(macros:, enums:, types:, ruby_fields:)
+ def initialize(src_path:, macros:, enums:, types:, ruby_fields:)
+ @preamble, @postamble = split_ambles(src_path)
@src = String.new
@macros = macros.sort
@enums = enums.transform_keys(&:to_s).transform_values(&:sort).sort.to_h
@@ -119,9 +123,7 @@ class BindingGenerator
end
def generate(_nodes)
- println "module RubyVM::MJIT"
- println " C = Object.new"
- println
+ println @preamble
# Define macros
@macros.each do |macro|
@@ -129,8 +131,7 @@ class BindingGenerator
println
end
- chomp
- println "end if RubyVM::MJIT.enabled?"
+ print @postamble
end
# TODO: Remove this
@@ -176,6 +177,20 @@ class BindingGenerator
private
+ # Return code before BINDGEN_BEG and code after BINDGEN_END
+ def split_ambles(src_path)
+ lines = File.read(src_path).lines
+
+ preamble_end = lines.index { |l| l.include?(BINDGEN_BEG) }
+ raise "`#{BINDGEN_BEG}` was not found in '#{src_path}'" if preamble_end.nil?
+
+ postamble_beg = lines.index { |l| l.include?(BINDGEN_END) }
+ raise "`#{BINDGEN_END}` was not found in '#{src_path}'" if postamble_beg.nil?
+ raise "`#{BINDGEN_BEG}` was found after `#{BINDGEN_END}`" if preamble_end >= postamble_beg
+
+ return lines[0..preamble_end].join, lines[postamble_beg..-1].join
+ end
+
def generate_macro(macro)
if macro.start_with?('USE_')
"Primitive.cexpr! %q{ RBOOL(#{macro} != 0) }"
@@ -293,6 +308,7 @@ class BindingGenerator
end
src_dir = File.expand_path('../..', __dir__)
+src_path = File.join(src_dir, 'tool/ruby_vm/views/mjit_c.rb.erb')
build_dir = File.expand_path(build_dir)
cflags = [
src_dir,
@@ -303,6 +319,7 @@ cflags = [
nodes = HeaderParser.new(File.join(src_dir, 'mjit_compiler.h'), cflags: cflags).parse
generator = BindingGenerator.new(
+ src_path: src_path,
macros: %w[
NOT_COMPILED_STACK_SIZE
USE_LAZY_LOAD
@@ -366,4 +383,4 @@ generator = BindingGenerator.new(
)
generator.generate(nodes)
-File.write(File.join(src_dir, 'tool/ruby_vm/views/mjit_c.rb.erb'), generator.src)
+File.write(src_path, generator.src)
diff --git a/tool/ruby_vm/views/mjit_c.rb.erb b/tool/ruby_vm/views/mjit_c.rb.erb
index 416f8bfeaf..5def975dcc 100644
--- a/tool/ruby_vm/views/mjit_c.rb.erb
+++ b/tool/ruby_vm/views/mjit_c.rb.erb
@@ -1,6 +1,128 @@
+# Part of this file is generated by tool/mjit/bindgen.rb.
+# Run `make mjit-bindgen` to update code between "MJIT bindgen begin" and "MJIT bindgen end".
module RubyVM::MJIT
C = Object.new
+ class << C
+ def ROBJECT_EMBED_LEN_MAX
+ Primitive.cexpr! 'INT2NUM(RBIMPL_EMBED_LEN_MAX_OF(VALUE))'
+ end
+
+ def cdhash_to_hash(cdhash_addr)
+ Primitive.cdhash_to_hash(cdhash_addr)
+ end
+
+ def builtin_compiler(f, bf, index, stack_size, builtin_inline_p)
+ Primitive.builtin_compile(f, bf.to_i, index, stack_size, builtin_inline_p)
+ end
+
+ def has_cache_for_send(cc, insn)
+ Primitive.has_cache_for_send(cc.to_i, insn)
+ end
+
+ def rb_iseq_check(iseq)
+ _iseq_addr = iseq.to_i
+ iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseq_check((rb_iseq_t *)NUM2PTR(_iseq_addr)))'
+ rb_iseq_t.new(iseq_addr)
+ end
+
+ def rb_iseq_path(iseq)
+ _iseq_addr = iseq.to_i
+ Primitive.cexpr! 'rb_iseq_path((rb_iseq_t *)NUM2PTR(_iseq_addr))'
+ end
+
+ def vm_ci_argc(ci)
+ _ci_addr = ci.to_i
+ Primitive.cexpr! 'UINT2NUM(vm_ci_argc((CALL_INFO)NUM2PTR(_ci_addr)))'
+ end
+
+ def vm_ci_flag(ci)
+ _ci_addr = ci.to_i
+ Primitive.cexpr! 'UINT2NUM(vm_ci_flag((CALL_INFO)NUM2PTR(_ci_addr)))'
+ end
+
+ def rb_splat_or_kwargs_p(ci)
+ _ci_addr = ci.to_i
+ Primitive.cexpr! 'RBOOL(rb_splat_or_kwargs_p((CALL_INFO)NUM2PTR(_ci_addr)))'
+ end
+
+ def fastpath_applied_iseq_p(ci, cc, iseq)
+ _ci_addr = ci.to_i
+ _cc_addr = cc.to_i
+ _iseq_addr = iseq.to_i
+ Primitive.cexpr! 'RBOOL(fastpath_applied_iseq_p((CALL_INFO)NUM2PTR(_ci_addr), (CALL_CACHE)NUM2PTR(_cc_addr), (rb_iseq_t *)NUM2PTR(_iseq_addr)))'
+ end
+
+ def mjit_opts
+ addr = Primitive.cexpr! 'PTR2NUM((VALUE)&mjit_opts)'
+ mjit_options.new(addr)
+ end
+
+ def mjit_call_attribute_sp_inc(insn, operands)
+ _operands_addr = operands.to_i
+ Primitive.cexpr! 'LONG2NUM(mjit_call_attribute_sp_inc(NUM2INT(insn), (VALUE *)NUM2PTR(_operands_addr)))'
+ end
+
+ def mjit_capture_cc_entries(compiled_body, captured_body)
+ _compiled_body_addr = compiled_body.to_i
+ _captured_body_addr = captured_body.to_i
+ Primitive.cexpr! 'INT2NUM(mjit_capture_cc_entries((struct rb_iseq_constant_body *)NUM2PTR(_compiled_body_addr), (struct rb_iseq_constant_body *)NUM2PTR(_captured_body_addr)))'
+ end
+
+ #const struct rb_iseq_constant_body *body, union iseq_inline_storage_entry *is_entries
+ def mjit_capture_is_entries(body, is_entries)
+ _body_addr = body.to_i
+ _is_entries_addr = is_entries.to_i
+ Primitive.cstmt! %{
+ mjit_capture_is_entries((struct rb_iseq_constant_body *)NUM2PTR(_body_addr), (union iseq_inline_storage_entry *)NUM2PTR(_is_entries_addr));
+ return Qnil;
+ }
+ end
+
+ # Convert encoded VM pointers to insn BINs.
+ def rb_vm_insn_decode(encoded)
+ Primitive.cexpr! 'INT2NUM(rb_vm_insn_decode(NUM2PTR(encoded)))'
+ end
+
+ # Convert insn BINs to encoded VM pointers. This one is not used by the compiler, but useful for debugging.
+ def rb_vm_insn_encode(bin)
+ Primitive.cexpr! 'PTR2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
+ end
+
+ def insn_may_depend_on_sp_or_pc(insn, opes)
+ _opes_addr = opes.to_i
+ Primitive.cexpr! 'RBOOL(insn_may_depend_on_sp_or_pc(NUM2INT(insn), (VALUE *)NUM2PTR(_opes_addr)))'
+ end
+
+ # Convert Integer VALUE to an actual Ruby object
+ def to_ruby(value)
+ Primitive.cexpr! '(VALUE)NUM2PTR(value)'
+ end
+
+ # Convert RubyVM::InstructionSequence to C.rb_iseq_t. Not used by the compiler, but useful for debugging.
+ def rb_iseqw_to_iseq(iseqw)
+ iseq_addr = Primitive.cexpr! 'PTR2NUM((VALUE)rb_iseqw_to_iseq(iseqw))'
+ rb_iseq_t.new(iseq_addr)
+ end
+
+ # TODO: remove this after migration
+ def fprintf(f, str)
+ Primitive.cstmt! %{
+ fprintf((FILE *)NUM2PTR(f), "%s", RSTRING_PTR(str));
+ return Qnil;
+ }
+ end
+
+ def rb_cFalseClass; Primitive.cexpr! 'PTR2NUM(rb_cFalseClass)' end
+ def rb_cNilClass; Primitive.cexpr! 'PTR2NUM(rb_cNilClass)' end
+ def rb_cTrueClass; Primitive.cexpr! 'PTR2NUM(rb_cTrueClass)' end
+ def rb_cInteger; Primitive.cexpr! 'PTR2NUM(rb_cInteger)' end
+ def rb_cSymbol; Primitive.cexpr! 'PTR2NUM(rb_cSymbol)' end
+ def rb_cFloat; Primitive.cexpr! 'PTR2NUM(rb_cFloat)' end
+ end
+
+ ### MJIT bindgen begin ###
+
def C.NOT_COMPILED_STACK_SIZE = Primitive.cexpr! %q{ INT2NUM(NOT_COMPILED_STACK_SIZE) }
def C.USE_LAZY_LOAD = Primitive.cexpr! %q{ RBOOL(USE_LAZY_LOAD != 0) }
@@ -10,4 +132,6 @@ module RubyVM::MJIT
def C.VM_CALL_KW_SPLAT = Primitive.cexpr! %q{ INT2NUM(VM_CALL_KW_SPLAT) }
def C.VM_CALL_TAILCALL = Primitive.cexpr! %q{ INT2NUM(VM_CALL_TAILCALL) }
+
+ ### MJIT bindgen end ###
end if RubyVM::MJIT.enabled?