Feature #10329 » 0002-optimize-foo-literal-string.patch
benchmark/bm_vm2_streq1.rb | ||
---|---|---|
i = 0
|
||
foo = "literal"
|
||
while i<6_000_000 # benchmark loop 2
|
||
i += 1
|
||
foo == "literal"
|
||
end
|
compile.c | ||
---|---|---|
}
|
||
break;
|
||
}
|
||
if (node->nd_mid == idEq && !private_recv_p(node) && node->nd_args &&
|
||
nd_type(node->nd_args) == NODE_ARRAY &&
|
||
node->nd_args->nd_alen == 1)
|
||
{
|
||
/* optimization shortcut
|
||
* obj == "literal" -> opt_streq1(obj, "literal")
|
||
*/
|
||
if (nd_type(node->nd_args->nd_head) == NODE_STR) {
|
||
VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit);
|
||
node->nd_args->nd_head->nd_lit = str;
|
||
COMPILE(ret, "recv", node->nd_recv);
|
||
ADD_INSN2(ret, line, opt_streq1,
|
||
new_callinfo(iseq, node->nd_mid, 1, 0, 0), str);
|
||
if (poped) {
|
||
ADD_INSN(ret, line, pop);
|
||
}
|
||
break;
|
||
}
|
||
/* TODO: optimization shortcut
|
||
* "yoda" == other -> opt_streq2("yoda", other)
|
||
*/
|
||
}
|
||
case NODE_FCALL:
|
||
case NODE_VCALL:{ /* VCALL: variable or call */
|
||
/*
|
insns.def | ||
---|---|---|
/**
|
||
@c optimize
|
||
@e recv == "literal string"
|
||
*/
|
||
DEFINE_INSN
|
||
opt_streq1
|
||
(CALL_INFO ci, VALUE lit)
|
||
(VALUE recv)
|
||
(VALUE val)
|
||
{
|
||
if (!SPECIAL_CONST_P(recv) && RBASIC_CLASS(recv) == rb_cString &&
|
||
BASIC_OP_UNREDEFINED_P(BOP_EQ, STRING_REDEFINED_OP_FLAG)) {
|
||
val = rb_str_equal(recv, lit);
|
||
}
|
||
else {
|
||
PUSH(recv);
|
||
PUSH(rb_str_resurrect(lit));
|
||
CALL_SIMPLE_METHOD(recv);
|
||
}
|
||
}
|
||
/**
|
||
@c optimize
|
||
@e optimized length
|
||
@j 最適化された recv.length()。
|
||
*/
|
test/ruby/test_string.rb | ||
---|---|---|
assert_equal before + nr, GC.stat(:total_allocated_objects)
|
||
end
|
||
end
|
||
def test_opt_streq1
|
||
assert_separately([], <<-RUBY)
|
||
class String
|
||
undef ==
|
||
def ==(str)
|
||
:TROO
|
||
end
|
||
end
|
||
assert_equal(:TROO, ("foo" == "foo"))
|
||
RUBY
|
||
if @cls == String
|
||
nr = 10
|
||
recv = "something"
|
||
res = []
|
||
before = GC.stat(:total_allocated_objects)
|
||
nr.times { res << (recv == "constant") }
|
||
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") }
|
||
assert_equal before, GC.stat(:total_allocated_objects)
|
||
assert_equal [ true ], res.uniq!
|
||
end
|
||
end
|
||
end
|
||
class TestString2 < TestString
|
||
-
|