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

ruby-changes:46289

From: shyouhei <ko1@a...>
Date: Wed, 19 Apr 2017 16:27:10 +0900 (JST)
Subject: [ruby-changes:46289] shyouhei:r58402 (trunk): refactor extract binop dispatcher

shyouhei	2017-04-19 16:27:03 +0900 (Wed, 19 Apr 2017)

  New Revision: 58402

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

  Log:
    refactor extract binop dispatcher
    
    Those opt_something instructions are worth refactoring. They tend to
    have similar ways of executions.  By extracting the common part,
    generated vm_exec_core function shrinks from 26,816 bytes to 26,256
    bytes (according to nm(1)).
    
    This changeset introduces negligible performance impact.  3 repeated
    runs of optcarrot benchmark on my machine resulted in:
    
       before this: 28.813363684823557, 27.523907198440366, 27.292766121965400
       after  this: 28.174038497265080, 28.999513875020405, 29.621399800428065
    
    in fps (greater==faster).
    
    ----
    
    * vm_insnhelper.c (vm_opt_binop_dispatch): new function.

  Modified files:
    trunk/vm_insnhelper.c
Index: vm_insnhelper.c
===================================================================
--- vm_insnhelper.c	(revision 58401)
+++ vm_insnhelper.c	(revision 58402)
@@ -3299,23 +3299,50 @@ vm_case_dispatch(CDHASH hash, OFFSET els https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3299
     return 0;
 }
 
-static VALUE
-vm_opt_plus(VALUE recv, VALUE obj)
+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_PLUS,INTEGER_REDEFINED_OP_FLAG)) {
-	return rb_fix_plus_fix(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_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
-	return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(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 (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_PLUS, FLOAT_REDEFINED_OP_FLAG)) {
-	return DBL2NUM(RFLOAT_VALUE(recv) + RFLOAT_VALUE(obj));
+    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 if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) {
-	if (RBASIC_CLASS(recv) == rb_cString && RBASIC_CLASS(obj) == rb_cString &&
+    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);
 	}
@@ -3327,72 +3354,40 @@ vm_opt_plus(VALUE recv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3354
 	    return Qundef;
 	}
     }
-    else {
-	return Qundef;
-    }
 }
 
 static VALUE
 vm_opt_minus(VALUE recv, VALUE obj)
 {
-    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 (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MINUS, FLOAT_REDEFINED_OP_FLAG)) {
-	return DBL2NUM(RFLOAT_VALUE(recv) - RFLOAT_VALUE(obj));
-    }
-    else {
-	return Qundef;
+    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;
     }
 }
 
 static VALUE
 vm_opt_mult(VALUE recv, VALUE obj)
 {
-    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 (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MULT, FLOAT_REDEFINED_OP_FLAG)) {
-	return DBL2NUM(RFLOAT_VALUE(recv) * RFLOAT_VALUE(obj));
-    }
-    else {
-	return Qundef;
+    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;
     }
 }
 
 static VALUE
 vm_opt_div(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_DIV, INTEGER_REDEFINED_OP_FLAG)) {
-	if (FIX2LONG(obj) == 0) {
-	    return Qundef;
-	}
-	else {
-	    return rb_fix_div_fix(recv, obj);
-	}
-    }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
+    switch (vm_opt_binop_dispatch(recv, obj, BOP_DIV)) {
+      case bot_float:
+      case bot_flonum:
 	return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
-    }
-    else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
-	return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
-    }
-    else {
+      case bot_fixnum:
+	return (FIX2LONG(obj) == 0) ? Qundef : rb_fix_div_fix(recv, obj);
+      default:
 	return Qundef;
     }
 }
@@ -3400,24 +3395,13 @@ vm_opt_div(VALUE recv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3395
 static VALUE
 vm_opt_mod(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_MOD, INTEGER_REDEFINED_OP_FLAG )) {
-	if (FIX2LONG(obj) == 0) {
-	    return Qundef;
-	}
-	else {
-	    return rb_fix_mod_fix(recv, obj);
-	}
-    }
-    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 (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_MOD, FLOAT_REDEFINED_OP_FLAG)) {
+    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)));
-    }
-    else {
+      case bot_fixnum:
+	return (FIX2LONG(obj) == 0) ? Qundef : rb_fix_mod_fix(recv, obj);
+      default:
 	return Qundef;
     }
 }
@@ -3449,27 +3433,16 @@ vm_opt_neq(CALL_INFO ci, CALL_CACHE cc, https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3433
 static VALUE
 vm_opt_lt(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_LT, INTEGER_REDEFINED_OP_FLAG)) {
-	SIGNED_VALUE a = recv, b = obj;
-
-	if (a < b) {
-	    return Qtrue;
-	}
-	else {
-	    return Qfalse;
-	}
-    }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
+    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 */
 	return RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
