ruby-changes:57643
From: Yusuke <ko1@a...>
Date: Sat, 7 Sep 2019 16:51:49 +0900 (JST)
Subject: [ruby-changes:57643] a2260bd636 (master): compile.c: Separate compile_list to two functions for Array and Hash
https://git.ruby-lang.org/ruby.git/commit/?id=a2260bd636 From a2260bd636646cde486afeebe5a0a7ef5ec78a4e Mon Sep 17 00:00:00 2001 From: Yusuke Endoh <mame@r...> Date: Sat, 7 Sep 2019 16:45:49 +0900 Subject: compile.c: Separate compile_list to two functions for Array and Hash compile_list was for the compilation of Array literal and Hash literal. I guess it was originally reasonable to handle them in one function, but now, compilation of Array is very different from Hash. So the function was complicated by many branches for Array and Hash. This change separates the function to two ones for Array and Hash. diff --git a/compile.c b/compile.c index 10dff7c..c2fbab0 100644 --- a/compile.c +++ b/compile.c @@ -3849,10 +3849,9 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, https://github.com/ruby/ruby/blob/trunk/compile.c#L3849 } static int -compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_root, +compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, struct rb_call_info_kw_arg **keywords_ptr, unsigned int *flag) { - const NODE *node = node_root; int len = 0; for (; node; len++, node = node->nd_next) { @@ -3872,11 +3871,6 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L3871 return len; } -enum compile_list_type_t { - COMPILE_ARRAY_TYPE_ARRAY, - COMPILE_ARRAY_TYPE_HASH, -}; - static inline int static_literal_node_p(const NODE *node, const rb_iseq_t *iseq) { @@ -3922,21 +3916,111 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/compile.c#L3916 } static int -compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_root, - enum compile_list_type_t type, int popped) +compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) { - const NODE *node = node_root; int line = (int)nd_line(node); int len = 0; if (nd_type(node) == NODE_ZLIST) { if (!popped) { - switch (type) { - case COMPILE_ARRAY_TYPE_ARRAY: ADD_INSN1(ret, line, newarray, INT2FIX(0)); break; - case COMPILE_ARRAY_TYPE_HASH: ADD_INSN1(ret, line, newhash, INT2FIX(0)); break; + ADD_INSN1(ret, line, newarray, INT2FIX(0)); + } + } + else { + int opt_p = 1; + int first = 1, i; + + while (node) { + const NODE *start_node = node, *end_node, *prev_node; + const int max = 0x100; + DECL_ANCHOR(anchor); + INIT_ANCHOR(anchor); + + for (i=0; i<max && node; i++, len++, prev_node = node, node = node->nd_next) { + if (CPDEBUG > 0) { + EXPECT_NODE("compile_array", node, NODE_LIST, -1); + } + + if (opt_p && !static_literal_node_p(node, iseq)) { + opt_p = 0; + } + + NO_CHECK(COMPILE_(anchor, "array element", node->nd_head, popped)); + } + + if (opt_p) { + if (!popped) { + VALUE ary = rb_ary_tmp_new(i); + + end_node = node; + node = start_node; + + while (node != end_node) { + rb_ary_push(ary, static_literal_value(node, iseq)); + node = node->nd_next; + } + while (node && static_literal_node_p(node, iseq)) { + rb_ary_push(ary, static_literal_value(node, iseq)); + node = node->nd_next; + len++; + } + + OBJ_FREEZE(ary); + + iseq_add_mark_object_compile_time(iseq, ary); + + if (first) { + first = 0; + ADD_INSN1(ret, line, duparray, ary); + } + else { + ADD_INSN1(ret, line, putobject, ary); + ADD_INSN(ret, line, concatarray); + } + } + } + else { + if (!popped) { + /* 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 */ + 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 { + ADD_INSN1(anchor, line, newarray, INT2FIX(i)); + } + + + if (first) { + first = 0; + } + else { + ADD_INSN(anchor, line, concatarray); + } + + APPEND_LIST(ret, anchor); + } + else { + /* popped */ + APPEND_LIST(ret, anchor); + } } } } + return len; +} + +static int +compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) +{ + int line = (int)nd_line(node); + int len = 0; + + if (nd_type(node) == NODE_ZLIST) { + if (!popped) { + ADD_INSN1(ret, line, newhash, INT2FIX(0)); + } + } else { int opt_p = 1; int first = 1, i; @@ -3944,18 +4028,18 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L4028 int num_kw = 0; while (node) { - const NODE *start_node = node, *end_node, *prev_node; + const NODE *start_node = node, *end_node; const NODE *kw = 0; const int max = 0x100; DECL_ANCHOR(anchor); INIT_ANCHOR(anchor); - for (i=0; i<max && node; i++, len++, prev_node = node, node = node->nd_next) { + for (i=0; i<max && node; i++, len++, node = node->nd_next) { if (CPDEBUG > 0) { - EXPECT_NODE("compile_list", node, NODE_LIST, -1); + EXPECT_NODE("compile_hash", node, NODE_LIST, -1); } - if (type == COMPILE_ARRAY_TYPE_HASH && !node->nd_head) { + if (!node->nd_head) { kw = node->nd_next; num_kw++; node = 0; @@ -3987,24 +4071,15 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L4071 rb_ary_push(ary, static_literal_value(node, iseq)); node = node->nd_next; } - 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++; - } + 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); @@ -4013,103 +4088,67 @@ compile_list(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node_roo https://github.com/ruby/ruby/blob/trunk/compile.c#L4088 if (first) { first = 0; - if (type == COMPILE_ARRAY_TYPE_ARRAY) { - ADD_INSN1(ret, line, duparray, ary); - } - else { /* COMPILE_ARRAY_TYPE_HASH */ - VALUE hash; + VALUE hash; - hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2); - rb_hash_bulk_insert(RARRAY_LEN(ary), RARRAY_CONST_PTR_TRANSIENT(ary), hash); - iseq_add_mark_object_compile_time(iseq, rb_obj_hide(hash)); - ADD_INSN1(ret, line, duphash, hash); - } + hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2); + rb_hash_bulk_insert(RARRAY_LEN(ary), RARRAY_CONST_PTR_TRANSIENT(ary), hash); + iseq_add_mark_object_compile_time(iseq, rb_obj_hide(hash)); + ADD_INSN1(ret, line, duphash, hash); } else { - if (type == COMPILE_ARRAY_TYPE_ARRAY) { - ADD_INSN1(ret, line, putobject, ary); - ADD_INSN(ret, line, concatarray); - } - else { - COMPILE_ERROR(ERROR_ARGS "core#hash_merge_ary"); - return -1; - } + COMPILE_ERROR(ERROR_ARGS "core#hash_merge_ary"); + return -1; } } } else { - if (!popped || kw) { - switch (type) { - case COMPILE_ARRAY_TYPE_ARRAY: { - /* 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 */ - if (!node && nd_type(prev_node->nd_head) == NODE_HASH && prev_node->nd_head->nd_brace == 0) { - ADD_INSN1(anchor, line, newarraykwsplat, INT2FIX(i)); + if (!popped || kw) { + if (i > 0) { + num_kw++; + if (first) { + if (!popped) { + ADD_INSN1(anchor, line, new (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/