summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYusuke Endoh <mame@ruby-lang.org>2019-09-07 16:26:38 +0900
committerYusuke Endoh <mame@ruby-lang.org>2019-09-07 16:26:38 +0900
commit2f2f8107d0d21f5ebaaaf3b2d7ed6d09dfec91d5 (patch)
treea53407c61568d3b38d3fc0f3feb50ba0621cf0d6
parent1e008105bc4576af46036f1c73f96f7f93bee319 (diff)
compile.c (compile_list): allow an odd-length hidden array literal
An array literal [1,2,...,301] was compiled to the following iseq: duparray [1,2,...,300] putobject [301] concatarray The Array literal optimization took every two elements maybe because it must handle not only Array but also Hash. Now the optimization takes each element if it is an Array literal. So the new iseq is: duparray [1,2,...,301].
-rw-r--r--compile.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/compile.c b/compile.c
index 43a103842a..10dff7ca03 100644
--- a/compile.c
+++ b/compile.c
@@ -3987,16 +3987,25 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo
rb_ary_push(ary, static_literal_value(node, iseq));
node = node->nd_next;
}
- while (node && node->nd_next &&
- static_literal_node_p(node, iseq) &&
- static_literal_node_p(node->nd_next, iseq)) {
- VALUE elem[2];
- elem[0] = static_literal_value(node, iseq);
- elem[1] = static_literal_value(node->nd_next, iseq);
- rb_ary_cat(ary, elem, 2);
- node = node->nd_next->nd_next;
- len++;
- }
+ if (type == COMPILE_ARRAY_TYPE_ARRAY) {
+ while (node && static_literal_node_p(node, iseq)) {
+ rb_ary_push(ary, static_literal_value(node, iseq));
+ node = node->nd_next;
+ len++;
+ }
+ }
+ else { /* COMPILE_ARRAY_TYPE_HASH */
+ while (node && node->nd_next &&
+ static_literal_node_p(node, iseq) &&
+ static_literal_node_p(node->nd_next, iseq)) {
+ VALUE elem[2];
+ elem[0] = static_literal_value(node, iseq);
+ elem[1] = static_literal_value(node->nd_next, iseq);
+ rb_ary_cat(ary, elem, 2);
+ node = node->nd_next->nd_next;
+ len++;
+ }
+ }
OBJ_FREEZE(ary);