dumping ground for random patches and texts
 help / color / mirror / Atom feed
From: Eric Wong <e@80x24.org>
To: spew@80x24.org
Subject: [PATCH] optimize case harder [ruby-core:71818] [Feature #11769]
Date: Tue,  8 Dec 2015 00:16:23 +0000	[thread overview]
Message-ID: <20151208001623.2666-1-e@80x24.org> (raw)

true and false may be used for optimized case dispatch, too

2015-12-08 00:07:31 +0000
target 0: a (ruby 2.3.0dev (2015-12-08 trunk 52928) [x86_64-linux]) at "/home/ew/rrrr/b/ruby"
target 1: b (ruby 2.3.0dev (2015-12-08 master 52928) [x86_64-linux]) at "/home/ew/ruby/b/ruby"

benchmark results:
minimum results in each 5 measurements.
Execution time (sec)
name	a	b
loop_whileloop2	0.102	0.103
vm2_case_lit*	1.657	0.549

Speedup ratio: compare with the result of `a' (greater is better)
name	b
loop_whileloop2	0.988
vm2_case_lit*	3.017
---
 benchmark/bm_vm2_case_lit.rb   | 19 +++++++++++++++++++
 compile.c                      |  6 +++++-
 insns.def                      |  5 +++++
 object.c                       |  2 ++
 test/ruby/test_optimization.rb | 13 +++++++++++++
 vm.c                           |  5 ++++-
 vm_core.h                      |  2 ++
 7 files changed, 50 insertions(+), 2 deletions(-)
 create mode 100644 benchmark/bm_vm2_case_lit.rb

diff --git a/benchmark/bm_vm2_case_lit.rb b/benchmark/bm_vm2_case_lit.rb
new file mode 100644
index 0000000..c62b294
--- /dev/null
+++ b/benchmark/bm_vm2_case_lit.rb
@@ -0,0 +1,19 @@
+i = 0
+@ret = [ "foo", true, false, :sym, 6, nil, 0.1, 0xffffffffffffffff ]
+def foo(i)
+  @ret[i % @ret.size]
+end
+
+while i<6_000_000 # while loop 2
+  case foo(i)
+  when "foo" then :foo
+  when true then true
+  when false then false
+  when :sym then :sym
+  when 6 then :fix
+  when nil then nil
+  when 0.1 then :float
+  when 0xffffffffffffffff then :big
+  end
+  i += 1
+end
diff --git a/compile.c b/compile.c
index 22c3062..abb5306 100644
--- a/compile.c
+++ b/compile.c
@@ -2920,7 +2920,11 @@ case_when_optimizable_literal(NODE * node)
 	break;
       }
       case NODE_NIL:
-	 return Qnil;
+	return Qnil;
+      case NODE_TRUE:
+	return Qtrue;
+      case NODE_FALSE:
+	return Qfalse;
       case NODE_STR:
 	return node->nd_lit = rb_fstring(node->nd_lit);
     }
diff --git a/insns.def b/insns.def
index 9f5b788..3c4d980 100644
--- a/insns.def
+++ b/insns.def
@@ -1264,6 +1264,9 @@ opt_case_dispatch
 	    key = FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival);
 	}
       }
+      case T_TRUE:
+      case T_FALSE:
+      case T_NIL:
       case T_SYMBOL: /* fall through */
       case T_FIXNUM:
       case T_BIGNUM:
@@ -1274,6 +1277,8 @@ opt_case_dispatch
 				   FLOAT_REDEFINED_OP_FLAG |
 				   BIGNUM_REDEFINED_OP_FLAG |
 				   NIL_REDEFINED_OP_FLAG    |
+				   TRUE_REDEFINED_OP_FLAG   |
+				   FALSE_REDEFINED_OP_FLAG  |
 				   STRING_REDEFINED_OP_FLAG)) {
 	    st_data_t val;
 	    if (st_lookup(RHASH_TBL_RAW(hash), key, &val)) {
diff --git a/object.c b/object.c
index e2bcf74..d339ff9 100644
--- a/object.c
+++ b/object.c
@@ -3554,6 +3554,7 @@ InitVM_Object(void)
     rb_define_method(rb_cTrueClass, "&", true_and, 1);
     rb_define_method(rb_cTrueClass, "|", true_or, 1);
     rb_define_method(rb_cTrueClass, "^", true_xor, 1);
+    rb_define_method(rb_cTrueClass, "===", rb_equal, 1);
     rb_undef_alloc_func(rb_cTrueClass);
     rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
     /*
@@ -3567,6 +3568,7 @@ InitVM_Object(void)
     rb_define_method(rb_cFalseClass, "&", false_and, 1);
     rb_define_method(rb_cFalseClass, "|", false_or, 1);
     rb_define_method(rb_cFalseClass, "^", false_xor, 1);
+    rb_define_method(rb_cFalseClass, "===", rb_equal, 1);
     rb_undef_alloc_func(rb_cFalseClass);
     rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
     /*
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 23c5226..1c50044 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -313,8 +313,11 @@ def test_opt_case_dispatch
     code = <<-EOF
       case foo
       when "foo" then :foo
+      when true then true
+      when false then false
       when :sym then :sym
       when 6 then :fix
+      when nil then nil
       when 0.1 then :float
       when 0xffffffffffffffff then :big
       else
@@ -323,8 +326,11 @@ def test_opt_case_dispatch
     EOF
     check = {
       'foo' => :foo,
+      true => true,
+      false => false,
       :sym => :sym,
       6 => :fix,
+      nil => nil,
       0.1 => :float,
       0xffffffffffffffff => :big,
     }
@@ -349,4 +355,11 @@ def ===(*args)
       end;
     end
   end
+
+  def test_eqq
+    [ nil, true, false, 0.1, :sym, 'str', 0xffffffffffffffff ].each do |v|
+      k = v.class.to_s
+      assert_redefine_method(k, '===', "assert_equal(#{v.inspect} === 0, 0)")
+    end
+  end
 end
diff --git a/vm.c b/vm.c
index 565f728..be9c7b2 100644
--- a/vm.c
+++ b/vm.c
@@ -1374,6 +1374,8 @@ vm_redefinition_check_flag(VALUE klass)
     if (klass == rb_cTime)   return TIME_REDEFINED_OP_FLAG;
     if (klass == rb_cRegexp) return REGEXP_REDEFINED_OP_FLAG;
     if (klass == rb_cNilClass) return NIL_REDEFINED_OP_FLAG;
+    if (klass == rb_cTrueClass) return TRUE_REDEFINED_OP_FLAG;
+    if (klass == rb_cFalseClass) return FALSE_REDEFINED_OP_FLAG;
     return 0;
 }
 
@@ -1438,7 +1440,8 @@ vm_init_redefined_flag(void)
     OP(DIV, DIV), (C(Fixnum), C(Float));
     OP(MOD, MOD), (C(Fixnum), C(Float));
     OP(Eq, EQ), (C(Fixnum), C(Float), C(String));
-    OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String), C(NilClass));
+    OP(Eqq, EQQ), (C(Fixnum), C(Bignum), C(Float), C(Symbol), C(String),
+		   C(NilClass), C(TrueClass), C(FalseClass));
     OP(LT, LT), (C(Fixnum), C(Float));
     OP(LE, LE), (C(Fixnum), C(Float));
     OP(GT, GT), (C(Fixnum), C(Float));
diff --git a/vm_core.h b/vm_core.h
index 657e82e..aecbe61 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -546,6 +546,8 @@ typedef struct rb_vm_struct {
 #define TIME_REDEFINED_OP_FLAG   (1 << 7)
 #define REGEXP_REDEFINED_OP_FLAG (1 << 8)
 #define NIL_REDEFINED_OP_FLAG    (1 << 9)
+#define TRUE_REDEFINED_OP_FLAG   (1 << 10)
+#define FALSE_REDEFINED_OP_FLAG  (1 << 11)
 
 #define BASIC_OP_UNREDEFINED_P(op, klass) (LIKELY((GET_VM()->redefined_flag[(op)]&(klass)) == 0))
 
-- 
EW


             reply	other threads:[~2015-12-08  0:16 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-08  0:16 Eric Wong [this message]
  -- strict thread matches above, loose matches on Subject: below --
2015-12-08  0:13 [PATCH] optimize case harder [ruby-core:71818] [Feature #11769] Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151208001623.2666-1-e@80x24.org \
    --to=e@80x24.org \
    --cc=spew@80x24.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).