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

ruby-changes:57641

From: Yusuke <ko1@a...>
Date: Sat, 7 Sep 2019 16:05:32 +0900 (JST)
Subject: [ruby-changes:57641] 1e008105bc (master): compile.c (compile_list): emit newarraykwsplat only at the last chunk

https://git.ruby-lang.org/ruby.git/commit/?id=1e008105bc

From 1e008105bc4576af46036f1c73f96f7f93bee319 Mon Sep 17 00:00:00 2001
From: Yusuke Endoh <mame@r...>
Date: Sat, 7 Sep 2019 16:01:16 +0900
Subject: compile.c (compile_list): emit newarraykwsplat only at the last chunk

`[{}, {}, {}, ..., {}, *{}]` is wrongly created.

A big array literal is created and concatenated for every 256 elements.
The newarraykwsplat must be emitted only at the last chunk.

diff --git a/compile.c b/compile.c
index ed9deea..43a1038 100644
--- a/compile.c
+++ b/compile.c
@@ -3944,13 +3944,13 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L3944
         int num_kw = 0;
 
 	while (node) {
-	    const NODE *start_node = node, *end_node;
+	    const NODE *start_node = node, *end_node, *prev_node;
 	    const NODE *kw = 0;
 	    const int max = 0x100;
 	    DECL_ANCHOR(anchor);
 	    INIT_ANCHOR(anchor);
 
-	    for (i=0; i<max && node; i++, len++, node = node->nd_next) {
+	    for (i=0; i<max && node; i++, len++, prev_node = node, node = node->nd_next) {
 		if (CPDEBUG > 0) {
 		    EXPECT_NODE("compile_list", node, NODE_LIST, -1);
 		}
@@ -4032,14 +4032,9 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L4032
 		if (!popped || kw) {
 		    switch (type) {
                       case COMPILE_ARRAY_TYPE_ARRAY: {
-                        const NODE *check_node = node_root;
-
                         /* Find last node in array, and if it is a keyword argument, then set
                            flag to check and remove empty keyword arguments hash from array */
-                        while(check_node->nd_next) {
-                            check_node = check_node->nd_next;
-                        }
-                        if (nd_type(check_node->nd_head) == NODE_HASH && check_node->nd_head->nd_brace == 0) {
+                        if (!node && nd_type(prev_node->nd_head) == NODE_HASH && prev_node->nd_head->nd_brace == 0) {
                             ADD_INSN1(anchor, line, newarraykwsplat, INT2FIX(i));
                         }
                         else {
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 335c2dc..955a00a 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -3213,6 +3213,14 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L3213
     assert_raise(TypeError) {[1].sum("")}
   end
 
+  def test_big_array_literal_with_kwsplat
+    lit = "["
+    10000.times { lit << "{}," }
+    lit << "**{}]"
+
+    assert_equal(10000, eval(lit).size)
+  end
+
   private
   def need_continuation
     unless respond_to?(:callcc, true)
-- 
cgit v0.10.2


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

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