Bug 877021 - Speed up CreateRegExpMatchResult(). r=h4writer

This commit is contained in:
Sean Stangl 2013-05-28 18:57:56 -07:00
parent ceb33f4d35
commit d4f121fc23

View File

@ -18,42 +18,19 @@ using namespace js::types;
using mozilla::ArrayLength;
class RegExpMatchBuilder
static inline bool
DefinePropertyHelper(JSContext *cx, HandleObject obj, Handle<PropertyName*> name, HandleValue v)
{
JSContext * const cx;
RootedObject array;
bool setProperty(Handle<PropertyName*> name, HandleValue v) {
return !!baseops::DefineProperty(cx, array, name, v,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
}
public:
RegExpMatchBuilder(JSContext *cx, HandleObject array) : cx(cx), array(cx, array) {}
bool append(uint32_t index, HandleValue v) {
JS_ASSERT(!array->getOps()->getElement);
return !!baseops::DefineElement(cx, array, index, v, JS_PropertyStub, JS_StrictPropertyStub,
JSPROP_ENUMERATE);
}
bool setIndex(int index) {
RootedValue value(cx, Int32Value(index));
return setProperty(cx->names().index, value);
}
bool setInput(HandleString str) {
JS_ASSERT(str);
RootedValue value(cx, StringValue(str));
return setProperty(cx->names().input, value);
}
};
return !!baseops::DefineProperty(cx, obj, name, v,
JS_PropertyStub, JS_StrictPropertyStub, JSPROP_ENUMERATE);
}
bool
js::CreateRegExpMatchResult(JSContext *cx, HandleString input_, const jschar *chars, size_t length,
MatchPairs &matches, MutableHandleValue rval)
{
RootedString input(cx, input_);
RootedValue undefinedValue(cx, UndefinedValue());
/*
* Create the (slow) result array for a match.
@ -64,39 +41,47 @@ js::CreateRegExpMatchResult(JSContext *cx, HandleString input_, const jschar *ch
* input: input string
* index: start index for the match
*/
RootedObject array(cx, NewDenseEmptyArray(cx));
if (!array)
return false;
if (!input) {
input = js_NewStringCopyN<CanGC>(cx, chars, length);
if (!input)
return false;
}
RegExpMatchBuilder builder(cx, array);
RootedValue undefinedValue(cx, UndefinedValue());
size_t numPairs = matches.length();
JS_ASSERT(numPairs > 0);
AutoValueVector elements(cx);
if (!elements.reserve(numPairs))
return false;
/* Accumulate a Value for each pair, in a rooted vector. */
for (size_t i = 0; i < numPairs; ++i) {
const MatchPair &pair = matches[i];
RootedString captured(cx);
if (pair.isUndefined()) {
JS_ASSERT(i != 0); /* Since we had a match, first pair must be present. */
if (!builder.append(i, undefinedValue))
return false;
elements.infallibleAppend(undefinedValue);
} else {
captured = js_NewDependentString(cx, input, pair.start, pair.length());
RootedValue value(cx, StringValue(captured));
if (!captured || !builder.append(i, value))
JSLinearString *str = js_NewDependentString(cx, input, pair.start, pair.length());
if (!str)
return false;
elements.infallibleAppend(StringValue(str));
}
}
if (!builder.setIndex(matches[0].start) || !builder.setInput(input))
/* Copy the rooted vector into the array object. */
RootedObject array(cx, NewDenseCopiedArray(cx, elements.length(), elements.begin()));
if (!array)
return false;
/* Set the |index| property. */
RootedValue index(cx, Int32Value(matches[0].start));
if (!DefinePropertyHelper(cx, array, cx->names().index, index))
return false;
/* Set the |input| property. */
RootedValue inputVal(cx, StringValue(input));
if (!DefinePropertyHelper(cx, array, cx->names().input, inputVal))
return false;
rval.setObject(*array);