diff options
-rw-r--r-- | test/ruby/test_optimization.rb | 40 | ||||
-rw-r--r-- | vm_insnhelper.c | 248 |
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; } } |