diff options
author | Yusuke Endoh <mame@ruby-lang.org> | 2019-09-07 16:01:16 +0900 |
---|---|---|
committer | Yusuke Endoh <mame@ruby-lang.org> | 2019-09-07 16:05:15 +0900 |
commit | 1e008105bc4576af46036f1c73f96f7f93bee319 (patch) | |
tree | 52bb069d7af5ca839e659e10b3e577ab6b01fe4e | |
parent | c725a4e48fc30cb60e539e86c917698209184345 (diff) | |
download | ruby-1e008105bc4576af46036f1c73f96f7f93bee319.tar.gz |
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.
-rw-r--r-- | compile.c | 11 | ||||
-rw-r--r-- | test/ruby/test_array.rb | 8 |
2 files changed, 11 insertions, 8 deletions
@@ -3944,13 +3944,13 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo 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 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 335c2dc042..955a00ad99 100644 --- a/test/ruby/test_array.rb +++ b/test/ruby/test_array.rb @@ -3213,6 +3213,14 @@ class TestArray < Test::Unit::TestCase 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) |