Revision: 6181
Author: [email protected]
Date: Wed Jan  5 05:52:00 2011
Log: Avoid double checking for IS_NUMBER by calling NonNumToNum instead of ToNumber
when the argument is known not to be a number.
Review URL: http://codereview.chromium.org/6061008
http://code.google.com/p/v8/source/detail?r=6181

Modified:
 /branches/bleeding_edge/src/macros.py
 /branches/bleeding_edge/src/math.js
 /branches/bleeding_edge/src/runtime.js
 /branches/bleeding_edge/src/v8natives.js

=======================================
--- /branches/bleeding_edge/src/macros.py       Wed Dec 22 05:19:25 2010
+++ /branches/bleeding_edge/src/macros.py       Wed Jan  5 05:52:00 2011
@@ -126,6 +126,7 @@
 macro TO_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
 macro TO_UINT32(arg) = (arg >>> 0);
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg)); +macro TO_NUMBER_INLINE(arg) = (IS_NUMBER(%IS_VAR(arg)) ? arg : NonNumberToNumber(arg));


 # Macros implemented in Python.
=======================================
--- /branches/bleeding_edge/src/math.js Tue Dec 14 10:53:48 2010
+++ /branches/bleeding_edge/src/math.js Wed Jan  5 05:52:00 2011
@@ -44,26 +44,26 @@
 // ECMA 262 - 15.8.2.1
 function MathAbs(x) {
   if (%_IsSmi(x)) return x >= 0 ? x : -x;
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   if (x === 0) return 0;  // To handle -0.
   return x > 0 ? x : -x;
 }

 // ECMA 262 - 15.8.2.2
 function MathAcos(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_acos(x);
 }

 // ECMA 262 - 15.8.2.3
 function MathAsin(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_asin(x);
 }

 // ECMA 262 - 15.8.2.4
 function MathAtan(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_atan(x);
 }

@@ -71,32 +71,32 @@
 // The naming of y and x matches the spec, as does the order in which
 // ToNumber (valueOf) is called.
 function MathAtan2(y, x) {
-  if (!IS_NUMBER(y)) y = ToNumber(y);
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_atan2(y, x);
 }

 // ECMA 262 - 15.8.2.6
 function MathCeil(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_ceil(x);
 }

 // ECMA 262 - 15.8.2.7
 function MathCos(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %_MathCos(x);
 }

 // ECMA 262 - 15.8.2.8
 function MathExp(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_exp(x);
 }

 // ECMA 262 - 15.8.2.9
 function MathFloor(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   // It's more common to call this with a positive number that's out
   // of range than negative numbers; check the upper bound first.
   if (x < 0x80000000 && x > 0) {
@@ -112,7 +112,7 @@

 // ECMA 262 - 15.8.2.10
 function MathLog(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %_MathLog(x);
 }

@@ -123,11 +123,11 @@
     return -1/0;  // Compiler constant-folds this to -Infinity.
   }
   var r = arg1;
-  if (!IS_NUMBER(r)) r = ToNumber(r);
+  if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
   if (NUMBER_IS_NAN(r)) return r;
   for (var i = 1; i < length; i++) {
     var n = %_Arguments(i);
-    if (!IS_NUMBER(n)) n = ToNumber(n);
+    if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
     if (NUMBER_IS_NAN(n)) return n;
// Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
     // a Smi or heap number.
@@ -143,11 +143,11 @@
     return 1/0;  // Compiler constant-folds this to Infinity.
   }
   var r = arg1;
-  if (!IS_NUMBER(r)) r = ToNumber(r);
+  if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
   if (NUMBER_IS_NAN(r)) return r;
   for (var i = 1; i < length; i++) {
     var n = %_Arguments(i);
-    if (!IS_NUMBER(n)) n = ToNumber(n);
+    if (!IS_NUMBER(n)) n = NonNumberToNumber(n);
     if (NUMBER_IS_NAN(n)) return n;
// Make sure -0 is considered less than +0. -0 is never a Smi, +0 can b a
     // Smi or a heap number.
@@ -158,8 +158,8 @@

 // ECMA 262 - 15.8.2.13
 function MathPow(x, y) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
-  if (!IS_NUMBER(y)) y = ToNumber(y);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
+  if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
   return %_MathPow(x, y);
 }

@@ -170,25 +170,25 @@

 // ECMA 262 - 15.8.2.15
 function MathRound(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %RoundNumber(x);
 }

 // ECMA 262 - 15.8.2.16
 function MathSin(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %_MathSin(x);
 }

 // ECMA 262 - 15.8.2.17
 function MathSqrt(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %_MathSqrt(x);
 }

 // ECMA 262 - 15.8.2.18
 function MathTan(x) {
-  if (!IS_NUMBER(x)) x = ToNumber(x);
+  if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
   return %Math_tan(x);
 }

=======================================
--- /branches/bleeding_edge/src/runtime.js      Thu Dec 16 04:49:55 2010
+++ /branches/bleeding_edge/src/runtime.js      Wed Jan  5 05:52:00 2011
@@ -165,7 +165,7 @@
   if (IS_STRING(a)) {
     return %_StringAdd(a, %ToString(b));
   } else if (IS_STRING(b)) {
-    return %_StringAdd(%ToString(a), b);
+    return %_StringAdd(%NonStringToString(a), b);
   } else {
     return %NumberAdd(%ToNumber(a), %ToNumber(b));
   }
@@ -205,32 +205,32 @@

 // ECMA-262, section 11.6.2, page 50.
 function SUB(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberSub(x, y);
 }


 // ECMA-262, section 11.5.1, page 48.
 function MUL(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberMul(x, y);
 }


 // ECMA-262, section 11.5.2, page 49.
 function DIV(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberDiv(x, y);
 }


 // ECMA-262, section 11.5.3, page 49.
 function MOD(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberMod(x, y);
 }

@@ -243,8 +243,8 @@

 // ECMA-262, section 11.10, page 57.
 function BIT_OR(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberOr(x, y);
 }

@@ -254,14 +254,14 @@
   var x;
   if (IS_NUMBER(this)) {
     x = this;
-    if (!IS_NUMBER(y)) y = %ToNumber(y);
+    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   } else {
-    x = %ToNumber(this);
+    x = %NonNumberToNumber(this);
     // Make sure to convert the right operand to a number before
     // bailing out in the fast case, but after converting the
     // left operand. This ensures that valueOf methods on the right
     // operand are always executed.
-    if (!IS_NUMBER(y)) y = %ToNumber(y);
+    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
     // Optimize for the case where we end up AND'ing a value
     // that doesn't convert to a number. This is common in
     // certain benchmarks.
@@ -273,30 +273,30 @@

 // ECMA-262, section 11.10, page 57.
 function BIT_XOR(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberXor(x, y);
 }


 // ECMA-262, section 11.4.7, page 47.
 function UNARY_MINUS() {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
   return %NumberUnaryMinus(x);
 }


 // ECMA-262, section 11.4.8, page 48.
 function BIT_NOT() {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
   return %NumberNot(x);
 }


 // ECMA-262, section 11.7.1, page 51.
 function SHL(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberShl(x, y);
 }

@@ -306,14 +306,14 @@
   var x;
   if (IS_NUMBER(this)) {
     x = this;
-    if (!IS_NUMBER(y)) y = %ToNumber(y);
+    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   } else {
-    x = %ToNumber(this);
+    x = %NonNumberToNumber(this);
     // Make sure to convert the right operand to a number before
     // bailing out in the fast case, but after converting the
     // left operand. This ensures that valueOf methods on the right
     // operand are always executed.
-    if (!IS_NUMBER(y)) y = %ToNumber(y);
+    if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
     // Optimize for the case where we end up shifting a value
     // that doesn't convert to a number. This is common in
     // certain benchmarks.
@@ -325,8 +325,8 @@

 // ECMA-262, section 11.7.3, page 52.
 function SHR(y) {
-  var x = IS_NUMBER(this) ? this : %ToNumber(this);
-  if (!IS_NUMBER(y)) y = %ToNumber(y);
+  var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
+  if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
   return %NumberShr(x, y);
 }

@@ -511,6 +511,16 @@
   return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
 }

+function NonNumberToNumber(x) {
+  if (IS_STRING(x)) {
+    return %_HasCachedArrayIndex(x) ? %_GetCachedArrayIndex(x)
+                                    : %StringToNumber(x);
+  }
+  if (IS_BOOLEAN(x)) return x ? 1 : 0;
+  if (IS_UNDEFINED(x)) return $NaN;
+  return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(x));
+}
+

 // ECMA-262, section 9.8, page 35.
 function ToString(x) {
@@ -568,12 +578,9 @@
   if (IS_NUMBER(x)) {
     if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
     // x is +0 and y is -0 or vice versa.
-    if (x === 0 && y === 0 && (1 / x) != (1 / y)) {
-      return false;
-    }
-    return x === y;
-  }
-  return x === y
+    if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false;
+  }
+  return x === y;
 }


