⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 100314 in webkit


Ignore:
Timestamp:
Nov 15, 2011, 1:38:35 PM (15 years ago)
Author:
msaboff@apple.com
Message:

Towards 8 bit Strings - Initial JS String Tuning
https://bugs.webkit.org/show_bug.cgi?id=72326

Added 8 bit optimized paths for the methods below.

Reviewed by Geoffrey Garen.

  • runtime/JSString.h:

(JSC::jsSubstring8):

  • runtime/StringPrototype.cpp:

(JSC::jsSpliceSubstrings):
(JSC::jsSpliceSubstringsWithSeparators):
(JSC::stringProtoFuncReplace):
(JSC::stringProtoFuncCharCodeAt):

Location:
trunk/Source/JavaScriptCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r100310 r100314  
     12011-11-15  Michael Saboff  <msaboff@apple.com>
     2
     3        Towards 8 bit Strings - Initial JS String Tuning
     4        https://bugs.webkit.org/show_bug.cgi?id=72326
     5
     6        Added 8 bit optimized paths for the methods below.
     7
     8        Reviewed by Geoffrey Garen.
     9
     10        * runtime/JSString.h:
     11        (JSC::jsSubstring8):
     12        * runtime/StringPrototype.cpp:
     13        (JSC::jsSpliceSubstrings):
     14        (JSC::jsSpliceSubstringsWithSeparators):
     15        (JSC::stringProtoFuncReplace):
     16        (JSC::stringProtoFuncCharCodeAt):
     17
    1182011-11-15  Gavin Barraclough  <barraclough@apple.com>
    219
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r100208 r100314  
    364364    }
    365365
    366     inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
     366    inline JSString* jsSubstring8(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
    367367    {
    368368        ASSERT(offset <= static_cast<unsigned>(s.length()));
     
    376376                return globalData->smallStrings.singleCharacterString(globalData, c);
    377377        }
     378        return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, StringImpl::create8(s.impl(), offset, length)));
     379    }
     380
     381    inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length)
     382    {
     383        ASSERT(offset <= static_cast<unsigned>(s.length()));
     384        ASSERT(length <= static_cast<unsigned>(s.length()));
     385        ASSERT(offset + length <= static_cast<unsigned>(s.length()));
     386        if (!length)
     387            return globalData->smallStrings.emptyString(globalData);
     388        if (length == 1) {
     389            UChar c = s[offset];
     390            if (c <= maxSingleCharacterString)
     391                return globalData->smallStrings.singleCharacterString(globalData, c);
     392        }
    378393        return fixupVPtr(globalData, JSString::createHasOtherOwner(*globalData, StringImpl::create(s.impl(), offset, length)));
    379394    }
     
    400415    inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); }
    401416    inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); }
     417    inline JSString* jsSubstring8(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring8(&exec->globalData(), s, offset, length); }
    402418    inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); }
    403419    inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); }
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r100006 r100314  
    284284        return jsString(exec, "");
    285285
     286    if (source.is8Bit()) {
     287        LChar* buffer;
     288        const LChar* sourceData = source.characters8();
     289        RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     290        if (!impl)
     291            return throwOutOfMemoryError(exec);
     292
     293        int bufferPos = 0;
     294        for (int i = 0; i < rangeCount; i++) {
     295            if (int srcLen = substringRanges[i].length) {
     296                StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
     297                bufferPos += srcLen;
     298            }
     299        }
     300
     301        return jsString(exec, impl.release());
     302    }
     303
    286304    UChar* buffer;
     305    const UChar* sourceData = source.characters16();
     306
    287307    RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
    288308    if (!impl)
     
    292312    for (int i = 0; i < rangeCount; i++) {
    293313        if (int srcLen = substringRanges[i].length) {
    294             StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
     314            StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
    295315            bufferPos += srcLen;
    296316        }
     
    313333
    314334    int totalLength = 0;
     335    bool allSeperators8Bit = true;
    315336    for (int i = 0; i < rangeCount; i++)
    316337        totalLength += substringRanges[i].length;
    317     for (int i = 0; i < separatorCount; i++)
     338    for (int i = 0; i < separatorCount; i++) {
    318339        totalLength += separators[i].length();
     340        if (separators[i].length() && !separators[i].is8Bit())
     341            allSeperators8Bit = false;
     342    }
    319343
    320344    if (!totalLength)
    321345        return jsString(exec, "");
     346
     347    if (source.is8Bit() && allSeperators8Bit) {
     348        LChar* buffer;
     349        const LChar* sourceData = source.characters8();
     350
     351        RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     352        if (!impl)
     353            return throwOutOfMemoryError(exec);
     354
     355        int maxCount = max(rangeCount, separatorCount);
     356        int bufferPos = 0;
     357        for (int i = 0; i < maxCount; i++) {
     358            if (i < rangeCount) {
     359                if (int srcLen = substringRanges[i].length) {
     360                    StringImpl::copyChars(buffer + bufferPos, sourceData + substringRanges[i].position, srcLen);
     361                    bufferPos += srcLen;
     362                }
     363            }
     364            if (i < separatorCount) {
     365                if (int sepLen = separators[i].length()) {
     366                    StringImpl::copyChars(buffer + bufferPos, separators[i].characters8(), sepLen);
     367                    bufferPos += sepLen;
     368                }
     369            }
     370        }       
     371
     372        return jsString(exec, impl.release());
     373    }
    322374
    323375    UChar* buffer;
     
    331383        if (i < rangeCount) {
    332384            if (int srcLen = substringRanges[i].length) {
    333                 StringImpl::copyChars(buffer + bufferPos, source.characters16() + substringRanges[i].position, srcLen);
     385                StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
    334386                bufferPos += srcLen;
    335387            }
     
    337389        if (i < separatorCount) {
    338390            if (int sepLen = separators[i].length()) {
    339                 StringImpl::copyChars(buffer + bufferPos, separators[i].characters16(), sepLen);
     391                StringImpl::copyChars(buffer + bufferPos, separators[i].characters(), sepLen);
    340392                bufferPos += sepLen;
    341393            }
     
    424476            if (exec->hadException())
    425477                return JSValue::encode(jsNull());
    426             while (true) {
    427                 int matchIndex;
    428                 int matchLen = 0;
    429                 int* ovector;
    430                 regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
    431                 if (matchIndex < 0)
    432                     break;
    433 
    434                 sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
    435 
    436                 int completeMatchStart = ovector[0];
    437                 unsigned i = 0;
    438                 for (; i < reg->numSubpatterns() + 1; ++i) {
    439                     int matchStart = ovector[i * 2];
    440                     int matchLen = ovector[i * 2 + 1] - matchStart;
    441 
    442                     if (matchStart < 0)
    443                         cachedCall.setArgument(i, jsUndefined());
     478            if (source.is8Bit()) {
     479                while (true) {
     480                    int matchIndex;
     481                    int matchLen = 0;
     482                    int* ovector;
     483                    regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
     484                    if (matchIndex < 0)
     485                        break;
     486
     487                    sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
     488
     489                    int completeMatchStart = ovector[0];
     490                    unsigned i = 0;
     491                    for (; i < reg->numSubpatterns() + 1; ++i) {
     492                        int matchStart = ovector[i * 2];
     493                        int matchLen = ovector[i * 2 + 1] - matchStart;
     494
     495                        if (matchStart < 0)
     496                            cachedCall.setArgument(i, jsUndefined());
     497                        else
     498                            cachedCall.setArgument(i, jsSubstring8(globalData, source, matchStart, matchLen));
     499                    }
     500
     501                    cachedCall.setArgument(i++, jsNumber(completeMatchStart));
     502                    cachedCall.setArgument(i++, sourceVal);
     503
     504                    cachedCall.setThis(jsUndefined());
     505                    JSValue result = cachedCall.call();
     506                    if (LIKELY(result.isString()))
     507                        replacements.append(asString(result)->value(exec));
    444508                    else
    445                         cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen));
     509                        replacements.append(result.toString(cachedCall.newCallFrame(exec)));
     510                    if (exec->hadException())
     511                        break;
     512
     513                    lastIndex = matchIndex + matchLen;
     514                    startPosition = lastIndex;
     515
     516                    // special case of empty match
     517                    if (!matchLen) {
     518                        startPosition++;
     519                        if (startPosition > sourceLen)
     520                            break;
     521                    }
    446522                }
    447 
    448                 cachedCall.setArgument(i++, jsNumber(completeMatchStart));
    449                 cachedCall.setArgument(i++, sourceVal);
    450 
    451                 cachedCall.setThis(jsUndefined());
    452                 JSValue result = cachedCall.call();
    453                 if (LIKELY(result.isString()))
    454                     replacements.append(asString(result)->value(exec));
    455                 else
    456                     replacements.append(result.toString(cachedCall.newCallFrame(exec)));
    457                 if (exec->hadException())
    458                     break;
    459 
    460                 lastIndex = matchIndex + matchLen;
    461                 startPosition = lastIndex;
    462 
    463                 // special case of empty match
    464                 if (!matchLen) {
    465                     startPosition++;
    466                     if (startPosition > sourceLen)
     523            } else {
     524                while (true) {
     525                    int matchIndex;
     526                    int matchLen = 0;
     527                    int* ovector;
     528                    regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
     529                    if (matchIndex < 0)
    467530                        break;
     531
     532                    sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
     533
     534                    int completeMatchStart = ovector[0];
     535                    unsigned i = 0;
     536                    for (; i < reg->numSubpatterns() + 1; ++i) {
     537                        int matchStart = ovector[i * 2];
     538                        int matchLen = ovector[i * 2 + 1] - matchStart;
     539
     540                        if (matchStart < 0)
     541                            cachedCall.setArgument(i, jsUndefined());
     542                        else
     543                            cachedCall.setArgument(i, jsSubstring(globalData, source, matchStart, matchLen));
     544                    }
     545
     546                    cachedCall.setArgument(i++, jsNumber(completeMatchStart));
     547                    cachedCall.setArgument(i++, sourceVal);
     548
     549                    cachedCall.setThis(jsUndefined());
     550                    JSValue result = cachedCall.call();
     551                    if (LIKELY(result.isString()))
     552                        replacements.append(asString(result)->value(exec));
     553                    else
     554                        replacements.append(result.toString(cachedCall.newCallFrame(exec)));
     555                    if (exec->hadException())
     556                        break;
     557
     558                    lastIndex = matchIndex + matchLen;
     559                    startPosition = lastIndex;
     560
     561                    // special case of empty match
     562                    if (!matchLen) {
     563                        startPosition++;
     564                        if (startPosition > sourceLen)
     565                            break;
     566                    }
    468567                }
    469568            }
     
    616715    if (a0.isUInt32()) {
    617716        uint32_t i = a0.asUInt32();
    618         if (i < len)
    619             return JSValue::encode(jsNumber(s.characters()[i]));
     717        if (i < len) {
     718            if (s.is8Bit())
     719                return JSValue::encode(jsNumber(s.characters8()[i]));
     720            return JSValue::encode(jsNumber(s.characters16()[i]));
     721        }
    620722        return JSValue::encode(jsNaN());
    621723    }
Note: See TracChangeset for help on using the changeset viewer.