diff options
Diffstat (limited to 'compile.c')
-rw-r--r-- | compile.c | 281 |
1 files changed, 160 insertions, 121 deletions
@@ -3849,10 +3849,9 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, } 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 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) } 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 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 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 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, newhash, INT2FIX(i)); + } + APPEND_LIST(ret, anchor); } else { - ADD_INSN1(anchor, line, newarray, INT2FIX(i)); - } - - - if (first) { - first = 0; - } - else { - ADD_INSN(anchor, line, concatarray); - } - - APPEND_LIST(ret, anchor); - break; - } - case COMPILE_ARRAY_TYPE_HASH: - if (i > 0) { - num_kw++; - if (first) { - if (!popped) { - ADD_INSN1(anchor, line, newhash, INT2FIX(i)); - } - APPEND_LIST(ret, anchor); - } - else { - if (!popped) { - ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN(ret, line, swap); - } - APPEND_LIST(ret, anchor); - if (!popped) { - ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(i + 1)); - } - } - } - if (kw) { - int empty_kw = nd_type(kw) == NODE_LIT; - int first_kw = num_kw == 1; - int only_kw = single_kw && first_kw; - - if (!popped && !empty_kw) { + if (!popped) { ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - if (i > 0 || !first) ADD_INSN(ret, line, swap); - else ADD_INSN1(ret, line, newhash, INT2FIX(0)); - } - - if (empty_kw && first_kw && !only_kw) { - ADD_INSN1(ret, line, newhash, INT2FIX(0)); + ADD_INSN(ret, line, swap); } - else if (!empty_kw || only_kw) { - NO_CHECK(COMPILE(ret, "keyword splat", kw)); + APPEND_LIST(ret, anchor); + if (!popped) { + ADD_SEND(ret, line, id_core_hash_merge_ptr, INT2FIX(i + 1)); } + } + } + if (kw) { + int empty_kw = nd_type(kw) == NODE_LIT; + int first_kw = num_kw == 1; + int only_kw = single_kw && first_kw; + + if (!popped && !empty_kw) { + ADD_INSN1(ret, line, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + if (i > 0 || !first) ADD_INSN(ret, line, swap); + else ADD_INSN1(ret, line, newhash, INT2FIX(0)); + } - if (popped) { - ADD_INSN(ret, line, pop); - } - else if (!empty_kw) { - ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2)); - } - } - first = 0; - break; - } - } + if (empty_kw && first_kw && !only_kw) { + ADD_INSN1(ret, line, newhash, INT2FIX(0)); + } + else if (!empty_kw || only_kw) { + NO_CHECK(COMPILE(ret, "keyword splat", kw)); + } + + if (popped) { + ADD_INSN(ret, line, pop); + } + else if (!empty_kw) { + ADD_SEND(ret, line, id_core_hash_merge_kwd, INT2FIX(2)); + } + } + first = 0; + } else { /* popped */ APPEND_LIST(ret, anchor); @@ -7439,7 +7478,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in break; } case NODE_LIST:{ - CHECK(compile_list(iseq, ret, node, COMPILE_ARRAY_TYPE_ARRAY, popped) >= 0); + CHECK(compile_array(iseq, ret, node, popped) >= 0); break; } case NODE_ZLIST:{ @@ -7467,7 +7506,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, in INIT_ANCHOR(list); switch (type) { case NODE_LIST: - CHECK(compile_list(iseq, list, node->nd_head, COMPILE_ARRAY_TYPE_HASH, popped) >= 0); + CHECK(compile_hash(iseq, list, node->nd_head, popped) >= 0); ADD_SEQ(ret, list); break; |