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
next 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).