Diff
Modified: trunk/JSTests/ChangeLog (223833 => 223834)
--- trunk/JSTests/ChangeLog 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/JSTests/ChangeLog 2017-10-23 11:50:21 UTC (rev 223834)
@@ -1,3 +1,17 @@
+2017-10-23 Yusuke Suzuki <utatane....@gmail.com>
+
+ [JSC] Use fastJoin in Array#toString
+ https://bugs.webkit.org/show_bug.cgi?id=178062
+
+ Reviewed by Darin Adler.
+
+ * microbenchmarks/contiguous-array-to-string.js: Added.
+ (target):
+ * microbenchmarks/double-array-to-string.js: Added.
+ (target):
+ * microbenchmarks/int32-array-to-string.js: Added.
+ (target):
+
2017-10-22 Zan Dobersek <zdober...@igalia.com>
stress/check-string-ident.js is improperly skipped
Added: trunk/JSTests/microbenchmarks/contiguous-array-to-string.js (0 => 223834)
--- trunk/JSTests/microbenchmarks/contiguous-array-to-string.js (rev 0)
+++ trunk/JSTests/microbenchmarks/contiguous-array-to-string.js 2017-10-23 11:50:21 UTC (rev 223834)
@@ -0,0 +1,12 @@
+var array = [];
+for (var i = 0; i < 20; ++i)
+ array.push(`${i}`);
+
+function target(array)
+{
+ return array.toString();
+}
+noInline(target);
+
+for (var i = 0; i < 1e5; ++i)
+ target(array);
Added: trunk/JSTests/microbenchmarks/double-array-to-string.js (0 => 223834)
--- trunk/JSTests/microbenchmarks/double-array-to-string.js (rev 0)
+++ trunk/JSTests/microbenchmarks/double-array-to-string.js 2017-10-23 11:50:21 UTC (rev 223834)
@@ -0,0 +1,12 @@
+var array = [];
+for (var i = 0; i < 20; ++i)
+ array.push(i * 0.1);
+
+function target(array)
+{
+ return array.toString();
+}
+noInline(target);
+
+for (var i = 0; i < 1e5; ++i)
+ target(array);
Added: trunk/JSTests/microbenchmarks/int32-array-to-string.js (0 => 223834)
--- trunk/JSTests/microbenchmarks/int32-array-to-string.js (rev 0)
+++ trunk/JSTests/microbenchmarks/int32-array-to-string.js 2017-10-23 11:50:21 UTC (rev 223834)
@@ -0,0 +1,12 @@
+var array = [];
+for (var i = 0; i < 20; ++i)
+ array.push(i);
+
+function target(array)
+{
+ return array.toString();
+}
+noInline(target);
+
+for (var i = 0; i < 1e5; ++i)
+ target(array);
Added: trunk/JSTests/stress/array-to-locale-string.js (0 => 223834)
--- trunk/JSTests/stress/array-to-locale-string.js (rev 0)
+++ trunk/JSTests/stress/array-to-locale-string.js 2017-10-23 11:50:21 UTC (rev 223834)
@@ -0,0 +1,7 @@
+function shouldBe(actual, expected) {
+ if (actual !== expected)
+ throw new Error('bad value: ' + actual);
+}
+
+var array = [null, null, null];
+shouldBe(array.toLocaleString(), `,,`)
Modified: trunk/Source/_javascript_Core/ChangeLog (223833 => 223834)
--- trunk/Source/_javascript_Core/ChangeLog 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-10-23 11:50:21 UTC (rev 223834)
@@ -1,3 +1,32 @@
+2017-10-23 Yusuke Suzuki <utatane....@gmail.com>
+
+ [JSC] Use fastJoin in Array#toString
+ https://bugs.webkit.org/show_bug.cgi?id=178062
+
+ Reviewed by Darin Adler.
+
+ Array#toString()'s fast path uses original join operation.
+ But this should use fastJoin if possible.
+ This patch adds a fast path using fastJoin in Array#toString.
+ And we also extend fastJoin to perform fast joining for int32
+ arrays.
+
+ baseline patched
+
+ double-array-to-string 126.6157+-5.8625 ^ 103.7343+-4.4968 ^ definitely 1.2206x faster
+ int32-array-to-string 64.7792+-2.6524 61.2390+-2.1749 might be 1.0578x faster
+ contiguous-array-to-string 62.6224+-2.6388 ^ 56.9899+-2.0852 ^ definitely 1.0988x faster
+
+
+ * runtime/ArrayPrototype.cpp:
+ (JSC::fastJoin):
+ (JSC::arrayProtoFuncToString):
+ (JSC::arrayProtoFuncToLocaleString):
+ * runtime/JSStringJoiner.h:
+ (JSC::JSStringJoiner::appendWithoutSideEffects):
+ (JSC::JSStringJoiner::appendInt32):
+ (JSC::JSStringJoiner::appendDouble):
+
2017-10-22 Zan Dobersek <zdober...@igalia.com>
[JSC] Remove !(OS(LINUX) && CPU(ARM64)) guards in RegisterState.h
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (223833 => 223834)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2017-10-23 11:50:21 UTC (rev 223834)
@@ -380,6 +380,9 @@
}
}
+static bool canUseFastJoin(const JSObject*);
+static JSValue fastJoin(ExecState&, JSObject*, StringView, unsigned);
+
EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec)
{
VM& vm = exec->vm();
@@ -424,6 +427,12 @@
if (JSValue earlyReturnValue = checker.earlyReturnValue())
return JSValue::encode(earlyReturnValue);
+ if (LIKELY(canUseFastJoin(thisArray))) {
+ const LChar comma = ',';
+ scope.release();
+ return JSValue::encode(fastJoin(*exec, thisArray, { &comma, 1 }, length));
+ }
+
JSStringJoiner joiner(*exec, ',', length);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -462,6 +471,7 @@
#if ENABLE(INTL)
ArgList arguments(exec);
+#endif
for (unsigned i = 0; i < length; ++i) {
JSValue element = thisObject->getIndex(exec, i);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -473,7 +483,11 @@
CallData callData;
CallType callType = getCallData(conversionFunction, callData);
if (callType != CallType::None) {
+#if ENABLE(INTL)
element = call(exec, conversionFunction, callType, callData, element, arguments);
+#else
+ element = call(exec, conversionFunction, callType, callData, element, *vm.emptyList);
+#endif
RETURN_IF_EXCEPTION(scope, encodedJSValue());
}
}
@@ -480,24 +494,6 @@
stringJoiner.append(*exec, element);
RETURN_IF_EXCEPTION(scope, encodedJSValue());
}
-#else // !ENABLE(INTL)
- for (unsigned i = 0; i < length; ++i) {
- JSValue element = thisObject->getIndex(exec, i);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- if (element.isUndefinedOrNull())
- continue;
- JSValue conversionFunction = element.get(exec, vm.propertyNames->toLocaleString);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- CallData callData;
- CallType callType = getCallData(conversionFunction, callData);
- if (callType != CallType::None) {
- element = call(exec, conversionFunction, callType, callData, element, *vm.emptyList);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
- stringJoiner.append(*exec, element);
- RETURN_IF_EXCEPTION(scope, encodedJSValue());
- }
-#endif // !ENABLE(INTL)
scope.release();
return JSValue::encode(stringJoiner.join(*exec));
@@ -594,10 +590,9 @@
auto scope = DECLARE_THROW_SCOPE(vm);
switch (thisObject->indexingType()) {
- case ALL_CONTIGUOUS_INDEXING_TYPES:
case ALL_INT32_INDEXING_TYPES: {
auto& butterfly = *thisObject->butterfly();
- if (length > butterfly.publicLength())
+ if (UNLIKELY(length > butterfly.publicLength()))
break;
JSStringJoiner joiner(state, separator, length);
RETURN_IF_EXCEPTION(scope, { });
@@ -604,6 +599,30 @@
auto data = ""
bool holesKnownToBeOK = false;
for (unsigned i = 0; i < length; ++i) {
+ JSValue value = data[i].get();
+ if (LIKELY(value))
+ joiner.appendNumber(vm, value.asInt32());
+ else {
+ if (!holesKnownToBeOK) {
+ if (holesMustForwardToPrototype(vm, thisObject))
+ goto generalCase;
+ holesKnownToBeOK = true;
+ }
+ joiner.appendEmptyString();
+ }
+ }
+ scope.release();
+ return joiner.join(state);
+ }
+ case ALL_CONTIGUOUS_INDEXING_TYPES: {
+ auto& butterfly = *thisObject->butterfly();
+ if (UNLIKELY(length > butterfly.publicLength()))
+ break;
+ JSStringJoiner joiner(state, separator, length);
+ RETURN_IF_EXCEPTION(scope, { });
+ auto data = ""
+ bool holesKnownToBeOK = false;
+ for (unsigned i = 0; i < length; ++i) {
if (JSValue value = data[i].get()) {
if (!joiner.appendWithoutSideEffects(state, value))
goto generalCase;
@@ -621,7 +640,7 @@
}
case ALL_DOUBLE_INDEXING_TYPES: {
auto& butterfly = *thisObject->butterfly();
- if (length > butterfly.publicLength())
+ if (UNLIKELY(length > butterfly.publicLength()))
break;
JSStringJoiner joiner(state, separator, length);
RETURN_IF_EXCEPTION(scope, { });
@@ -629,8 +648,8 @@
bool holesKnownToBeOK = false;
for (unsigned i = 0; i < length; ++i) {
double value = data[i];
- if (!isHole(value))
- joiner.append(state, jsDoubleNumber(value));
+ if (LIKELY(!isHole(value)))
+ joiner.appendNumber(vm, value);
else {
if (!holesKnownToBeOK) {
if (holesMustForwardToPrototype(vm, thisObject))
Modified: trunk/Source/_javascript_Core/runtime/JSStringJoiner.h (223833 => 223834)
--- trunk/Source/_javascript_Core/runtime/JSStringJoiner.h 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/Source/_javascript_Core/runtime/JSStringJoiner.h 2017-10-23 11:50:21 UTC (rev 223834)
@@ -37,6 +37,8 @@
~JSStringJoiner();
void append(ExecState&, JSValue);
+ void appendNumber(VM&, int32_t);
+ void appendNumber(VM&, double);
bool appendWithoutSideEffects(ExecState&, JSValue);
void appendEmptyString();
@@ -121,11 +123,11 @@
}
if (value.isInt32()) {
- append8Bit(state.vm().numericStrings.add(value.asInt32()));
+ appendNumber(state.vm(), value.asInt32());
return true;
}
if (value.isDouble()) {
- append8Bit(state.vm().numericStrings.add(value.asDouble()));
+ appendNumber(state.vm(), value.asDouble());
return true;
}
if (value.isTrue()) {
@@ -149,4 +151,14 @@
}
}
+ALWAYS_INLINE void JSStringJoiner::appendNumber(VM& vm, int32_t value)
+{
+ append8Bit(vm.numericStrings.add(value));
+}
+
+ALWAYS_INLINE void JSStringJoiner::appendNumber(VM& vm, double value)
+{
+ append8Bit(vm.numericStrings.add(value));
+}
+
} // namespace JSC
Modified: trunk/Source/WTF/ChangeLog (223833 => 223834)
--- trunk/Source/WTF/ChangeLog 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/Source/WTF/ChangeLog 2017-10-23 11:50:21 UTC (rev 223834)
@@ -1,3 +1,16 @@
+2017-10-23 Yusuke Suzuki <utatane....@gmail.com>
+
+ [JSC] Use fastJoin in Array#toString
+ https://bugs.webkit.org/show_bug.cgi?id=178062
+
+ Reviewed by Darin Adler.
+
+ A bit cleaning up to use StringImpl::copyChars instead of
+ using for-loop directly.
+
+ * wtf/text/StringView.h:
+ (WTF::StringView::getCharactersWithUpconvert const):
+
2017-10-20 Antoine Quint <grao...@apple.com>
[Web Animations] Provide basic timeline and animation interfaces
Modified: trunk/Source/WTF/wtf/text/StringView.h (223833 => 223834)
--- trunk/Source/WTF/wtf/text/StringView.h 2017-10-23 10:11:12 UTC (rev 223833)
+++ trunk/Source/WTF/wtf/text/StringView.h 2017-10-23 11:50:21 UTC (rev 223834)
@@ -451,22 +451,16 @@
inline void StringView::getCharactersWithUpconvert(LChar* destination) const
{
ASSERT(is8Bit());
- auto characters8 = this->characters8();
- for (unsigned i = 0; i < m_length; ++i)
- destination[i] = characters8[i];
+ StringImpl::copyChars(destination, characters8(), m_length);
}
inline void StringView::getCharactersWithUpconvert(UChar* destination) const
{
if (is8Bit()) {
- auto characters8 = this->characters8();
- for (unsigned i = 0; i < m_length; ++i)
- destination[i] = characters8[i];
+ StringImpl::copyChars(destination, characters8(), m_length);
return;
}
- auto characters16 = this->characters16();
- for (unsigned i = 0; i < m_length; ++i)
- destination[i] = characters16[i];
+ StringImpl::copyChars(destination, characters16(), m_length);
}
inline StringView::UpconvertedCharacters::UpconvertedCharacters(const StringView& string)