aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2023-04-02 12:56:27 -0700
committerTakashi Kokubun <takashikkbn@gmail.com>2023-04-02 13:58:39 -0700
commit66f8efc342bd36ae14090f14e7c2b9a0e30b9be3 (patch)
tree0be84b050006a8e3ef30d3c7f3c75ef29a0f8780
parent284a0ff96c97be0c2413e3fb59a7874e4092c90b (diff)
downloadruby-66f8efc342bd36ae14090f14e7c2b9a0e30b9be3.tar.gz
RJIT: Simplify cfunc implementation
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb276
-rw-r--r--rjit_c.c15
-rw-r--r--rjit_c.h6
-rw-r--r--rjit_c.rb14
-rwxr-xr-xtool/rjit/bindgen.rb2
5 files changed, 207 insertions, 106 deletions
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
index b0244d800e..495d4ebfd5 100644
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ b/lib/ruby_vm/rjit/insn_compiler.rb
@@ -1,7 +1,7 @@
module RubyVM::RJIT
class InsnCompiler
# struct rb_calling_info. Storing flags instead of ci.
- CallingInfo = Struct.new(:argc, :flags, :kwarg, :send_shift, :block_handler) do
+ CallingInfo = Struct.new(:argc, :flags, :kwarg, :ci_addr, :send_shift, :block_handler) do
def kw_splat = flags & C::VM_CALL_KW_SPLAT != 0
end
@@ -1591,7 +1591,7 @@ module RubyVM::RJIT
frame_type = C::VM_FRAME_MAGIC_METHOD | C::VM_ENV_FLAG_LOCAL
jit_call_iseq(jit, ctx, asm, cme, calling, iseq, frame_type:)
in C::VM_METHOD_TYPE_CFUNC
- jit_call_cfunc(jit, ctx, asm, cme, calling, nil)
+ jit_call_cfunc(jit, ctx, asm, cme, calling)
end
end
@@ -4055,7 +4055,7 @@ module RubyVM::RJIT
asm.incr_counter(:send_notimplemented)
return CantCompile
in C::VM_METHOD_TYPE_CFUNC
- jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class)
+ jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class:)
in C::VM_METHOD_TYPE_ATTRSET
jit_call_attrset(jit, ctx, asm, cme, calling, comptime_recv, recv_opnd)
in C::VM_METHOD_TYPE_IVAR
@@ -4217,7 +4217,7 @@ module RubyVM::RJIT
end
block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
- # jit_caller_setup_arg_block already handled send_blockarg_not_nil_or_proxy
+ # jit_caller_setup_arg_block already handled send_block_arg
# If we have unfilled optional arguments and keyword arguments then we
# would need to adjust the arguments location to account for that.
@@ -4332,8 +4332,7 @@ module RubyVM::RJIT
# We will not have CantCompile from here.
- # Pop blockarg after all side exits
- if flags & C::VM_CALL_ARGS_BLOCKARG != 0
+ if block_arg
ctx.stack_pop(1)
end
@@ -4380,7 +4379,7 @@ module RubyVM::RJIT
# This is a .send call and we need to adjust the stack
if flags & C::VM_CALL_OPT_SEND != 0
- jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
end
if iseq_has_rest
@@ -4675,57 +4674,64 @@ module RubyVM::RJIT
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
- def jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class)
+ def jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class: nil)
argc = calling.argc
flags = calling.flags
- send_shift = calling.send_shift
- block_handler = calling.block_handler
- if jit_caller_setup_arg(jit, ctx, asm, flags, splat: true) == CantCompile
+ cfunc = cme.def.body.cfunc
+ cfunc_argc = cfunc.argc
+
+ # If the function expects a Ruby array of arguments
+ if cfunc_argc < 0 && cfunc_argc != -1
+ asm.incr_counter(:send_cfunc_ruby_array_varg)
return CantCompile
end
- if jit_caller_remove_empty_kw_splat(jit, ctx, asm, flags) == CantCompile
+
+ # We aren't handling a vararg cfuncs with splat currently.
+ if flags & C::VM_CALL_ARGS_SPLAT != 0 && cfunc_argc == -1
+ asm.incr_counter(:send_args_splat_cfunc_var_args)
return CantCompile
end
- jit_call_cfunc_with_frame(jit, ctx, asm, cme, flags, argc, block_handler, known_recv_class, send_shift:)
- end
-
- # jit_call_cfunc_with_frame
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_cfunc_with_frame(jit, ctx, asm, cme, flags, argc, block_handler, known_recv_class, send_shift:)
- cfunc = cme.def.body.cfunc
-
- if argc + 1 > C_ARGS.size
- asm.incr_counter(:send_cfunc_too_many_args)
- return CantCompile
+ if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_ZSUPER != 0
+ # zsuper methods are super calls without any arguments.
+ # They are also marked as splat, but don't actually have an array
+ # they pull arguments from, instead we need to change to call
+ # a different method with the current stack.
+ asm.incr_counter(:send_args_splat_cfunc_zuper)
+ return CantCompile;
end
- frame_type = C::VM_FRAME_MAGIC_CFUNC | C::VM_FRAME_FLAG_CFRAME | C::VM_ENV_FLAG_LOCAL
- if flags & C::VM_CALL_KW_SPLAT != 0
- frame_type |= C::VM_FRAME_FLAG_CFRAME_KW
+ # In order to handle backwards compatibility between ruby 3 and 2
+ # ruby2_keywords was introduced. It is called only on methods
+ # with splat and changes they way they handle them.
+ # We are just going to not compile these.
+ # https://docs.ruby-lang.org/en/3.2/Module.html#method-i-ruby2_keywords
+ if jit.iseq.body.param.flags.ruby2_keywords && flags & C::VM_CALL_ARGS_SPLAT != 0
+ asm.incr_counter(:send_args_splat_cfunc_ruby2_keywords)
+ return CantCompile;
end
- # EXEC_EVENT_HOOK: RUBY_EVENT_C_CALL and RUBY_EVENT_C_RETURN
- if c_method_tracing_currently_enabled?
- asm.incr_counter(:send_c_tracing)
- return CantCompile
+ kw_arg = calling.kwarg
+ kw_arg_num = if kw_arg.nil?
+ 0
+ else
+ kw_arg.keyword_len
end
- # rb_check_arity
- if cfunc.argc >= 0 && argc != cfunc.argc
- asm.incr_counter(:send_arity)
+ if kw_arg_num != 0 && flags & C::VM_CALL_ARGS_SPLAT != 0
+ asm.incr_counter(:send_cfunc_splat_with_kw)
return CantCompile
end
- if cfunc.argc == -2
- asm.incr_counter(:send_cfunc_ruby_array_varg)
+
+ if c_method_tracing_currently_enabled?
+ # Don't JIT if tracing c_call or c_return
+ asm.incr_counter(:send_cfunc_tracing)
return CantCompile
end
# Delegate to codegen for C methods if we have it.
- if flags & C::VM_CALL_KWARG == 0 && flags & C::VM_CALL_OPT_SEND == 0
+ if kw_arg.nil? && flags & C::VM_CALL_OPT_SEND == 0
known_cfunc_codegen = lookup_cfunc_codegen(cme.def)
if known_cfunc_codegen&.call(jit, ctx, asm, argc, known_recv_class)
# cfunc codegen generated code. Terminate the block so
@@ -4735,78 +4741,151 @@ module RubyVM::RJIT
end
end
- # Push splat args, which was skipped in jit_caller_setup_arg.
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- # We aren't handling a vararg cfuncs with splat currently.
- if cfunc.argc == -1
- asm.incr_counter(:send_args_splat_cfunc_var_args)
- return CantCompile
- end
+ # Check for interrupts
+ jit_check_ints(jit, ctx, asm)
+
+ # Stack overflow check
+ # #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
+ # REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
+ asm.comment('stack overflow check')
+ asm.lea(:rax, ctx.sp_opnd(C.VALUE.size * 4 + 2 * C.rb_control_frame_t.size))
+ asm.cmp(CFP, :rax)
+ asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
+
+ # Number of args which will be passed through to the callee
+ # This is adjusted by the kwargs being combined into a hash.
+ passed_argc = if kw_arg.nil?
+ argc
+ else
+ argc - kw_arg_num + 1
+ end
- required_args = cfunc.argc - (argc - 1)
- # + 1 for self
+ # If the argument count doesn't match
+ if cfunc_argc >= 0 && cfunc_argc != passed_argc && flags & C::VM_CALL_ARGS_SPLAT == 0
+ asm.incr_counter(:send_cfunc_argc_mismatch)
+ return CantCompile
+ end
+
+ # Don't JIT functions that need C stack arguments for now
+ if cfunc_argc >= 0 && passed_argc + 1 > C_ARGS.size
+ asm.incr_counter(:send_cfunc_toomany_args)
+ return CantCompile
+ end
+
+ block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
+ # jit_caller_setup_arg_block already handled send_block_arg
+
+ if block_arg
+ ctx.stack_pop(1)
+ end
+
+ # push_splat_args does stack manipulation so we can no longer side exit
+ if flags & C::VM_CALL_ARGS_SPLAT != 0
+ assert_equal(true, cfunc_argc >= 0)
+ required_args = cfunc_argc - (argc - 1)
+ # + 1 because we pass self
if required_args + 1 >= C_ARGS.size
- asm.incr_counter(:send_cfunc_too_many_args)
+ asm.incr_counter(:send_cfunc_toomany_args)
return CantCompile
end
- # We are going to assume that the splat fills all the remaining arguments.
- # So the number of args should just equal the number of args the cfunc takes.
- # In the generated code we test if this is true and if not side exit.
- argc = cfunc.argc
+ # We are going to assume that the splat fills
+ # all the remaining arguments. So the number of args
+ # should just equal the number of args the cfunc takes.
+ # In the generated code we test if this is true
+ # and if not side exit.
+ argc = cfunc_argc
+ passed_argc = argc
push_splat_args(required_args, jit, ctx, asm)
end
- # We will not have side exits from here. Adjust the stack, which was skipped in jit_call_opt_send.
+ # This is a .send call and we need to adjust the stack
if flags & C::VM_CALL_OPT_SEND != 0
- jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ handle_opt_send_shift_stack(asm, argc, ctx, send_shift: calling.send_shift)
end
- # Check interrupts before SP motion to safely side-exit with the original SP.
- jit_check_ints(jit, ctx, asm)
+ # Points to the receiver operand on the stack
- # Stack overflow check
- # #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
- # REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
- asm.comment('stack overflow check')
- asm.lea(:rax, ctx.sp_opnd(C.VALUE.size * 4 + 2 * C.rb_control_frame_t.size))
- asm.cmp(CFP, :rax)
- asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
+ # Store incremented PC into current control frame in case callee raises.
+ jit_save_pc(jit, asm)
- # Pop blockarg after all side exits
- if flags & C::VM_CALL_ARGS_BLOCKARG != 0
- ctx.stack_pop(1)
+ # Increment the stack pointer by 3 (in the callee)
+ # sp += 3
+
+ frame_type = C::VM_FRAME_MAGIC_CFUNC | C::VM_FRAME_FLAG_CFRAME | C::VM_ENV_FLAG_LOCAL
+ if kw_arg
+ frame_type |= C::VM_FRAME_FLAG_CFRAME_KW
end
- # Push a callee frame. SP register and ctx are not modified inside this.
- jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, block_handler)
+ jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, calling.block_handler)
- asm.comment('call C function')
- case cfunc.argc
+ if kw_arg
+ # Build a hash from all kwargs passed
+ asm.comment('build_kwhash')
+ imemo_ci = calling.ci_addr
+ # we assume all callinfos with kwargs are on the GC heap
+ assert_equal(true, C.imemo_type_p(imemo_ci, C.imemo_callinfo))
+ asm.mov(C_ARGS[0], imemo_ci)
+ asm.lea(C_ARGS[1], ctx.sp_opnd(0))
+ asm.call(C.rjit_build_kwhash)
+
+ # Replace the stack location at the start of kwargs with the new hash
+ stack_opnd = ctx.stack_opnd(argc - passed_argc)
+ asm.mov(stack_opnd, C_RET)
+ end
+
+ # Copy SP because REG_SP will get overwritten
+ sp = :rax
+ asm.lea(sp, ctx.sp_opnd(0))
+
+ # Pop the C function arguments from the stack (in the caller)
+ ctx.stack_pop(argc + 1)
+
+ # Write interpreter SP into CFP.
+ # Needed in case the callee yields to the block.
+ jit_save_sp(ctx, asm)
+
+ # Non-variadic method
+ case cfunc_argc
in (0..) # Non-variadic method
- # Push receiver and args
- (1 + argc).times do |i|
- asm.mov(C_ARGS[i], ctx.stack_opnd(argc - i)) # TODO: +1 for VM_CALL_ARGS_BLOCKARG
+ # Copy the arguments from the stack to the C argument registers
+ # self is the 0th argument and is at index argc from the stack top
+ (0..passed_argc).each do |i|
+ asm.mov(C_ARGS[i], [sp, -(argc + 1 - i) * C.VALUE.size])
end
in -1 # Variadic method: rb_f_puts(int argc, VALUE *argv, VALUE recv)
- asm.mov(C_ARGS[0], argc)
- asm.lea(C_ARGS[1], ctx.stack_opnd(argc - 1)) # argv
- asm.mov(C_ARGS[2], ctx.stack_opnd(argc)) # recv
+ # The method gets a pointer to the first argument
+ # rb_f_puts(int argc, VALUE *argv, VALUE recv)
+ asm.mov(C_ARGS[0], passed_argc)
+ asm.lea(C_ARGS[1], [sp, -argc * C.VALUE.size]) # argv
+ asm.mov(C_ARGS[2], [sp, -(argc + 1) * C.VALUE.size]) # recv
end
+
+ # Call the C function
+ # VALUE ret = (cfunc->func)(recv, argv[0], argv[1]);
+ # cfunc comes from compile-time cme->def, which we assume to be stable.
+ # Invalidation logic is in yjit_method_lookup_change()
+ asm.comment('call C function')
asm.mov(:rax, cfunc.func)
asm.call(:rax) # TODO: use rel32 if close enough
- ctx.stack_pop(1 + argc)
+ # Record code position for TracePoint patching. See full_cfunc_return().
Invariants.record_global_inval_patch(asm, full_cfunc_return)
- asm.comment('push the return value')
+ # Push the return value on the Ruby stack
stack_ret = ctx.stack_push
asm.mov(stack_ret, C_RET)
- asm.comment('pop the stack frame')
+ # Pop the stack frame (ec->cfp++)
+ # Instead of recalculating, we can reuse the previous CFP, which is stored in a callee-saved
+ # register
asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], CFP)
- # Let guard chains share the same successor (ctx.sp_offset == 1)
+ # Note: the return block of gen_send_iseq() has ctx->sp_offset == 1
+ # which allows for sharing the same successor.
+
+ # Jump (fall through) to the call continuation block
+ # We do this to end the current block after the call
assert_equal(1, ctx.sp_offset)
jump_to_next_insn(jit, ctx, asm)
EndBlock
@@ -4845,7 +4924,7 @@ module RubyVM::RJIT
# This is a .send call and we need to adjust the stack
if flags & C::VM_CALL_OPT_SEND != 0
- jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ handle_opt_send_shift_stack(ctx, asm, argc, send_shift:)
end
# Save the PC and SP because the callee may allocate
@@ -4886,7 +4965,7 @@ module RubyVM::RJIT
return CantCompile
end
- # We don't support jit_call_opt_send_shift_stack for this yet.
+ # We don't support handle_opt_send_shift_stack for this yet.
if flags & C::VM_CALL_OPT_SEND != 0
asm.incr_counter(:send_ivar_opt_send)
return CantCompile
@@ -4998,7 +5077,7 @@ module RubyVM::RJIT
asm.incr_counter(:send_optimized_send_send)
return CantCompile
end
- # Lazily handle stack shift in jit_call_opt_send_shift_stack
+ # Lazily handle stack shift in handle_opt_send_shift_stack
calling.send_shift += 1
jit_call_symbol(jit, ctx, asm, cme, calling, known_recv_class, C::VM_CALL_FCALL)
@@ -5033,7 +5112,7 @@ module RubyVM::RJIT
# If this is a .send call we need to adjust the stack
if flags & C::VM_CALL_OPT_SEND != 0
- jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ handle_opt_send_shift_stack(ctx, asm, argc, send_shift:)
end
# About to reset the SP, need to load this here
@@ -5080,7 +5159,7 @@ module RubyVM::RJIT
# This is a .send call and we need to adjust the stack
if flags & C::VM_CALL_OPT_SEND != 0
- jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ handle_opt_send_shift_stack(ctx, asm, argc, send_shift:)
end
# All structs from the same Struct class should have the same
@@ -5109,7 +5188,7 @@ module RubyVM::RJIT
# vm_call_opt_send (lazy part)
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
- def jit_call_opt_send_shift_stack(ctx, asm, argc, send_shift:)
+ def handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
# We don't support `send(:send, ...)` for now.
assert_equal(1, send_shift)
@@ -5298,18 +5377,14 @@ module RubyVM::RJIT
# @param jit [RubyVM::RJIT::JITState]
# @param ctx [RubyVM::RJIT::Context]
# @param asm [RubyVM::RJIT::Assembler]
- def jit_caller_setup_arg(jit, ctx, asm, flags, splat: false)
+ def jit_caller_setup_arg(jit, ctx, asm, flags)
if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_KW_SPLAT != 0
asm.incr_counter(:send_args_splat_kw_splat)
return CantCompile
elsif flags & C::VM_CALL_ARGS_SPLAT != 0
- if splat
- # Lazily handle splat in jit_call_cfunc_with_frame
- else
- # splat is not supported in this path
- asm.incr_counter(:send_args_splat)
- return CantCompile
- end
+ # splat is not supported in this path
+ asm.incr_counter(:send_args_splat)
+ return CantCompile
elsif flags & C::VM_CALL_KW_SPLAT != 0
asm.incr_counter(:send_args_kw_splat)
return CantCompile
@@ -5429,18 +5504,6 @@ module RubyVM::RJIT
end
end
- # CALLER_REMOVE_EMPTY_KW_SPLAT: Return CantCompile if not supported
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_caller_remove_empty_kw_splat(jit, ctx, asm, flags)
- if (flags & C::VM_CALL_KW_SPLAT) > 0
- # We don't support removing the last Hash argument
- asm.incr_counter(:send_kw_splat)
- return CantCompile
- end
- end
-
# Generate RARRAY_LEN. For array_opnd, use Opnd::Reg to reduce memory access,
# and use Opnd::Mem to save registers.
def jit_array_len(asm, array_reg, len_reg)
@@ -5597,6 +5660,7 @@ module RubyVM::RJIT
argc: C.vm_ci_argc(ci),
flags: C.vm_ci_flag(ci),
kwarg: C.vm_ci_kwarg(ci),
+ ci_addr: ci.to_i,
send_shift: 0,
block_handler:,
)
diff --git a/rjit_c.c b/rjit_c.c
index 9e442f5f6f..7b5376701a 100644
--- a/rjit_c.c
+++ b/rjit_c.c
@@ -183,6 +183,21 @@ rjit_rb_ary_subseq_length(VALUE ary, long beg)
return rb_ary_subseq(ary, beg, len);
}
+static VALUE
+rjit_build_kwhash(const struct rb_callinfo *ci, VALUE *sp)
+{
+ const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci);
+ int kw_len = kw_arg->keyword_len;
+ VALUE hash = rb_hash_new_with_size(kw_len);
+
+ for (int i = 0; i < kw_len; i++) {
+ VALUE key = kw_arg->keywords[i];
+ VALUE val = *(sp - kw_len + i);
+ rb_hash_aset(hash, key, val);
+ }
+ return hash;
+}
+
// The code we generate in gen_send_cfunc() doesn't fire the c_return TracePoint event
// like the interpreter. When tracing for c_return is enabled, we patch the code after
// the C method return to call into this to fire the event.
diff --git a/rjit_c.h b/rjit_c.h
index 6aca73556c..5756ec19ef 100644
--- a/rjit_c.h
+++ b/rjit_c.h
@@ -27,6 +27,8 @@ RJIT_RUNTIME_COUNTERS(
send_args_splat_cfunc_var_args,
send_args_splat_arity_error,
send_args_splat_ruby2_hash,
+ send_args_splat_cfunc_zuper,
+ send_args_splat_cfunc_ruby2_keywords,
send_kw_splat,
send_kwarg,
send_klass_megamorphic,
@@ -80,6 +82,10 @@ RJIT_RUNTIME_COUNTERS(
send_cfunc_variadic,
send_cfunc_too_many_args,
send_cfunc_ruby_array_varg,
+ send_cfunc_splat_with_kw,
+ send_cfunc_tracing,
+ send_cfunc_argc_mismatch,
+ send_cfunc_toomany_args,
send_attrset_splat,
send_attrset_kwarg,
diff --git a/rjit_c.rb b/rjit_c.rb
index 2ba8f2d378..bd7ef3bf0b 100644
--- a/rjit_c.rb
+++ b/rjit_c.rb
@@ -475,6 +475,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM(idRespond_to_missing) }
end
+ def C.imemo_callinfo
+ Primitive.cexpr! %q{ SIZET2NUM(imemo_callinfo) }
+ end
+
def C.imemo_iseq
Primitive.cexpr! %q{ SIZET2NUM(imemo_iseq) }
end
@@ -735,6 +739,10 @@ module RubyVM::RJIT # :nodoc: all
Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_yield_with_cfunc) }
end
+ def C.rjit_build_kwhash
+ Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_build_kwhash) }
+ end
+
def C.rjit_full_cfunc_return
Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) }
end
@@ -1315,6 +1323,8 @@ module RubyVM::RJIT # :nodoc: all
send_args_splat_cfunc_var_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_var_args)")],
send_args_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_arity_error)")],
send_args_splat_ruby2_hash: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_ruby2_hash)")],
+ send_args_splat_cfunc_zuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_zuper)")],
+ send_args_splat_cfunc_ruby2_keywords: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_ruby2_keywords)")],
send_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_kw_splat)")],
send_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_kwarg)")],
send_klass_megamorphic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_klass_megamorphic)")],
@@ -1365,6 +1375,10 @@ module RubyVM::RJIT # :nodoc: all
send_cfunc_variadic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_variadic)")],
send_cfunc_too_many_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_too_many_args)")],
send_cfunc_ruby_array_varg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_ruby_array_varg)")],
+ send_cfunc_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_splat_with_kw)")],
+ send_cfunc_tracing: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_tracing)")],
+ send_cfunc_argc_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_argc_mismatch)")],
+ send_cfunc_toomany_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_toomany_args)")],
send_attrset_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_splat)")],
send_attrset_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_kwarg)")],
send_attrset_method: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_method)")],
diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb
index 98d1ee775a..da8526c29c 100755
--- a/tool/rjit/bindgen.rb
+++ b/tool/rjit/bindgen.rb
@@ -492,6 +492,7 @@ generator = BindingGenerator.new(
SIZET: %w[
block_type_iseq
imemo_iseq
+ imemo_callinfo
rb_block_param_proxy
rb_cFalseClass
rb_cFloat
@@ -566,6 +567,7 @@ generator = BindingGenerator.new(
rb_ary_dup
rjit_rb_ary_subseq_length
rb_ary_unshift_m
+ rjit_build_kwhash
],
types: %w[
CALL_DATA