[前][次][番号順一覧][スレッド一覧]

ruby-changes:49004

From: ko1 <ko1@a...>
Date: Tue, 12 Dec 2017 05:30:42 +0900 (JST)
Subject: [ruby-changes:49004] ko1:r61123 (trunk): remove vm_opt_binop_dispatch().

ko1	2017-12-12 05:30:37 +0900 (Tue, 12 Dec 2017)

  New Revision: 61123

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61123

  Log:
    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.

  Modified files:
    trunk/test/ruby/test_optimization.rb
    trunk/vm_insnhelper.c
Index: test/ruby/test_optimization.rb
===================================================================
--- test/ruby/test_optimization.rb	(revision 61122)
+++ test/ruby/test_optimization.rb	(revision 61123)
@@ -45,6 +45,26 @@ class TestRubyOptimization < Test::Unit: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_optimization.rb#L45
     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: https://github.com/ruby/ruby/blob/trunk/test/ruby/test_optimization.rb#L85
     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')
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 61122)
+++ vm_insnhelper.c	(revision 61123)
@@ -3345,95 +3345,107 @@ vm_stack_consistency_error(const rb_exec https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3345
 #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);
+    }
+    else if (RBASIC_CLASS(recv) == rb_cArray &&
+	     BASIC_OP_UNREDEFINED_P(BOP_PLUS, ARRAY_REDEFINED_OP_FLAG)) {
+	return rb_ary_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 {
+	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) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3453
 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, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3493
 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) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3518
 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) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3543
 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) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3568
 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;
     }
 }

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]