Commit e90249bd authored by sandholm@chromium.org's avatar sandholm@chromium.org

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6181 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8669f630
......@@ -126,6 +126,7 @@ macro TO_INTEGER_MAP_MINUS_ZERO(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : %NumberToI
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.
......
......@@ -44,26 +44,26 @@ $Math.__proto__ = global.Object.prototype;
// 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 @@ function MathAtan(x) {
// 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 @@ function MathFloor(x) {
// 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 @@ function MathMax(arg1, arg2) { // length == 2
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 @@ function MathMin(arg1, arg2) { // length == 2
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 @@ function MathMin(arg1, arg2) { // length == 2
// 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 @@ function MathRandom() {
// 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);
}
......
......@@ -165,7 +165,7 @@ function ADD(x) {
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 @@ function STRING_ADD_RIGHT(y) {
// 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 @@ function MOD(y) {
// 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 @@ function BIT_AND(y) {
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 @@ function BIT_AND(y) {
// 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 @@ function SAR(y) {
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 @@ function SAR(y) {
// 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 @@ function ToNumber(x) {
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 @@ function SameValue(x, y) {
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;
if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false;
}
return x === y
return x === y;
}
......
......@@ -83,7 +83,7 @@ function GlobalIsNaN(number) {
// 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 @@ SetupObject();
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 @@ function NumberToString(radix) {
}
// 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 @@ function NewFunction(arg1) { // length == 1
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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment