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

ruby-changes:57665

From: Yusuke <ko1@a...>
Date: Sun, 8 Sep 2019 03:17:19 +0900 (JST)
Subject: [ruby-changes:57665] 46bfe907f1 (master): compile.c (compile_hash): rewrite keyword splat handling

https://git.ruby-lang.org/ruby.git/commit/?id=46bfe907f1

From 46bfe907f1d61217215bcd1a7da9dff258c63294 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Sun, 8 Sep 2019 03:06:38 +0900
Subject: compile.c (compile_hash): rewrite keyword splat handling

and add some comments.
(I confirm that `foo(**{})` allocates no hash object.)

diff --git a/compile.c b/compile.c
index 988493f..ade5806 100644
--- a/compile.c
+++ b/compile.c
@@ -4191,20 +4191,32 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popp https://github.com/ruby/ruby/blob/trunk/compile.c#L4191
                 int last_kw = !node->nd_next->nd_next;        /* foo(  ..., **kw) */
                 int only_kw = last_kw && first_kw;            /* foo(1,2,3, **kw) */
 
-                if (!empty_kw) {
-                    ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
-                    if (!first_kw) ADD_INSN(ret, line, swap);
-                    else ADD_INSN1(ret, line, newhash, INT2FIX(0));
+                if (empty_kw) {
+                    if (only_kw) {
+                        /* **{} appears at the last, so it won't be modified.
+                         * kw is a special NODE_LIT that contains a special empty hash,
+                         * so this emits: putobject {}
+                         */
+                        NO_CHECK(COMPILE(ret, "keyword splat", kw));
+                    }
+                    else if (first_kw) {
+                        /* **{} appears at the first, so it may be modified.
+                         * We need to create a fresh hash object.
+                         */
+                        ADD_INSN1(ret, line, newhash, INT2FIX(0));
+                    }
                 }
+                else {
+                    /* This is not empty hash: **{k:1}.
+                     * We need to clone the hash (if first), or merge the hash to
+                     * the accumulated hash (if not first).
+                     */
+                    ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+                    if (first_kw) ADD_INSN1(ret, line, newhash, INT2FIX(0));
+                    else ADD_INSN(ret, line, swap);
 
-                if (empty_kw && first_kw && !only_kw) {
-                    ADD_INSN1(ret, line, newhash, INT2FIX(0));
-                }
-                else if (!empty_kw || only_kw) {
                     NO_CHECK(COMPILE(ret, "keyword splat", kw));
-                }
 
-                if (!empty_kw) {
                     ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2));
                 }
 
-- 
cgit v0.10.2


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

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