- Revision
- 113396
- Author
- [email protected]
- Date
- 2012-04-05 17:12:25 -0700 (Thu, 05 Apr 2012)
Log 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 <[email protected]> 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):
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (113395 => 113396)
--- trunk/Source/_javascript_Core/ChangeLog 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/ChangeLog 2012-04-06 00:12:25 UTC (rev 113396)
@@ -1,5 +1,41 @@
2012-04-05 Benjamin Poulain <[email protected]>
+ Speed up the conversion from JSValue to String for bulk operations
+ https://bugs.webkit.org/show_bug.cgi?id=83243
+
+ 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):
+
+2012-04-05 Benjamin Poulain <[email protected]>
+
Use QuickSort when sorting primitive values by string representation
https://bugs.webkit.org/show_bug.cgi?id=83312
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2012-04-06 00:12:25 UTC (rev 113396)
@@ -281,7 +281,7 @@
if (element.isUndefinedOrNull())
continue;
- UString str = element.toString(exec)->value(exec);
+ UString str = element.toUString(exec);
strBuffer[k] = str.impl();
totalSize += str.length();
allStrings8Bit = allStrings8Bit && str.is8Bit();
@@ -358,9 +358,9 @@
CallData callData;
CallType callType = getCallData(conversionFunction, callData);
if (callType != CallTypeNone)
- str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec);
+ str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toUString(exec);
else
- str = element.toString(exec)->value(exec);
+ str = element.toUString(exec);
if (exec->hadException())
return JSValue::encode(jsUndefined());
stringJoiner.append(str);
@@ -383,7 +383,7 @@
UString separator;
if (!exec->argument(0).isUndefined())
- separator = exec->argument(0).toString(exec)->value(exec);
+ separator = exec->argument(0).toUString(exec);
if (separator.isNull())
separator = UString(",");
@@ -399,7 +399,7 @@
JSValue element = array->getIndex(k);
if (!element.isUndefinedOrNull())
- stringJoiner.append(element.toString(exec)->value(exec));
+ stringJoiner.append(element.toUStringInline(exec));
else
stringJoiner.append(UString());
}
@@ -408,7 +408,7 @@
for (; k < length; k++) {
JSValue element = thisObj->get(exec, k);
if (!element.isUndefinedOrNull())
- stringJoiner.append(element.toString(exec)->value(exec));
+ stringJoiner.append(element.toUStringInline(exec));
else
stringJoiner.append(UString());
}
@@ -501,7 +501,7 @@
thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true);
else {
PutPropertySlot slot;
- Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec));
+ Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toUString(exec));
thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot);
}
if (exec->hadException())
@@ -642,7 +642,7 @@
l.append(minObj);
compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec);
} else
- compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1;
+ compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1;
if (compareResult < 0) {
themin = j;
Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h 2012-04-06 00:12:25 UTC (rev 113396)
@@ -76,6 +76,7 @@
#define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \
macro(null) \
+ macro(undefined) \
macro(true) \
macro(false) \
macro(break) \
Modified: trunk/Source/_javascript_Core/runtime/JSArray.cpp (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/JSArray.cpp 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSArray.cpp 2012-04-06 00:12:25 UTC (rev 113396)
@@ -1487,7 +1487,7 @@
// a toString call raises an exception.
for (size_t i = 0; i < lengthNotIncludingUndefined; i++)
- values[i].second = values[i].first.toString(exec)->value(exec);
+ values[i].second = values[i].first.toUStringInline(exec);
if (exec->hadException()) {
Heap::heap(this)->popTempSortVector(&values);
Modified: trunk/Source/_javascript_Core/runtime/JSString.h (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/JSString.h 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSString.h 2012-04-06 00:12:25 UTC (rev 113396)
@@ -462,6 +462,39 @@
return toStringSlowCase(exec);
}
+ inline UString JSValue::toUString(ExecState* exec) const
+ {
+ if (isString())
+ return static_cast<JSString*>(asCell())->value(exec);
+ return toUStringSlowCase(exec);
+ }
+
+ ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec)
+ {
+ JSGlobalData& globalData = exec->globalData();
+ if (value.isInt32())
+ return globalData.numericStrings.add(value.asInt32());
+ if (value.isDouble())
+ return globalData.numericStrings.add(value.asDouble());
+ if (value.isTrue())
+ return globalData.propertyNames->trueKeyword.ustring();
+ if (value.isFalse())
+ return globalData.propertyNames->falseKeyword.ustring();
+ if (value.isNull())
+ return globalData.propertyNames->nullKeyword.ustring();
+ if (value.isUndefined())
+ return globalData.propertyNames->undefinedKeyword.ustring();
+ return value.toString(exec)->value(exec);
+ }
+
+ ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const
+ {
+ if (isString())
+ return static_cast<JSString*>(asCell())->value(exec);
+
+ return inlineJSValueNotStringtoUString(*this, exec);
+ }
+
} // namespace JSC
#endif // JSString_h
Modified: trunk/Source/_javascript_Core/runtime/JSValue.cpp (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/JSValue.cpp 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSValue.cpp 2012-04-06 00:12:25 UTC (rev 113396)
@@ -283,4 +283,9 @@
return value.toString(exec);
}
+UString JSValue::toUStringSlowCase(ExecState* exec) const
+{
+ return inlineJSValueNotStringtoUString(*this, exec);
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSValue.h (113395 => 113396)
--- trunk/Source/_javascript_Core/runtime/JSValue.h 2012-04-05 23:54:06 UTC (rev 113395)
+++ trunk/Source/_javascript_Core/runtime/JSValue.h 2012-04-06 00:12:25 UTC (rev 113396)
@@ -203,6 +203,8 @@
// been set in the ExecState already.
double toNumber(ExecState*) const;
JSString* toString(ExecState*) const;
+ UString toUString(ExecState*) const;
+ UString toUStringInline(ExecState*) const;
JSObject* toObject(ExecState*) const;
JSObject* toObject(ExecState*, JSGlobalObject*) const;
@@ -251,6 +253,7 @@
inline const JSValue asValue() const { return *this; }
JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const;
JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const;
+ JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const;
JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const;
JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const;