diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-10-01 10:19:36 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2016-10-01 10:19:36 +0000 |
commit | 8c401de5d90f33d7afecb813737a1f2924a5f096 (patch) | |
tree | d8e06388e7158e5bfdfe00e6eaa2483d787a2bc8 /compile.c | |
parent | 4bb748546407bdb8e5fc7d8f7492f5a298efbfa8 (diff) | |
download | ruby-8c401de5d90f33d7afecb813737a1f2924a5f096.tar.gz |
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.c | 80 |
1 files changed, 39 insertions, 41 deletions
@@ -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); |