diff options
author | Takashi Kokubun <takashikkbn@gmail.com> | 2023-04-02 12:56:27 -0700 |
---|---|---|
committer | Takashi Kokubun <takashikkbn@gmail.com> | 2023-04-02 13:58:39 -0700 |
commit | 66f8efc342bd36ae14090f14e7c2b9a0e30b9be3 (patch) | |
tree | 0be84b050006a8e3ef30d3c7f3c75ef29a0f8780 | |
parent | 284a0ff96c97be0c2413e3fb59a7874e4092c90b (diff) | |
download | ruby-66f8efc342bd36ae14090f14e7c2b9a0e30b9be3.tar.gz |
RJIT: Simplify cfunc implementation
-rw-r--r-- | lib/ruby_vm/rjit/insn_compiler.rb | 276 | ||||
-rw-r--r-- | rjit_c.c | 15 | ||||
-rw-r--r-- | rjit_c.h | 6 | ||||
-rw-r--r-- | rjit_c.rb | 14 | ||||
-rwxr-xr-x | tool/rjit/bindgen.rb | 2 |
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:, ) @@ -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. @@ -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, @@ -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 |