Ignore:
Timestamp:
Oct 26, 2007, 12:51:25 AM (18 years ago)
Author:
darin
Message:

JavaScriptCore:

Reviewed by Maciej.

Gives about 1% gain on SunSpider.

  • kjs/value.h: Added toIntegerPreserveNan, removed toUInt16. (KJS::JSValue::toInt32): Changed to call getTruncatedInt32 in a way that works with both immediate and number values. (KJS::JSValue::toUInt32): Ditto.
  • kjs/value.cpp: (KJS::JSValue::toInteger): Moved the logic from roundValue here, with a couple differences. One is that it now correctly returns 0 for NaN, and another is that there's no special case for 0 or infinity, since the general case already handles those correctly. (KJS::JSValue::toIntegerPreserveNaN): Added. Like toInteger, but without the check for NaN. (KJS::JSValue::toInt32SlowCase): Call toNumber instead of roundValue. The truncation done by the typecast already does the necessary truncation that roundValue was doing. (KJS::JSValue::toUInt32SlowCase): Ditto. (KJS::JSValue::toUInt16): Removed.
  • kjs/internal.h: Removed roundValue.
  • kjs/internal.cpp: Ditto.
  • kjs/array_object.cpp: (KJS::ArrayProtoFunc::callAsFunction): Remove unneeded code to handle NaN in Array.slice; toInteger now never returns NaN as specified.
  • kjs/date_object.cpp: (KJS::fillStructuresUsingTimeArgs): Replaced call to roundValue with a call to toNumber as specified. (KJS::DateProtoFunc::callAsFunction): In SetTime case, replaced call to roundValue with a call to toNumber and timeClip as specified. (KJS::DateObjectImp::construct): Removed unnecessary checks of numArgs in cases where the default behavior of toInt32 (returning 0) was already correct. Replaced call to roundValue with a call to toNumber as specified. (KJS::DateObjectFuncImp::callAsFunction): Ditto.
  • kjs/math_object.cpp: (MathFuncImp::callAsFunction): Removed unnecessary special cases for the pow function that the library already handles correctly.
  • kjs/number_object.cpp: (NumberProtoFunc::callAsFunction): Changed ToString to call toIntegerPreserveNaN, so we can continue to handle the NaN case differently. The real toInteger now returns 0 for NaN. Took out unneeded special case in ToFixed for undefined; was only needed because our toInteger was wrong. Same thing in ToExponential. Changed ToPrecision to call toIntegerPreserveNaN.
  • kjs/string_object.cpp: (KJS::StringProtoFunc::callAsFunction): Took out CharAt and CharCodeAt special cases for undefined that were only needed because toInteger was wrong. Same in IndexOf, and was able to remove some special cases. In LastIndexOf, used toIntegerPreserveNaN, but was able to remove some special cases there too. Changed Substr implementation to preserve correct behavior with the change to toInteger and match the specification. Also made sure we weren't converting an out of range double to an int. (KJS::StringObjectFuncImp::callAsFunction): Changed constructor to just use toUInt32, because truncating toUInt32 to 16 bits is the same thing and there's no reason to have toUInt16 as a second, less-optimized function that's only called at this one call site.
  • wtf/MathExtras.h: Added trunc function for Windows.

LayoutTests:

Reviewed by Maciej.

  • fast/js/resources/char-at.js: Updated test to expect that we get the first character if we pass NaN to charAt and charCodeAt; it's what the specification asks for and matches other browsers too.
  • fast/js/char-at-expected.txt: Updated.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/string_object.cpp

    r27011 r27095  
    458458    break;
    459459  case CharAt:
    460     // Other browsers treat an omitted parameter as 0 rather than NaN.
    461     // That doesn't match the ECMA standard, but is needed for site compatibility.
    462     dpos = a0->isUndefined() ? 0 : a0->toInteger(exec);
    463     if (dpos >= 0 && dpos < len) // false for NaN
     460    dpos = a0->toInteger(exec);
     461    if (dpos >= 0 && dpos < len)
    464462      u = s.substr(static_cast<int>(dpos), 1);
    465463    else
     
    468466    break;
    469467  case CharCodeAt:
    470     // Other browsers treat an omitted parameter as 0 rather than NaN.
    471     // That doesn't match the ECMA standard, but is needed for site compatibility.
    472     dpos = a0->isUndefined() ? 0 : a0->toInteger(exec);
    473     if (dpos >= 0 && dpos < len) // false for NaN
     468    dpos = a0->toInteger(exec);
     469    if (dpos >= 0 && dpos < len)
    474470      result = jsNumber(s[static_cast<int>(dpos)].unicode());
    475471    else
     
    486482  case IndexOf:
    487483    u2 = a0->toString(exec);
    488     if (a1->isUndefined())
     484    dpos = a1->toInteger(exec);
     485    if (dpos < 0)
    489486      dpos = 0;
    490     else {
    491       dpos = a1->toInteger(exec);
    492       if (dpos >= 0) { // false for NaN
    493         if (dpos > len)
    494           dpos = len;
    495       } else
    496         dpos = 0;
    497     }
     487    else if (dpos > len)
     488      dpos = len;
    498489    result = jsNumber(s.find(u2, static_cast<int>(dpos)));
    499490    break;
     
    501492    u2 = a0->toString(exec);
    502493    d = a1->toNumber(exec);
    503     if (a1->isUndefined() || KJS::isNaN(d))
     494    dpos = a1->toIntegerPreserveNaN(exec);
     495    if (dpos < 0)
     496      dpos = 0;
     497    else if (!(dpos <= len)) // true for NaN
    504498      dpos = len;
    505     else {
    506       dpos = a1->toInteger(exec);
    507       if (dpos >= 0) { // false for NaN
    508         if (dpos > len)
    509           dpos = len;
    510       } else
    511         dpos = 0;
    512     }
    513499    result = jsNumber(s.rfind(u2, static_cast<int>(dpos)));
    514500    break;
     
    659645    break;
    660646  case Substr: {
    661     double d = a0->toInteger(exec);
    662     double d2 = a1->toInteger(exec);
    663     if (!(d >= 0)) { // true for NaN
    664       d += len;
    665       if (!(d >= 0)) // true for NaN
    666         d = 0;
    667     }
    668     if (isNaN(d2))
    669       d2 = len - d;
    670     else {
    671       if (d2 < 0)
    672         d2 = 0;
    673       if (d2 > len - d)
    674         d2 = len - d;
    675     }
    676     result = jsString(s.substr(static_cast<int>(d), static_cast<int>(d2)));
     647    double start = a0->toInteger(exec);
     648    double length = a1->isUndefined() ? len : a1->toInteger(exec);
     649    if (start >= len)
     650      return jsString("");
     651    if (length < 0)
     652      return jsString("");
     653    if (start < 0) {
     654      start += len;
     655      if (start < 0)
     656        start = 0;
     657    }
     658    if (length > len - d)
     659      length = len - d;
     660    result = jsString(s.substr(static_cast<int>(start), static_cast<int>(length)));
    677661    break;
    678662  }
     
    853837    ListIterator it = args.begin();
    854838    while (it != args.end()) {
    855       unsigned short u = it->toUInt16(exec);
     839      unsigned short u = it->toUInt32(exec);
    856840      *p++ = UChar(u);
    857841      it++;
Note: See TracChangeset for help on using the changeset viewer.