dumping ground for random patches and texts
 help / color / mirror / Atom feed
* [PATCH] compile.c: move some "literal" opts to peephole
@ 2014-10-08  1:56 Eric Wong
  0 siblings, 0 replies; only message in thread
From: Eric Wong @ 2014-10-08  1:56 UTC (permalink / raw)
  To: spew

`"literal".freeze', `obj["literal"]'
are all peephole optimizations and not appropriate for
iseq_compile_each.

TODO: move `obj["literal"] = val', too.
---
 compile.c                      | 66 ++++++++++++++++++++++--------------------
 test/-ext-/symbol/test_type.rb |  1 +
 test/objspace/test_objspace.rb |  1 +
 test/ruby/envutil.rb           | 10 +++++++
 test/ruby/test_hash.rb         |  2 ++
 test/ruby/test_iseq.rb         |  1 +
 test/ruby/test_string.rb       |  7 +++++
 7 files changed, 57 insertions(+), 31 deletions(-)

diff --git a/compile.c b/compile.c
index dda22b0..b38eedb 100644
--- a/compile.c
+++ b/compile.c
@@ -1819,6 +1819,41 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
 	    }
 	}
     }
+
+    /* string literal optimizations */
+    if (iobj->insn_id == BIN(putstring)) {
+	INSN *niobj = (INSN *)get_next_insn((INSN *)list);
+
+	if (niobj && niobj->insn_id == BIN(send)) {
+	    rb_call_info_t *ci = (rb_call_info_t *)niobj->operands[0];
+
+	    if (ci->blockiseq == 0 &&
+		(ci->flag & ~VM_CALL_ARGS_SKIP_SETUP) == 0) {
+
+		/* "literal".freeze -> opt_str_freeze("literal") */
+		if (ci->mid == idFreeze && ci->orig_argc == 0) {
+		    iobj->insn_id = BIN(opt_str_freeze);
+		    REMOVE_ELEM((LINK_ELEMENT *)niobj);
+		}
+
+		/* obj["literal"] -> opt_aref_with(obj, "literal") */
+		else if (ci->mid == idAREF && ci->orig_argc == 1) {
+		    VALUE *old_operands = iobj->operands;
+
+		    iobj->insn_id = BIN(opt_aref_with);
+		    iobj->operand_size = insn_len(iobj->insn_id) - 1;
+
+		    iobj->operands = (VALUE *)compile_data_alloc(iseq,
+					iobj->operand_size * sizeof(VALUE));
+		    iobj->operands[0] = (VALUE)ci;
+		    iobj->operands[1] = old_operands[0];
+
+		    REMOVE_ELEM((LINK_ELEMENT *)niobj);
+		}
+	    }
+	}
+    }
+
     return COMPILE_OK;
 }
 
@@ -4238,37 +4273,6 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
 	break;
       }
       case NODE_CALL:
-	/* optimization shortcut
-	 *   "literal".freeze -> opt_str_freeze("literal")
-	 */
-	if (node->nd_recv && nd_type(node->nd_recv) == NODE_STR &&
-	    node->nd_mid == idFreeze && node->nd_args == NULL)
-	{
-	    VALUE str = rb_fstring(node->nd_recv->nd_lit);
-	    iseq_add_mark_object(iseq, str);
-	    ADD_INSN1(ret, line, opt_str_freeze, str);
-	    if (poped) {
-		ADD_INSN(ret, line, pop);
-	    }
-	    break;
-	}
-	/* optimization shortcut
-	 *   obj["literal"] -> opt_aref_with(obj, "literal")
-	 */
-	if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args &&
-	    nd_type(node->nd_args) == NODE_ARRAY && node->nd_args->nd_alen == 1 &&
-	    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_aref_with,
-		      new_callinfo(iseq, idAREF, 1, 0, 0), str);
-	    if (poped) {
-		ADD_INSN(ret, line, pop);
-	    }
-	    break;
-	}
       case NODE_FCALL:
       case NODE_VCALL:{		/* VCALL: variable or call */
 	/*
diff --git a/test/-ext-/symbol/test_type.rb b/test/-ext-/symbol/test_type.rb
index f1749f5..5bd79b8 100644
--- a/test/-ext-/symbol/test_type.rb
+++ b/test/-ext-/symbol/test_type.rb
@@ -4,6 +4,7 @@ require "-test-/symbol"
 module Test_Symbol
   class TestType < Test::Unit::TestCase
     def test_id2str_fstring_bug9171
+      require_compile_option(:peephole_optimization)
       fstr = eval("# encoding: us-ascii
         'foobar'.freeze")
       assert_same fstr, Bug::Symbol.id2str(:foobar)
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 8a5ed34..faacf48 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -195,6 +195,7 @@ class TestObjSpace < Test::Unit::TestCase
   end
 
   def test_dump_flags
+    require_compile_option(:peephole_optimization)
     info = ObjectSpace.dump("foo".freeze)
     assert_match /"wb_protected":true, "old":true, "long_lived":true, "marked":true/, info
     assert_match /"fstring":true/, info
diff --git a/test/ruby/envutil.rb b/test/ruby/envutil.rb
index 81b982c..e844822 100644
--- a/test/ruby/envutil.rb
+++ b/test/ruby/envutil.rb
@@ -477,6 +477,16 @@ eom
         AssertFile
       end
 
+      def require_compile_option(opt)
+        case RubyVM::InstructionSequence.compile_option[opt]
+        when true
+        when false
+          skip(":#{opt} disabled")
+        else
+          raise ArgumentError, "unrecognized compile option: #{opt.inspect}"
+        end
+      end
+
       class << (AssertFile = Struct.new(:failure_message).new)
         include Assertions
         def assert_file_predicate(predicate, *args)
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 4431552..bb7e8b5 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -216,6 +216,7 @@ class TestHash < Test::Unit::TestCase
   end
 
   def test_AREF_fstring_key
+    require_compile_option(:peephole_optimization)
     h = {"abc" => 1}
     before = GC.stat(:total_allocated_objects)
     5.times{ h["abc"] }
@@ -230,6 +231,7 @@ class TestHash < Test::Unit::TestCase
   end
 
   def test_NEWHASH_fstring_key
+    require_compile_option(:peephole_optimization)
     a = {"ABC" => :t}
     b = {"ABC" => :t}
     assert_same a.keys[0], b.keys[0]
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 94a814c..ac1c417 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -118,6 +118,7 @@ class TestISeq < Test::Unit::TestCase
   end
 
   def test_label_fstring
+    require_compile_option(:peephole_optimization)
     c = Class.new{ def foobar() end }
 
     a, b = eval("# encoding: us-ascii\n'foobar'.freeze"),
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index d82d2bc..4dc790f 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -1908,6 +1908,13 @@ class TestString < Test::Unit::TestCase
     }
   end
 
+  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)
+  end
+
   class S2 < String
   end
   def test_str_new4
-- 
EW


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2014-10-08  1:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-10-08  1:56 [PATCH] compile.c: move some "literal" opts to peephole 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).