summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}
}