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 ...@@ -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_INT32(arg) = (%_IsSmi(%IS_VAR(arg)) ? arg : (arg >> 0));
macro TO_UINT32(arg) = (arg >>> 0); macro TO_UINT32(arg) = (arg >>> 0);
macro TO_STRING_INLINE(arg) = (IS_STRING(%IS_VAR(arg)) ? arg : NonStringToString(arg)); 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. # Macros implemented in Python.
......
...@@ -44,26 +44,26 @@ $Math.__proto__ = global.Object.prototype; ...@@ -44,26 +44,26 @@ $Math.__proto__ = global.Object.prototype;
// ECMA 262 - 15.8.2.1 // ECMA 262 - 15.8.2.1
function MathAbs(x) { function MathAbs(x) {
if (%_IsSmi(x)) return x >= 0 ? x : -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. if (x === 0) return 0; // To handle -0.
return x > 0 ? x : -x; return x > 0 ? x : -x;
} }
// ECMA 262 - 15.8.2.2 // ECMA 262 - 15.8.2.2
function MathAcos(x) { function MathAcos(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_acos(x); return %Math_acos(x);
} }
// ECMA 262 - 15.8.2.3 // ECMA 262 - 15.8.2.3
function MathAsin(x) { function MathAsin(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_asin(x); return %Math_asin(x);
} }
// ECMA 262 - 15.8.2.4 // ECMA 262 - 15.8.2.4
function MathAtan(x) { function MathAtan(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_atan(x); return %Math_atan(x);
} }
...@@ -71,32 +71,32 @@ function MathAtan(x) { ...@@ -71,32 +71,32 @@ function MathAtan(x) {
// The naming of y and x matches the spec, as does the order in which // The naming of y and x matches the spec, as does the order in which
// ToNumber (valueOf) is called. // ToNumber (valueOf) is called.
function MathAtan2(y, x) { function MathAtan2(y, x) {
if (!IS_NUMBER(y)) y = ToNumber(y); if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_atan2(y, x); return %Math_atan2(y, x);
} }
// ECMA 262 - 15.8.2.6 // ECMA 262 - 15.8.2.6
function MathCeil(x) { function MathCeil(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_ceil(x); return %Math_ceil(x);
} }
// ECMA 262 - 15.8.2.7 // ECMA 262 - 15.8.2.7
function MathCos(x) { function MathCos(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %_MathCos(x); return %_MathCos(x);
} }
// ECMA 262 - 15.8.2.8 // ECMA 262 - 15.8.2.8
function MathExp(x) { function MathExp(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_exp(x); return %Math_exp(x);
} }
// ECMA 262 - 15.8.2.9 // ECMA 262 - 15.8.2.9
function MathFloor(x) { 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 // It's more common to call this with a positive number that's out
// of range than negative numbers; check the upper bound first. // of range than negative numbers; check the upper bound first.
if (x < 0x80000000 && x > 0) { if (x < 0x80000000 && x > 0) {
...@@ -112,7 +112,7 @@ function MathFloor(x) { ...@@ -112,7 +112,7 @@ function MathFloor(x) {
// ECMA 262 - 15.8.2.10 // ECMA 262 - 15.8.2.10
function MathLog(x) { function MathLog(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %_MathLog(x); return %_MathLog(x);
} }
...@@ -123,11 +123,11 @@ function MathMax(arg1, arg2) { // length == 2 ...@@ -123,11 +123,11 @@ function MathMax(arg1, arg2) { // length == 2
return -1/0; // Compiler constant-folds this to -Infinity. return -1/0; // Compiler constant-folds this to -Infinity.
} }
var r = arg1; var r = arg1;
if (!IS_NUMBER(r)) r = ToNumber(r); if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
if (NUMBER_IS_NAN(r)) return r; if (NUMBER_IS_NAN(r)) return r;
for (var i = 1; i < length; i++) { for (var i = 1; i < length; i++) {
var n = %_Arguments(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; if (NUMBER_IS_NAN(n)) return n;
// Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be // Make sure +0 is considered greater than -0. -0 is never a Smi, +0 can be
// a Smi or heap number. // a Smi or heap number.
...@@ -143,11 +143,11 @@ function MathMin(arg1, arg2) { // length == 2 ...@@ -143,11 +143,11 @@ function MathMin(arg1, arg2) { // length == 2
return 1/0; // Compiler constant-folds this to Infinity. return 1/0; // Compiler constant-folds this to Infinity.
} }
var r = arg1; var r = arg1;
if (!IS_NUMBER(r)) r = ToNumber(r); if (!IS_NUMBER(r)) r = NonNumberToNumber(r);
if (NUMBER_IS_NAN(r)) return r; if (NUMBER_IS_NAN(r)) return r;
for (var i = 1; i < length; i++) { for (var i = 1; i < length; i++) {
var n = %_Arguments(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; if (NUMBER_IS_NAN(n)) return n;
// Make sure -0 is considered less than +0. -0 is never a Smi, +0 can b a // Make sure -0 is considered less than +0. -0 is never a Smi, +0 can b a
// Smi or a heap number. // Smi or a heap number.
...@@ -158,8 +158,8 @@ function MathMin(arg1, arg2) { // length == 2 ...@@ -158,8 +158,8 @@ function MathMin(arg1, arg2) { // length == 2
// ECMA 262 - 15.8.2.13 // ECMA 262 - 15.8.2.13
function MathPow(x, y) { function MathPow(x, y) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
if (!IS_NUMBER(y)) y = ToNumber(y); if (!IS_NUMBER(y)) y = NonNumberToNumber(y);
return %_MathPow(x, y); return %_MathPow(x, y);
} }
...@@ -170,25 +170,25 @@ function MathRandom() { ...@@ -170,25 +170,25 @@ function MathRandom() {
// ECMA 262 - 15.8.2.15 // ECMA 262 - 15.8.2.15
function MathRound(x) { function MathRound(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %RoundNumber(x); return %RoundNumber(x);
} }
// ECMA 262 - 15.8.2.16 // ECMA 262 - 15.8.2.16
function MathSin(x) { function MathSin(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %_MathSin(x); return %_MathSin(x);
} }
// ECMA 262 - 15.8.2.17 // ECMA 262 - 15.8.2.17
function MathSqrt(x) { function MathSqrt(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %_MathSqrt(x); return %_MathSqrt(x);
} }
// ECMA 262 - 15.8.2.18 // ECMA 262 - 15.8.2.18
function MathTan(x) { function MathTan(x) {
if (!IS_NUMBER(x)) x = ToNumber(x); if (!IS_NUMBER(x)) x = NonNumberToNumber(x);
return %Math_tan(x); return %Math_tan(x);
} }
......
...@@ -165,7 +165,7 @@ function ADD(x) { ...@@ -165,7 +165,7 @@ function ADD(x) {
if (IS_STRING(a)) { if (IS_STRING(a)) {
return %_StringAdd(a, %ToString(b)); return %_StringAdd(a, %ToString(b));
} else if (IS_STRING(b)) { } else if (IS_STRING(b)) {
return %_StringAdd(%ToString(a), b); return %_StringAdd(%NonStringToString(a), b);
} else { } else {
return %NumberAdd(%ToNumber(a), %ToNumber(b)); return %NumberAdd(%ToNumber(a), %ToNumber(b));
} }
...@@ -205,32 +205,32 @@ function STRING_ADD_RIGHT(y) { ...@@ -205,32 +205,32 @@ function STRING_ADD_RIGHT(y) {
// ECMA-262, section 11.6.2, page 50. // ECMA-262, section 11.6.2, page 50.
function SUB(y) { function SUB(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberSub(x, y); return %NumberSub(x, y);
} }
// ECMA-262, section 11.5.1, page 48. // ECMA-262, section 11.5.1, page 48.
function MUL(y) { function MUL(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberMul(x, y); return %NumberMul(x, y);
} }
// ECMA-262, section 11.5.2, page 49. // ECMA-262, section 11.5.2, page 49.
function DIV(y) { function DIV(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberDiv(x, y); return %NumberDiv(x, y);
} }
// ECMA-262, section 11.5.3, page 49. // ECMA-262, section 11.5.3, page 49.
function MOD(y) { function MOD(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberMod(x, y); return %NumberMod(x, y);
} }
...@@ -243,8 +243,8 @@ function MOD(y) { ...@@ -243,8 +243,8 @@ function MOD(y) {
// ECMA-262, section 11.10, page 57. // ECMA-262, section 11.10, page 57.
function BIT_OR(y) { function BIT_OR(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberOr(x, y); return %NumberOr(x, y);
} }
...@@ -254,14 +254,14 @@ function BIT_AND(y) { ...@@ -254,14 +254,14 @@ function BIT_AND(y) {
var x; var x;
if (IS_NUMBER(this)) { if (IS_NUMBER(this)) {
x = this; x = this;
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
} else { } else {
x = %ToNumber(this); x = %NonNumberToNumber(this);
// Make sure to convert the right operand to a number before // Make sure to convert the right operand to a number before
// bailing out in the fast case, but after converting the // bailing out in the fast case, but after converting the
// left operand. This ensures that valueOf methods on the right // left operand. This ensures that valueOf methods on the right
// operand are always executed. // 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 // Optimize for the case where we end up AND'ing a value
// that doesn't convert to a number. This is common in // that doesn't convert to a number. This is common in
// certain benchmarks. // certain benchmarks.
...@@ -273,30 +273,30 @@ function BIT_AND(y) { ...@@ -273,30 +273,30 @@ function BIT_AND(y) {
// ECMA-262, section 11.10, page 57. // ECMA-262, section 11.10, page 57.
function BIT_XOR(y) { function BIT_XOR(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberXor(x, y); return %NumberXor(x, y);
} }
// ECMA-262, section 11.4.7, page 47. // ECMA-262, section 11.4.7, page 47.
function UNARY_MINUS() { function UNARY_MINUS() {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
return %NumberUnaryMinus(x); return %NumberUnaryMinus(x);
} }
// ECMA-262, section 11.4.8, page 48. // ECMA-262, section 11.4.8, page 48.
function BIT_NOT() { function BIT_NOT() {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
return %NumberNot(x); return %NumberNot(x);
} }
// ECMA-262, section 11.7.1, page 51. // ECMA-262, section 11.7.1, page 51.
function SHL(y) { function SHL(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberShl(x, y); return %NumberShl(x, y);
} }
...@@ -306,14 +306,14 @@ function SAR(y) { ...@@ -306,14 +306,14 @@ function SAR(y) {
var x; var x;
if (IS_NUMBER(this)) { if (IS_NUMBER(this)) {
x = this; x = this;
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
} else { } else {
x = %ToNumber(this); x = %NonNumberToNumber(this);
// Make sure to convert the right operand to a number before // Make sure to convert the right operand to a number before
// bailing out in the fast case, but after converting the // bailing out in the fast case, but after converting the
// left operand. This ensures that valueOf methods on the right // left operand. This ensures that valueOf methods on the right
// operand are always executed. // 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 // Optimize for the case where we end up shifting a value
// that doesn't convert to a number. This is common in // that doesn't convert to a number. This is common in
// certain benchmarks. // certain benchmarks.
...@@ -325,8 +325,8 @@ function SAR(y) { ...@@ -325,8 +325,8 @@ function SAR(y) {
// ECMA-262, section 11.7.3, page 52. // ECMA-262, section 11.7.3, page 52.
function SHR(y) { function SHR(y) {
var x = IS_NUMBER(this) ? this : %ToNumber(this); var x = IS_NUMBER(this) ? this : %NonNumberToNumber(this);
if (!IS_NUMBER(y)) y = %ToNumber(y); if (!IS_NUMBER(y)) y = %NonNumberToNumber(y);
return %NumberShr(x, y); return %NumberShr(x, y);
} }
...@@ -511,6 +511,16 @@ function ToNumber(x) { ...@@ -511,6 +511,16 @@ function ToNumber(x) {
return (IS_NULL(x)) ? 0 : ToNumber(%DefaultNumber(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. // ECMA-262, section 9.8, page 35.
function ToString(x) { function ToString(x) {
...@@ -568,12 +578,9 @@ function SameValue(x, y) { ...@@ -568,12 +578,9 @@ function SameValue(x, y) {
if (IS_NUMBER(x)) { if (IS_NUMBER(x)) {
if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true; if (NUMBER_IS_NAN(x) && NUMBER_IS_NAN(y)) return true;
// x is +0 and y is -0 or vice versa. // x is +0 and y is -0 or vice versa.
if (x === 0 && y === 0 && (1 / x) != (1 / y)) { if (x === 0 && y === 0 && (1 / x) != (1 / y)) return false;
return false;
}
return x === y;
} }
return x === y return x === y;
} }
......
...@@ -83,7 +83,7 @@ function GlobalIsNaN(number) { ...@@ -83,7 +83,7 @@ function GlobalIsNaN(number) {
// ECMA 262 - 15.1.5 // ECMA 262 - 15.1.5
function GlobalIsFinite(number) { 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. // NaN - NaN == NaN, Infinity - Infinity == NaN, -Infinity - -Infinity == NaN.
return %_IsSmi(number) || number - number == 0; return %_IsSmi(number) || number - number == 0;
...@@ -896,9 +896,14 @@ SetupObject(); ...@@ -896,9 +896,14 @@ SetupObject();
function BooleanToString() { function BooleanToString() {
// NOTE: Both Boolean objects and values can enter here as // NOTE: Both Boolean objects and values can enter here as
// 'this'. This is not as dictated by ECMA-262. // 'this'. This is not as dictated by ECMA-262.
if (!IS_BOOLEAN(this) && !IS_BOOLEAN_WRAPPER(this)) var b = this;
throw new $TypeError('Boolean.prototype.toString is not generic'); if (!IS_BOOLEAN(b)) {
return ToString(%_ValueOf(this)); 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) { ...@@ -951,7 +956,7 @@ function NumberToString(radix) {
} }
// Fast case: Convert number in radix 10. // Fast case: Convert number in radix 10.
if (IS_UNDEFINED(radix) || radix === 10) { if (IS_UNDEFINED(radix) || radix === 10) {
return ToString(number); return %_NumberToString(number);
} }
// Convert the radix to an integer and check the range. // Convert the radix to an integer and check the range.
...@@ -1150,11 +1155,8 @@ function NewFunction(arg1) { // length == 1 ...@@ -1150,11 +1155,8 @@ function NewFunction(arg1) { // length == 1
var p = ''; var p = '';
if (n > 1) { if (n > 1) {
p = new $Array(n - 1); p = new $Array(n - 1);
// Explicitly convert all parameters to strings. for (var i = 0; i < n - 1; i++) p[i] = %_Arguments(i);
// Array.prototype.join replaces null with empty strings which is p = Join(p, n - 1, ',', ToString);
// not appropriate.
for (var i = 0; i < n - 1; i++) p[i] = ToString(%_Arguments(i));
p = p.join(',');
// If the formal parameters string include ) - an illegal // If the formal parameters string include ) - an illegal
// character - it may make the combined function expression // character - it may make the combined function expression
// compile. We avoid this problem by checking for this early on. // 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