Commit 425a221b authored by sandholm@chromium.org's avatar sandholm@chromium.org

Optimizing BuildResultFromMatchInfo, StringReplace and StringSplit.

Review URL: http://codereview.chromium.org/5708006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5982 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1e494335
...@@ -120,22 +120,28 @@ function DoRegExpExec(regexp, string, index) { ...@@ -120,22 +120,28 @@ function DoRegExpExec(regexp, string, index) {
function BuildResultFromMatchInfo(lastMatchInfo, s) { function BuildResultFromMatchInfo(lastMatchInfo, s) {
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1; var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s); var start = lastMatchInfo[CAPTURE0];
if (numResults === 1) { var end = lastMatchInfo[CAPTURE1];
var matchStart = lastMatchInfo[CAPTURE(0)]; var result = %_RegExpConstructResult(numResults, start, s);
var matchEnd = lastMatchInfo[CAPTURE(1)]; if (start + 1 == end) {
result[0] = SubString(s, matchStart, matchEnd); result[0] = %_StringCharAt(s, start);
} else { } else {
for (var i = 0; i < numResults; i++) { result[0] = %_SubString(s, start, end);
var matchStart = lastMatchInfo[CAPTURE(i << 1)]; }
var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)]; var j = REGEXP_FIRST_CAPTURE + 2;
if (matchStart != -1 && matchEnd != -1) { for (var i = 1; i < numResults; i++) {
result[i] = SubString(s, matchStart, matchEnd); start = lastMatchInfo[j++];
end = lastMatchInfo[j++];
if (end != -1) {
if (start + 1 == end) {
result[i] = %_StringCharAt(s, start);
} else { } else {
// Make sure the element is present. Avoid reading the undefined result[i] = %_SubString(s, start, end);
// property from the global object since this may change.
result[i] = void 0;
} }
} else {
// Make sure the element is present. Avoid reading the undefined
// property from the global object since this may change.
result[i] = void 0;
} }
} }
return result; return result;
...@@ -166,12 +172,7 @@ function RegExpExec(string) { ...@@ -166,12 +172,7 @@ function RegExpExec(string) {
} }
string = regExpInput; string = regExpInput;
} }
var s; string = TO_STRING_INLINE(string);
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex; var lastIndex = this.lastIndex;
// Conversion is required by the ES5 specification (RegExp.prototype.exec // Conversion is required by the ES5 specification (RegExp.prototype.exec
...@@ -180,7 +181,7 @@ function RegExpExec(string) { ...@@ -180,7 +181,7 @@ function RegExpExec(string) {
var global = this.global; var global = this.global;
if (global) { if (global) {
if (i < 0 || i > s.length) { if (i < 0 || i > string.length) {
this.lastIndex = 0; this.lastIndex = 0;
return null; return null;
} }
...@@ -188,9 +189,9 @@ function RegExpExec(string) { ...@@ -188,9 +189,9 @@ function RegExpExec(string) {
i = 0; i = 0;
} }
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
// matchIndices is either null or the lastMatchInfo array. // matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
if (matchIndices === null) { if (matchIndices === null) {
if (global) this.lastIndex = 0; if (global) this.lastIndex = 0;
...@@ -202,7 +203,7 @@ function RegExpExec(string) { ...@@ -202,7 +203,7 @@ function RegExpExec(string) {
if (global) { if (global) {
this.lastIndex = lastMatchInfo[CAPTURE1]; this.lastIndex = lastMatchInfo[CAPTURE1];
} }
return BuildResultFromMatchInfo(matchIndices, s); return BuildResultFromMatchInfo(matchIndices, string);
} }
...@@ -227,12 +228,7 @@ function RegExpTest(string) { ...@@ -227,12 +228,7 @@ function RegExpTest(string) {
string = regExpInput; string = regExpInput;
} }
var s; string = TO_STRING_INLINE(string);
if (IS_STRING(string)) {
s = string;
} else {
s = ToString(string);
}
var lastIndex = this.lastIndex; var lastIndex = this.lastIndex;
...@@ -241,13 +237,13 @@ function RegExpTest(string) { ...@@ -241,13 +237,13 @@ function RegExpTest(string) {
var i = TO_INTEGER(lastIndex); var i = TO_INTEGER(lastIndex);
if (this.global) { if (this.global) {
if (i < 0 || i > s.length) { if (i < 0 || i > string.length) {
this.lastIndex = 0; this.lastIndex = 0;
return false; return false;
} }
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
// matchIndices is either null or the lastMatchInfo array. // matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo); var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
if (matchIndices === null) { if (matchIndices === null) {
this.lastIndex = 0; this.lastIndex = 0;
return false; return false;
...@@ -269,11 +265,11 @@ function RegExpTest(string) { ...@@ -269,11 +265,11 @@ function RegExpTest(string) {
(this.ignoreCase ? 'i' : '') (this.ignoreCase ? 'i' : '')
+ (this.multiline ? 'm' : '')); + (this.multiline ? 'm' : ''));
} }
if (!regexp_val.test(s)) return false; if (!regexp_val.test(string)) return false;
} }
%_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, s, lastIndex]); %_Log('regexp', 'regexp-exec,%0r,%1S,%2i', [this, string, lastIndex]);
// matchIndices is either null or the lastMatchInfo array. // matchIndices is either null or the lastMatchInfo array.
var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo); var matchIndices = %_RegExpExec(this, string, 0, lastMatchInfo);
if (matchIndices === null) return false; if (matchIndices === null) return false;
lastMatchInfoOverride = null; lastMatchInfoOverride = null;
return true; return true;
......
...@@ -101,28 +101,28 @@ function StringConcat() { ...@@ -101,28 +101,28 @@ function StringConcat() {
// ECMA-262 section 15.5.4.7 // ECMA-262 section 15.5.4.7
function StringIndexOf(searchString /* position */) { // length == 1 function StringIndexOf(pattern /* position */) { // length == 1
var subject_str = TO_STRING_INLINE(this); var subject = TO_STRING_INLINE(this);
var pattern_str = TO_STRING_INLINE(searchString); var pattern = TO_STRING_INLINE(pattern);
var subject_str_len = subject_str.length; var subject_len = subject.length;
var pattern_str_len = pattern_str.length; var pattern_len = pattern.length;
var index = 0; var index = 0;
if (%_ArgumentsLength() > 1) { if (%_ArgumentsLength() > 1) {
var arg1 = %_Arguments(1); // position var arg1 = %_Arguments(1); // position
index = TO_INTEGER(arg1); index = TO_INTEGER(arg1);
} }
if (index < 0) index = 0; if (index < 0) index = 0;
if (index > subject_str_len) index = subject_str_len; if (index > subject_len) index = subject_len;
if (pattern_str_len + index > subject_str_len) return -1; if (pattern_len + index > subject_len) return -1;
return %StringIndexOf(subject_str, pattern_str, index); return %StringIndexOf(subject, pattern, index);
} }
// ECMA-262 section 15.5.4.8 // ECMA-262 section 15.5.4.8
function StringLastIndexOf(searchString /* position */) { // length == 1 function StringLastIndexOf(pat /* position */) { // length == 1
var sub = TO_STRING_INLINE(this); var sub = TO_STRING_INLINE(this);
var subLength = sub.length; var subLength = sub.length;
var pat = TO_STRING_INLINE(searchString); var pat = TO_STRING_INLINE(pat);
var patLength = pat.length; var patLength = pat.length;
var index = subLength - patLength; var index = subLength - patLength;
if (%_ArgumentsLength() > 1) { if (%_ArgumentsLength() > 1) {
...@@ -150,10 +150,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1 ...@@ -150,10 +150,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1
// do anything locale specific. // do anything locale specific.
function StringLocaleCompare(other) { function StringLocaleCompare(other) {
if (%_ArgumentsLength() === 0) return 0; if (%_ArgumentsLength() === 0) return 0;
return %StringLocaleCompare(TO_STRING_INLINE(this),
var this_str = TO_STRING_INLINE(this); TO_STRING_INLINE(other));
var other_str = TO_STRING_INLINE(other);
return %StringLocaleCompare(this_str, other_str);
} }
...@@ -177,9 +175,7 @@ function StringMatch(regexp) { ...@@ -177,9 +175,7 @@ function StringMatch(regexp) {
// otherwise we call the runtime system. // otherwise we call the runtime system.
function SubString(string, start, end) { function SubString(string, start, end) {
// Use the one character string cache. // Use the one character string cache.
if (start + 1 == end) { if (start + 1 == end) return %_StringCharAt(string, start);
return %_StringCharAt(string, start);
}
return %_SubString(string, start, end); return %_SubString(string, start, end);
} }
...@@ -208,7 +204,10 @@ function StringReplace(search, replace) { ...@@ -208,7 +204,10 @@ function StringReplace(search, replace) {
replace); replace);
} }
} else { } else {
return StringReplaceRegExp(subject, search, replace); return %StringReplaceRegExpWithString(subject,
search,
TO_STRING_INLINE(replace),
lastMatchInfo);
} }
} }
...@@ -224,7 +223,11 @@ function StringReplace(search, replace) { ...@@ -224,7 +223,11 @@ function StringReplace(search, replace) {
// Compute the string to replace with. // Compute the string to replace with.
if (IS_FUNCTION(replace)) { if (IS_FUNCTION(replace)) {
builder.add(replace.call(null, search, start, subject)); builder.add(%_CallFunction(%GetGlobalReceiver(),
search,
start,
subject,
replace));
} else { } else {
reusableMatchInfo[CAPTURE0] = start; reusableMatchInfo[CAPTURE0] = start;
reusableMatchInfo[CAPTURE1] = end; reusableMatchInfo[CAPTURE1] = end;
...@@ -239,15 +242,6 @@ function StringReplace(search, replace) { ...@@ -239,15 +242,6 @@ function StringReplace(search, replace) {
} }
// Helper function for regular expressions in String.prototype.replace.
function StringReplaceRegExp(subject, regexp, replace) {
return %StringReplaceRegExpWithString(subject,
regexp,
TO_STRING_INLINE(replace),
lastMatchInfo);
}
// Expand the $-expressions in the string and return a new string with // Expand the $-expressions in the string and return a new string with
// the result. // the result.
function ExpandReplacement(string, subject, matchInfo, builder) { function ExpandReplacement(string, subject, matchInfo, builder) {
...@@ -408,9 +402,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { ...@@ -408,9 +402,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
lastMatchInfoOverride = override; lastMatchInfoOverride = override;
var func_result = var func_result =
%_CallFunction(receiver, elem, match_start, subject, replace); %_CallFunction(receiver, elem, match_start, subject, replace);
if (!IS_STRING(func_result)) { func_result = TO_STRING_INLINE(func_result);
func_result = NonStringToString(func_result);
}
res[i] = func_result; res[i] = func_result;
match_start += elem.length; match_start += elem.length;
} }
...@@ -424,9 +416,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) { ...@@ -424,9 +416,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
// Use the apply argument as backing for global RegExp properties. // Use the apply argument as backing for global RegExp properties.
lastMatchInfoOverride = elem; lastMatchInfoOverride = elem;
var func_result = replace.apply(null, elem); var func_result = replace.apply(null, elem);
if (!IS_STRING(func_result)) { func_result = TO_STRING_INLINE(func_result);
func_result = NonStringToString(func_result);
}
res[i] = func_result; res[i] = func_result;
} }
i++; i++;
...@@ -487,8 +477,7 @@ function StringSearch(re) { ...@@ -487,8 +477,7 @@ function StringSearch(re) {
} else { } else {
regexp = new $RegExp(re); regexp = new $RegExp(re);
} }
var s = TO_STRING_INLINE(this); var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0);
var match = DoRegExpExec(regexp, s, 0);
if (match) { if (match) {
return match[CAPTURE0]; return match[CAPTURE0];
} }
...@@ -576,14 +565,14 @@ function StringSplit(separator, limit) { ...@@ -576,14 +565,14 @@ function StringSplit(separator, limit) {
while (true) { while (true) {
if (startIndex === length) { if (startIndex === length) {
result[result.length] = subject.slice(currentIndex, length); result.push(subject.slice(currentIndex, length));
break; break;
} }
var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); var matchInfo = splitMatch(separator, subject, currentIndex, startIndex);
if (IS_NULL(matchInfo)) { if (IS_NULL(matchInfo)) {
result[result.length] = subject.slice(currentIndex, length); result.push(subject.slice(currentIndex, length));
break; break;
} }
...@@ -595,17 +584,21 @@ function StringSplit(separator, limit) { ...@@ -595,17 +584,21 @@ function StringSplit(separator, limit) {
continue; continue;
} }
result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]); result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0]));
if (result.length === limit) break; if (result.length === limit) break;
var num_captures = NUMBER_OF_CAPTURES(matchInfo); var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
for (var i = 2; i < num_captures; i += 2) { for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
var start = matchInfo[CAPTURE(i)]; var start = matchInfo[i++];
var end = matchInfo[CAPTURE(i + 1)]; var end = matchInfo[i++];
if (start != -1 && end != -1) { if (end != -1) {
result[result.length] = SubString(subject, start, end); if (start + 1 == end) {
result.push(%_StringCharAt(subject, start));
} else {
result.push(%_SubString(subject, start, end));
}
} else { } else {
result[result.length] = void 0; result.push(void 0);
} }
if (result.length === limit) break outer_loop; if (result.length === limit) break outer_loop;
} }
...@@ -656,7 +649,9 @@ function StringSubstring(start, end) { ...@@ -656,7 +649,9 @@ function StringSubstring(start, end) {
} }
} }
return SubString(s, start_i, end_i); return (start_i + 1 == end_i
? %_StringCharAt(s, start_i)
: %_SubString(s, start_i, end_i));
} }
...@@ -694,7 +689,9 @@ function StringSubstr(start, n) { ...@@ -694,7 +689,9 @@ function StringSubstr(start, n) {
var end = start + len; var end = start + len;
if (end > s.length) end = s.length; if (end > s.length) end = s.length;
return SubString(s, start, end); return (start + 1 == end
? %_StringCharAt(s, start)
: %_SubString(s, start, end));
} }
......
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