ruby-changes:69240
From: Kevin <ko1@a...>
Date: Thu, 21 Oct 2021 08:24:20 +0900 (JST)
Subject: [ruby-changes:69240] 885bb972bf (master): Get kwargs working for all passed in the correct order
https://git.ruby-lang.org/ruby.git/commit/?id=885bb972bf From 885bb972bfd80cb1c6ca4e5f521e823a1ae14c4a Mon Sep 17 00:00:00 2001 From: Kevin Newton <kddnewton@g...> Date: Tue, 28 Sep 2021 14:45:35 -0400 Subject: Get kwargs working for all passed in the correct order --- yjit_codegen.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/yjit_codegen.c b/yjit_codegen.c index e16a41f425..4e3bb353c6 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -3358,6 +3358,7 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3358 // Arity handling and optional parameter setup int num_params = iseq->body->param.size; uint32_t start_pc_offset = 0; + if (iseq_lead_only_arg_setup_p(iseq)) { num_params = iseq->body->param.lead_num; @@ -3387,9 +3388,58 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3388 start_pc_offset = (uint32_t)iseq->body->param.opt_table[opts_filled]; } else if (rb_iseq_only_kwparam_p(iseq)) { - // vm_callee_setup_arg() has a fast path for this. - GEN_COUNTER_INC(cb, send_iseq_only_keywords); - return YJIT_CANT_COMPILE; + const int required_num = iseq->body->param.lead_num; + + if (vm_ci_flag(ci) & VM_CALL_KWARG) { + // Calling a method with keyword parameters and specifying keyword + // arguments + + const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci); + + if (argc - kw_arg->keyword_len != required_num) { + // There is a mix of required and optional keyword arguments and + // not every one is specified + + GEN_COUNTER_INC(cb, send_iseq_kwargs_req_and_opt_missing); + return YJIT_CANT_COMPILE; + } + + const int req_key_num = iseq->body->param.keyword->required_num; + RUBY_ASSERT(req_key_num == kw_arg->keyword_len); + + // callee expects keyword arguments + // caller is sending the correct number of positional arguments + // caller is sending keyword arguments + + const ID *acceptable_keywords = iseq->body->param.keyword->table; + const VALUE * const ci_keywords = kw_arg->keywords; + + // Check that the names of the given keyword arguments match up to + // the names of the keyword parameters and that they were passed in + // the exact same order + for (int i = 0; i < req_key_num; i++) { + if (ID2SYM(acceptable_keywords[i]) != ci_keywords[i]) { + GEN_COUNTER_INC(cb, send_iseq_kwargs_need_shuffling); + return YJIT_CANT_COMPILE; + } + } + + // caller and callee specified all the same keywords in the exact + // same order + + // Kwargs adds a special weird little local that specifies a bitmap + // that corresponds to the keyword arguments that are not passed. + num_params--; + } else if (argc == required_num) { + // Calling a method that accepts keyword parameters but not + // specifying any keyword arguments + + GEN_COUNTER_INC(cb, send_iseq_kwargs_none_passed); + return YJIT_CANT_COMPILE; + } else { + GEN_COUNTER_INC(cb, send_iseq_complex_callee); + return YJIT_CANT_COMPILE; + } } else { // Only handle iseqs that have simple parameter setup. @@ -3605,10 +3655,6 @@ gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3655 GEN_COUNTER_INC(cb, send_args_splat); return YJIT_CANT_COMPILE; } - if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { - GEN_COUNTER_INC(cb, send_keywords); - return YJIT_CANT_COMPILE; - } if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) != 0) { GEN_COUNTER_INC(cb, send_block_arg); return YJIT_CANT_COMPILE; @@ -3671,6 +3717,10 @@ gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3717 case VM_METHOD_TYPE_ISEQ: return gen_send_iseq(jit, ctx, ci, cme, block, argc); case VM_METHOD_TYPE_CFUNC: + if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { + GEN_COUNTER_INC(cb, send_cfunc_kwargs); + return YJIT_CANT_COMPILE; + } return gen_send_cfunc(jit, ctx, ci, cme, block, argc, &comptime_recv_klass); case VM_METHOD_TYPE_IVAR: if (argc != 0) { @@ -3685,7 +3735,10 @@ gen_send_general(jitstate_t *jit, ctx_t *ctx, struct rb_call_data *cd, rb_iseq_t https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L3735 return gen_get_ivar(jit, ctx, SEND_MAX_DEPTH, comptime_recv, ivar_name, recv_opnd, side_exit); } case VM_METHOD_TYPE_ATTRSET: - if (argc != 1 || !RB_TYPE_P(comptime_recv, T_OBJECT)) { + if ((vm_ci_flag(ci) & VM_CALL_KWARG) != 0) { + GEN_COUNTER_INC(cb, send_attrset_keywords); + return YJIT_CANT_COMPILE; + } else if (argc != 1 || !RB_TYPE_P(comptime_recv, T_OBJECT)) { GEN_COUNTER_INC(cb, send_ivar_set_method); return YJIT_CANT_COMPILE; } -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/