зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
4bb7485464
Коммит
8c401de5d9
|
@ -1,3 +1,10 @@
|
|||
Sat Oct 1 19:19:34 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* compile.c (compile_flip_flop): simplify generated code.
|
||||
|
||||
* compile.c (compile_branch_condition): flip-flop can appear only
|
||||
in coditional expressions.
|
||||
|
||||
Sat Oct 1 02:02:02 2016 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||
|
||||
* win32/win32.c (poll_child_status): rb_w32_wait_events_blocking() sets
|
||||
|
|
80
compile.c
80
compile.c
|
@ -2786,6 +2786,39 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node)
|
|||
return COMPILE_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -3,8 +3,11 @@ require 'test/unit'
|
|||
|
||||
class TestFlip < Test::Unit::TestCase
|
||||
def test_flip_flop
|
||||
assert_equal [4,5], (1..9).select {|n| true if (n==4)..(n==5)}
|
||||
assert_equal [4,5], (1..9).select {|n| true if (n==4)...(n==5)}
|
||||
assert_equal [2], (1..9).select {|n| true if (n==2)..(n%2).zero?}
|
||||
assert_equal [2,3,4], (1..9).select {|n| true if (n==2)...(n%2).zero?}
|
||||
assert_equal [4,5,7,8], (1..9).select {|n| true if (n==4)...(n==5) or (n==7)...(n==8)}
|
||||
end
|
||||
|
||||
def test_hidden_key
|
||||
|
|
Загрузка…
Ссылка в новой задаче