-    }
-    else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
-	return double_cmp_lt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
-    }
-    else {
+      case bot_fixnum:
+        return (SIGNED_VALUE)recv < (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+      default:
 	return Qundef;
     }
 }
@@ -3477,27 +3450,16 @@ vm_opt_lt(VALUE recv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3450
 static VALUE
 vm_opt_le(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_LE, INTEGER_REDEFINED_OP_FLAG)) {
-	SIGNED_VALUE a = recv, b = obj;
-
-	if (a <= b) {
-	    return Qtrue;
-	}
-	else {
-	    return Qfalse;
-	}
-    }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LE, FLOAT_REDEFINED_OP_FLAG)) {
+    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 */
 	return RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
-    }
-    else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_LT, FLOAT_REDEFINED_OP_FLAG)) {
-	return double_cmp_le(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
-    }
-    else {
+      case bot_fixnum:
+        return (SIGNED_VALUE)recv <= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+      default:
 	return Qundef;
     }
 }
@@ -3505,27 +3467,16 @@ vm_opt_le(VALUE recv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3467
 static VALUE
 vm_opt_gt(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_GT, INTEGER_REDEFINED_OP_FLAG)) {
-	SIGNED_VALUE a = recv, b = obj;
-
-	if (a > b) {
-	    return Qtrue;
-	}
-	else {
-	    return Qfalse;
-	}
-    }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
+    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 */
 	return RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
-    }
-    else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
-	return double_cmp_gt(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
-    }
-    else {
+      case bot_fixnum:
+        return (SIGNED_VALUE)recv > (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+      default:
 	return Qundef;
     }
 }
@@ -3533,31 +3484,21 @@ vm_opt_gt(VALUE recv, VALUE obj) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3484
 static VALUE
 vm_opt_ge(VALUE recv, VALUE obj)
 {
-    if (FIXNUM_2_P(recv, obj) &&
-	BASIC_OP_UNREDEFINED_P(BOP_GE, INTEGER_REDEFINED_OP_FLAG)) {
-	SIGNED_VALUE a = recv, b = obj;
-
-	if (a >= b) {
-	    return Qtrue;
-	}
-	else {
-	    return Qfalse;
-	}
-    }
-    else if (FLONUM_2_P(recv, obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GE, FLOAT_REDEFINED_OP_FLAG)) {
+    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 */
 	return RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj) ? Qtrue : Qfalse;
-    }
-    else if (FLOAT_INSTANCE_P(recv) && FLOAT_INSTANCE_P(obj) &&
-	     BASIC_OP_UNREDEFINED_P(BOP_GT, FLOAT_REDEFINED_OP_FLAG)) {
-	return double_cmp_ge(RFLOAT_VALUE(recv), RFLOAT_VALUE(obj));
-    }
-    else {
+      case bot_fixnum:
+        return (SIGNED_VALUE)recv >= (SIGNED_VALUE)obj ? Qtrue : Qfalse;
+      default:
 	return Qundef;
     }
 }
 
+
 static VALUE
 vm_opt_ltlt(VALUE recv, VALUE obj)
 {
@@ -3686,29 +3627,25 @@ vm_opt_empty_p(VALUE recv) https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3627
 static VALUE
 vm_opt_succ(VALUE recv)
 {
-    if (SPECIAL_CONST_P(recv)) {
-	if (FIXNUM_P(recv) &&
-	    BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
-	    /* fixnum + INT2FIX(1) */
-	    if (recv == LONG2FIX(FIXNUM_MAX)) {
-		return LONG2NUM(FIXNUM_MAX + 1);
-	    }
-	    else {
-		return recv - 1 + INT2FIX(1);
-	    }
+    if (FIXNUM_P(recv) &&
+	BASIC_OP_UNREDEFINED_P(BOP_SUCC, INTEGER_REDEFINED_OP_FLAG)) {
+	/* fixnum + INT2FIX(1) */
+	if (recv == LONG2FIX(FIXNUM_MAX)) {
+	    return LONG2NUM(FIXNUM_MAX + 1);
 	}
 	else {
-	    return Qundef;
+	    return recv - 1 + INT2FIX(1);
 	}
     }
+    else if (SPECIAL_CONST_P(recv)) {
+	return Qundef;
+    }
+    else if (RBASIC_CLASS(recv) == rb_cString &&
+	     BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
+	return rb_str_succ(recv);
+    }
     else {
-	if (RBASIC_CLASS(recv) == rb_cString &&
-	    BASIC_OP_UNREDEFINED_P(BOP_SUCC, STRING_REDEFINED_OP_FLAG)) {
-	    return rb_str_succ(recv);
-	}
-	else {
-	    return Qundef;
-	}
+	return Qundef;
     }
 }
 
@@ -3745,4 +3682,3 @@ vm_opt_regexpmatch2(VALUE recv, VALUE ob https://github.com/ruby/ruby/blob/trunk/vm_insnhelper.c#L3682
 	return Qundef;
     }
 }
-

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

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