[前][次][番号順一覧][スレッド一覧]

ruby-changes:69145

From: Kevin <ko1@a...>
Date: Thu, 21 Oct 2021 08:21:00 +0900 (JST)
Subject: [ruby-changes:69145] 266e12ac22 (master): Push the unspecified_bits_value onto the stack

https://git.ruby-lang.org/ruby.git/commit/?id=266e12ac22

From 266e12ac2262db776c6138e144628b9f31d763a8 Mon Sep 17 00:00:00 2001
From: Kevin Newton <kddnewton@g...>
Date: Mon, 4 Oct 2021 13:08:57 -0400
Subject: Push the unspecified_bits_value onto the stack

---
 yjit_codegen.c | 43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/yjit_codegen.c b/yjit_codegen.c
index b125f0c6f7..e25d0dc01d 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -3400,8 +3400,14 @@ 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#L3400
             // Here we're calling a method with keyword arguments and specifying
             // keyword arguments at this call site.
 
+            // This struct represents the metadata about the caller-specified
+            // keyword arguments.
             const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci);
 
+            // This struct represents the metadata about the callee-specified
+            // keyword parameters.
+            const struct rb_iseq_param_keyword *keyword = iseq->body->param.keyword;
+
             if (argc - kw_arg->keyword_len != required_num) {
                 // Here the method being called specifies optional and required
                 // keyword arguments and the callee is not specifying every one
@@ -3413,30 +3419,29 @@ 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#L3419
             // Here we should be safe to assume that the caller is specifying
             // every keyword argument that the callee has declared in its
             // definition (whether or not they were required).
-            const int req_key_num = iseq->body->param.keyword->required_num;
-            RUBY_ASSERT(req_key_num == kw_arg->keyword_len);
+            RUBY_ASSERT(kw_arg->keyword_len == keyword->num);
 
             // This is the list of keyword arguments that the callee specified
             // in its initial declaration.
-            const ID *callee_kwargs = iseq->body->param.keyword->table;
+            const ID *callee_kwargs = keyword->table;
 
             // Here we're going to build up a list of the IDs that correspond to
             // the caller-specified keyword arguments. If they're not in the
             // same order as the order specified in the callee declaration, then
             // we're going to need to generate some code to swap values around
             // on the stack.
-            ID *caller_kwargs = ALLOCA_N(VALUE, req_key_num);
-            for (int kwarg_idx = 0; kwarg_idx < req_key_num; kwarg_idx++)
+            ID *caller_kwargs = ALLOCA_N(VALUE, kw_arg->keyword_len);
+            for (int kwarg_idx = 0; kwarg_idx < kw_arg->keyword_len; kwarg_idx++)
                 caller_kwargs[kwarg_idx] = SYM2ID(kw_arg->keywords[kwarg_idx]);
 
             // First, we're going to be sure that the names of every
-            // callee-specified keyword argument correspond to a name in the
-            // list of caller-specified keyword arguments.
-            for (int callee_idx = 0; callee_idx < req_key_num; callee_idx++) {
-                int caller_idx;
+            // caller-specified keyword argument correspond to a name in the
+            // list of callee-specified keyword parameters.
+            for (int caller_idx = 0; caller_idx < kw_arg->keyword_len; caller_idx++) {
+                int callee_idx;
 
-                for (caller_idx = 0; caller_idx < req_key_num; caller_idx++) {
-                    if (callee_kwargs[callee_idx] == caller_kwargs[caller_idx]) {
+                for (callee_idx = 0; callee_idx < keyword->num; callee_idx++) {
+                    if (caller_kwargs[caller_idx] == callee_kwargs[callee_idx]) {
                         break;
                     }
                 }
@@ -3444,16 +3449,16 @@ 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#L3449
                 // If the keyword was never found, then we know we have a
                 // mismatch in the names of the keyword arguments, so we need to
                 // bail.
-                if (caller_idx == req_key_num) {
+                if (callee_idx == keyword->num) {
                     GEN_COUNTER_INC(cb, send_iseq_kwargs_mismatch);
                     return YJIT_CANT_COMPILE;
                 }
             }
 
-            // Next, we're going to loop through every keyword was that
+            // Next, we're going to loop through every keyword that was
             // specified by the caller and make sure that it's in the correct
             // place. If it's not we're going to swap it around with another one.
-            for (int kwarg_idx = 0; kwarg_idx < req_key_num; kwarg_idx++) {
+            for (int kwarg_idx = 0; kwarg_idx < kw_arg->keyword_len; kwarg_idx++) {
                 ID callee_kwarg = callee_kwargs[kwarg_idx];
 
                 // If the argument is already in the right order, then we don't
@@ -3464,7 +3469,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#L3469
                 // In this case the argument is not in the right place, so we
                 // need to find its position where it _should_ be and swap with
                 // that location.
-                for (int swap_idx = kwarg_idx + 1; swap_idx < req_key_num; swap_idx++) {
+                for (int swap_idx = kwarg_idx + 1; swap_idx < kw_arg->keyword_len; swap_idx++) {
                     if (callee_kwarg == caller_kwargs[swap_idx]) {
                         // First we're going to generate the code that is going
                         // to perform the actual swapping at runtime.
@@ -3482,9 +3487,13 @@ 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#L3487
                 }
             }
 
-            // Kwargs adds a special weird little local that specifies a bitmap
-            // that corresponds to the keyword arguments that are not passed.
+            // Keyword arguments cause a special extra local variable to be
+            // pushed onto the stack that represents the parameters that weren't
+            // explicitly given a value. Its value is a bitmap that corresponds
+            // to the indices of the missing parameters. In this case since we
+            // know every value was specified, we can just write the value 0.
             num_params--;
+            mov(cb, ctx_stack_opnd(ctx, argc - 1 - kw_arg->keyword_len), imm_opnd(INT2FIX(0)));
         } else if (argc == required_num) {
             // Here we are calling a method that accepts keyword arguments
             // (optional or required) but we're not passing any keyword
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]