summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c248
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;
}
}