summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-10-01 10:19:36 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-10-01 10:19:36 +0000
commit8c401de5d90f33d7afecb813737a1f2924a5f096 (patch)
treed8e06388e7158e5bfdfe00e6eaa2483d787a2bc8 /compile.c
parent4bb748546407bdb8e5fc7d8f7492f5a298efbfa8 (diff)
compile.c: optimize flip-flop
* compile.c (compile_flip_flop): simplify generated code. * compile.c (compile_branch_condition): flip-flop can appear only in coditional expressions. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@56315 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c80
1 files changed, 39 insertions, 41 deletions
diff --git a/compile.c b/compile.c
index 72181d3b9f..674ae70068 100644
--- a/compile.c
+++ b/compile.c
@@ -2787,6 +2787,39 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
}
static int
+compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *node, int again,
+ LABEL *then_label, LABEL *else_label)
+{
+ const int line = nd_line(node);
+ LABEL *lend = NEW_LABEL(line);
+ rb_num_t cnt = ISEQ_FLIP_CNT_INCREMENT(iseq->body->local_iseq)
+ + VM_SVAR_FLIPFLOP_START;
+ VALUE key = INT2FIX(cnt);
+
+ ADD_INSN2(ret, line, getspecial, key, INT2FIX(0));
+ ADD_INSNL(ret, line, branchif, lend);
+
+ /* *flip == 0 */
+ COMPILE(ret, "flip2 beg", node->nd_beg);
+ ADD_INSNL(ret, line, branchunless, else_label);
+ ADD_INSN1(ret, line, putobject, Qtrue);
+ ADD_INSN1(ret, line, setspecial, key);
+ if (!again) {
+ ADD_INSNL(ret, line, jump, then_label);
+ }
+
+ /* *flip == 1 */
+ ADD_LABEL(ret, lend);
+ COMPILE(ret, "flip2 end", node->nd_end);
+ ADD_INSNL(ret, line, branchunless, then_label);
+ ADD_INSN1(ret, line, putobject, Qfalse);
+ ADD_INSN1(ret, line, setspecial, key);
+ ADD_INSNL(ret, line, jump, then_label);
+
+ return COMPILE_OK;
+}
+
+static int
compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond,
LABEL *then_label, LABEL *else_label)
{
@@ -2834,6 +2867,12 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * cond,
/* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */
ADD_INSNL(ret, nd_line(cond), jump, else_label);
break;
+ case NODE_FLIP2:
+ compile_flip_flop(iseq, ret, cond, TRUE, then_label, else_label);
+ break;
+ case NODE_FLIP3:
+ compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label);
+ break;
default:
COMPILE(ret, "branch condition", cond);
ADD_INSNL(ret, nd_line(cond), branchunless, else_label);
@@ -5896,47 +5935,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
break;
}
- case NODE_FLIP2:
- case NODE_FLIP3:{
- LABEL *lend = NEW_LABEL(line);
- LABEL *lfin = NEW_LABEL(line);
- LABEL *ltrue = NEW_LABEL(line);
- rb_iseq_t *local_iseq = iseq->body->local_iseq;
- rb_num_t cnt;
- VALUE key;
-
- cnt = ISEQ_FLIP_CNT_INCREMENT(local_iseq) + VM_SVAR_FLIPFLOP_START;
- key = INT2FIX(cnt);
-
- ADD_INSN2(ret, line, getspecial, key, INT2FIX(0));
- ADD_INSNL(ret, line, branchif, lend);
-
- /* *flip == 0 */
- COMPILE(ret, "flip2 beg", node->nd_beg);
- ADD_INSN(ret, line, dup);
- ADD_INSNL(ret, line, branchunless, lfin);
- if (nd_type(node) == NODE_FLIP3) {
- ADD_INSN(ret, line, dup);
- ADD_INSN1(ret, line, setspecial, key);
- ADD_INSNL(ret, line, jump, lfin);
- }
- else {
- ADD_INSN1(ret, line, setspecial, key);
- }
-
- /* *flip == 1 */
- ADD_LABEL(ret, lend);
- COMPILE(ret, "flip2 end", node->nd_end);
- ADD_INSNL(ret, line, branchunless, ltrue);
- ADD_INSN1(ret, line, putobject, Qfalse);
- ADD_INSN1(ret, line, setspecial, key);
-
- ADD_LABEL(ret, ltrue);
- ADD_INSN1(ret, line, putobject, Qtrue);
-
- ADD_LABEL(ret, lfin);
- break;
- }
case NODE_SELF:{
if (!poped) {
ADD_INSN(ret, line, putself);