aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-26 09:34:46 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-09-26 09:34:46 +0000
commit1bebb22ce16c6129a805adad83e0f1e29f3874a0 (patch)
tree5b6f7577de49c048fab45e5c293b01824f494e03
parent24793ac32db538306899aed7ba588b7231f93a95 (diff)
downloadruby-1bebb22ce16c6129a805adad83e0f1e29f3874a0.tar.gz
* insns.def: add new instruction `opt_empty_p' for optimize `empty?'
method. Apply a patch proposed at [ruby-dev:46120] [ruby-trunk - Feature #6972] by Glass_saga (Masaki Matsushita). * compile.c (iseq_specialized_instruction), vm.c, vm_insnhelper.h: ditto. * id.c, template/id.h.tmpl: ditto. * test/ruby/test_optimization.rb: test for this changes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37036 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog13
-rw-r--r--compile.c1
-rw-r--r--id.c1
-rw-r--r--insns.def38
-rw-r--r--template/id.h.tmpl1
-rw-r--r--test/ruby/test_optimization.rb18
-rw-r--r--vm.c1
-rw-r--r--vm_insnhelper.h1
8 files changed, 74 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 38dec62e52..05038f5a43 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+Wed Sep 26 16:39:57 2012 Koichi Sasada <ko1@atdot.net>
+
+ * insns.def: add new instruction `opt_empty_p' for optimize `empty?'
+ method. Apply a patch proposed at [ruby-dev:46120]
+ [ruby-trunk - Feature #6972] by Glass_saga (Masaki Matsushita).
+
+ * compile.c (iseq_specialized_instruction), vm.c, vm_insnhelper.h:
+ ditto.
+
+ * id.c, template/id.h.tmpl: ditto.
+
+ * test/ruby/test_optimization.rb: test for this changes.
+
Tue Sep 25 09:59:26 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
* insns.def (invokesuper): klass in cfp is not valid in at_exit and
diff --git a/compile.c b/compile.c
index 2f8cbb51cd..368e3cf6db 100644
--- a/compile.c
+++ b/compile.c
@@ -1872,6 +1872,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
switch (mid) {
case idLength: SP_INSN(length); break;
case idSize: SP_INSN(size); break;
+ case idEmptyP: SP_INSN(empty_p);break;
case idSucc: SP_INSN(succ); break;
case idNot: SP_INSN(not); break;
}
diff --git a/id.c b/id.c
index e5f971d3e2..b6143971a1 100644
--- a/id.c
+++ b/id.c
@@ -41,6 +41,7 @@ Init_id(void)
REGISTER_SYMID(idEach, "each");
REGISTER_SYMID(idLength, "length");
REGISTER_SYMID(idSize, "size");
+ REGISTER_SYMID(idEmptyP, "empty?");
REGISTER_SYMID(idLambda, "lambda");
REGISTER_SYMID(idIntern, "intern");
REGISTER_SYMID(idGets, "gets");
diff --git a/insns.def b/insns.def
index a1b8756d17..1dc4328d72 100644
--- a/insns.def
+++ b/insns.def
@@ -1994,6 +1994,44 @@ opt_size
/**
@c optimize
+ @e optimized empty?
+ @j 最適化された recv.empty?()。
+ */
+DEFINE_INSN
+opt_empty_p
+(IC ic)
+(VALUE recv)
+(VALUE val)
+{
+ if (!SPECIAL_CONST_P(recv)) {
+ if (HEAP_CLASS_OF(recv) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, STRING_REDEFINED_OP_FLAG)) {
+ if (RSTRING_LEN(recv) == 0) val = Qtrue;
+ else val = Qfalse;
+ }
+ else if (HEAP_CLASS_OF(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, ARRAY_REDEFINED_OP_FLAG)) {
+ if (RARRAY_LEN(recv) == 0) val = Qtrue;
+ else val = Qfalse;
+ }
+ else if (HEAP_CLASS_OF(recv) == rb_cHash &&
+ BASIC_OP_UNREDEFINED_P(BOP_EMPTY_P, HASH_REDEFINED_OP_FLAG)) {
+ if (RHASH_EMPTY_P(recv)) val = Qtrue;
+ else val = Qfalse;
+ }
+ else {
+ goto INSN_LABEL(normal_dispatch);
+ }
+ }
+ else {
+ INSN_LABEL(normal_dispatch):
+ PUSH(recv);
+ CALL_SIMPLE_METHOD(0, idEmptyP, recv);
+ }
+}
+
+/**
+ @c optimize
@e optimized succ
@j 最適化された recv.succ()。
*/
diff --git a/template/id.h.tmpl b/template/id.h.tmpl
index 0e54e762f4..f7e764c123 100644
--- a/template/id.h.tmpl
+++ b/template/id.h.tmpl
@@ -20,6 +20,7 @@ method_ids = %w[
MethodMissing
Length
Size
+ EmptyP
Gets
Succ
Each
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 1b0c730996..a3b4aedcdc 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -85,6 +85,14 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal 6, "string".length
end
+ def test_string_empty?
+ assert_equal true, "".empty?
+ assert_equal false, "string".empty?
+ assert_nil redefine_method('String', 'empty?') { "string".empty? }
+ assert_equal true, "".empty?
+ assert_equal false, "string".empty?
+ end
+
def test_string_plus
assert_equal "", "" + ""
assert_equal "x", "x" + ""
@@ -116,11 +124,21 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal 3, [1,2,3].length
end
+ def test_array_empty?
+ assert_equal true, [].empty?
+ assert_equal false, [1,2,3].empty?
+ end
+
def test_hash_length
assert_equal 0, {}.length
assert_equal 1, {1=>1}.length
end
+ def test_hash_empty?
+ assert_equal true, {}.empty?
+ assert_equal false, {1=>1}.empty?
+ end
+
class MyObj
def ==(other)
true
diff --git a/vm.c b/vm.c
index f842a6dfba..c59ef0b895 100644
--- a/vm.c
+++ b/vm.c
@@ -1005,6 +1005,7 @@ vm_init_redefined_flag(void)
OP(ASET, ASET), (C(Array), C(Hash));
OP(Length, LENGTH), (C(Array), C(String), C(Hash));
OP(Size, SIZE), (C(Array), C(String), C(Hash));
+ OP(EmptyP, EMPTY_P), (C(Array), C(String), C(Hash));
OP(Succ, SUCC), (C(Fixnum), C(String), C(Time));
#undef C
#undef OP
diff --git a/vm_insnhelper.h b/vm_insnhelper.h
index 4d5f0e36b6..7c7745ae60 100644
--- a/vm_insnhelper.h
+++ b/vm_insnhelper.h
@@ -49,6 +49,7 @@ enum {
BOP_ASET,
BOP_LENGTH,
BOP_SIZE,
+ BOP_EMPTY_P,
BOP_SUCC,
BOP_GT,
BOP_GE,