From 568c0a2dff72459d65e58c0c828144cc5a19438c Mon Sep 17 00:00:00 2001 From: ko1 Date: Mon, 11 Dec 2017 20:30:37 +0000 Subject: 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 --- vm_insnhelper.c | 248 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 151 insertions(+), 97 deletions(-) (limited to 'vm_insnhelper.c') 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; } } -- cgit v1.2.3