Bug 943126 - Fast-path for String.split(""). r=h4writer

This commit is contained in:
Sean Stangl 2013-11-26 10:15:32 -08:00
parent 8f9eb02165
commit dfbafafce3
2 changed files with 57 additions and 5 deletions

View File

@ -0,0 +1,16 @@
// Test fast-path for String.split("").
load(libdir + 'eqArrayHelper.js');
assertEqArray("".split(""), []);
assertEqArray("a".split(""), ["a"]);
assertEqArray("abc".split(""), ["a", "b", "c"]);
assertEqArray("abcd".split("", 2), ["a", "b"]);
assertEqArray("abcd".split("", 0), []);
assertEqArray("abcd".split("", -1), ["a", "b", "c", "d"]);
// Note: V8 disagrees about this one, but we are correct by ecma-262 15.5.4.14 part 9.
assertEqArray("abcd".split(undefined, 0), []);
assertEqArray("abcd".split(undefined, 1), ["abcd"]);

View File

@ -2645,7 +2645,8 @@ AppendSubstrings(JSContext *cx, Handle<JSStableString*> stableStr,
return nullptr;
/* Appending to the rope permanently roots the substring. */
rope.append(part);
if (!rope.append(part))
return nullptr;
}
return rope.result();
@ -3132,6 +3133,31 @@ SplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit, const Ma
return NewDenseCopiedArray(cx, splits.length(), splits.begin());
}
// Fast-path for splitting a string into a character array via split("").
static ArrayObject *
CharSplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit)
{
size_t strLength = str->length();
if (strLength == 0)
return NewDenseEmptyArray(cx);
js::StaticStrings &staticStrings = cx->runtime()->staticStrings;
uint32_t resultlen = (limit < strLength ? limit : strLength);
AutoValueVector splits(cx);
if (!splits.reserve(resultlen))
return nullptr;
for (size_t i = 0; i < resultlen; ++i) {
JSString *sub = staticStrings.getUnitStringForElement(cx, str, i);
if (!sub)
return nullptr;
splits.infallibleAppend(StringValue(sub));
}
return NewDenseCopiedArray(cx, splits.length(), splits.begin());
}
namespace {
/*
@ -3274,8 +3300,12 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
/* Steps 11-15. */
RootedObject aobj(cx);
if (!re.initialized()) {
if (sepstr->length() == 0) {
aobj = CharSplitHelper(cx, linearStr, limit);
} else {
SplitStringMatcher matcher(cx, sepstr);
aobj = SplitHelper(cx, linearStr, limit, matcher, type);
}
} else {
SplitRegExpMatcher matcher(*re, cx->global()->getRegExpStatics());
aobj = SplitHelper(cx, linearStr, limit, matcher, type);
@ -3302,8 +3332,14 @@ js::str_split_string(JSContext *cx, HandleTypeObject type, HandleString str, Han
uint32_t limit = UINT32_MAX;
RootedObject aobj(cx);
if (linearSep->length() == 0) {
aobj = CharSplitHelper(cx, linearStr, limit);
} else {
SplitStringMatcher matcher(cx, linearSep);
ArrayObject *aobj = SplitHelper(cx, linearStr, limit, matcher, type);
aobj = SplitHelper(cx, linearStr, limit, matcher, type);
}
if (!aobj)
return nullptr;