Adding boolean saveAnswer property of RegExpCache to avoid unnecessary cloning of the regexp answer object/array.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4364 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sandholm@chromium.org 2010-04-08 14:42:27 +00:00
parent a6e6131bf7
commit c9b3e45cca
2 changed files with 40 additions and 30 deletions

View File

@ -126,6 +126,9 @@ function RegExpCache() {
this.replaceString = 0; this.replaceString = 0;
this.lastIndex = 0; this.lastIndex = 0;
this.answer = 0; this.answer = 0;
// answerSaved marks whether the contents of answer is valid for a cache
// hit in RegExpExec, StringMatch and StringSplit.
this.answerSaved = false;
} }
@ -133,6 +136,7 @@ var regExpCache = new RegExpCache();
function CloneRegexpAnswer(array) { function CloneRegexpAnswer(array) {
if (array == null) return null;
var len = array.length; var len = array.length;
var answer = new $Array(len); var answer = new $Array(len);
for (var i = 0; i < len; i++) { for (var i = 0; i < len; i++) {
@ -151,17 +155,19 @@ function RegExpExec(string) {
} }
var cache = regExpCache; var cache = regExpCache;
var saveAnswer = false;
if (%_ObjectEquals(cache.type, 'exec') && if (%_ObjectEquals(cache.type, 'exec') &&
%_ObjectEquals(cache.lastIndex, this.lastIndex) && %_ObjectEquals(cache.lastIndex, this.lastIndex) &&
%_ObjectEquals(cache.regExp, this) && %_ObjectEquals(cache.regExp, this) &&
%_ObjectEquals(cache.subject, string)) { %_ObjectEquals(cache.subject, string)) {
var last = cache.answer; if (cache.answerSaved) {
if (last == null) { return CloneRegexpAnswer(cache.answer);
return last;
} else { } else {
return CloneRegexpAnswer(last); saveAnswer = true;
} }
} else {
cache.answerSaved = false;
} }
if (%_ArgumentsLength() == 0) { if (%_ArgumentsLength() == 0) {
@ -196,6 +202,7 @@ function RegExpExec(string) {
cache.regExp = this; cache.regExp = this;
cache.subject = s; cache.subject = s;
cache.answer = matchIndices; // Null. cache.answer = matchIndices; // Null.
cache.answerSaved = true; // Safe since no cloning is needed.
cache.type = 'exec'; cache.type = 'exec';
return matchIndices; // No match. return matchIndices; // No match.
} }
@ -225,15 +232,18 @@ function RegExpExec(string) {
result.input = s; result.input = s;
if (this.global) { if (this.global) {
this.lastIndex = lastMatchInfo[CAPTURE1]; this.lastIndex = lastMatchInfo[CAPTURE1];
return result;
} else { } else {
cache.regExp = this; cache.regExp = this;
cache.subject = s; cache.subject = s;
cache.lastIndex = lastIndex; cache.lastIndex = lastIndex;
cache.answer = result; if (saveAnswer) {
cache.answer = CloneRegexpAnswer(result);
cache.answerSaved = true;
}
cache.type = 'exec'; cache.type = 'exec';
return CloneRegexpAnswer(result);
} }
return result;
} }

View File

@ -170,15 +170,15 @@ function StringMatch(regexp) {
if (!regexp.global) return regexp.exec(subject); if (!regexp.global) return regexp.exec(subject);
var cache = regExpCache; var cache = regExpCache;
var saveAnswer = false;
if (%_ObjectEquals(cache.type, 'match') && if (%_ObjectEquals(cache.type, 'match') &&
%_ObjectEquals(cache.regExp, regexp) && %_ObjectEquals(cache.regExp, regexp) &&
%_ObjectEquals(cache.subject, subject)) { %_ObjectEquals(cache.subject, subject)) {
var last = cache.answer; if (cache.answerSaved) {
if (last == null) { return CloneRegexpAnswer(cache.answer);
return last;
} else { } else {
return CloneRegexpAnswer(last); saveAnswer = true;
} }
} }
@ -188,12 +188,9 @@ function StringMatch(regexp) {
cache.type = 'match'; cache.type = 'match';
cache.regExp = regexp; cache.regExp = regexp;
cache.subject = subject; cache.subject = subject;
cache.answer = result; if (saveAnswer) cache.answer = CloneRegexpAnswer(result);
if (result == null) { cache.answerSaved = saveAnswer;
return result; return result;
} else {
return CloneRegexpAnswer(result);
}
} }
@ -596,11 +593,16 @@ function StringSplit(separator, limit) {
} }
var cache = regExpCache; var cache = regExpCache;
var saveAnswer = false;
if (%_ObjectEquals(cache.type, 'split') && if (%_ObjectEquals(cache.type, 'split') &&
%_ObjectEquals(cache.regExp, separator) && %_ObjectEquals(cache.regExp, separator) &&
%_ObjectEquals(cache.subject, subject)) { %_ObjectEquals(cache.subject, subject)) {
return CloneRegexpAnswer(cache.answer); if (cache.answerSaved) {
return CloneRegexpAnswer(cache.answer);
} else {
saveAnswer = true;
}
} }
cache.type = 'split'; cache.type = 'split';
@ -610,6 +612,7 @@ function StringSplit(separator, limit) {
%_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]); %_Log('regexp', 'regexp-split,%0S,%1r', [subject, separator]);
if (length === 0) { if (length === 0) {
cache.answerSaved = true;
if (splitMatch(separator, subject, 0, 0) != null) { if (splitMatch(separator, subject, 0, 0) != null) {
cache.answer = []; cache.answer = [];
return []; return [];
@ -622,20 +625,19 @@ function StringSplit(separator, limit) {
var startIndex = 0; var startIndex = 0;
var result = []; var result = [];
outer_loop:
while (true) { while (true) {
if (startIndex === length) { if (startIndex === length) {
result[result.length] = subject.slice(currentIndex, length); result[result.length] = subject.slice(currentIndex, length);
cache.answer = result; break;
return CloneRegexpAnswer(result);
} }
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[result.length] = subject.slice(currentIndex, length);
cache.answer = result; break;
return CloneRegexpAnswer(result);
} }
var endIndex = matchInfo[CAPTURE1]; var endIndex = matchInfo[CAPTURE1];
@ -647,10 +649,7 @@ function StringSplit(separator, limit) {
} }
result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]); result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]);
if (result.length === limit) { if (result.length === limit) break;
cache.answer = result;
return CloneRegexpAnswer(result);
}
var num_captures = NUMBER_OF_CAPTURES(matchInfo); var num_captures = NUMBER_OF_CAPTURES(matchInfo);
for (var i = 2; i < num_captures; i += 2) { for (var i = 2; i < num_captures; i += 2) {
@ -661,14 +660,15 @@ function StringSplit(separator, limit) {
} else { } else {
result[result.length] = void 0; result[result.length] = void 0;
} }
if (result.length === limit) { if (result.length === limit) break outer_loop;
cache.answer = result;
return CloneRegexpAnswer(result);
}
} }
startIndex = currentIndex = endIndex; startIndex = currentIndex = endIndex;
} }
if (saveAnswer) cache.answer = CloneRegexpAnswer(result);
cache.answerSaved = saveAnswer;
return result;
} }