Changeset 251736 in webkit


Ignore:
Timestamp:
Oct 29, 2019 2:43:30 PM (4 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] Add fast path for String#localeCompare
https://bugs.webkit.org/show_bug.cgi?id=202676

Reviewed by Mark Lam.

JSTests:

  • stress/locale-compare-bits.js: Added.

(shouldBe):

Source/JavaScriptCore:

When String#localeCompare is invoked, we are setting up UCharIterator to iterate code points.
But this is too slow since its implementation is invoking function pointer for each code point
to get next code point. Strings have many code points typically. Invoking function pointer so many times
takes too much time just for locale-aware comparison.

This patch revises the implementation by adding 2 fast path and 1 slow path. The slow path requires extra memory,
but it is soon released (not GC-managed).

  1. If both strings are ASCII (not Latin1), we use ucol_strcollUTF8.
  2. If both strings are 16-bit, we use ucol_strcoll.
  3. Otherwise, we convert strings to 16-bit strings, and then we use ucol_strcoll.

JetStream2/cdjs is improved from 56 to 85 on iMac Pro (50%).

  • runtime/IntlCollator.cpp:

(JSC::IntlCollator::compareStrings):

  • tools/JSDollarVM.cpp:

(JSC::functionMake16BitStringIfPossible):
(JSC::JSDollarVM::finishCreation):

Source/WTF:

  • wtf/text/StringView.h:

(WTF::StringView::isAllASCII const):

