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>
Reviewed by Cameron Zwarich and Oliver Hunt.
......@@ -231,50 +231,96 @@ JSValuePtr stringProtoFuncReplace(ExecState* exec, JSObject*, JSValuePtr thisVal
Vector<UString, 16> replacements;
// This is either a loop (if global is set) or a one-way (if not).
do {
int matchIndex;
int matchLen;
int* ovector;
regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector);
if (matchIndex < 0)
break;
sourceRanges.append(UString::Range(lastIndex, matchIndex - lastIndex));
if (global && callType == CallTypeJS) {
// reg->numSubpatterns() + 1 for pattern args, + 2 for match start and sourceValue
int argCount = reg->numSubpatterns() + 1 + 2;
JSFunction* func = asFunction(replacement);
CachedCall cachedCall(exec, func, argCount, exec->exceptionSlot());
while (true) {
int matchIndex;
int matchLen;
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];
ArgList args;
for (unsigned i = 0; i < reg->numSubpatterns() + 1; ++i) {
unsigned i = 0;
for (; i < reg->numSubpatterns() + 1; ++i) {
int matchStart = ovector[i * 2];
int matchLen = ovector[i * 2 + 1] - matchStart;
if (matchStart < 0)
args.append(jsUndefined());
cachedCall.setArgument(i, jsUndefined());
else
args.append(jsSubstring(exec, source, matchStart, matchLen));
cachedCall.setArgument(i, 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())
cachedCall.setArgument(i++, jsNumber(exec, completeMatchStart));
cachedCall.setArgument(i++, sourceVal);
cachedCall.setThis(exec->globalThisValue());
replacements.append(cachedCall.call().toString(cachedCall.newCallFrame()));
if (exec->hadException() || cachedCall.newCallFrame()->hadException())
break;
} else
replacements.append(substituteBackreferences(replacementString, source, ovector, reg));
lastIndex = matchIndex + matchLen;
startPosition = lastIndex;
lastIndex = matchIndex + matchLen;
startPosition = lastIndex;
// special case of empty match
if (matchLen == 0) {
startPosition++;
if (startPosition > source.size())
// special case of empty match
if (matchLen == 0) {
startPosition++;
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;
}
} 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())
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