=======================================
--- /branches/bleeding_edge/src/v8natives.js    Thu Dec 16 04:21:08 2010
+++ /branches/bleeding_edge/src/v8natives.js    Wed Jan  5 05:52:00 2011
@@ -83,7 +83,7 @@

 // ECMA 262 - 15.1.5
 function GlobalIsFinite(number) {
-  if (!IS_NUMBER(number)) number = ToNumber(number);
+  if (!IS_NUMBER(number)) number = NonNumberToNumber(number);

// NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN.
   return %_IsSmi(number) || number - number == 0;
@@ -896,9 +896,14 @@
 function BooleanToString() {
   // NOTE: Both Boolean objects and values can enter here as
   // 'this'. This is not as dictated by ECMA-262.
-  if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this))
-    throw new $TypeError('Boolean.prototype.toString is not generic');
-  return ToString(%_ValueOf(this));
+  var b = this;
+  if (!IS_BOOLEAN(b)) {
+    if (!IS_BOOLEAN_WRAPPER(b)) {
+      throw new $TypeError('Boolean.prototype.toString is not generic');
+    }
+    b = %_ValueOf(b);
+  }
+  return b ? 'true' : 'false';
 }


@@ -951,7 +956,7 @@
   }
   // Fast case: Convert number in radix 10.
   if (IS_UNDEFINED(radix) || radix === 10) {
-    return ToString(number);
+    return %_NumberToString(number);
   }

   // Convert the radix to an integer and check the range.
@@ -1150,11 +1155,8 @@
   var p = '';
   if (n > 1) {
     p = new $Array(n - 1);
-    // Explicitly convert all parameters to strings.
-    // Array.prototype.join replaces null with empty strings which is
-    // not appropriate.
-    for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
-    p = p.join(',');
+    for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
+    p = Join(p, n - 1, ',', ToString);
     // If the formal parameters string include ) - an illegal
     // character - it may make the combined function expression
     // compile. We avoid this problem by checking for this early on.

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to