* [PATCH 1/4] compile.c (opt_str_lit_1): hoist out of iseq_peephole_optimize
@ 2014-10-14 21:17 Eric Wong
2014-10-14 21:17 ` [PATCH 2/4] test/ruby/test_optimization.rb (test_hash_aset_with): assert assignment Eric Wong
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Eric Wong @ 2014-10-14 21:17 UTC (permalink / raw)
To: spew
---
compile.c | 67 ++++++++++++++++++++++++++++++++++-----------------------------
1 file changed, 36 insertions(+), 31 deletions(-)
diff --git a/compile.c b/compile.c
index 205ff6a..f1123cc 100644
--- a/compile.c
+++ b/compile.c
@@ -1746,21 +1746,51 @@ new_recvinfo_for_arg_(rb_iseq_t *iseq, VALUE str,
}
/*
+ * optimize allocation:
+ * hash["lit"] # hash lookups
+ * str == "lit"
+ * str != "lit"
+ * str << "lit"
+ * str + "lit"
+ * str === "lit"
+ */
+static VALUE
+opt_str_lit_1(rb_iseq_t *iseq, VALUE str, rb_call_info_t *ci, INSN *list)
+{
+ enum ruby_optimized_method om;
+ VALUE c;
+
+ switch (ci->mid) {
+#define C(mid,klass) case mid: om = OM_##mid##__##klass; c = rb_c##klass; break
+ C(idAREF, Hash);
+ C(idEq, String);
+ C(idNeq, String);
+ C(idLTLT, String);
+ C(idPLUS, String);
+ C(idEqq, String);
+#undef C
+ default: return Qfalse;
+ }
+
+ return new_recvinfo_for_arg_(iseq, str, om, c, 0);
+}
+
+/*
* optimize common calls which take two string literals:
* foo.sub(/../, "to")
* foo.sub!(/../, "to")
* foo.gsub(/../, "to")
* foo.gsub!(/../, "to")
- * foo.tr(/../, "to")
- * foo.tr!(/../, "to")
- * foo.tr_s(/../, "to")
- * foo.tr_s!(/../, "to")
+ * foo.tr("from", "to")
+ * foo.tr!("from", "to")
+ * foo.tr_s("from", "to")
+ * foo.tr_s!("from", "to")
*/
static VALUE
opt_str_lit_2(rb_iseq_t *iseq, VALUE str, rb_call_info_t *ci, INSN *list)
{
INSN *piobj;
- enum ruby_optimized_method om = OM_LAST_;
+ enum ruby_optimized_method om;
switch (ci->mid) {
#define C(mid) case mid: om = OM_##mid##__String; break
@@ -1943,32 +1973,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
break;
case 1:
- switch (ci->mid) {
- case idAREF:
- /* optimize allocation: obj["lit"] */
- ri = new_recvinfo_for_arg(iseq, str, idAREF, Hash, 0);
- break;
- case idEq:
- /* optimize allocation: obj == "lit" */
- ri = new_recvinfo_for_arg(iseq, str, idEq, String, 0);
- break;
- case idNeq:
- /* optimize allocation: obj != "lit" */
- ri = new_recvinfo_for_arg(iseq, str, idNeq, String, 0);
- break;
- case idLTLT:
- /* optimize allocation: obj << "lit" */
- ri = new_recvinfo_for_arg(iseq, str, idLTLT, String, 0);
- break;
- case idPLUS:
- /* optimize allocation: obj + "lit" */
- ri = new_recvinfo_for_arg(iseq, str, idPLUS, String, 0);
- break;
- case idEqq:
- /* optimize allocation: obj === "lit" */
- ri = new_recvinfo_for_arg(iseq, str, idEqq, String, 0);
- break;
- }
+ ri = opt_str_lit_1(iseq, str, ci, (INSN *)list);
break;
case 2:
ri = opt_str_lit_2(iseq, str, ci, (INSN *)list);
--
EW
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/4] test/ruby/test_optimization.rb (test_hash_aset_with): assert assignment
2014-10-14 21:17 [PATCH 1/4] compile.c (opt_str_lit_1): hoist out of iseq_peephole_optimize Eric Wong
@ 2014-10-14 21:17 ` Eric Wong
2014-10-14 21:17 ` [PATCH 3/4] test/ruby/test_optimization.rb: redefinition tests for string Eric Wong
2014-10-14 21:17 ` [PATCH 4/4] test/ruby/test_string.rb: cleanup allocation tests Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2014-10-14 21:17 UTC (permalink / raw)
To: spew
---
test/ruby/test_optimization.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index f991bea..40b1cba 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -164,7 +164,7 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal 1, h["foo"] = 1
assert_redefine_method('Hash', '[]=', <<-end)
h = {}
- h["foo"] = 1
+ assert_equal 1, h["foo"] = 1, "assignment always returns value set"
assert_nil h["foo"]
end
end
--
EW
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/4] test/ruby/test_optimization.rb: redefinition tests for string
2014-10-14 21:17 [PATCH 1/4] compile.c (opt_str_lit_1): hoist out of iseq_peephole_optimize Eric Wong
2014-10-14 21:17 ` [PATCH 2/4] test/ruby/test_optimization.rb (test_hash_aset_with): assert assignment Eric Wong
@ 2014-10-14 21:17 ` Eric Wong
2014-10-14 21:17 ` [PATCH 4/4] test/ruby/test_string.rb: cleanup allocation tests Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2014-10-14 21:17 UTC (permalink / raw)
To: spew
---
test/ruby/test_optimization.rb | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 40b1cba..2f9c0f6 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -116,6 +116,25 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('String', 'freeze', 'assert_nil "foo".freeze')
end
+ def test_string_eq_neq
+ %w(== !=).each do |m|
+ assert_redefine_method('String', m, <<-end)
+ assert_equal :b, ("a" #{m} "b").to_sym
+ b = 'b'
+ assert_equal :b, ("a" #{m} b).to_sym
+ assert_equal :b, (b #{m} "b").to_sym
+ end
+ end
+ end
+
+ def test_string_ltlt
+ assert_equal "", "" << ""
+ assert_equal "x", "x" << ""
+ assert_equal "x", "" << "x"
+ assert_equal "ab", "a" << "b"
+ assert_redefine_method('String', '<<', 'assert_equal "b", "a" << "b"')
+ end
+
def test_array_plus
assert_equal [1,2], [1]+[2]
assert_redefine_method('Array', '+', 'assert_equal [2], [1]+[2]')
--
EW
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 4/4] test/ruby/test_string.rb: cleanup allocation tests
2014-10-14 21:17 [PATCH 1/4] compile.c (opt_str_lit_1): hoist out of iseq_peephole_optimize Eric Wong
2014-10-14 21:17 ` [PATCH 2/4] test/ruby/test_optimization.rb (test_hash_aset_with): assert assignment Eric Wong
2014-10-14 21:17 ` [PATCH 3/4] test/ruby/test_optimization.rb: redefinition tests for string Eric Wong
@ 2014-10-14 21:17 ` Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2014-10-14 21:17 UTC (permalink / raw)
To: spew
---
test/ruby/test_string.rb | 76 ++++++++++++++++++++++++------------------------
1 file changed, 38 insertions(+), 38 deletions(-)
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 8d46764..3d82bb3 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1910,9 +1910,9 @@ class TestString < Test::Unit::TestCase
def test_literal_freeze
require_compile_option(:peephole_optimization)
- before = GC.stat(:total_allocated_objects)
- 5.times { "".freeze }
- assert_equal before, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations do
+ 5.times { "".freeze }
+ end
end
class S2 < String
@@ -2296,14 +2296,14 @@ class TestString < Test::Unit::TestCase
if @cls == String
nr = 10
recv = ""
- before = GC.stat(:total_allocated_objects)
- nr.times { recv << "constant" }
- assert_equal before, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations do
+ nr.times { recv << "constant" }
+ end
assert_equal "constant" * nr, recv
- before = GC.stat(:total_allocated_objects)
- nr.times { "recv" << "constant" }
- assert_equal before + nr, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("'lit' << 'lit' (LTLT)", nr) do
+ nr.times { "recv" << "constant" }
+ end
end
end
@@ -2386,48 +2386,48 @@ class TestString < Test::Unit::TestCase
recv = "something"
res = []
- before = GC.stat(:total_allocated_objects)
- nr.times { res << (recv == "constant") } # opt_streq1
- nr.times { res << ("constant" == recv) } # opt_streq2
- nr.times { res << ("something" != recv) } # 1st pass peephole
- nr.times { res << ("constant" == recv) } # opt_streq2
- nr.times { res << ("constant" === recv) } # opt_streqq2
- nr.times { res << (recv != "something") } # 2nd pass peephole
- assert_equal before, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("false comparisons") do
+ nr.times { res << (recv == "constant") } # opt_streq1
+ nr.times { res << ("constant" == recv) } # opt_streq2
+ nr.times { res << ("something" != recv) } # 1st pass peephole
+ nr.times { res << ("constant" == recv) } # opt_streq2
+ nr.times { res << ("constant" === recv) } # opt_streqq2
+ nr.times { res << (recv != "something") } # 2nd pass peephole
+ end
assert_equal [ false ], res.uniq!
res.clear
- before = GC.stat(:total_allocated_objects)
- nr.times { res << (recv == "something") } # opt_streq1
- nr.times { res << ("something" == recv) } # opt_streq2
- nr.times { res << ("something" === recv) } # opt_streqq2
- nr.times { res << (recv === "something") } # opt_streqq2
- nr.times { res << ("constant" != recv) } # 1st pass peephole
- nr.times { res << (recv != "constant") } # 2nd pass peephole
- nr.times { res << ("a" != "b") } # 1st pass peephole
- nr.times { res << ("a" == "a") } # 1st pass peephole
- nr.times { res << ("".size == 0) } # 2nd pass peephole
- nr.times { res << ("".length == 0) } # 2nd pass peephole
- assert_equal before, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("true comparisons") do
+ nr.times { res << (recv == "something") } # opt_streq1
+ nr.times { res << ("something" == recv) } # opt_streq2
+ nr.times { res << ("something" === recv) } # opt_streqq2
+ nr.times { res << (recv === "something") } # opt_streqq2
+ nr.times { res << ("constant" != recv) } # 1st pass peephole
+ nr.times { res << (recv != "constant") } # 2nd pass peephole
+ nr.times { res << ("a" != "b") } # 1st pass peephole
+ nr.times { res << ("a" == "a") } # 1st pass peephole
+ nr.times { res << ("".size == 0) } # 2nd pass peephole
+ nr.times { res << ("".length == 0) } # 2nd pass peephole
+ end
assert_equal [ true ], res.uniq!
# :+ optimizations
res.clear
- before = GC.stat(:total_allocated_objects)
- nr.times { res << ("foo" + recv) }
- assert_equal before + nr, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("'str' + (PLUS)", nr) do
+ nr.times { res << ("foo" + recv) }
+ end
assert_equal [ "foosomething" ], res.uniq!
res.clear
- before = GC.stat(:total_allocated_objects)
- nr.times { res << (recv + "foo") }
- assert_equal before + nr, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("+ 'str' (PLUS)", nr) do
+ nr.times { res << (recv + "foo") }
+ end
assert_equal [ "somethingfoo" ], res.uniq!
res.clear
- before = GC.stat(:total_allocated_objects)
- nr.times { res << ('a' * 3) }
- assert_equal before + nr, GC.stat(:total_allocated_objects)
+ assert_no_new_allocations("'str' * (MULT)", nr) do
+ nr.times { res << ('a' * 3) }
+ end
assert_equal [ "aaa" ], res.uniq!
end
end
--
EW
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2014-10-14 21:17 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-14 21:17 [PATCH 1/4] compile.c (opt_str_lit_1): hoist out of iseq_peephole_optimize Eric Wong
2014-10-14 21:17 ` [PATCH 2/4] test/ruby/test_optimization.rb (test_hash_aset_with): assert assignment Eric Wong
2014-10-14 21:17 ` [PATCH 3/4] test/ruby/test_optimization.rb: redefinition tests for string Eric Wong
2014-10-14 21:17 ` [PATCH 4/4] test/ruby/test_string.rb: cleanup allocation tests Eric Wong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).