| Index: src/runtime.js | 
| =================================================================== | 
| --- src/runtime.js	(revision 457) | 
| +++ src/runtime.js	(working copy) | 
| @@ -52,36 +52,31 @@ | 
|  | 
| // ECMA-262, section 11.9.1, page 55. | 
| function EQUALS(y) { | 
| +  if (IS_STRING(this) && IS_STRING(y)) return %StringEquals(this, y); | 
| var x = this; | 
|  | 
| // NOTE: We use iteration instead of recursion, because it is | 
| // difficult to call EQUALS with the correct setting of 'this' in | 
| // an efficient way. | 
| - | 
| while (true) { | 
| - | 
| if (IS_NUMBER(x)) { | 
| if (y == null) return 1;  // not equal | 
| return %NumberEquals(x, %ToNumber(y)); | 
| - | 
| } else if (IS_STRING(x)) { | 
| if (IS_STRING(y)) return %StringEquals(x, y); | 
| if (IS_NUMBER(y)) return %NumberEquals(%ToNumber(x), y); | 
| if (IS_BOOLEAN(y)) return %NumberEquals(%ToNumber(x), %ToNumber(y)); | 
| if (y == null) return 1;  // not equal | 
| y = %ToPrimitive(y, NO_HINT); | 
| - | 
| } else if (IS_BOOLEAN(x)) { | 
| if (IS_BOOLEAN(y)) { | 
| return %_ObjectEquals(x, y) ? 0 : 1; | 
| } | 
| if (y == null) return 1;  // not equal | 
| return %NumberEquals(%ToNumber(x), %ToNumber(y)); | 
| - | 
| } else if (x == null) { | 
| // NOTE: This checks for both null and undefined. | 
| return (y == null) ? 0 : 1; | 
| - | 
| } else { | 
| if (IS_OBJECT(y)) { | 
| return %_ObjectEquals(x, y) ? 0 : 1; | 
| @@ -90,12 +85,10 @@ | 
| return %_ObjectEquals(x, y) ? 0 : 1; | 
| } | 
| x = %ToPrimitive(x, NO_HINT); | 
| - | 
| } | 
| } | 
| } | 
|  | 
| - | 
| // ECMA-262, section 11.9.4, page 56. | 
| function STRICT_EQUALS(x) { | 
| if (IS_NUMBER(this)) { | 
| @@ -125,11 +118,15 @@ | 
| // ECMA-262, section 11.8.5, page 53. The 'ncr' parameter is used as | 
| // the result when either (or both) the operands are NaN. | 
| function COMPARE(x, ncr) { | 
| -  // Improve performance for floating point compares | 
| +  // Fast case for numbers and strings. | 
| if (IS_NUMBER(this) && IS_NUMBER(x)) { | 
| return %NumberCompare(this, x, ncr); | 
| } | 
| +  if (IS_STRING(this) && IS_STRING(x)) { | 
| +    return %StringCompare(this, x); | 
| +  } | 
|  | 
| +  // Default implementation. | 
| var a = %ToPrimitive(this, NUMBER_HINT); | 
| var b = %ToPrimitive(x, NUMBER_HINT); | 
| if (IS_STRING(a) && IS_STRING(b)) { | 
| @@ -149,10 +146,10 @@ | 
| // ECMA-262, section 11.6.1, page 50. | 
| function ADD(x) { | 
| // Fast case: Check for number operands and do the addition. | 
| -  if (IS_NUMBER(this) && IS_NUMBER(x)) { | 
| -    return %NumberAdd(this, x); | 
| -  } | 
| +  if (IS_NUMBER(this) && IS_NUMBER(x)) return %NumberAdd(this, x); | 
| +  if (IS_STRING(this) && IS_STRING(x)) return %StringAdd(this, x); | 
|  | 
| +  // Default implementation. | 
| var a = %ToPrimitive(this, NO_HINT); | 
| var b = %ToPrimitive(x, NO_HINT); | 
|  | 
| @@ -397,6 +394,10 @@ | 
| // ECMA-262, section 9.1, page 30. Use null/undefined for no hint, | 
| // (1) for number hint, and (2) for string hint. | 
| function ToPrimitive(x, hint) { | 
| +  // Fast case check. | 
| +  if (IS_STRING(x)) return x; | 
| +  if ((hint != NUMBER_HINT) && %IsStringClass(x)) return %_ValueOf(x); | 
| +  // Normal behaior. | 
| if (!IS_OBJECT(x) && !IS_FUNCTION(x)) return x; | 
| if (x == null) return x;  // check for null, undefined | 
| if (hint == NO_HINT) hint = (IS_DATE(x)) ? STRING_HINT : NUMBER_HINT; | 
|  |