mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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
This commit is contained in:
parent
975e3a19a7
commit
568c0a2dff
2 changed files with 203 additions and 109 deletions
|
@ -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')
|
||||
|
|
272
vm_insnhelper.c
272
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)
|
||||
{
|
||||
if (FIXNUM_2_P(recv, obj) &&
|
||||
BASIC_OP_UNREDEFINED_P(BOP, INTEGER_REDEFINED_OP_FLAG)) {
|
||||
return bot_fixnum;
|
||||
}
|
||||
else if (FLONUM_2_P(recv, obj) &&
|
||||
BASIC_OP_UNREDEFINED_P(BOP, FLOAT_REDEFINED_OP_FLAG)) {
|
||||
return bot_flonum;
|
||||
}
|
||||
else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
|
||||
return bot_others;
|
||||
}
|
||||
else if (RBASIC_CLASS(recv) == rb_cFloat &&
|
||||
RBASIC_CLASS(obj) == rb_cFloat &&
|
||||
BASIC_OP_UNREDEFINED_P(BOP, FLOAT_REDEFINED_OP_FLAG)) {
|
||||
return bot_float;
|
||||
}
|
||||
else {
|
||||
return bot_others;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (FIXNUM_2_P(recv, obj) &&
|
||||
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_PLUS, 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_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
|
||||
return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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:
|
||||
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
|
||||
/* FALLTHROUGH */
|
||||
case bot_flonum:
|
||||
/* flonum is not NaN */
|
||||
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;
|
||||
case bot_fixnum:
|
||||
return (SIGNED_VALUE)recv < (SIGNED_VALUE)obj ? Qtrue : Qfalse;
|
||||
default:
|
||||
}
|
||||
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));
|
||||
return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
|
||||
}
|
||||
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:
|
||||
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
|
||||
/* FALLTHROUGH */
|
||||
case bot_flonum:
|
||||
/* flonum is not NaN */
|
||||
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;
|
||||
case bot_fixnum:
|
||||
return (SIGNED_VALUE)recv <= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
|
||||
default:
|
||||
}
|
||||
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));
|
||||
return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
|
||||
}
|
||||
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:
|
||||
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
|
||||
/* FALLTHROUGH */
|
||||
case bot_flonum:
|
||||
/* flonum is not NaN */
|
||||
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;
|
||||
case bot_fixnum:
|
||||
return (SIGNED_VALUE)recv > (SIGNED_VALUE)obj ? Qtrue : Qfalse;
|
||||
default:
|
||||
}
|
||||
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));
|
||||
return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
|
||||
}
|
||||
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:
|
||||
CHECK_CMP_NAN(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
|
||||
/* FALLTHROUGH */
|
||||
case bot_flonum:
|
||||
/* flonum is not NaN */
|
||||
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;
|
||||
case bot_fixnum:
|
||||
return (SIGNED_VALUE)recv >= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
|
||||
default:
|
||||
}
|
||||
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));
|
||||
return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
|
||||
}
|
||||
else {
|
||||
return Qundef;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue