From 70ea58bd5ba42b26ff39f51079af0efa422ac036 Mon Sep 17 00:00:00 2001 From: Takashi Kokubun Date: Sun, 19 Mar 2023 21:18:09 -0700 Subject: RJIT: Break up RJIT send_iseq_complex exit reasons --- lib/ruby_vm/rjit/insn_compiler.rb | 99 +++++++++++++++++++++++++++++++++++++-- rjit_c.h | 13 ++++- rjit_c.rb | 15 +++++- tool/rjit/bindgen.rb | 2 + 4 files changed, 122 insertions(+), 7 deletions(-) diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb index 013f961829..80d09376d3 100644 --- a/lib/ruby_vm/rjit/insn_compiler.rb +++ b/lib/ruby_vm/rjit/insn_compiler.rb @@ -4705,7 +4705,7 @@ module RubyVM::RJIT return 0 else - return jit_setup_parameters_complex(jit, ctx, asm, calling.flags, calling.argc, iseq) + return jit_setup_parameters_complex(jit, ctx, asm, calling.flags, calling.argc, iseq, arg_setup_type:) end end @@ -4713,10 +4713,99 @@ module RubyVM::RJIT # @param jit [RubyVM::RJIT::JITState] # @param ctx [RubyVM::RJIT::Context] # @param asm [RubyVM::RJIT::Assembler] - def jit_setup_parameters_complex(jit, ctx, asm, flags, argc, iseq) - # We don't support setup_parameters_complex - asm.incr_counter(:send_iseq_complex) - return CantCompile + def jit_setup_parameters_complex(jit, ctx, asm, flags, argc, iseq, arg_setup_type: nil) + min_argc = iseq.body.param.lead_num + iseq.body.param.post_num + max_argc = (iseq.body.param.flags.has_rest == false) ? min_argc + iseq.body.param.opt_num : C::UNLIMITED_ARGUMENTS + kw_flag = flags & (C::VM_CALL_KWARG | C::VM_CALL_KW_SPLAT | C::VM_CALL_KW_SPLAT_MUT) + opt_pc = 0 + keyword_hash = nil + flag_keyword_hash = nil + given_argc = argc + + if kw_flag & C::VM_CALL_KWARG != 0 + asm.incr_counter(:send_iseq_complex_kwarg) + return CantCompile + end + + if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_KW_SPLAT != 0 + asm.incr_counter(:send_iseq_complex_kw_splat) + return CantCompile + elsif flags & C::VM_CALL_ARGS_SPLAT != 0 + asm.incr_counter(:send_iseq_complex_splat) + return CantCompile + else + if argc > 0 && kw_flag & C::VM_CALL_KW_SPLAT != 0 + asm.incr_counter(:send_iseq_complex_kw_splat) + return CantCompile + end + end + + if flag_keyword_hash && C.RB_TYPE_P(flag_keyword_hash, C::RUBY_T_HASH) + raise NotImplementedError # unreachable + end + + if kw_flag != 0 && iseq.body.param.flags.accepts_no_kwarg + asm.incr_counter(:send_iseq_complex_accepts_no_kwarg) + return CantCompile + end + + case arg_setup_type + when :arg_setup_block + asm.incr_counter(:send_iseq_complex_arg_setup_block) + return CantCompile + end + + if given_argc < min_argc + asm.incr_counter(:send_iseq_complex_arity) + return CantCompile + end + + if given_argc > max_argc && max_argc != C::UNLIMITED_ARGUMENTS + asm.incr_counter(:send_iseq_complex_arity) + return CantCompile + end + + if iseq.body.param.flags.has_lead + asm.incr_counter(:send_iseq_complex_has_lead) + return CantCompile + end + + if iseq.body.param.flags.has_rest || iseq.body.param.flags.has_post + asm.incr_counter(:send_iseq_complex_has_rest_or_post) + return CantCompile + end + + if iseq.body.param.flags.has_post + asm.incr_counter(:send_iseq_complex_has_rest_or_post) + return CantCompile + end + + if iseq.body.param.flags.has_opt + asm.incr_counter(:send_iseq_complex_has_opt) + return CantCompile + end + + if iseq.body.param.flags.has_rest + asm.incr_counter(:send_iseq_complex_has_rest_or_post) + return CantCompile + end + + if iseq.body.param.flags.has_kw + asm.incr_counter(:send_iseq_complex_has_kw) + return CantCompile + elsif iseq.body.param.flags.has_kwrest + asm.incr_counter(:send_iseq_complex_has_kwrest) + return CantCompile + elsif !keyword_hash.nil? && keyword_hash.size > 0 # && arg_setup_type == :arg_setup_method + raise NotImplementedError # unreachable + end + + if iseq.body.param.flags.has_block + asm.incr_counter(:send_iseq_complex_has_block) + return CantCompile + end + + return opt_pc end # CALLER_SETUP_ARG: Return CantCompile if not supported diff --git a/rjit_c.h b/rjit_c.h index 9a7f2ba542..384b517480 100644 --- a/rjit_c.h +++ b/rjit_c.h @@ -51,7 +51,18 @@ RJIT_RUNTIME_COUNTERS( send_block_not_proxy, send_iseq_kwparam, - send_iseq_complex, + send_iseq_complex_kwarg, + send_iseq_complex_kw_splat, + send_iseq_complex_splat, + send_iseq_complex_accepts_no_kwarg, + send_iseq_complex_arg_setup_block, + send_iseq_complex_arity, + send_iseq_complex_has_lead, + send_iseq_complex_has_rest_or_post, + send_iseq_complex_has_opt, + send_iseq_complex_has_kw, + send_iseq_complex_has_kwrest, + send_iseq_complex_has_block, send_cfunc_variadic, send_cfunc_too_many_args, diff --git a/rjit_c.rb b/rjit_c.rb index c50911c55a..d87dbb8aab 100644 --- a/rjit_c.rb +++ b/rjit_c.rb @@ -349,6 +349,7 @@ module RubyVM::RJIT # :nodoc: all ### RJIT bindgen begin ### + C::UNLIMITED_ARGUMENTS = Primitive.cexpr! %q{ LONG2NUM(UNLIMITED_ARGUMENTS) } 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) } C::ARRAY_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(ARRAY_REDEFINED_OP_FLAG) } @@ -419,6 +420,7 @@ module RubyVM::RJIT # :nodoc: all C::VM_CALL_FCALL = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_FCALL) } C::VM_CALL_KWARG = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KWARG) } C::VM_CALL_KW_SPLAT = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT) } + C::VM_CALL_KW_SPLAT_MUT = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT_MUT) } C::VM_CALL_KW_SPLAT_bit = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT_bit) } C::VM_CALL_OPT_SEND = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_OPT_SEND) } C::VM_CALL_TAILCALL = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_TAILCALL) } @@ -1294,7 +1296,18 @@ module RubyVM::RJIT # :nodoc: all send_block_not_nil: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_not_nil)")], send_block_not_proxy: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_not_proxy)")], send_iseq_kwparam: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kwparam)")], - send_iseq_complex: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex)")], + send_iseq_complex_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_kwarg)")], + send_iseq_complex_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_kw_splat)")], + send_iseq_complex_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_splat)")], + send_iseq_complex_accepts_no_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_accepts_no_kwarg)")], + send_iseq_complex_arg_setup_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_arg_setup_block)")], + send_iseq_complex_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_arity)")], + send_iseq_complex_has_lead: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_lead)")], + send_iseq_complex_has_rest_or_post: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_rest_or_post)")], + send_iseq_complex_has_opt: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_opt)")], + send_iseq_complex_has_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_kw)")], + send_iseq_complex_has_kwrest: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_kwrest)")], + send_iseq_complex_has_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_complex_has_block)")], 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)")], diff --git a/tool/rjit/bindgen.rb b/tool/rjit/bindgen.rb index cd8502a2a7..66d45af361 100755 --- a/tool/rjit/bindgen.rb +++ b/tool/rjit/bindgen.rb @@ -377,6 +377,7 @@ generator = BindingGenerator.new( src_path: src_path, consts: { LONG: %w[ + UNLIMITED_ARGUMENTS VM_ENV_DATA_INDEX_ME_CREF VM_ENV_DATA_INDEX_SPECVAL ], @@ -447,6 +448,7 @@ generator = BindingGenerator.new( VM_CALL_FCALL VM_CALL_KWARG VM_CALL_KW_SPLAT + VM_CALL_KW_SPLAT_MUT VM_CALL_KW_SPLAT_bit VM_CALL_OPT_SEND VM_CALL_TAILCALL -- cgit v1.2.1