summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-04-29 03:48:26 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2015-04-29 03:48:26 +0000
commit810522e0ff0d0ccf891eebe75e1765baeef324de (patch)
treea125791dc177295dee89443903db6c1fa192b7ef
parent69ba9302c5cc6a0edc2cd6e38ee233ac3b5df2d3 (diff)
compile.c: move expansion of massign
* compile.c (iseq_compile_each): move expansion for massign to variable of for-loop from the parser, to reduce method calls on intermediate objects. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@50398 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--compile.c30
-rw-r--r--parse.y20
2 files changed, 29 insertions, 21 deletions
diff --git a/compile.c b/compile.c
index 39d10f8..9427ade 100644
--- a/compile.c
+++ b/compile.c
@@ -3624,8 +3624,34 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
iseq->compile_data->ensure_node_stack = iseq->compile_data->ensure_node_stack->prev;
break;
}
- case NODE_ITER:
- case NODE_FOR:{
+ case NODE_FOR:
+ if (node->nd_var) {
+ /* massign to var in "for"
+ * args.length == 1 && Array === (tmp = args[0]) ? tmp : args
+ */
+ NODE *var = node->nd_var;
+ LABEL *not_single = NEW_LABEL(nd_line(var));
+ LABEL *not_ary = NEW_LABEL(nd_line(var));
+ COMPILE(ret, "for var", var);
+ ADD_INSN(ret, line, dup);
+ ADD_CALL(ret, line, idLength, INT2FIX(0));
+ ADD_INSN1(ret, line, putobject, INT2FIX(1));
+ ADD_CALL(ret, line, idEq, INT2FIX(1));
+ ADD_INSNL(ret, line, branchunless, not_single);
+ ADD_INSN(ret, line, dup);
+ ADD_INSN1(ret, line, putobject, INT2FIX(0));
+ ADD_CALL(ret, line, idAREF, INT2FIX(1));
+ ADD_INSN1(ret, line, putobject, rb_cArray);
+ ADD_INSN1(ret, line, topn, INT2FIX(1));
+ ADD_CALL(ret, line, idEqq, INT2FIX(1));
+ ADD_INSNL(ret, line, branchunless, not_ary);
+ ADD_INSN(ret, line, swap);
+ ADD_LABEL(ret, not_ary);
+ ADD_INSN(ret, line, pop);
+ ADD_LABEL(ret, not_single);
+ break;
+ }
+ case NODE_ITER:{
VALUE prevblock = iseq->compile_data->current_block;
LABEL *retry_label = NEW_LABEL(line);
LABEL *retry_end_l = NEW_LABEL(line);
diff --git a/parse.y b/parse.y
index 7e85d70..6e3e54e 100644
--- a/parse.y
+++ b/parse.y
@@ -2909,25 +2909,7 @@ primary : literal
NODE *args, *scope;
if (nd_type($2) == NODE_MASGN) {
- /* if args.length == 1 && args[0].kind_of?(Array)
- * args = args[0]
- * end
- */
- NODE *one = NEW_LIST(NEW_LIT(INT2FIX(1)));
- NODE *zero = NEW_LIST(NEW_LIT(INT2FIX(0)));
- m->nd_next = block_append(
- NEW_IF(
- NEW_NODE(NODE_AND,
- NEW_CALL(NEW_CALL(NEW_DVAR(id), idLength, 0),
- idEq, one),
- NEW_CALL(NEW_CALL(NEW_DVAR(id), idAREF, zero),
- rb_intern("kind_of?"), NEW_LIST(NEW_LIT(rb_cArray))),
- 0),
- NEW_DASGN_CURR(id,
- NEW_CALL(NEW_DVAR(id), idAREF, zero)),
- 0),
- node_assign($2, NEW_DVAR(id)));
-
+ m->nd_next = node_assign($2, NEW_FOR(NEW_DVAR(id), 0, 0));
args = new_args(m, 0, id, 0, new_args_tail(0, 0, 0));
}
else {