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:
parent
a6e6131bf7
commit
c9b3e45cca
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user