Changeset 113396 in webkit


Ignore:
Timestamp:
Apr 5, 2012 5:12:25 PM (12 years ago)
Author:
benjamin@webkit.org
Message:

Speed up the conversion from JSValue to String for bulk operations
https://bugs.webkit.org/show_bug.cgi?id=83243

Patch by Benjamin Poulain <bpoulain@apple.com> on 2012-04-05
Reviewed by Geoffrey Garen.

When making operations on primitive types, we loose some time converting
values to JSString in order to extract the string.

This patch speeds up some basic Array operations by avoiding the creation
of intermediary JSString when possible.

For the cases where we need to convert a lot of JSValue in a tight loop,
an inline conversion is used.

  • runtime/ArrayPrototype.cpp:

(JSC::arrayProtoFuncToString):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncJoin):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncSort):

  • runtime/CommonIdentifiers.h:
  • runtime/JSArray.cpp:

(JSC::JSArray::sort):

  • runtime/JSString.h:

(JSC::JSValue::toUString):
(JSC):
(JSC::inlineJSValueNotStringtoUString):
(JSC::JSValue::toUStringInline):

  • runtime/JSValue.cpp:

(JSC::JSValue::toUStringSlowCase):
(JSC):

  • runtime/JSValue.h:

(JSValue):

Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r113391 r113396  
     12012-04-05  Benjamin Poulain  <bpoulain@apple.com>
     2
     3        Speed up the conversion from JSValue to String for bulk operations
     4        https://bugs.webkit.org/show_bug.cgi?id=83243
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        When making operations on primitive types, we loose some time converting
     9        values to JSString in order to extract the string.
     10
     11        This patch speeds up some basic Array operations by avoiding the creation
     12        of intermediary JSString when possible.
     13
     14        For the cases where we need to convert a lot of JSValue in a tight loop,
     15        an inline conversion is used.
     16
     17        * runtime/ArrayPrototype.cpp:
     18        (JSC::arrayProtoFuncToString):
     19        (JSC::arrayProtoFuncToLocaleString):
     20        (JSC::arrayProtoFuncJoin):
     21        (JSC::arrayProtoFuncPush):
     22        (JSC::arrayProtoFuncSort):
     23        * runtime/CommonIdentifiers.h:
     24        * runtime/JSArray.cpp:
     25        (JSC::JSArray::sort):
     26        * runtime/JSString.h:
     27        (JSC::JSValue::toUString):
     28        (JSC):
     29        (JSC::inlineJSValueNotStringtoUString):
     30        (JSC::JSValue::toUStringInline):
     31        * runtime/JSValue.cpp:
     32        (JSC::JSValue::toUStringSlowCase):
     33        (JSC):
     34        * runtime/JSValue.h:
     35        (JSValue):
     36
    1372012-04-05  Benjamin Poulain  <bpoulain@apple.com>
    238
  • trunk/Source/JavaScriptCore/runtime/ArrayPrototype.cpp

    r113355 r113396  
    282282            continue;
    283283       
    284         UString str = element.toString(exec)->value(exec);
     284        UString str = element.toUString(exec);
    285285        strBuffer[k] = str.impl();
    286286        totalSize += str.length();
     
    359359            CallType callType = getCallData(conversionFunction, callData);
    360360            if (callType != CallTypeNone)
    361                 str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
     361                str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toUString(exec);
    362362            else
    363                 str = element.toString(exec)->value(exec);
     363                str = element.toUString(exec);
    364364            if (exec->hadException())
    365365                return JSValue::encode(jsUndefined());
     
    384384    UString separator;
    385385    if (!exec->argument(0).isUndefined())
    386         separator = exec->argument(0).toString(exec)->value(exec);
     386        separator = exec->argument(0).toUString(exec);
    387387    if (separator.isNull())
    388388        separator = UString(",");
     
    400400            JSValue element = array->getIndex(k);
    401401            if (!element.isUndefinedOrNull())
    402                 stringJoiner.append(element.toString(exec)->value(exec));
     402                stringJoiner.append(element.toUStringInline(exec));
    403403            else
    404404                stringJoiner.append(UString());
     
    409409        JSValue element = thisObj->get(exec, k);
    410410        if (!element.isUndefinedOrNull())
    411             stringJoiner.append(element.toString(exec)->value(exec));
     411            stringJoiner.append(element.toUStringInline(exec));
    412412        else
    413413            stringJoiner.append(UString());
     
    502502        else {
    503503            PutPropertySlot slot;
    504             Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
     504            Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toUString(exec));
    505505            thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
    506506        }
     
    643643                compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
    644644            } else
    645                 compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1;
     645                compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1;
    646646
    647647            if (compareResult < 0) {
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r111433 r113396  
    7777#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
    7878    macro(null) \
     79    macro(undefined) \
    7980    macro(true) \
    8081    macro(false) \
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r113391 r113396  
    14881488
    14891489    for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
    1490         values[i].second = values[i].first.toString(exec)->value(exec);
     1490        values[i].second = values[i].first.toUStringInline(exec);
    14911491
    14921492    if (exec->hadException()) {
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r113363 r113396  
    463463    }
    464464
     465    inline UString JSValue::toUString(ExecState* exec) const
     466    {
     467        if (isString())
     468            return static_cast<JSString*>(asCell())->value(exec);
     469        return toUStringSlowCase(exec);
     470    }
     471
     472    ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec)
     473    {
     474        JSGlobalData& globalData = exec->globalData();
     475        if (value.isInt32())
     476            return globalData.numericStrings.add(value.asInt32());
     477        if (value.isDouble())
     478            return globalData.numericStrings.add(value.asDouble());
     479        if (value.isTrue())
     480            return globalData.propertyNames->trueKeyword.ustring();
     481        if (value.isFalse())
     482            return globalData.propertyNames->falseKeyword.ustring();
     483        if (value.isNull())
     484            return globalData.propertyNames->nullKeyword.ustring();
     485        if (value.isUndefined())
     486            return globalData.propertyNames->undefinedKeyword.ustring();
     487        return value.toString(exec)->value(exec);
     488    }
     489
     490    ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const
     491    {
     492        if (isString())
     493            return static_cast<JSString*>(asCell())->value(exec);
     494
     495        return inlineJSValueNotStringtoUString(*this, exec);
     496    }
     497
    465498} // namespace JSC
    466499
  • trunk/Source/JavaScriptCore/runtime/JSValue.cpp

    r111433 r113396  
    284284}
    285285
     286UString JSValue::toUStringSlowCase(ExecState* exec) const
     287{
     288    return inlineJSValueNotStringtoUString(*this, exec);
     289}
     290
    286291} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSValue.h

    r111739 r113396  
    204204        double toNumber(ExecState*) const;
    205205        JSString* toString(ExecState*) const;
     206        UString toUString(ExecState*) const;
     207        UString toUStringInline(ExecState*) const;
    206208        JSObject* toObject(ExecState*) const;
    207209        JSObject* toObject(ExecState*, JSGlobalObject*) const;
     
    252254        JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
    253255        JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
     256        JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const;
    254257        JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
    255258        JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;
Note: See TracChangeset for help on using the changeset viewer.