summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-11 20:30:37 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-12-11 20:30:37 +0000
commit568c0a2dff72459d65e58c0c828144cc5a19438c (patch)
treec0505a2b3643a61d3fa72c2151e4227a86d546ba
parent975e3a19a7ef725f6358d74f5bf7fd20d4403587 (diff)
remove vm_opt_binop_dispatch().
* vm_insnhelper.c (vm_opt_binop_dispatch): removed because this function has several issues for micro-benchmark. Write conditions manually. The worst point is that we can't control value checking order. For example, we can assume FIXNUM arithmetic operations are most popular in Ruby, so that we need to check FIXNUM at first. * test/ruby/test_optimization.rb: also fix redef bug for LE/GT/GE. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--test/ruby/test_optimization.rb40
-rw-r--r--vm_insnhelper.c248
2 files changed, 191 insertions, 97 deletions
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 3ea867e8e1..ba45ca2855 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -45,6 +45,26 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('Integer', '%', 'assert_equal 7, 8 % 7')
end
+ def test_fixnum_lt
+ assert_equal true, 1 < 2
+ assert_redefine_method('Integer', '<', 'assert_equal 2, 1 < 2')
+ end
+
+ def test_fixnum_le
+ assert_equal true, 1 <= 2
+ assert_redefine_method('Integer', '<=', 'assert_equal 2, 1 <= 2')
+ end
+
+ def test_fixnum_gt
+ assert_equal false, 1 > 2
+ assert_redefine_method('Integer', '>', 'assert_equal 2, 1 > 2')
+ end
+
+ def test_fixnum_ge
+ assert_equal false, 1 >= 2
+ assert_redefine_method('Integer', '>=', 'assert_equal 2, 1 >= 2')
+ end
+
def test_float_plus
assert_equal 4.0, 2.0 + 2.0
assert_redefine_method('Float', '+', 'assert_equal 2.0, 2.0 + 2.0')
@@ -65,6 +85,26 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_redefine_method('Float', '/', 'assert_equal 6.66, 4.2 / 6.66', "[Bug #9238]")
end
+ def test_float_lt
+ assert_equal true, 1.1 < 2.2
+ assert_redefine_method('Float', '<', 'assert_equal 2.2, 1.1 < 2.2')
+ end
+
+ def test_float_le
+ assert_equal true, 1.1 <= 2.2
+ assert_redefine_method('Float', '<=', 'assert_equal 2.2, 1.1 <= 2.2')
+ end
+
+ def test_float_gt
+ assert_equal false, 1.1 > 2.2
+ assert_redefine_method('Float', '>', 'assert_equal 2.2, 1.1 > 2.2')
+ end
+
+ def test_fixnum_ge
+ assert_equal false, 1.1 >= 2.2
+ assert_redefine_method('Float', '>=', 'assert_equal 2.2, 1.1 >= 2.2')
+ end
+
def test_string_length
assert_equal 6, "string".length
assert_redefine_method('String', 'length', 'assert_nil "string".length')
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 40175ad587..377f58e8f3 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -3345,95 +3345,107 @@ vm_stack_consistency_error(const rb_execution_context_t *ec,
#endif
}
-enum binop_operands_type {
- bot_others = 0,
- bot_fixnum,
- bot_flonum,
- bot_float
-};
-
-static enum binop_operands_type
-vm_opt_binop_dispatch(VALUE recv, VALUE obj, enum ruby_basic_operators BOP)
+static VALUE
+vm_opt_plus(VALUE recv, VALUE obj)
{
if (FIXNUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP, INTEGER_REDEFINED_OP_FLAG)) {
- return bot_fixnum;
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_plus_fix(recv, obj);
}
else if (FLONUM_2_P(recv, obj) &&
- BASIC_OP_UNREDEFINED_P(BOP, FLOAT_REDEFINED_OP_FLAG)) {
- return bot_flonum;
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
}
else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
- return bot_others;
+ return Qundef;
}
else if (RBASIC_CLASS(recv) == rb_cFloat &&
RBASIC_CLASS(obj) == rb_cFloat &&
- BASIC_OP_UNREDEFINED_P(BOP, FLOAT_REDEFINED_OP_FLAG)) {
- return bot_float;
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
}
- else {
- return bot_others;
+ else if (RBASIC_CLASS(recv) == rb_cString &&
+ RBASIC_CLASS(obj) == rb_cString &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
+ return rb_str_plus(recv, obj);
}
-}
-
-static VALUE
-vm_opt_plus(VALUE recv, VALUE obj)
-{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_PLUS)) {
- case bot_float:
- case bot_flonum: return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
- case bot_fixnum: return rb_fix_plus_fix(recv, obj);
- default:
- if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
- return Qundef;
- }
- else if (RBASIC_CLASS(recv) == rb_cString &&
- RBASIC_CLASS(obj) == rb_cString &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, STRING_REDEFINED_OP_FLAG)) {
- return rb_str_plus(recv, obj);
- }
- else if (RBASIC_CLASS(recv) == rb_cArray &&
- BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
- return rb_ary_plus(recv, obj);
- }
- else {
- return Qundef;
- }
+ else if (RBASIC_CLASS(recv) == rb_cArray &&
+ BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
+ return rb_ary_plus(recv, obj);
+ }
+ else {
+ return Qundef;
}
}
static VALUE
vm_opt_minus(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_MINUS)) {
- case bot_float:
- case bot_flonum: return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
- case bot_fixnum: return rb_fix_minus_fix(recv, obj);
- default: return Qundef;
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_minus_fix(recv, obj);
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
}
}
static VALUE
vm_opt_mult(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_MULT)) {
- case bot_float:
- case bot_flonum: return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
- case bot_fixnum: return rb_fix_mul_fix(recv, obj);
- default: return Qundef;
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, INTEGER_REDEFINED_OP_FLAG)) {
+ return rb_fix_mul_fix(recv, obj);
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
+ }
+ else {
+ return Qundef;
}
}
static VALUE
vm_opt_div(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_DIV)) {
- case bot_float:
- case bot_flonum:
- return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
- case bot_fixnum:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
return (FIX2LONG(obj) == 0) ? Qundef : rb_fix_div_fix(recv, obj);
- default:
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
+ }
+ else {
return Qundef;
}
}
@@ -3441,13 +3453,23 @@ vm_opt_div(VALUE recv, VALUE obj)
static VALUE
vm_opt_mod(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_MOD)) {
- case bot_float:
- case bot_flonum:
- return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
- case bot_fixnum:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG)) {
return (FIX2LONG(obj) == 0) ? Qundef : rb_fix_mod_fix(recv, obj);
- default:
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+ return DBL2NUM(ruby_float_mod(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj)));
+ }
+ else {
return Qundef;
}
}
@@ -3471,16 +3493,24 @@ vm_opt_neq(CALL_INFO ci, CALL_CACHE cc,
static VALUE
vm_opt_lt(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_LT)) {
- case bot_float:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
+ return (SIGNED_VALUE)recv < (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+ return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- /* FALLTHROUGH */
- case bot_flonum:
- /* flonum is not NaN */
return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- case bot_fixnum:
- return (SIGNED_VALUE)recv < (SIGNED_VALUE)obj ? Qtrue : Qfalse;
- default:
+ }
+ else {
return Qundef;
}
}
@@ -3488,16 +3518,24 @@ vm_opt_lt(VALUE recv, VALUE obj)
static VALUE
vm_opt_le(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_LT)) {
- case bot_float:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
+ return (SIGNED_VALUE)recv <= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
+ return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- /* FALLTHROUGH */
- case bot_flonum:
- /* flonum is not NaN */
return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- case bot_fixnum:
- return (SIGNED_VALUE)recv <= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
- default:
+ }
+ else {
return Qundef;
}
}
@@ -3505,16 +3543,24 @@ vm_opt_le(VALUE recv, VALUE obj)
static VALUE
vm_opt_gt(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_LT)) {
- case bot_float:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
+ return (SIGNED_VALUE)recv > (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+ return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- /* FALLTHROUGH */
- case bot_flonum:
- /* flonum is not NaN */
return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- case bot_fixnum:
- return (SIGNED_VALUE)recv > (SIGNED_VALUE)obj ? Qtrue : Qfalse;
- default:
+ }
+ else {
return Qundef;
}
}
@@ -3522,16 +3568,24 @@ vm_opt_gt(VALUE recv, VALUE obj)
static VALUE
vm_opt_ge(VALUE recv, VALUE obj)
{
- switch (vm_opt_binop_dispatch(recv, obj, BOP_LT)) {
- case bot_float:
+ if (FIXNUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
+ return (SIGNED_VALUE)recv >= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+ }
+ else if (FLONUM_2_P(recv, obj) &&
+ BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
+ return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
+ }
+ else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
+ return Qundef;
+ }
+ else if (RBASIC_CLASS(recv) == rb_cFloat &&
+ RBASIC_CLASS(obj) == rb_cFloat &&
+ BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
- /* FALLTHROUGH */
- case bot_flonum:
- /* flonum is not NaN */
return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
- case bot_fixnum:
- return (SIGNED_VALUE)recv >= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
- default:
+ }
+ else {
return Qundef;
}
}