diff options
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r-- | vm_insnhelper.c | 248 |
1 files changed, 151 insertions, 97 deletions
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; } } |