Commit be864702 authored by oliver@apple.com's avatar oliver@apple.com

Improve String.replace performance slightly

Reviewed by Maciej Stachowiak

Apply our vm reentry caching logic to String.replace with global
regexes.


git-svn-id: svn://svn.chromium.org/blink/trunk@42743 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 5db41f15
2009-04-21 Oliver Hunt <oliver@apple.com>
Reviewed by Maciej Stachowiak.
Improve String.replace performance slightly
Apply our vm reentry caching logic to String.replace with global
regexes.
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncReplace):
2009-04-21 Geoffrey Garen <ggaren@apple.com> 2009-04-21 Geoffrey Garen <ggaren@apple.com>
Reviewed by Cameron Zwarich and Oliver Hunt. Reviewed by Cameron Zwarich and Oliver Hunt.
...@@ -231,50 +231,96 @@ JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisVal ...@@ -231,50 +231,96 @@ JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisVal
Vector<UString, 16> replacements; Vector<UString, 16> replacements;
// This is either a loop (if global is set) or a one-way (if not). // This is either a loop (if global is set) or a one-way (if not).
do { if (global && callType == CallTypeJS) {
int matchIndex; // reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
int matchLen; int argCount = reg->numSubpatterns() + 1 + 2;
int* ovector; JSFunction* func = asFunction(replacement);
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
if (matchIndex < 0) while (true) {
break; int matchIndex;
int matchLen;
sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex)); int* ovector;
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
break;
sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
if (callType != CallTypeNone) {
int completeMatchStart = ovector[0]; int completeMatchStart = ovector[0];
ArgList args; unsigned i = 0;
for (; i < reg->numSubpatterns() + 1; ++i) {
for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
int matchStart = ovector[i * 2]; int matchStart = ovector[i * 2];
int matchLen = ovector[i * 2 + 1] - matchStart; int matchLen = ovector[i * 2 + 1] - matchStart;
if (matchStart < 0) if (matchStart < 0)
args.append(jsUndefined()); cachedCall.setArgument(i, jsUndefined());
else else
args.append(jsSubstring(exec, source, matchStart, matchLen)); cachedCall.setArgument(i, jsSubstring(exec, source, matchStart, matchLen));
} }
args.append(jsNumber(exec, completeMatchStart)); cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
args.append(sourceVal); cachedCall.setArgument(i++, sourceVal);
replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec)); cachedCall.setThis(exec->globalThisValue());
if (exec->hadException()) replacements.append(cachedCall.call().toString(cachedCall.newCallFrame()));
if (exec->hadException() || cachedCall.newCallFrame()->hadException())
break; break;
} else
replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
lastIndex = matchIndex + matchLen; lastIndex = matchIndex + matchLen;
startPosition = lastIndex; startPosition = lastIndex;
// special case of empty match // special case of empty match
if (matchLen == 0) { if (matchLen == 0) {
startPosition++; startPosition++;
if (startPosition > source.size()) if (startPosition > source.size())
break;
}
}
} else {
do {
int matchIndex;
int matchLen;
int* ovector;
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
break; break;
}
} while (global);
sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
if (callType != CallTypeNone) {
int completeMatchStart = ovector[0];
ArgList args;
for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
int matchStart = ovector[i * 2];
int matchLen = ovector[i * 2 + 1] - matchStart;
if (matchStart < 0)
args.append(jsUndefined());
else
args.append(jsSubstring(exec, source, matchStart, matchLen));
}
args.append(jsNumber(exec, completeMatchStart));
args.append(sourceVal);
replacements.append(call(exec, replacement, callType, callData, exec->globalThisValue(), args).toString(exec));
if (exec->hadException())
break;
} else
replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
lastIndex = matchIndex + matchLen;
startPosition = lastIndex;
// special case of empty match
if (matchLen == 0) {
startPosition++;
if (startPosition > source.size())
break;
}
} while (global);
}
if (lastIndex < source.size()) if (lastIndex < source.size())
sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex)); sourceRanges.append(UString::Range(lastIndex, source.size() - lastIndex));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment