mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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.
This commit is contained in:
parent
c725a4e48f
commit
1e008105bc
2 changed files with 11 additions and 8 deletions
11
compile.c
11
compile.c
|
@ -3944,13 +3944,13 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo
|
||||||
int num_kw = 0;
|
int num_kw = 0;
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
const NODE *start_node = node, *end_node;
|
const NODE *start_node = node, *end_node, *prev_node;
|
||||||
const NODE *kw = 0;
|
const NODE *kw = 0;
|
||||||
const int max = 0x100;
|
const int max = 0x100;
|
||||||
DECL_ANCHOR(anchor);
|
DECL_ANCHOR(anchor);
|
||||||
INIT_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) {
|
if (CPDEBUG > 0) {
|
||||||
EXPECT_NODE("compile_list", node, NODE_LIST, -1);
|
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) {
|
if (!popped || kw) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case COMPILE_ARRAY_TYPE_ARRAY: {
|
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
|
/* 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 */
|
flag to check and remove empty keyword arguments hash from array */
|
||||||
while(check_node->nd_next) {
|
if (!node && nd_type(prev_node->nd_head) == NODE_HASH && prev_node->nd_head->nd_brace == 0) {
|
||||||
check_node = check_node->nd_next;
|
|
||||||
}
|
|
||||||
if (nd_type(check_node->nd_head) == NODE_HASH && check_node->nd_head->nd_brace == 0) {
|
|
||||||
ADD_INSN1(anchor, line, newarraykwsplat, INT2FIX(i));
|
ADD_INSN1(anchor, line, newarraykwsplat, INT2FIX(i));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -3213,6 +3213,14 @@ class TestArray < Test::Unit::TestCase
|
||||||
assert_raise(TypeError) {[1].sum("")}
|
assert_raise(TypeError) {[1].sum("")}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_big_array_literal_with_kwsplat
|
||||||
|
lit = "["
|
||||||
|
10000.times { lit << "{}," }
|
||||||
|
lit << "**{}]"
|
||||||
|
|
||||||
|
assert_equal(10000, eval(lit).size)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def need_continuation
|
def need_continuation
|
||||||
unless respond_to?(:callcc, true)
|
unless respond_to?(:callcc, true)
|
||||||
|
|
Loading…
Reference in a new issue