Tools:

  • TestWebKitAPI/Tests/WTF/StringView.cpp:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r251671 r251736  
     12019-10-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Add fast path for String#localeCompare
     4        https://bugs.webkit.org/show_bug.cgi?id=202676
     5
     6        Reviewed by Mark Lam.
     7
     8        * stress/locale-compare-bits.js: Added.
     9        (shouldBe):
     10
    1112019-10-28  Yusuke Suzuki  <ysuzuki@apple.com>
    212
  • trunk/Source/JavaScriptCore/ChangeLog

    r251691 r251736  
     12019-10-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Add fast path for String#localeCompare
     4        https://bugs.webkit.org/show_bug.cgi?id=202676
     5
     6        Reviewed by Mark Lam.
     7
     8        When String#localeCompare is invoked, we are setting up UCharIterator to iterate code points.
     9        But this is too slow since its implementation is invoking function pointer for each code point
     10        to get next code point. Strings have many code points typically. Invoking function pointer so many times
     11        takes too much time just for locale-aware comparison.
     12
     13        This patch revises the implementation by adding 2 fast path and 1 slow path. The slow path requires extra memory,
     14        but it is soon released (not GC-managed).
     15
     16        1. If both strings are ASCII (not Latin1), we use ucol_strcollUTF8.
     17        2. If both strings are 16-bit, we use ucol_strcoll.
     18        3. Otherwise, we convert strings to 16-bit strings, and then we use ucol_strcoll.
     19
     20        JetStream2/cdjs is improved from 56 to 85 on iMac Pro (50%).
     21
     22        * runtime/IntlCollator.cpp:
     23        (JSC::IntlCollator::compareStrings):
     24        * tools/JSDollarVM.cpp:
     25        (JSC::functionMake16BitStringIfPossible):
     26        (JSC::JSDollarVM::finishCreation):
     27
    1282019-10-28  Yusuke Suzuki  <ysuzuki@apple.com>
    229
  • trunk/Source/JavaScriptCore/runtime/IntlCollator.cpp

    r251425 r251736  
    343343
    344344    UErrorCode status = U_ZERO_ERROR;
    345     UCharIterator iteratorX = createIterator(x);
    346     UCharIterator iteratorY = createIterator(y);
    347     auto result = ucol_strcollIter(m_collator.get(), &iteratorX, &iteratorY, &status);
     345    UCollationResult result = UCOL_EQUAL;
     346    if (x.is8Bit() && y.is8Bit() && x.isAllASCII() && y.isAllASCII())
     347        result = ucol_strcollUTF8(m_collator.get(), bitwise_cast<const char*>(x.characters8()), x.length(), bitwise_cast<const char*>(y.characters8()), y.length(), &status);
     348    else {
     349        auto getCharacters = [&] (const StringView& view, Vector<UChar>& buffer) -> const UChar* {
     350            if (!view.is8Bit())
     351                return view.characters16();
     352            buffer.resize(view.length());
     353            StringImpl::copyCharacters(buffer.data(), view.characters8(), view.length());
     354            return buffer.data();
     355        };
     356
     357        Vector<UChar> xBuffer;
     358        Vector<UChar> yBuffer;
     359        const UChar* xCharacters = getCharacters(x, xBuffer);
     360        const UChar* yCharacters = getCharacters(y, yBuffer);
     361        result = ucol_strcoll(m_collator.get(), xCharacters, x.length(), yCharacters, y.length());
     362    }
    348363    if (U_FAILURE(status))
    349364        return throwException(globalObject, scope, createError(globalObject, "Failed to compare strings."_s));
  • trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp

    r251518 r251736  
    25562556}
    25572557
     2558static EncodedJSValue JSC_HOST_CALL functionMake16BitStringIfPossible(JSGlobalObject* globalObject, CallFrame* callFrame)
     2559{
     2560    DollarVMAssertScope assertScope;
     2561    VM& vm = globalObject->vm();
     2562    auto scope = DECLARE_THROW_SCOPE(vm);
     2563    String string = callFrame->argument(0).toWTFString(globalObject);
     2564    RETURN_IF_EXCEPTION(scope, { });
     2565    if (!string.is8Bit())
     2566        return JSValue::encode(jsString(vm, WTFMove(string)));
     2567    Vector<UChar> buffer;
     2568    buffer.resize(string.length());
     2569    StringImpl::copyCharacters(buffer.data(), string.characters8(), string.length());
     2570    return JSValue::encode(jsString(vm, String::adopt(WTFMove(buffer))));
     2571}
     2572
    25582573void JSDollarVM::finishCreation(VM& vm)
    25592574{
     
    26782693
    26792694    addFunction(vm, "isWasmSupported", functionIsWasmSupported, 0);
     2695    addFunction(vm, "make16BitStringIfPossible", functionMake16BitStringIfPossible, 1);
    26802696}
    26812697
  • trunk/Source/WTF/ChangeLog

    r251630 r251736  
     12019-10-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Add fast path for String#localeCompare
     4        https://bugs.webkit.org/show_bug.cgi?id=202676
     5
     6        Reviewed by Mark Lam.
     7
     8        * wtf/text/StringView.h:
     9        (WTF::StringView::isAllASCII const):
     10
    1112019-10-26  Chris Lord  <clord@igalia.com>
    212
  • trunk/Source/WTF/wtf/text/StringView.h

    r248546 r251736  
    9393    const UChar* characters16() const;
    9494
     95    bool isAllASCII() const;
     96
    9597    String toString() const;
    9698    String toStringWithoutCopying() const;
     
    404406}
    405407
     408inline bool StringView::isAllASCII() const
     409{
     410    if (is8Bit())
     411        return charactersAreAllASCII(characters8(), length());
     412    return charactersAreAllASCII(characters16(), length());
     413}
     414
    406415class StringView::UpconvertedCharacters {
    407416    WTF_MAKE_FAST_ALLOCATED;
  • trunk/Tools/ChangeLog

    r251720 r251736  
     12019-10-29  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] Add fast path for String#localeCompare
     4        https://bugs.webkit.org/show_bug.cgi?id=202676
     5
     6        Reviewed by Mark Lam.
     7
     8        * TestWebKitAPI/Tests/WTF/StringView.cpp:
     9        (TestWebKitAPI::TEST):
     10
    1112019-10-27  Wenson Hsieh  <wenson_hsieh@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp

    r248316 r251736  
    972972}
    973973
     974TEST(WTF, StringViewIsAllASCII)
     975{
     976    EXPECT_TRUE(StringView(String("Hello")).isAllASCII());
     977    EXPECT_TRUE(StringView(String("Cocoa")).isAllASCII());
     978    EXPECT_FALSE(StringView(String("📱")).isAllASCII());
     979    EXPECT_FALSE(StringView(String("\u0080")).isAllASCII());
     980    EXPECT_TRUE(StringView(String(bitwise_cast<const UChar*>(u"Hello"))).isAllASCII());
     981}
     982
    974983} // namespace TestWebKitAPI
Note: See TracChangeset for help on using the changeset viewer.