* 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:
nobu 2016-10-01 10:19:36 +00:00
Родитель 4bb7485464
Коммит 8c401de5d9
3 изменённых файлов: 49 добавлений и 41 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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