platform/shared/ruby/compile.c in rhodes-3.1.1 vs platform/shared/ruby/compile.c in rhodes-3.2.0.beta.1

- old
+ new

@@ -15,10 +15,13 @@ #include "vm_core.h" #include "iseq.h" #include "insns.inc" #include "insns_info.inc" +#define numberof(array) (int)(sizeof(array) / sizeof((array)[0])) +#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) +#define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) typedef struct iseq_link_element { enum { ISEQ_ELEMENT_NONE = INT2FIX(0x00), ISEQ_ELEMENT_LABEL = INT2FIX(0x01), @@ -164,18 +167,18 @@ #define NEW_LABEL(l) new_label_body(iseq, l) #define iseq_filename(iseq) \ (((rb_iseq_t*)DATA_PTR(iseq))->filename) -#define NEW_ISEQVAL(node, name, type) \ - new_child_iseq(iseq, node, name, 0, type) +#define iseq_filepath(iseq) \ + (((rb_iseq_t*)DATA_PTR(iseq))->filepath) -#define NEW_CHILD_ISEQVAL(node, name, type) \ - new_child_iseq(iseq, node, name, iseq->self, type) +#define NEW_ISEQVAL(node, name, type, line_no) \ + new_child_iseq(iseq, node, name, 0, type, line_no) -#define NEW_SPECIAQL_BLOCK_ISEQVAL(iseq, sym) \ - new_child_iseq(iseq, iseq->node, iseq->name, iseq->parent_iseq, iseq->type, sym) +#define NEW_CHILD_ISEQVAL(node, name, type, line_no) \ + new_child_iseq(iseq, node, name, iseq->self, type, line_no) /* add instructions */ #define ADD_SEQ(seq1, seq2) \ APPEND_LIST(seq1, seq2) @@ -220,12 +223,13 @@ (VALUE)id, (VALUE)argc, (VALUE)block, (VALUE)flag)) #define ADD_TRACE(seq, line, event) \ do { \ if ((event) == RUBY_EVENT_LINE && iseq->coverage && \ - RARRAY_PTR(iseq->coverage)[(line) - 1] == Qnil) { \ + (line) != iseq->compile_data->last_coverable_line) { \ RARRAY_PTR(iseq->coverage)[(line) - 1] = INT2FIX(0); \ + iseq->compile_data->last_coverable_line = (line); \ ADD_INSN1(seq, line, trace, INT2FIX(RUBY_EVENT_COVERAGE)); \ } \ if (iseq->compile_data->option->trace_instruction) { \ ADD_INSN1(seq, line, trace, INT2FIX(event)); \ } \ @@ -250,16 +254,16 @@ /* compile node */ #define COMPILE(anchor, desc, node) \ (debug_compile("== " desc "\n", \ iseq_compile_each(iseq, anchor, node, 0))) -/* compile node, this node's value will be poped */ +/* compile node, this node's value will be popped */ #define COMPILE_POPED(anchor, desc, node) \ (debug_compile("== " desc "\n", \ iseq_compile_each(iseq, anchor, node, 1))) -/* compile node, which is poped when 'poped' is true */ +/* compile node, which is popped when 'poped' is true */ #define COMPILE_(anchor, desc, node, poped) \ (debug_compile("== " desc "\n", \ iseq_compile_each(iseq, anchor, node, poped))) #define OPERAND_AT(insn, idx) \ @@ -325,11 +329,11 @@ static int calc_sp_depth(int depth, INSN *iobj); static void ADD_ELEM(ISEQ_ARG_DECLARE LINK_ANCHOR *anchor, LINK_ELEMENT *elem); static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int insn_id, int argc, ...); -static LABEL *new_label_body(rb_iseq_t *iseq, int line); +static LABEL *new_label_body(rb_iseq_t *iseq, long line); static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line); static int iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *anchor, NODE * n, int); static int iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *anchor); static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *anchor); @@ -445,17 +449,17 @@ ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, 0, start); ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, 0, end); break; } case ISEQ_TYPE_CLASS: { - ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CLASS); + ADD_TRACE(ret, FIX2INT(iseq->line_no), RUBY_EVENT_CLASS); COMPILE(ret, "scoped node", node->nd_body); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_END); break; } case ISEQ_TYPE_METHOD: { - ADD_TRACE(ret, nd_line(node), RUBY_EVENT_CALL); + ADD_TRACE(ret, FIX2INT(iseq->line_no), RUBY_EVENT_CALL); COMPILE(ret, "scoped node", node->nd_body); ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); break; } default: { @@ -511,17 +515,17 @@ #if OPT_DIRECT_THREADED_CODE const void * const *table = rb_vm_get_insns_address_table(); #else const void * const *table = rb_vm_get_insns_address_table(); #endif - int i; + unsigned long i; iseq->iseq_encoded = ALLOC_N(VALUE, iseq->iseq_size); MEMCPY(iseq->iseq_encoded, iseq->iseq, VALUE, iseq->iseq_size); for (i = 0; i < iseq->iseq_size; /* */ ) { - int insn = iseq->iseq_encoded[i]; + int insn = (int)iseq->iseq_encoded[i]; int len = insn_len(insn); iseq->iseq_encoded[i] = (VALUE)table[insn]; i += len; } #else @@ -832,11 +836,11 @@ #define debug_list(anc) debug_list(iseq, anc) #endif #endif static LABEL * -new_label_body(rb_iseq_t *iseq, int line) +new_label_body(rb_iseq_t *iseq, long line) { LABEL *labelobj = compile_data_alloc_label(iseq); labelobj->link.type = ISEQ_ELEMENT_LABEL; labelobj->link.next = 0; @@ -861,10 +865,11 @@ static INSN * new_insn_core(rb_iseq_t *iseq, int line_no, int insn_id, int argc, VALUE *argv) { INSN *iobj = compile_data_alloc_insn(iseq); + /* printf("insn_id: %d, line: %d\n", insn_id, line_no); */ iobj->link.type = ISEQ_ELEMENT_INSN; iobj->link.next = 0; iobj->insn_id = insn_id; iobj->line_no = line_no; @@ -901,23 +906,23 @@ (VALUE *)compile_data_alloc(iseq, sizeof(VALUE) * 5); operands[0] = id; operands[1] = argc; operands[2] = block; operands[3] = flag; - operands[4] = 0; + operands[4] = INT2FIX(iseq->ic_size++); iobj = new_insn_core(iseq, line_no, BIN(send), 5, operands); return iobj; } static VALUE new_child_iseq(rb_iseq_t *iseq, NODE *node, - VALUE name, VALUE parent, VALUE type) + VALUE name, VALUE parent, VALUE type, int line_no) { VALUE ret; debugs("[new_child_iseq]> ---------------------------------------\n"); - ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), + ret = rb_iseq_new_with_opt(node, name, iseq_filename(iseq->self), iseq_filepath(iseq->self), INT2FIX(line_no), parent, type, iseq->compile_data->option); debugs("[new_child_iseq]< ---------------------------------------\n"); iseq_add_mark_object(iseq, ret); return ret; } @@ -978,11 +983,11 @@ iseq_set_exception_local_table(rb_iseq_t *iseq) { ID id_dollar_bang; CONST_ID(id_dollar_bang, "#$!"); - iseq->local_table = (ID *)ALLOC_N(ID *, 1); + iseq->local_table = (ID *)ALLOC_N(ID, 1); iseq->local_table_size = 1; iseq->local_size = iseq->local_table_size + 1; iseq->local_table[0] = id_dollar_bang; return COMPILE_OK; } @@ -1052,22 +1057,22 @@ rb_bug("iseq_set_arguments: NODE_ARGS is expected, but %s", ruby_node_name(nd_type(node_args))); } /* - * new argument infromation: + * new argument information: * NODE_ARGS [m: int, o: NODE_OPT_ARG, ->] * NODE_ARGS_AUX [r: ID, b: ID, ->] * NODE_ARGS_AUX [Pst: id, Plen: int, init: NODE*] * optarg information: * NODE_OPT_ARGS [idx, expr, next ->] * init arg: * NODE_AND(m_init, p_init) * if "r" is 1, it's means "{|x,|}" type block parameter. */ - iseq->argc = node_args->nd_frml; + iseq->argc = (int)node_args->nd_frml; debugs(" - argc: %d\n", iseq->argc); if (node_aux) { rest_id = node_aux->nd_rest; if (rest_id == 1) { @@ -1078,19 +1083,19 @@ node_aux = node_aux->nd_next; if (node_aux) { ID post_start_id = node_aux->nd_pid; iseq->arg_post_start = get_dyna_var_idx_at_raw(iseq, post_start_id); - iseq->arg_post_len = node_aux->nd_plen; + iseq->arg_post_len = (int)node_aux->nd_plen; node_init = node_aux->nd_next; } } if (node_opt) { NODE *node = node_opt; LABEL *label; - VALUE labels = rb_ary_new(); + VALUE labels = rb_ary_tmp_new(1); int i = 0, j; while (node) { label = NEW_LABEL(nd_line(node)); rb_ary_push(labels, (VALUE)label | 1); @@ -1110,10 +1115,11 @@ iseq->arg_opt_table = ALLOC_N(VALUE, i); MEMCPY(iseq->arg_opt_table, RARRAY_PTR(labels), VALUE, i); for (j = 0; j < i; j++) { iseq->arg_opt_table[j] &= ~1; } + rb_ary_clear(labels); } else { iseq->arg_opts = 0; } @@ -1188,20 +1194,20 @@ iseq_set_local_table(rb_iseq_t *iseq, ID *tbl) { int size; if (tbl) { - size = *tbl; + size = (int)*tbl; tbl++; } else { size = 0; } if (size > 0) { - iseq->local_table = (ID *)ALLOC_N(ID *, size); - MEMCPY(iseq->local_table, tbl, ID *, size); + iseq->local_table = (ID *)ALLOC_N(ID, size); + MEMCPY(iseq->local_table, tbl, ID, size); } iseq->local_size = iseq->local_table_size = size; iseq->local_size += 1; /* @@ -1230,18 +1236,18 @@ return rb_str_hash_cmp(lit, val); } return !rb_eql(lit, val); } -static int +static st_index_t cdhash_hash(VALUE a) { - if (SPECIAL_CONST_P(a)) return (int)a; + if (SPECIAL_CONST_P(a)) return (st_index_t)a; if (TYPE(a) == T_STRING) return rb_str_hash(a); { VALUE hval = rb_hash(a); - return (int)FIX2LONG(hval); + return (st_index_t)FIX2LONG(hval); } } static const struct st_hash_type cdhash_type = { cdhash_cmp, @@ -1277,11 +1283,11 @@ } case ISEQ_ELEMENT_LABEL: { lobj = (LABEL *)list; lobj->position = pos; - lobj->set = Qtrue; + lobj->set = TRUE; break; } case ISEQ_ELEMENT_NONE: { /* ignore */ @@ -1307,10 +1313,12 @@ } /* make instruction sequence */ generated_iseq = ALLOC_N(VALUE, pos); insn_info_table = ALLOC_N(struct iseq_insn_info_entry, k); + iseq->ic_entries = ALLOC_N(struct iseq_inline_cache_entry, iseq->ic_size); + MEMZERO(iseq->ic_entries, struct iseq_inline_cache_entry, iseq->ic_size); list = FIRST_ELEMENT(anchor); k = pos = sp = 0; while (list) { @@ -1328,19 +1336,19 @@ if (sp > stack_max) { stack_max = sp; } /* fprintf(stderr, "insn: %-16s, sp: %d\n", insn_name(iobj->insn_id), sp); */ - operands = iobj->operands; insn = iobj->insn_id; generated_iseq[pos] = insn; types = insn_op_types(insn); len = insn_len(insn); /* operand check */ if (iobj->operand_size != len - 1) { + /* printf("operand size miss! (%d, %d)\n", iobj->operand_size, len); */ dump_disasm_list(list); rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, "operand size miss! (%d for %d)", iobj->operand_size, len - 1); xfree(generated_iseq); @@ -1354,11 +1362,11 @@ switch (type) { case TS_OFFSET: { /* label(destination position) */ lobj = (LABEL *)operands[j]; - if (lobj->set != Qtrue) { + if (!lobj->set) { rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, "unknown label"); } if (lobj->sp == -1) { lobj->sp = sp; @@ -1380,11 +1388,11 @@ for (i=0; i < RARRAY_LEN(lits); i+=2) { VALUE obj = rb_ary_entry(lits, i); VALUE lv = rb_ary_entry(lits, i+1); lobj = (LABEL *)(lv & ~1); - if (lobj->set != Qtrue) { + if (!lobj->set) { rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, "unknown label"); } if (!st_lookup(rb_hash_tbl(map), obj, 0)) { rb_hash_aset(map, obj, INT2FIX(lobj->position - (pos+len))); @@ -1392,10 +1400,11 @@ else { rb_compile_warning(RSTRING_PTR(iseq->filename), iobj->line_no, "duplicated when clause is ignored"); } } + hide_obj(map); generated_iseq[pos + 1 + j] = map; iseq_add_mark_object(iseq, map); break; } case TS_LINDEX: @@ -1421,22 +1430,26 @@ iseq_add_mark_object(iseq, v); break; } case TS_IC: /* inline cache */ { - VALUE v = (VALUE)NEW_INLINE_CACHE_ENTRY(); - generated_iseq[pos + 1 + j] = v; - iseq_add_mark_object(iseq, v); + int ic_index = FIX2INT(operands[j]); + IC ic = &iseq->ic_entries[ic_index]; + if (UNLIKELY(ic_index >= iseq->ic_size)) { + rb_bug("iseq_set_sequence: ic_index overflow: index: %d, size: %d", + ic_index, iseq->ic_size); + } + generated_iseq[pos + 1 + j] = (VALUE)ic; break; } case TS_ID: /* ID */ generated_iseq[pos + 1 + j] = SYM2ID(operands[j]); break; case TS_GENTRY: { - struct global_entry *entry = - (struct global_entry *)(operands[j] & (~1)); + struct rb_global_entry *entry = + (struct rb_global_entry *)(operands[j] & (~1)); generated_iseq[pos + 1 + j] = (VALUE)entry; } break; default: rb_compile_error(RSTRING_PTR(iseq->filename), iobj->line_no, @@ -1540,11 +1553,11 @@ { VALUE *tptr, *ptr; int tlen, i; struct iseq_catch_table_entry *entry; - tlen = RARRAY_LEN(iseq->compile_data->catch_table_ary); + tlen = (int)RARRAY_LEN(iseq->compile_data->catch_table_ary); tptr = RARRAY_PTR(iseq->compile_data->catch_table_ary); iseq->catch_table = tlen ? ALLOC_N(struct iseq_catch_table_entry, tlen) : 0; iseq->catch_table_size = tlen; @@ -1759,40 +1772,36 @@ INSN *piobj = (INSN *)get_prev_insn((INSN *)list); if (piobj->insn_id == BIN(send) && piobj->operands[2] == 0 /* block */ ) { - piobj->operands[3] = INT2FIX(FIX2INT(piobj->operands[3]) | VM_CALL_TAILCALL_BIT); + piobj->operands[3] = FIXNUM_OR(piobj->operands[3], VM_CALL_TAILCALL_BIT); } } return COMPILE_OK; } static int -insn_set_specialized_instruction(INSN *iobj, int insn_id) +insn_set_specialized_instruction(rb_iseq_t *iseq, INSN *iobj, int insn_id) { - iobj->insn_id = insn_id; - iobj->operand_size = 0; - return COMPILE_OK; -} + int i, old_opsize = iobj->operand_size; -static int -insn_set_specialized_instruction_with_ic(INSN *iobj, int insn_id, int n) -{ - int i; iobj->insn_id = insn_id; - iobj->operand_size = n; + iobj->operand_size = insn_len(insn_id) - 1; + /* printf("iobj->operand_size: %d\n", iobj->operand_size); */ - /* max of n is 4 */ - for (i=0; i<n; i++) { - iobj->operands[i] = Qnil; + if (iobj->operand_size > old_opsize) { + iobj->operands = (VALUE *)compile_data_alloc(iseq, iobj->operand_size); } + for (i=0; i<iobj->operand_size; i++) { + iobj->operands[i] = INT2FIX(iseq->ic_size++); + } + return COMPILE_OK; } - static int iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) { if (iobj->insn_id == BIN(send)) { ID mid = SYM2ID(OPERAND_AT(iobj, 0)); @@ -1802,69 +1811,66 @@ /* TODO: should be more sophisticated search */ if (block == 0 && flag == INT2FIX(0)) { if (argc == 0) { if (mid == idLength) { - insn_set_specialized_instruction(iobj, BIN(opt_length)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_length)); } + else if (mid == idSize) { + insn_set_specialized_instruction(iseq, iobj, BIN(opt_size)); + } else if (mid == idSucc) { - insn_set_specialized_instruction(iobj, BIN(opt_succ)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_succ)); } else if (mid == idNot) { - insn_set_specialized_instruction_with_ic(iobj, BIN(opt_not), 1); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_not)); } } else if (argc == 1) { if (0) { } else if (mid == idPLUS) { - insn_set_specialized_instruction(iobj, BIN(opt_plus)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_plus)); } else if (mid == idMINUS) { - insn_set_specialized_instruction(iobj, BIN(opt_minus)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_minus)); } else if (mid == idMULT) { - insn_set_specialized_instruction(iobj, BIN(opt_mult)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_mult)); } else if (mid == idDIV) { - insn_set_specialized_instruction(iobj, BIN(opt_div)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_div)); } else if (mid == idMOD) { - insn_set_specialized_instruction(iobj, BIN(opt_mod)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_mod)); } else if (mid == idEq) { - insn_set_specialized_instruction_with_ic(iobj, BIN(opt_eq), 1); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_eq)); } else if (mid == idNeq) { - insn_set_specialized_instruction_with_ic(iobj, BIN(opt_neq), 2); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_neq)); } else if (mid == idLT) { - insn_set_specialized_instruction(iobj, BIN(opt_lt)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_lt)); } else if (mid == idLE) { - insn_set_specialized_instruction(iobj, BIN(opt_le)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_le)); } else if (mid == idGT) { - insn_set_specialized_instruction(iobj, BIN(opt_gt)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_gt)); } else if (mid == idGE) { - insn_set_specialized_instruction(iobj, BIN(opt_ge)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_ge)); } else if (mid == idLTLT) { - insn_set_specialized_instruction(iobj, BIN(opt_ltlt)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_ltlt)); } else if (mid == idAREF) { - insn_set_specialized_instruction(iobj, BIN(opt_aref)); + insn_set_specialized_instruction(iseq, iobj, BIN(opt_aref)); } } } - - if (argc > 0) { - if (mid == idSend || mid == id__send__ ) { - OPERAND_AT(iobj, 3) |= INT2FIX(VM_CALL_SEND_BIT); - } - } } return COMPILE_OK; } static int @@ -1939,20 +1945,21 @@ iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *anchor) { #if OPT_INSTRUCTIONS_UNIFICATION LINK_ELEMENT *list; INSN *iobj, *niobj; - int id, j, k; + int id, k; + intptr_t j; list = FIRST_ELEMENT(anchor); while (list) { if (list->type == ISEQ_ELEMENT_INSN) { iobj = (INSN *)list; id = iobj->insn_id; if (unified_insns_data[id] != 0) { const int *const *entry = unified_insns_data[id]; - for (j = 1; j < (int)entry[0]; j++) { + for (j = 1; j < (intptr_t)entry[0]; j++) { const int *unified = entry[j]; LINK_ELEMENT *li = list->next; for (k = 2; k < unified[1]; k++) { if (li->type != ISEQ_ELEMENT_INSN || ((INSN *)li)->insn_id != unified[k]) { @@ -2149,14 +2156,18 @@ static int compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int *cntp) { NODE *list = node->nd_next; VALUE lit = node->nd_lit; - int cnt = 1; + int cnt = 0; debugp_param("nd_lit", lit); - ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); + if (!NIL_P(lit)) { + hide_obj(lit); + cnt++; + ADD_INSN1(ret, nd_line(node), putobject, lit); + } while (list) { COMPILE(ret, "each string", list->nd_head); cnt++; list = list->nd_next; @@ -2210,16 +2221,16 @@ break; } case NODE_LIT: /* NODE_LIT is always not true */ case NODE_TRUE: case NODE_STR: - /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ + /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ ADD_INSNL(ret, nd_line(cond), jump, then_label); break; case NODE_FALSE: case NODE_NIL: - /* printf("useless conditon eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ + /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ ADD_INSNL(ret, nd_line(cond), jump, else_label); break; default: COMPILE(ret, "branch condition", cond); ADD_INSNL(ret, nd_line(cond), branchunless, else_label); @@ -2232,11 +2243,11 @@ static int compile_array_(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE* node_root, VALUE opt_p, int poped) { NODE *node = node_root; - int len = node->nd_alen, line = nd_line(node), i=0; + int len = (int)node->nd_alen, line = (int)nd_line(node), i=0; DECL_ANCHOR(anchor); INIT_ANCHOR(anchor); if (nd_type(node) != NODE_ZARRAY) { while (node) { @@ -2268,11 +2279,11 @@ node = node_root; while (node) { rb_ary_push(ary, node->nd_head->nd_lit); node = node->nd_next; } - + OBJ_FREEZE(ary); iseq_add_mark_object_compile_time(iseq, ary); ADD_INSN1(ret, nd_line(node_root), duparray, ary); } } else { @@ -2345,11 +2356,11 @@ COMPILE_POPED(ret, "masgn lhs (NODE_ATTRASGN)", node); POP_ELEMENT(ret); /* pop pop insn */ iobj = (INSN *)POP_ELEMENT(ret); /* pop send insn */ dupidx = iobj->operands[1]; - dupidx = INT2FIX(FIX2INT(dupidx) + 1); + dupidx = FIXNUM_INC(dupidx, 1); iobj->operands[1] = dupidx; ADD_INSN1(ret, nd_line(node), topn, dupidx); ADD_ELEM(ret, (LINK_ELEMENT *)iobj); ADD_INSN(ret, nd_line(node), pop); /* result */ @@ -2388,11 +2399,11 @@ static int compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *rhsn, NODE *orig_lhsn) { VALUE mem[64]; - const int memsize = sizeof(mem) / sizeof(mem[0]); + const int memsize = numberof(mem); int memindex = 0; int llen = 0, rlen = 0; int i; NODE *lhsn = orig_lhsn; @@ -2429,11 +2440,11 @@ llen++; } while (rhsn) { if (llen <= rlen) { - COMPILE_POPED(ret, "masgn val (poped)", rhsn->nd_head); + COMPILE_POPED(ret, "masgn val (popped)", rhsn->nd_head); } else { COMPILE(ret, "masgn val", rhsn->nd_head); } rhsn = rhsn->nd_next; @@ -2483,11 +2494,11 @@ if (lhs_splat) { if (nd_type(splatn) == NODE_POSTARG) { /*a, b, *r, p1, p2 */ NODE *postn = splatn->nd_2nd; NODE *restn = splatn->nd_1st; - int num = postn->nd_alen; + int num = (int)postn->nd_alen; int flag = 0x02 | (((VALUE)restn == (VALUE)-1) ? 0x00 : 0x01); ADD_INSN2(ret, nd_line(splatn), expandarray, INT2FIX(num), INT2FIX(flag)); @@ -2548,11 +2559,12 @@ COMPILE(ret, "nd_else->nd_head", cpath->nd_head); return Qfalse; } else { /* class at cbase Foo */ - ADD_INSN1(ret, nd_line(cpath), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); + ADD_INSN1(ret, nd_line(cpath), putspecialobject, + INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); return Qtrue; } } static int @@ -2612,11 +2624,11 @@ return 1; case NODE_GVAR: ADD_INSN(ret, nd_line(node), putnil); ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_GVAR), - ((VALUE)node->nd_entry) | 1, needstr); + ID2SYM(node->nd_entry->id), needstr); return 1; case NODE_CVAR: ADD_INSN(ret, nd_line(node), putnil); ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CVAR), @@ -2655,17 +2667,17 @@ /* method dispatch */ case NODE_CALL: case NODE_VCALL: case NODE_FCALL: case NODE_ATTRASGN:{ - int self = Qtrue; + int self = TRUE; switch (type) { case NODE_ATTRASGN: if (node->nd_recv == (NODE *)1) break; case NODE_CALL: - self = Qfalse; + self = FALSE; break; default: /* through */; } if (!lfinish[1]) { @@ -2680,11 +2692,11 @@ LABEL *lend = NEW_LABEL(nd_line(node)); VALUE rescue = NEW_CHILD_ISEQVAL(NEW_NIL(), rb_str_concat(rb_str_new2 ("defined guard in "), iseq->name), - ISEQ_TYPE_DEFINED_GUARD); + ISEQ_TYPE_DEFINED_GUARD, 0); defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse); ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]); ADD_LABEL(ret, lstart); @@ -2949,11 +2961,11 @@ ADD_INSN(ret, iseq->compile_data->last_line, putnil); } return COMPILE_OK; } - iseq->compile_data->last_line = nd_line(node); + iseq->compile_data->last_line = (int)nd_line(node); debug_node_start(node); type = nd_type(node); if (node->flags & NODE_FL_NEWLINE) { @@ -3008,11 +3020,11 @@ NODE *tempnode = node; LABEL *endlabel, *elselabel; DECL_ANCHOR(head); DECL_ANCHOR(body_seq); DECL_ANCHOR(cond_seq); - VALUE special_literals = rb_ary_new(); + VALUE special_literals = rb_ary_tmp_new(1); INIT_ANCHOR(head); INIT_ANCHOR(body_seq); INIT_ANCHOR(cond_seq); if (node->nd_head == 0) { @@ -3115,45 +3127,35 @@ ADD_LABEL(body_seq, l1); COMPILE_(body_seq, "when", node->nd_body, poped); ADD_INSNL(body_seq, nd_line(node), jump, endlabel); vals = node->nd_head; - if (vals && nd_type(vals) == NODE_ARRAY) { + if (!vals) { + rb_bug("NODE_WHEN: must be NODE_ARRAY, but 0"); + } + switch (nd_type(vals)) { + case NODE_ARRAY: while (vals) { val = vals->nd_head; COMPILE(ret, "when2", val); ADD_INSNL(ret, nd_line(val), branchif, l1); vals = vals->nd_next; } + break; + case NODE_SPLAT: + case NODE_ARGSCAT: + case NODE_ARGSPUSH: + ADD_INSN(ret, nd_line(vals), putnil); + COMPILE(ret, "when2/cond splat", vals); + ADD_INSN1(ret, nd_line(vals), checkincludearray, Qfalse); + ADD_INSN(ret, nd_line(vals), pop); + ADD_INSNL(ret, nd_line(vals), branchif, l1); + break; + default: + rb_bug("NODE_WHEN: unknown node (%s)", + ruby_node_name(nd_type(vals))); } - else if (nd_type(vals) == NODE_SPLAT || - nd_type(vals) == NODE_ARGSCAT || - nd_type(vals) == NODE_ARGSPUSH) { - - NODE *val = vals->nd_head; - - if (nd_type(vals) == NODE_ARGSCAT || nd_type(vals) == NODE_ARGSPUSH) { - NODE *vs = vals->nd_head; - val = vals->nd_body; - - while (vs) { - NODE* val = vs->nd_head; - COMPILE(ret, "when/argscat", val); - ADD_INSNL(ret, nd_line(val), branchif, l1); - vs = vs->nd_next; - } - } - - ADD_INSN(ret, nd_line(val), putnil); - COMPILE(ret, "when2/splat", val); - ADD_INSN1(ret, nd_line(val), checkincludearray, Qfalse); - ADD_INSN(ret, nd_line(val), pop); - ADD_INSNL(ret, nd_line(val), branchif, l1); - } - else { - rb_bug("err"); - } node = node->nd_next; } /* else */ COMPILE_(ret, "else", node, poped); ADD_INSNL(ret, nd_line(orig_node), jump, endlabel); @@ -3167,11 +3169,11 @@ case NODE_WHILE: case NODE_UNTIL:{ LABEL *prev_start_label = iseq->compile_data->start_label; LABEL *prev_end_label = iseq->compile_data->end_label; LABEL *prev_redo_label = iseq->compile_data->redo_label; - VALUE prev_loopval_popped = iseq->compile_data->loopval_popped; + int prev_loopval_popped = iseq->compile_data->loopval_popped; struct iseq_compile_data_ensure_node_stack enl; LABEL *next_label = iseq->compile_data->start_label = NEW_LABEL(nd_line(node)); /* next */ LABEL *redo_label = iseq->compile_data->redo_label = NEW_LABEL(nd_line(node)); /* redo */ @@ -3258,20 +3260,20 @@ if (nd_type(node) == NODE_FOR) { COMPILE(ret, "iter caller (for)", node->nd_iter); iseq->compile_data->current_block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), - ISEQ_TYPE_BLOCK); + ISEQ_TYPE_BLOCK, nd_line(node)); mid = idEach; ADD_SEND_R(ret, nd_line(node), ID2SYM(idEach), INT2FIX(0), iseq->compile_data->current_block, INT2FIX(0)); } else { iseq->compile_data->current_block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), - ISEQ_TYPE_BLOCK); + ISEQ_TYPE_BLOCK, nd_line(node)); COMPILE(ret, "iter caller", node->nd_iter); } ADD_LABEL(ret, retry_end_l); if (poped) { @@ -3355,10 +3357,13 @@ COMPILE(ret, "next val/valid syntax?", node->nd_stts); add_ensure_iseq(ret, iseq, 0); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->redo_label); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->start_label); ADD_ADJUST_RESTORE(ret, splabel); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } } else if (iseq->compile_data->end_label) { LABEL *splabel = NEW_LABEL(0); debugs("next in block\n"); ADD_LABEL(ret, splabel); @@ -3420,10 +3425,13 @@ ADD_LABEL(ret, splabel); ADD_ADJUST(ret, nd_line(node), iseq->compile_data->redo_label); add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, nd_line(node), jump, iseq->compile_data->redo_label); ADD_ADJUST_RESTORE(ret, splabel); + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } } else if (iseq->type == ISEQ_TYPE_EVAL) { redo_in_eval: COMPILE_ERROR((ERROR_ARGS "Can't escape from eval with redo")); } @@ -3501,11 +3509,11 @@ LABEL *lend = NEW_LABEL(nd_line(node)); LABEL *lcont = NEW_LABEL(nd_line(node)); VALUE rescue = NEW_CHILD_ISEQVAL( node->nd_resq, rb_str_concat(rb_str_new2("rescue in "), iseq->name), - ISEQ_TYPE_RESCUE); + ISEQ_TYPE_RESCUE, nd_line(node)); ADD_LABEL(ret, lstart); COMPILE(ret, "rescue head", node->nd_head); ADD_LABEL(ret, lend); if (node->nd_else) { @@ -3517,11 +3525,11 @@ if (poped) { ADD_INSN(ret, nd_line(node), pop); } - /* resgister catch entry */ + /* register catch entry */ ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lcont); ADD_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, 0, lstart); break; } case NODE_RESBODY:{ @@ -3583,11 +3591,11 @@ DECL_ANCHOR(ensr); VALUE ensure = NEW_CHILD_ISEQVAL(node->nd_ensr, rb_str_concat(rb_str_new2 ("ensure in "), iseq->name), - ISEQ_TYPE_ENSURE); + ISEQ_TYPE_ENSURE, nd_line(node)); LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); LABEL *lcont = NEW_LABEL(nd_line(node)); struct ensure_range er; struct iseq_compile_data_ensure_node_stack enl; @@ -3697,23 +3705,24 @@ case NODE_IASGN2:{ COMPILE(ret, "lvalue", node->nd_value); if (!poped) { ADD_INSN(ret, nd_line(node), dup); } - ADD_INSN1(ret, nd_line(node), setinstancevariable, - ID2SYM(node->nd_vid)); + ADD_INSN2(ret, nd_line(node), setinstancevariable, + ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++)); break; } case NODE_CDECL:{ COMPILE(ret, "lvalue", node->nd_value); if (!poped) { ADD_INSN(ret, nd_line(node), dup); } if (node->nd_vid) { - ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); + ADD_INSN1(ret, nd_line(node), putspecialobject, + INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); ADD_INSN1(ret, nd_line(node), setconstant, ID2SYM(node->nd_vid)); } else { compile_cpath(ret, iseq, node->nd_else); ADD_INSN1(ret, nd_line(node), setconstant, ID2SYM(node->nd_else->nd_mid)); @@ -3732,41 +3741,51 @@ case NODE_OP_ASGN1: { DECL_ANCHOR(args); VALUE argc; unsigned long flag = 0; ID id = node->nd_mid; + int boff = 0; /* * a[x] (op)= y * - * eval a # a - * eval x # a x - * dupn 2 # a x a x - * send :[] # a x a[x] - * eval y # a x a[x] y - * send op # a x a[x]+y - * send []= # ret + * nil # nil + * eval a # nil a + * eval x # nil a x + * dupn 2 # nil a x a x + * send :[] # nil a x a[x] + * eval y # nil a x a[x] y + * send op # nil a x ret + * setn 3 # ret a x ret + * send []= # ret ? + * pop # ret */ /* * nd_recv[nd_args->nd_body] (nd_mid)= nd_args->nd_head; * NODE_OP_ASGN nd_recv * nd_args->nd_head * nd_args->nd_body * nd_mid */ + if (!poped) { + ADD_INSN(ret, nd_line(node), putnil); + } COMPILE(ret, "NODE_OP_ASGN1 recv", node->nd_recv); - if (nd_type(node->nd_args->nd_body) != NODE_ZARRAY) { + switch (nd_type(node->nd_args->nd_head)) { + case NODE_ZARRAY: + argc = INT2FIX(0); + break; + case NODE_BLOCK_PASS: + boff = 1; + default: INIT_ANCHOR(args); - argc = setup_args(iseq, args, node->nd_args->nd_body, &flag); + argc = setup_args(iseq, args, node->nd_args->nd_head, &flag); ADD_SEQ(ret, args); } - else { - argc = INT2FIX(0); - } - ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(FIX2INT(argc)+1)); + ADD_INSN1(ret, nd_line(node), dupn, FIXNUM_INC(argc, 1 + boff)); ADD_SEND_R(ret, nd_line(node), ID2SYM(idAREF), argc, Qfalse, LONG2FIX(flag)); if (id == 0 || id == 1) { /* 0: or, 1: and a[x] ||= y @@ -3778,60 +3797,84 @@ end */ LABEL *label = NEW_LABEL(nd_line(node)); LABEL *lfin = NEW_LABEL(nd_line(node)); + ADD_INSN(ret, nd_line(node), dup); if (id == 0) { /* or */ - ADD_INSN(ret, nd_line(node), dup); ADD_INSNL(ret, nd_line(node), branchif, label); - ADD_INSN(ret, nd_line(node), pop); } else { /* and */ - ADD_INSN(ret, nd_line(node), dup); ADD_INSNL(ret, nd_line(node), branchunless, label); - ADD_INSN(ret, nd_line(node), pop); } + ADD_INSN(ret, nd_line(node), pop); - COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head); + COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); + if (!poped) { + ADD_INSN1(ret, nd_line(node), setn, FIXNUM_INC(argc, 2+boff)); + } if (flag & VM_CALL_ARGS_SPLAT_BIT) { ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1)); + if (boff > 0) { + ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(3)); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); + } ADD_INSN(ret, nd_line(node), concatarray); + if (boff > 0) { + ADD_INSN1(ret, nd_line(node), setn, INT2FIX(3)); + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), pop); + } ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET), argc, Qfalse, LONG2FIX(flag)); } else { + if (boff > 0) + ADD_INSN(ret, nd_line(node), swap); ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET), - INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag)); + FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag)); } + ADD_INSN(ret, nd_line(node), pop); ADD_INSNL(ret, nd_line(node), jump, lfin); ADD_LABEL(ret, label); - if (id == 0 || id == 1) { /* 0: or, 1: and */ - ADD_INSN(ret, nd_line(node), swap); - ADD_INSN(ret, nd_line(node), pop); - ADD_INSN(ret, nd_line(node), swap); - ADD_INSN(ret, nd_line(node), pop); + if (!poped) { + ADD_INSN1(ret, nd_line(node), setn, FIXNUM_INC(argc, 2+boff)); } + ADD_INSN1(ret, nd_line(node), adjuststack, FIXNUM_INC(argc, 2+boff)); ADD_LABEL(ret, lfin); } else { - COMPILE(ret, "NODE_OP_ASGN1 args->head: ", node->nd_args->nd_head); + COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body); ADD_SEND(ret, nd_line(node), ID2SYM(id), INT2FIX(1)); + if (!poped) { + ADD_INSN1(ret, nd_line(node), setn, FIXNUM_INC(argc, 2+boff)); + } if (flag & VM_CALL_ARGS_SPLAT_BIT) { ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1)); + if (boff > 0) { + ADD_INSN1(ret, nd_line(node), dupn, INT2FIX(3)); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); + } ADD_INSN(ret, nd_line(node), concatarray); + if (boff > 0) { + ADD_INSN1(ret, nd_line(node), setn, INT2FIX(3)); + ADD_INSN(ret, nd_line(node), pop); + ADD_INSN(ret, nd_line(node), pop); + } ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET), argc, Qfalse, LONG2FIX(flag)); } else { + if (boff > 0) + ADD_INSN(ret, nd_line(node), swap); ADD_SEND_R(ret, nd_line(node), ID2SYM(idASET), - INT2FIX(FIX2INT(argc) + 1), Qfalse, LONG2FIX(flag)); + FIXNUM_INC(argc, 1), Qfalse, LONG2FIX(flag)); } - } - - if (poped) { ADD_INSN(ret, nd_line(node), pop); } break; } @@ -3851,26 +3894,30 @@ # or dup # r o o if lcfin # r o pop # r eval v # r v - send a= # v - jump lfin # v + swap # v r + topn 1 # v r v + send a= # v ? + jump lfin # v ? lcfin: # r o swap # o r + + lfin: # o ? pop # o - lfin: # v - # and dup # r o o unless lcfin pop # r eval v # r v - send a= # v - jump lfin # v + swap # v r + topn 1 # v r v + send a= # v ? + jump lfin # v ? # others eval v # r o v send ?? # r w send a= # w @@ -3890,30 +3937,36 @@ else { ADD_INSNL(ret, nd_line(node), branchunless, lcfin); } ADD_INSN(ret, nd_line(node), pop); COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN1(ret, nd_line(node), topn, INT2FIX(1)); ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_aid), INT2FIX(1)); ADD_INSNL(ret, nd_line(node), jump, lfin); ADD_LABEL(ret, lcfin); ADD_INSN(ret, nd_line(node), swap); - ADD_INSN(ret, nd_line(node), pop); ADD_LABEL(ret, lfin); + ADD_INSN(ret, nd_line(node), pop); + if (poped) { + /* we can apply more optimize */ + ADD_INSN(ret, nd_line(node), pop); + } } else { COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value); ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_mid), INT2FIX(1)); + if (!poped) { + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN1(ret, nd_line(node), topn, INT2FIX(1)); + } ADD_SEND(ret, nd_line(node), ID2SYM(node->nd_next->nd_aid), INT2FIX(1)); - } - - if (poped) { - /* we can apply more optimize */ ADD_INSN(ret, nd_line(node), pop); } break; } case NODE_OP_ASGN_AND: @@ -3991,11 +4044,10 @@ ID goto_id; ID label_id; VALUE label; VALUE label_sym; - CONST_ID(goto_id, "__goto__"); CONST_ID(label_id, "__label__"); if (nd_type(node) == NODE_FCALL && (mid == goto_id || mid == label_id)) { @@ -4023,11 +4075,11 @@ } break; } } #endif - /* reciever */ + /* receiver */ if (type == NODE_CALL) { COMPILE(recv, "recv", node->nd_recv); } else if (type == NODE_FCALL || type == NODE_VCALL) { ADD_CALL_RECEIVER(recv, nd_line(node)); @@ -4133,11 +4185,11 @@ } } } } - /* dummy reciever */ + /* dummy receiver */ ADD_INSN1(ret, nd_line(node), putobject, nd_type(node) == NODE_ZSUPER ? Qfalse : Qtrue); ADD_SEQ(ret, args); ADD_INSN3(ret, nd_line(node), invokesuper, argc, parent_block, LONG2FIX(flag)); @@ -4198,14 +4250,13 @@ break; } case NODE_RETURN:{ rb_iseq_t *is = iseq; - while (is) { - if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) { + if (is) { + if (is->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid return")); - break; } else { LABEL *splabel = 0; if (is->type == ISEQ_TYPE_METHOD) { @@ -4216,10 +4267,11 @@ COMPILE(ret, "return nd_stts (return val)", node->nd_stts); if (is->type == ISEQ_TYPE_METHOD) { add_ensure_iseq(ret, iseq, 1); + ADD_TRACE(ret, nd_line(node), RUBY_EVENT_RETURN); ADD_INSN(ret, nd_line(node), leave); ADD_ADJUST_RESTORE(ret, splabel); if (!poped) { ADD_INSN(ret, nd_line(node), putnil); @@ -4229,22 +4281,21 @@ ADD_INSN1(ret, nd_line(node), throw, INT2FIX(0x01) /* TAG_RETURN */ ); if (poped) { ADD_INSN(ret, nd_line(node), pop); } } - break; } } break; } case NODE_YIELD:{ DECL_ANCHOR(args); VALUE argc; unsigned long flag = 0; INIT_ANCHOR(args); - if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) { + if (iseq->type == ISEQ_TYPE_TOP) { COMPILE_ERROR((ERROR_ARGS "Invalid yield")); } if (node->nd_head) { argc = setup_args(iseq, args, node->nd_head, &flag); @@ -4292,26 +4343,25 @@ break; } case NODE_IVAR:{ debugi("nd_vid", node->nd_vid); if (!poped) { - ADD_INSN1(ret, nd_line(node), getinstancevariable, - ID2SYM(node->nd_vid)); + ADD_INSN2(ret, nd_line(node), getinstancevariable, + ID2SYM(node->nd_vid), INT2FIX(iseq->ic_size++)); } break; } case NODE_CONST:{ debugi("nd_vid", node->nd_vid); if (iseq->compile_data->option->inline_const_cache) { - LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); + int ic_index = iseq->ic_size++; - ADD_LABEL(ret, lstart); - ADD_INSN2(ret, nd_line(node), getinlinecache, 0, lend); + ADD_INSN2(ret, nd_line(node), getinlinecache, lend, INT2FIX(ic_index)); ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid)); - ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_INSN1(ret, nd_line(node), setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); } else { ADD_INSN(ret, nd_line(node), putnil); ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_vid)); @@ -4356,15 +4406,15 @@ ADD_INSN1(recv, nd_line(node), putobject, node->nd_lit); ADD_INSN2(val, nd_line(node), getspecial, INT2FIX(0), INT2FIX(0)); break; case NODE_MATCH2: - COMPILE(recv, "reciever", node->nd_recv); + COMPILE(recv, "receiver", node->nd_recv); COMPILE(val, "value", node->nd_value); break; case NODE_MATCH3: - COMPILE(recv, "reciever", node->nd_value); + COMPILE(recv, "receiver", node->nd_value); COMPILE(val, "value", node->nd_recv); break; } if (iseq->compile_data->option->specialized_instruction) { @@ -4401,11 +4451,11 @@ break; } case NODE_STR:{ debugp_param("nd_lit", node->nd_lit); if (!poped) { - hide_obj(node->nd_lit); + OBJ_FREEZE(node->nd_lit); ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit); } break; } case NODE_DSTR:{ @@ -4415,10 +4465,11 @@ ADD_INSN(ret, nd_line(node), pop); } break; } case NODE_XSTR:{ + OBJ_FREEZE(node->nd_lit); ADD_CALL_RECEIVER(ret, nd_line(node)); ADD_INSN1(ret, nd_line(node), putobject, node->nd_lit); ADD_CALL(ret, nd_line(node), ID2SYM(idBackquote), INT2FIX(1)); if (poped) { @@ -4455,38 +4506,55 @@ } break; } case NODE_DREGX_ONCE:{ /* TODO: once? */ - LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); + int ic_index = iseq->ic_size++; - ADD_LABEL(ret, lstart); - ADD_INSN2(ret, nd_line(node), onceinlinecache, 0, lend); + ADD_INSN2(ret, nd_line(node), onceinlinecache, lend, INT2FIX(ic_index)); ADD_INSN(ret, nd_line(node), pop); compile_dregx(iseq, ret, node); - ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_INSN1(ret, nd_line(node), setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); if (poped) { ADD_INSN(ret, nd_line(node), pop); } break; } case NODE_ARGSCAT:{ - COMPILE(ret, "argscat head", node->nd_head); - COMPILE(ret, "argscat body", node->nd_body); - ADD_INSN(ret, nd_line(node), concatarray); + if (poped) { + COMPILE(ret, "argscat head", node->nd_head); + ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); + ADD_INSN(ret, nd_line(node), pop); + COMPILE(ret, "argscat body", node->nd_body); + ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); + ADD_INSN(ret, nd_line(node), pop); + } + else { + COMPILE(ret, "argscat head", node->nd_head); + COMPILE(ret, "argscat body", node->nd_body); + ADD_INSN(ret, nd_line(node), concatarray); + } break; } case NODE_ARGSPUSH:{ - COMPILE(ret, "arsgpush head", node->nd_head); - COMPILE(ret, "argspush body", node->nd_body); - ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1)); - ADD_INSN(ret, nd_line(node), concatarray); + if (poped) { + COMPILE(ret, "arsgpush head", node->nd_head); + ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); + ADD_INSN(ret, nd_line(node), pop); + COMPILE_(ret, "argspush body", node->nd_body, poped); + } + else { + COMPILE(ret, "arsgpush head", node->nd_head); + COMPILE_(ret, "argspush body", node->nd_body, poped); + ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(1)); + ADD_INSN(ret, nd_line(node), concatarray); + } break; } case NODE_SPLAT:{ COMPILE(ret, "splat", node->nd_head); ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); @@ -4497,11 +4565,11 @@ break; } case NODE_DEFN:{ VALUE iseqval = NEW_ISEQVAL(node->nd_defn, rb_str_dup(rb_id2str(node->nd_mid)), - ISEQ_TYPE_METHOD); + ISEQ_TYPE_METHOD, nd_line(node)); debugp_param("defn/iseq", iseqval); ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); @@ -4517,11 +4585,11 @@ break; } case NODE_DEFS:{ VALUE iseqval = NEW_ISEQVAL(node->nd_defn, rb_str_dup(rb_id2str(node->nd_mid)), - ISEQ_TYPE_METHOD); + ISEQ_TYPE_METHOD, nd_line(node)); debugp_param("defs/iseq", iseqval); ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); COMPILE(ret, "defs: recv", node->nd_recv); @@ -4571,11 +4639,11 @@ case NODE_CLASS:{ VALUE iseqval = NEW_CHILD_ISEQVAL( node->nd_body, rb_sprintf("<class:%s>", rb_id2name(node->nd_cpath->nd_mid)), - ISEQ_TYPE_CLASS); + ISEQ_TYPE_CLASS, nd_line(node)); compile_cpath(ret, iseq, node->nd_cpath); COMPILE(ret, "super", node->nd_super); ADD_INSN3(ret, nd_line(node), defineclass, ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(0)); @@ -4586,11 +4654,11 @@ } case NODE_MODULE:{ VALUE iseqval = NEW_CHILD_ISEQVAL( node->nd_body, rb_sprintf("<module:%s>", rb_id2name(node->nd_cpath->nd_mid)), - ISEQ_TYPE_CLASS); + ISEQ_TYPE_CLASS, nd_line(node)); compile_cpath(ret, iseq, node->nd_cpath); ADD_INSN (ret, nd_line(node), putnil); /* dummy */ ADD_INSN3(ret, nd_line(node), defineclass, ID2SYM(node->nd_cpath->nd_mid), iseqval, INT2FIX(2)); @@ -4601,11 +4669,11 @@ } case NODE_SCLASS:{ ID singletonclass; VALUE iseqval = NEW_ISEQVAL(node->nd_body, rb_str_new2("singletonclass"), - ISEQ_TYPE_CLASS); + ISEQ_TYPE_CLASS, nd_line(node)); COMPILE(ret, "sclass#recv", node->nd_recv); ADD_INSN (ret, nd_line(node), putnil); CONST_ID(singletonclass, "singletonclass"); ADD_INSN3(ret, nd_line(node), defineclass, @@ -4617,31 +4685,31 @@ break; } case NODE_COLON2:{ if (rb_is_const_id(node->nd_mid)) { /* constant */ - LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); + int ic_index = iseq->ic_size++; + DECL_ANCHOR(pref); DECL_ANCHOR(body); INIT_ANCHOR(pref); INIT_ANCHOR(body); compile_colon2(iseq, node, pref, body); if (LIST_SIZE_ZERO(pref)) { if (iseq->compile_data->option->inline_const_cache) { - ADD_LABEL(ret, lstart); - ADD_INSN2(ret, nd_line(node), getinlinecache, 0, lend); + ADD_INSN2(ret, nd_line(node), getinlinecache, lend, INT2FIX(ic_index)); } else { ADD_INSN(ret, nd_line(node), putnil); } ADD_SEQ(ret, body); if (iseq->compile_data->option->inline_const_cache) { - ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_INSN1(ret, nd_line(node), setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); } } else { ADD_SEQ(ret, pref); @@ -4659,37 +4727,37 @@ ADD_INSN(ret, nd_line(node), pop); } break; } case NODE_COLON3:{ - LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); - debugi("colon3#nd_mid", node->nd_mid); + int ic_index = iseq->ic_size++; + debugi("colon3#nd_mid", node->nd_mid); + /* add cache insn */ if (iseq->compile_data->option->inline_const_cache) { - ADD_LABEL(ret, lstart); - ADD_INSN2(ret, nd_line(node), getinlinecache, 0, lend); + ADD_INSN2(ret, nd_line(node), getinlinecache, lend, INT2FIX(ic_index)); ADD_INSN(ret, nd_line(node), pop); } ADD_INSN1(ret, nd_line(node), putobject, rb_cObject); ADD_INSN1(ret, nd_line(node), getconstant, ID2SYM(node->nd_mid)); if (iseq->compile_data->option->inline_const_cache) { - ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_INSN1(ret, nd_line(node), setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); } if (poped) { ADD_INSN(ret, nd_line(node), pop); } break; } case NODE_DOT2: case NODE_DOT3:{ - int flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1); + VALUE flag = type == NODE_DOT2 ? INT2FIX(0) : INT2FIX(1); COMPILE(ret, "min", (NODE *) node->nd_beg); COMPILE(ret, "max", (NODE *) node->nd_end); if (poped) { ADD_INSN(ret, nd_line(node), pop); ADD_INSN(ret, nd_line(node), pop); @@ -4706,10 +4774,11 @@ LABEL *ltrue = NEW_LABEL(nd_line(node)); VALUE key = rb_sprintf("flipflag/%s-%p-%d", RSTRING_PTR(iseq->name), (void *)iseq, iseq->compile_data->flip_cnt++); + hide_obj(key); iseq_add_mark_object_compile_time(iseq, key); ADD_INSN2(ret, nd_line(node), getspecial, key, INT2FIX(0)); ADD_INSNL(ret, nd_line(node), branchif, lend); /* *flip == 0 */ @@ -4790,34 +4859,34 @@ case NODE_DEFINED:{ if (!poped) { LABEL *lfinish[2]; lfinish[0] = NEW_LABEL(nd_line(node)); lfinish[1] = 0; + ADD_INSN(ret, nd_line(node), putnil); defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue); + ADD_INSN(ret, nd_line(node), swap); + ADD_INSN(ret, nd_line(node), pop); if (lfinish[1]) { - ADD_INSNL(ret, nd_line(node), jump, lfinish[0]); ADD_LABEL(ret, lfinish[1]); - ADD_INSN(ret, nd_line(node), putnil); } ADD_LABEL(ret, lfinish[0]); } break; } case NODE_POSTEXE:{ - LABEL *lstart = NEW_LABEL(nd_line(node)); LABEL *lend = NEW_LABEL(nd_line(node)); - VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK); + VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, nd_line(node)); + int ic_index = iseq->ic_size++; - ADD_LABEL(ret, lstart); - ADD_INSN2(ret, nd_line(node), onceinlinecache, 0, lend); + ADD_INSN2(ret, nd_line(node), onceinlinecache, lend, INT2FIX(ic_index)); ADD_INSN(ret, nd_line(node), pop); ADD_INSN1(ret, nd_line(node), putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, nd_line(node), putiseq, block); ADD_SEND (ret, nd_line(node), ID2SYM(id_core_set_postexe), INT2FIX(1)); - ADD_INSN1(ret, nd_line(node), setinlinecache, lstart); + ADD_INSN1(ret, nd_line(node), setinlinecache, INT2FIX(ic_index)); ADD_LABEL(ret, lend); if (poped) { ADD_INSN(ret, nd_line(node), pop); } @@ -4859,17 +4928,17 @@ ADD_SEQ(ret, recv); ADD_SEQ(ret, args); if (flag & VM_CALL_ARGS_BLOCKARG_BIT) { ADD_INSN1(ret, nd_line(node), topn, INT2FIX(1)); - ADD_INSN1(ret, nd_line(node), setn, INT2FIX(FIX2INT(argc) + 3)); + ADD_INSN1(ret, nd_line(node), setn, FIXNUM_INC(argc, 3)); ADD_INSN (ret, nd_line(node), pop); } else { - ADD_INSN1(ret, nd_line(node), setn, INT2FIX(FIX2INT(argc) + 1)); + ADD_INSN1(ret, nd_line(node), setn, FIXNUM_INC(argc, 1)); + } } - } else { ADD_SEQ(ret, recv); ADD_SEQ(ret, args); } ADD_SEND_R(ret, nd_line(node), ID2SYM(node->nd_mid), argc, 0, LONG2FIX(flag)); @@ -4896,11 +4965,11 @@ COMPILE_(ret, "body", node->nd_body, poped); break; } case NODE_LAMBDA:{ /* compile same as lambda{...} */ - VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK); + VALUE block = NEW_CHILD_ISEQVAL(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, nd_line(node)); VALUE argc = INT2FIX(0); ADD_CALL_RECEIVER(ret, nd_line(node)); ADD_CALL_WITH_BLOCK(ret, nd_line(node), ID2SYM(idLambda), argc, block); if (poped) { @@ -4908,11 +4977,11 @@ } break; } default: rb_bug("iseq_compile_each: unknown node: %s", ruby_node_name(type)); - return Qnil; + return COMPILE_NG; } debug_node_end(); return COMPILE_OK; } @@ -4940,19 +5009,19 @@ } static VALUE insn_data_to_s_detail(INSN *iobj) { - VALUE str = rb_str_new(0, 0); + VALUE str = rb_sprintf("%-16s", insn_name(iobj->insn_id)); - str = rb_sprintf("%-16s", insn_name(iobj->insn_id)); if (iobj->operands) { const char *types = insn_op_types(iobj->insn_id); int j; for (j = 0; types[j]; j++) { char type = types[j]; + printf("str: %"PRIxVALUE", type: %c\n", str, type); switch (type) { case TS_OFFSET: /* label(destination position) */ { LABEL *lobj = (LABEL *)OPERAND_AT(iobj, j); @@ -4979,16 +5048,16 @@ case TS_ID: /* ID */ rb_str_concat(str, rb_inspect(OPERAND_AT(iobj, j))); break; case TS_GENTRY: { - struct global_entry *entry = (struct global_entry *) + struct rb_global_entry *entry = (struct rb_global_entry *) (OPERAND_AT(iobj, j) & (~1)); rb_str_cat2(str, rb_id2name(entry->id)); } case TS_IC: /* method cache */ - rb_str_cat2(str, "<ic>"); + rb_str_catf(str, "<ic:%d>", FIX2INT(OPERAND_AT(iobj, j))); break; case TS_CDHASH: /* case/when condition cache */ rb_str_cat2(str, "<ch>"); break; default:{ @@ -5053,11 +5122,11 @@ VALUE rb_insns_name_array(void) { VALUE ary = rb_ary_new(); int i; - for (i = 0; i < sizeof(insn_name_info) / sizeof(insn_name_info[0]); i++) { + for (i = 0; i < numberof(insn_name_info); i++) { rb_ary_push(ary, rb_obj_freeze(rb_str_new2(insn_name_info[i]))); } return rb_obj_freeze(ary); } @@ -5081,10 +5150,11 @@ static VALUE get_exception_sym2type(VALUE sym) { #undef rb_intern #define rb_intern(str) rb_intern_const(str) + VALUE sym_inspect; static VALUE symRescue, symEnsure, symRetry; static VALUE symBreak, symRedo, symNext; if (symRescue == 0) { symRescue = ID2SYM(rb_intern("rescue")); @@ -5099,12 +5169,13 @@ if (sym == symEnsure) return CATCH_TYPE_ENSURE; if (sym == symRetry) return CATCH_TYPE_RETRY; if (sym == symBreak) return CATCH_TYPE_BREAK; if (sym == symRedo) return CATCH_TYPE_REDO; if (sym == symNext) return CATCH_TYPE_NEXT; + sym_inspect = rb_inspect(sym); rb_raise(rb_eSyntaxError, "invalid exception symbol: %s", - RSTRING_PTR(rb_inspect(sym))); + StringValuePtr(sym_inspect)); return 0; } static int iseq_build_exception(rb_iseq_t *iseq, struct st_table *labels_table, @@ -5126,11 +5197,11 @@ type = get_exception_sym2type(ptr[0]); if (ptr[1] == Qnil) { eiseqval = 0; } else { - eiseqval = ruby_iseq_load(ptr[1], iseq->self, Qnil); + eiseqval = rb_iseq_load(ptr[1], iseq->self, Qnil); } lstart = register_label(iseq, labels_table, ptr[2]); lend = register_label(iseq, labels_table, ptr[3]); lcont = register_label(iseq, labels_table, ptr[4]); @@ -5157,14 +5228,14 @@ static int iseq_build_body(rb_iseq_t *iseq, LINK_ANCHOR *anchor, VALUE body, struct st_table *labels_table) { - /* TODO: body should be freezed */ + /* TODO: body should be frozen */ VALUE *ptr = RARRAY_PTR(body); - int len = RARRAY_LEN(body); - int i, j; + long i, len = RARRAY_LEN(body); + int j; int line_no = 0; /* * index -> LABEL *label */ static struct st_table *insn_table; @@ -5183,11 +5254,11 @@ else if (FIXNUM_P(obj)) { line_no = NUM2INT(obj); } else if (TYPE(obj) == T_ARRAY) { VALUE *argv = 0; - int argc = RARRAY_LEN(obj) - 1; + int argc = RARRAY_LENINT(obj) - 1; VALUE insn_id; VALUE insn; insn = (argc < 0) ? Qnil : RARRAY_PTR(obj)[0]; if (st_lookup(insn_table, insn, &insn_id) == 0) { @@ -5224,11 +5295,11 @@ break; case TS_ISEQ: { if (op != Qnil) { if (TYPE(op) == T_ARRAY) { - argv[j] = ruby_iseq_load(op, iseq->self, Qnil); + argv[j] = rb_iseq_load(op, iseq->self, Qnil); } else if (CLASS_OF(op) == rb_cISeq) { argv[j] = op; } else { @@ -5244,12 +5315,13 @@ case TS_GENTRY: op = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym"); argv[j] = (VALUE)rb_global_entry(SYM2ID(op)); break; case TS_IC: - argv[j] = (VALUE)NEW_INLINE_CACHE_ENTRY(); - iseq_add_mark_object(iseq, argv[j]); + argv[j] = op; + if (NUM2INT(op) >= iseq->ic_size) + iseq->ic_size = NUM2INT(op) + 1; break; case TS_ID: argv[j] = rb_convert_type(op, T_SYMBOL, "Symbol", "to_sym"); break; @@ -5263,20 +5335,21 @@ LABEL *label = register_label(iseq, labels_table, sym); rb_ary_store(op, i+1, (VALUE)label | 1); } argv[j] = op; + iseq_add_mark_object_compile_time(iseq, op); } break; default: rb_raise(rb_eSyntaxError, "unknown operand: %c", insn_op_type(insn_id, j)); } } } ADD_ELEM(anchor, (LINK_ELEMENT*)new_insn_core(iseq, line_no, - insn_id, argc, argv)); + (enum ruby_vminsn_type)insn_id, argc, argv)); } else { rb_raise(rb_eTypeError, "unexpected object for instruction"); } } @@ -5288,29 +5361,34 @@ #define CHECK_ARRAY(v) rb_convert_type(v, T_ARRAY, "Array", "to_ary") #define CHECK_STRING(v) rb_convert_type(v, T_STRING, "String", "to_str") #define CHECK_SYMBOL(v) rb_convert_type(v, T_SYMBOL, "Symbol", "to_sym") static inline VALUE CHECK_INTEGER(VALUE v) {NUM2LONG(v); return v;} +//RHO : misc VALUE rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE locals, VALUE args, - VALUE exception, VALUE body) + VALUE exception, VALUE body, VALUE misc) +//RHO { int i; ID *tbl; struct st_table *labels_table = st_init_numtable(); DECL_ANCHOR(anchor); INIT_ANCHOR(anchor); - iseq->local_table_size = RARRAY_LEN(locals); - iseq->local_table = tbl = (ID *)ALLOC_N(ID *, iseq->local_table_size); - iseq->local_size = iseq->local_table_size + 1; + iseq->local_table_size = RARRAY_LENINT(locals); + iseq->local_table = tbl = (ID *)ALLOC_N(ID, iseq->local_table_size); + //RHO + iseq->local_size = FIX2INT(rb_hash_aref(misc, ID2SYM(rb_intern("local_size")))); + //iseq->local_size = iseq->local_table_size + 1; + //RHO for (i=0; i<RARRAY_LEN(locals); i++) { VALUE lv = RARRAY_PTR(locals)[i]; - tbl[i] = FIXNUM_P(lv) ? FIX2INT(lv) : SYM2ID(CHECK_SYMBOL(lv)); + tbl[i] = FIXNUM_P(lv) ? (ID)FIX2LONG(lv) : SYM2ID(CHECK_SYMBOL(lv)); } /* args */ if (FIXNUM_P(args)) { iseq->arg_size = iseq->argc = FIX2INT(args); @@ -5329,11 +5407,11 @@ iseq->argc = FIX2INT(argc); iseq->arg_rest = FIX2INT(arg_rest); iseq->arg_post_len = FIX2INT(arg_post_len); iseq->arg_post_start = FIX2INT(arg_post_start); iseq->arg_block = FIX2INT(arg_block); - iseq->arg_opts = RARRAY_LEN(arg_opt_labels); + iseq->arg_opts = RARRAY_LENINT(arg_opt_labels); iseq->arg_opt_table = (VALUE *)ALLOC_N(VALUE, iseq->arg_opts); if (iseq->arg_block != -1) { iseq->arg_size = iseq->arg_block + 1; } @@ -5411,10 +5489,10 @@ } int rb_parse_in_eval(void) { - return GET_THREAD()->parse_in_eval != 0; + return GET_THREAD()->parse_in_eval > 0; } int rb_parse_in_main(void) {