Project

General

Profile

Feature #10333 » 0001-optimize-yoda-literal-string.patch

normalperson (Eric Wong), 10/07/2014 01:11 AM

View differences:

benchmark/bm_vm2_streq2.rb
i = 0
foo = "literal"
while i<6_000_000 # benchmark loop 2
i += 1
"literal" == foo
end
compile.c
}
break;
}
/* TODO: optimization shortcut
/* optimization shortcut
* "yoda" == other -> opt_streq2("yoda", other)
*/
if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR) {
DECL_ANCHOR(args);
unsigned int flag = 0;
VALUE argc;
VALUE yoda = rb_fstring(node->nd_recv->nd_lit);
node->nd_recv->nd_lit = yoda;
INIT_ANCHOR(args);
argc = setup_args(iseq, args, node->nd_args, &flag);
assert(flag == 0 && argc == INT2FIX(1));
ADD_SEQ(ret, args);
ADD_INSN2(ret, line, opt_streq2,
new_callinfo(iseq, node->nd_mid, 1, 0, 0), yoda);
if (poped) {
ADD_INSN(ret, line, pop);
}
break;
}
}
case NODE_FCALL:
case NODE_VCALL:{ /* VCALL: variable or call */
insns.def
/**
@c optimize
@e "yoda" == other
*/
DEFINE_INSN
opt_streq2
(CALL_INFO ci, VALUE yoda)
(VALUE other)
(VALUE val)
{
if (BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) {
val = rb_str_equal(yoda, other);
}
else {
yoda = rb_str_resurrect(yoda);
PUSH(yoda);
PUSH(other);
CALL_SIMPLE_METHOD(yoda);
}
}
/**
@c optimize
@e optimized length
@j 最適化された recv.length()。
*/
test/ruby/test_string.rb
end
end
def test_opt_streq1
def test_opt_streq
assert_separately([], <<-RUBY)
class String
undef ==
......
:TROO
end
end
assert_equal(:TROO, ("foo" == "foo"))
foo = "foo"
assert_equal(:TROO, (foo == "foo"), 'opt_streq1')
assert_equal(:TROO, ("foo" == foo), 'opt_streq2')
RUBY
if @cls == String
......
recv = "something"
res = []
before = GC.stat(:total_allocated_objects)
nr.times { res << (recv == "constant") }
nr.times { res << (recv == "constant") } # opt_streq1
nr.times { res << ("constant" == recv) } # opt_streq2
assert_equal before, GC.stat(:total_allocated_objects)
assert_equal [ false ], res.uniq!
res.clear
before = GC.stat(:total_allocated_objects)
nr.times { res << (recv == "something") }
nr.times { res << (recv == "something") } # opt_streq1
nr.times { res << ("something" == recv) } # opt_streq2
assert_equal before, GC.stat(:total_allocated_objects)
assert_equal [ true ], res.uniq!
end
-
    (1-1/1)