diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 86983bdc3f..162b8c2eb5 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -200,7 +200,7 @@ module RubyVM::RJIT asm.mov(C_ARGS[0], EC) # The block handler for the current frame # note, VM_ASSERT(VM_ENV_LOCAL_P(ep)) - asm.mov(C_ARGS[1], [ep_reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL]) + asm.mov(C_ARGS[1], [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) asm.call(C.rb_vm_bh_to_procval) # Load environment pointer EP from CFP (again) @@ -271,7 +271,7 @@ module RubyVM::RJIT # Load the block handler for the current frame # note, VM_ASSERT(VM_ENV_LOCAL_P(ep)) block_handler = :rax - asm.mov(block_handler, [ep_reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL]) + asm.mov(block_handler, [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # Specialize compilation for the case where no block handler is present if comptime_handler == 0 @@ -2821,7 +2821,7 @@ module RubyVM::RJIT asm.mov(reg, [CFP, C.rb_control_frame_t.offsetof(:ep)]) level.times do # GET_PREV_EP: ep[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03 - asm.mov(reg, [reg, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL]) + asm.mov(reg, [reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) asm.and(reg, ~0x03) end end @@ -2965,7 +2965,7 @@ module RubyVM::RJIT # Guard no block passed. Only handle that case for now. asm.comment('guard no block given') jit_get_lep(jit, asm, reg: :rax) - asm.cmp([:rax, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL], C.VM_BLOCK_HANDLER_NONE) + asm.cmp([:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL], C.VM_BLOCK_HANDLER_NONE) asm.jne(counted_exit(side_exit, :send_block_handler)) return C.VM_BLOCK_HANDLER_NONE else @@ -3092,7 +3092,7 @@ module RubyVM::RJIT jit_get_lep(jit, asm, reg: :rax) asm.mov(:rcx, me.to_i) - asm.cmp([:rax, C.VALUE.size * C.VM_ENV_DATA_INDEX_ME_CREF], :rcx) + asm.cmp([:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_ME_CREF], :rcx) asm.jne(counted_exit(side_exit, :invokesuper_me_changed)) # We need to assume that both our current method entry and the super @@ -3711,7 +3711,7 @@ module RubyVM::RJIT # VALUE handler = VM_CF_BLOCK_HANDLER(reg_cfp); # reg_cfp->block_code = (const void *) handler; jit_get_lep(jit, asm, reg: :rax) - asm.mov(:rax, [:rax, C.VALUE.size * C.VM_ENV_DATA_INDEX_SPECVAL]) # handler + asm.mov(:rax, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # handler asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax) asm.mov(:rax, C.rb_block_param_proxy) diff --git a/lib/ruby_vm/rjit/jit_state.rb b/lib/ruby_vm/rjit/jit_state.rb index 6becee19f7..a365559d17 100644 --- a/lib/ruby_vm/rjit/jit_state.rb +++ b/lib/ruby_vm/rjit/jit_state.rb @@ -40,7 +40,7 @@ module RubyVM::RJIT def peek_at_block_handler(level) ep = ep_at_level(cfp, level:) - ep[C.VM_ENV_DATA_INDEX_SPECVAL] + ep[C::VM_ENV_DATA_INDEX_SPECVAL] end private @@ -49,7 +49,7 @@ module RubyVM::RJIT ep = cfp.ep level.times do # VM_ENV_PREV_EP - ep = C.VALUE.new(ep[C.VM_ENV_DATA_INDEX_SPECVAL] & ~0x03) + ep = C.VALUE.new(ep[C::VM_ENV_DATA_INDEX_SPECVAL] & ~0x03) end ep end diff --git a/rjit_c.rb b/rjit_c.rb index 6e4c05bc87..7f510f2014 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -2,9 +2,9 @@ # Part of this file is generated by tool/rjit/bindgen.rb. # Run `make rjit-bindgen` to update code between "RJIT bindgen begin" and "RJIT bindgen end". module RubyVM::RJIT # :nodoc: all - # This `class << C` section is for calling C functions. For importing variables - # or macros as is, please consider using tool/rjit/bindgen.rb instead. - class << C = Object.new + # This `class << C` section is for calling C functions with Primitive. + # For importing variables or macros, use tool/rjit/bindgen.rb instead. + class << C = Module.new def mmap(mem_size) Primitive.cexpr! 'SIZET2NUM((size_t)rjit_reserve_addr_space(NUM2UINT(mem_size)))' end @@ -312,13 +312,8 @@ module RubyVM::RJIT # :nodoc: all ### RJIT bindgen begin ### - def C.VM_ENV_DATA_INDEX_ME_CREF - Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_ME_CREF) } - end - - def C.VM_ENV_DATA_INDEX_SPECVAL - Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_SPECVAL) } - end + C::VM_ENV_DATA_INDEX_ME_CREF = Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_ME_CREF) } + C::VM_ENV_DATA_INDEX_SPECVAL = Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_SPECVAL) } def C.ARRAY_REDEFINED_OP_FLAG Primitive.cexpr! %q{ SIZET2NUM(ARRAY_REDEFINED_OP_FLAG) } diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb index fc6900808f..ba5e3c1ad7 100644 --- a/tool/mk_builtin_loader.rb +++ b/tool/mk_builtin_loader.rb @@ -265,7 +265,8 @@ def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_nam f = StringIO.new f.puts '{' lineno += 1 - locals.reverse_each.with_index{|param, i| + # locals is nil outside methods + locals&.reverse_each&.with_index{|param, i| next unless Symbol === param f.puts "MAYBE_UNUSED(const VALUE) #{param} = rb_vm_lvar(ec, #{-3 - i});" lineno += 1 diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index abff60fdc3..a34ac9649b 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -106,15 +106,17 @@ class BindingGenerator attr_reader :src # @param src_path [String] + # @param consts [Hash{ Symbol => Array }] # @param values [Hash{ Symbol => Array }] # @param funcs [Array] # @param types [Array] # @param dynamic_types [Array] #ifdef-dependent immediate types, which need Primitive.cexpr! for type detection # @param skip_fields [Hash{ Symbol => Array }] Struct fields that are skipped from bindgen # @param ruby_fields [Hash{ Symbol => Array }] Struct VALUE fields that are considered Ruby objects - def initialize(src_path:, values:, funcs:, types:, dynamic_types:, skip_fields:, ruby_fields:) + def initialize(src_path:, consts:, values:, funcs:, types:, dynamic_types:, skip_fields:, ruby_fields:) @preamble, @postamble = split_ambles(src_path) @src = String.new + @consts = consts.transform_values(&:sort) @values = values.transform_values(&:sort) @funcs = funcs.sort @types = types.sort @@ -128,6 +130,15 @@ class BindingGenerator println @preamble # Define macros/enums + @consts.each do |type, values| + values.each do |value| + raise "#{value} isn't a valid constant name" unless ('A'..'Z').include?(value[0]) + println " C::#{value} = Primitive.cexpr! %q{ #{type}2NUM(#{value}) }" + end + end + println + + # Define variables @values.each do |type, values| values.each do |value| println " def C.#{value}" @@ -137,6 +148,7 @@ class BindingGenerator end end + # Define function pointers @funcs.each do |func| println " def C.#{func}" println " Primitive.cexpr! %q{ SIZET2NUM((size_t)#{func}) }" @@ -351,11 +363,13 @@ end nodes = HeaderParser.new(File.join(src_dir, 'rjit_c.h'), cflags: cflags).parse generator = BindingGenerator.new( src_path: src_path, - values: { + consts: { LONG: %w[ VM_ENV_DATA_INDEX_ME_CREF VM_ENV_DATA_INDEX_SPECVAL ], + }, + values: { SIZET: %w[ ARRAY_REDEFINED_OP_FLAG BOP_AND