summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-03-25 06:26:32 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-03-25 06:26:32 +0000
commit708e5ddde62fc424a40f61f8c73b6909e33f6da3 (patch)
treec42f71c8d206e6e362f63888f050a13c5c34e2ba
parentf2025c33ffa71480cde4d7d4edce47c21191fceb (diff)
* compile.c (defined_expr): false short-circuit destination label may
be needed. [ruby-talk:295296] * compile.c (iseq_compile_each): put nil if false short-circuit is created. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@15836 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog8
-rw-r--r--compile.c94
2 files changed, 50 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index a000a3116e..15fc2e527f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,10 @@
-Tue Mar 25 15:09:36 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+Tue Mar 25 15:26:30 2008 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * compile.c (defined_expr): false short-circuit destination label may
+ be needed. [ruby-talk:295296]
+
+ * compile.c (iseq_compile_each): put nil if false short-circuit is
+ created.
* compile.c (compile_massign_opt): no need to use alloca.
diff --git a/compile.c b/compile.c
index eaa046f2b7..8d4a78b620 100644
--- a/compile.c
+++ b/compile.c
@@ -2258,7 +2258,7 @@ compile_cpath(LINK_ANCHOR *ret, rb_iseq_t *iseq, NODE *cpath)
static int
defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
- NODE * node, LABEL *lfinish, VALUE needstr)
+ NODE *node, LABEL **lfinish, VALUE needstr)
{
char *estr = 0;
enum node_type type;
@@ -2280,22 +2280,21 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
break;
case NODE_ARRAY:{
- LABEL *lfalse = NULL;
NODE *vals = node;
do {
defined_expr(iseq, ret, vals->nd_head, lfinish, Qfalse);
- if (lfalse) {
- ADD_INSNL(ret, nd_line(node), branchunless, lfalse);
+ if (lfinish[1]) {
+ ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
}
else {
LABEL *lcont = NEW_LABEL(nd_line(node));
- lfalse = NEW_LABEL(nd_line(node));
+ lfinish[1] = NEW_LABEL(nd_line(node));
ADD_INSNL(ret, nd_line(node), branchif, lcont);
- ADD_LABEL(ret, lfalse);
+ ADD_LABEL(ret, lfinish[1]);
ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
+ ADD_INSNL(ret, nd_line(node), jump, lfinish[0]);
ADD_LABEL(ret, lcont);
}
} while ((vals = vals->nd_next) != NULL);
@@ -2336,28 +2335,18 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
ID2SYM(node->nd_vid), needstr);
return 1;
case NODE_COLON2:
- if (rb_is_const_id(node->nd_mid)) {
- LABEL *lcont = NEW_LABEL(nd_line(node));
- defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
-
- ADD_INSNL(ret, nd_line(node), branchif, lcont);
- ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
+ if (!lfinish[1]) {
+ lfinish[1] = NEW_LABEL(nd_line(node));
+ }
+ defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
+ ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
- ADD_LABEL(ret, lcont);
+ if (rb_is_const_id(node->nd_mid)) {
COMPILE(ret, "defined/colon2#nd_head", node->nd_head);
ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_CONST),
ID2SYM(node->nd_mid), needstr);
}
else {
- LABEL *lcont = NEW_LABEL(nd_line(node));
- defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
-
- ADD_INSNL(ret, nd_line(node), branchif, lcont);
- ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
-
- ADD_LABEL(ret, lcont);
COMPILE(ret, "defined/colon2#nd_head", node->nd_head);
ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD),
ID2SYM(node->nd_mid), needstr);
@@ -2374,7 +2363,6 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
case NODE_VCALL:
case NODE_FCALL:
case NODE_ATTRASGN:{
- LABEL *lfalse = NULL;
int self = Qtrue;
switch (type) {
@@ -2386,23 +2374,17 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
default:
/* through */;
}
+ if (!lfinish[1]) {
+ lfinish[1] = NEW_LABEL(nd_line(node));
+ }
if (node->nd_args) {
- lfalse = NEW_LABEL(nd_line(node));
defined_expr(iseq, ret, node->nd_args, lfinish, Qfalse);
- ADD_INSNL(ret, nd_line(node), branchunless, lfalse);
+ ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
}
if (!self) {
- LABEL *lcont = NEW_LABEL(nd_line(node));
-
defined_expr(iseq, ret, node->nd_recv, lfinish, Qfalse);
- ADD_INSNL(ret, nd_line(node), branchif, lcont);
- if (lfalse) {
- ADD_LABEL(ret, lfalse);
- }
- ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
+ ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
- ADD_LABEL(ret, lcont);
COMPILE(ret, "defined/recv", node->nd_recv);
ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_METHOD),
ID2SYM(node->nd_mid), needstr);
@@ -2411,12 +2393,6 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
ADD_INSN(ret, nd_line(node), putself);
ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_FUNC),
ID2SYM(node->nd_mid), needstr);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
- if (lfalse) {
- ADD_LABEL(ret, lfalse);
- ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lfinish);
- }
}
return 1;
}
@@ -2458,7 +2434,6 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
default:{
LABEL *lstart = NEW_LABEL(nd_line(node));
LABEL *lend = NEW_LABEL(nd_line(node));
- LABEL *ldefed = NEW_LABEL(nd_line(node));
VALUE ensure = NEW_CHILD_ISEQVAL(NEW_NIL(),
rb_str_concat(rb_str_new2
("defined guard in "),
@@ -2467,10 +2442,10 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
ADD_LABEL(ret, lstart);
COMPILE(ret, "defined expr (others)", node);
- ADD_INSNL(ret, nd_line(node), branchif, ldefed);
- ADD_INSN(ret, nd_line(node), putnil);
- ADD_INSNL(ret, nd_line(node), jump, lend);
- ADD_LABEL(ret, ldefed);
+ if (!lfinish[1]) {
+ lfinish[1] = NEW_LABEL(nd_line(node));
+ }
+ ADD_INSNL(ret, nd_line(node), branchunless, lfinish[1]);
if (needstr) {
ADD_INSN1(ret, nd_line(node), putstring, rb_str_new2("expression"));
}
@@ -2479,7 +2454,7 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *ret,
}
ADD_LABEL(ret, lend);
- ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, lfinish);
+ ADD_CATCH_ENTRY(CATCH_TYPE_ENSURE, lstart, lend, ensure, lfinish[1]);
return 1;
} /* end of default */
}
@@ -3609,12 +3584,22 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
case NODE_OP_ASGN_AND:
case NODE_OP_ASGN_OR:{
LABEL *lfin = NEW_LABEL(nd_line(node));
- LABEL *lassign = NEW_LABEL(nd_line(node));
+ LABEL *lassign;
if (nd_type(node) == NODE_OP_ASGN_OR) {
- defined_expr(iseq, ret, node->nd_head, lassign, Qfalse);
+ LABEL *lfinish[2];
+ lfinish[0] = lfin;
+ lfinish[1] = 0;
+ defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse);
+ lassign = lfinish[1];
+ if (!lassign) {
+ lassign = NEW_LABEL(nd_line(node));
+ }
ADD_INSNL(ret, nd_line(node), branchunless, lassign);
}
+ else {
+ lassign = NEW_LABEL(nd_line(node));
+ }
COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head);
ADD_INSN(ret, nd_line(node), dup);
@@ -4459,9 +4444,16 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
case NODE_DEFINED:{
if (!poped) {
- LABEL *lfinish = NEW_LABEL(nd_line(node));
+ LABEL *lfinish[2];
+ lfinish[0] = NEW_LABEL(nd_line(node));
+ lfinish[1] = 0;
defined_expr(iseq, ret, node->nd_head, lfinish, Qtrue);
- ADD_LABEL(ret, lfinish);
+ 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;
}