Changeset 92540 in webkit


Ignore:
Timestamp:
Aug 5, 2011 7:17:55 PM (13 years ago)
Author:
barraclough@apple.com
Message:

String replace with the empty string means string removal
https://bugs.webkit.org/show_bug.cgi?id=65799

Reviewed by Sam Weinig.

Optimization for String.prototype.replace([RegExp], ""), this improves v8-regexp by ~3%.

  • runtime/StringPrototype.cpp:

(JSC::jsSpliceSubstrings):
(JSC::stringProtoFuncReplace):

Location:
trunk/Source/JavaScriptCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r92536 r92540  
     12011-08-05  Gavin Barraclough  <barraclough@apple.com>
     2
     3        String replace with the empty string means string removal
     4        https://bugs.webkit.org/show_bug.cgi?id=65799
     5
     6        Reviewed by Sam Weinig.
     7
     8        Optimization for String.prototype.replace([RegExp], ""), this improves v8-regexp by ~3%.
     9
     10        * runtime/StringPrototype.cpp:
     11        (JSC::jsSpliceSubstrings):
     12        (JSC::stringProtoFuncReplace):
     13
    1142011-08-05  Noel Gordon  <noel.gordon@gmail.com>
    215
  • trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp

    r91284 r92540  
    249249};
    250250
     251static ALWAYS_INLINE JSValue jsSpliceSubstrings(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount)
     252{
     253    if (rangeCount == 1) {
     254        int sourceSize = source.length();
     255        int position = substringRanges[0].position;
     256        int length = substringRanges[0].length;
     257        if (position <= 0 && length >= sourceSize)
     258            return sourceVal;
     259        // We could call UString::substr, but this would result in redundant checks
     260        return jsString(exec, StringImpl::create(source.impl(), max(0, position), min(sourceSize, length)));
     261    }
     262
     263    int totalLength = 0;
     264    for (int i = 0; i < rangeCount; i++)
     265        totalLength += substringRanges[i].length;
     266
     267    if (!totalLength)
     268        return jsString(exec, "");
     269
     270    UChar* buffer;
     271    RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     272    if (!impl)
     273        return throwOutOfMemoryError(exec);
     274
     275    int bufferPos = 0;
     276    for (int i = 0; i < rangeCount; i++) {
     277        if (int srcLen = substringRanges[i].length) {
     278            StringImpl::copyChars(buffer + bufferPos, source.characters() + substringRanges[i].position, srcLen);
     279            bufferPos += srcLen;
     280        }
     281    }
     282
     283    return jsString(exec, impl.release());
     284}
     285
    251286static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, JSString* sourceVal, const UString& source, const StringRange* substringRanges, int rangeCount, const UString* separators, int separatorCount)
    252287{
     
    267302        totalLength += separators[i].length();
    268303
    269     if (totalLength == 0)
     304    if (!totalLength)
    270305        return jsString(exec, "");
    271306
    272307    UChar* buffer;
    273     PassRefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
     308    RefPtr<StringImpl> impl = StringImpl::tryCreateUninitialized(totalLength, buffer);
    274309    if (!impl)
    275310        return throwOutOfMemoryError(exec);
     
    292327    }
    293328
    294     return jsString(exec, impl);
     329    return jsString(exec, impl.release());
    295330}
    296331
     
    320355
    321356        RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor();
     357
     358        // Optimization for substring removal (replace with empty).
     359        if (global && callType == CallTypeNone && !replacementString.length()) {
     360            int lastIndex = 0;
     361            unsigned startPosition = 0;
     362
     363            Vector<StringRange, 16> sourceRanges;
     364
     365            while (true) {
     366                int matchIndex;
     367                int matchLen = 0;
     368                int* ovector;
     369                regExpConstructor->performMatch(*globalData, reg, source, startPosition, matchIndex, matchLen, &ovector);
     370                if (matchIndex < 0)
     371                    break;
     372
     373                if (lastIndex < matchIndex)
     374                    sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex));
     375
     376                lastIndex = matchIndex + matchLen;
     377                startPosition = lastIndex;
     378
     379                // special case of empty match
     380                if (!matchLen) {
     381                    startPosition++;
     382                    if (startPosition > sourceLen)
     383                        break;
     384                }
     385            }
     386
     387            if (!lastIndex)
     388                return JSValue::encode(sourceVal);
     389
     390            if (static_cast<unsigned>(lastIndex) < sourceLen)
     391                sourceRanges.append(StringRange(lastIndex, sourceLen - lastIndex));
     392
     393            return JSValue::encode(jsSpliceSubstrings(exec, sourceVal, source, sourceRanges.data(), sourceRanges.size()));
     394        }
    322395
    323396        int lastIndex = 0;
     
    373446
    374447                // special case of empty match
    375                 if (matchLen == 0) {
     448                if (!matchLen) {
    376449                    startPosition++;
    377450                    if (startPosition > sourceLen)
     
    426499
    427500                // special case of empty match
    428                 if (matchLen == 0) {
     501                if (!matchLen) {
    429502                    startPosition++;
    430503                    if (startPosition > sourceLen)
Note: See TracChangeset for help on using the changeset viewer.