Permalink
Browse files

Optimizing BuildResultFromMatchInfo, StringReplace and StringSplit.

  • Loading branch information...
1 parent 1e49433 commit 425a221b02306cb43b4aae64d7d2f2734958a376 sandholm@chromium.org committed Dec 13, 2010
Showing with 76 additions and 83 deletions.
  1. +31 −35 src/regexp.js
  2. +45 −48 src/string.js
View
66 src/regexp.js
@@ -120,22 +120,28 @@ function DoRegExpExec(regexp, string, index) {
function BuildResultFromMatchInfo(lastMatchInfo, s) {
var numResults = NUMBER_OF_CAPTURES(lastMatchInfo) >> 1;
- var result = %_RegExpConstructResult(numResults, lastMatchInfo[CAPTURE0], s);
- if (numResults === 1) {
- var matchStart = lastMatchInfo[CAPTURE(0)];
- var matchEnd = lastMatchInfo[CAPTURE(1)];
- result[0] = SubString(s, matchStart, matchEnd);
+ var start = lastMatchInfo[CAPTURE0];
+ var end = lastMatchInfo[CAPTURE1];
+ var result = %_RegExpConstructResult(numResults, start, s);
+ if (start + 1 == end) {
+ result[0] = %_StringCharAt(s, start);
} else {
- for (var i = 0; i < numResults; i++) {
- var matchStart = lastMatchInfo[CAPTURE(i << 1)];
- var matchEnd = lastMatchInfo[CAPTURE((i << 1) + 1)];
- if (matchStart != -1 && matchEnd != -1) {
- result[i] = SubString(s, matchStart, matchEnd);
+ result[0] = %_SubString(s, start, end);
+ }
+ var j = REGEXP_FIRST_CAPTURE + 2;
+ for (var i = 1; i < numResults; i++) {
+ start = lastMatchInfo[j++];
+ end = lastMatchInfo[j++];
+ if (end != -1) {
+ if (start + 1 == end) {
+ result[i] = %_StringCharAt(s, start);
} else {
- // Make sure the element is present. Avoid reading the undefined
- // property from the global object since this may change.
- result[i] = void 0;
+ result[i] = %_SubString(s, start, end);
}
+ } 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;
@@ -166,12 +172,7 @@ function RegExpExec(string) {
}
string = regExpInput;
}
- var s;
- if (IS_STRING(string)) {
- s = string;
- } else {
- s = ToString(string);
- }
+ string = TO_STRING_INLINE(string);
var lastIndex = this.lastIndex;
// Conversion is required by the ES5 specification (RegExp.prototype.exec
@@ -180,17 +181,17 @@ function RegExpExec(string) {
var global = this.global;
if (global) {
- if (i < 0 || i > s.length) {
+ if (i < 0 || i > string.length) {
this.lastIndex = 0;
return null;
}
} else {
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.
- var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
+ var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
if (matchIndices === null) {
if (global) this.lastIndex = 0;
@@ -202,7 +203,7 @@ function RegExpExec(string) {
if (global) {
this.lastIndex = lastMatchInfo[CAPTURE1];
}
- return BuildResultFromMatchInfo(matchIndices, s);
+ return BuildResultFromMatchInfo(matchIndices, string);
}
@@ -227,12 +228,7 @@ function RegExpTest(string) {
string = regExpInput;
}
- var s;
- if (IS_STRING(string)) {
- s = string;
- } else {
- s = ToString(string);
- }
+ string = TO_STRING_INLINE(string);
var lastIndex = this.lastIndex;
@@ -241,13 +237,13 @@ function RegExpTest(string) {
var i = TO_INTEGER(lastIndex);
if (this.global) {
- if (i < 0 || i > s.length) {
+ if (i < 0 || i > string.length) {
this.lastIndex = 0;
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.
- var matchIndices = %_RegExpExec(this, s, i, lastMatchInfo);
+ var matchIndices = %_RegExpExec(this, string, i, lastMatchInfo);
if (matchIndices === null) {
this.lastIndex = 0;
return false;
@@ -269,11 +265,11 @@ function RegExpTest(string) {
(this.ignoreCase ? 'i' : '')
+ (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.
- var matchIndices = %_RegExpExec(this, s, 0, lastMatchInfo);
+ var matchIndices = %_RegExpExec(this, string, 0, lastMatchInfo);
if (matchIndices === null) return false;
lastMatchInfoOverride = null;
return true;
View
93 src/string.js
@@ -101,28 +101,28 @@ function StringConcat() {
// ECMA-262 section 15.5.4.7
-function StringIndexOf(searchString /* position */) { // length == 1
- var subject_str = TO_STRING_INLINE(this);
- var pattern_str = TO_STRING_INLINE(searchString);
- var subject_str_len = subject_str.length;
- var pattern_str_len = pattern_str.length;
+function StringIndexOf(pattern /* position */) { // length == 1
+ var subject = TO_STRING_INLINE(this);
+ var pattern = TO_STRING_INLINE(pattern);
+ var subject_len = subject.length;
+ var pattern_len = pattern.length;
var index = 0;
if (%_ArgumentsLength() > 1) {
var arg1 = %_Arguments(1); // position
index = TO_INTEGER(arg1);
}
if (index < 0) index = 0;
- if (index > subject_str_len) index = subject_str_len;
- if (pattern_str_len + index > subject_str_len) return -1;
- return %StringIndexOf(subject_str, pattern_str, index);
+ if (index > subject_len) index = subject_len;
+ if (pattern_len + index > subject_len) return -1;
+ return %StringIndexOf(subject, pattern, index);
}
// 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 subLength = sub.length;
- var pat = TO_STRING_INLINE(searchString);
+ var pat = TO_STRING_INLINE(pat);
var patLength = pat.length;
var index = subLength - patLength;
if (%_ArgumentsLength() > 1) {
@@ -150,10 +150,8 @@ function StringLastIndexOf(searchString /* position */) { // length == 1
// do anything locale specific.
function StringLocaleCompare(other) {
if (%_ArgumentsLength() === 0) return 0;
-
- var this_str = TO_STRING_INLINE(this);
- var other_str = TO_STRING_INLINE(other);
- return %StringLocaleCompare(this_str, other_str);
+ return %StringLocaleCompare(TO_STRING_INLINE(this),
+ TO_STRING_INLINE(other));
}
@@ -177,9 +175,7 @@ function StringMatch(regexp) {
// otherwise we call the runtime system.
function SubString(string, start, end) {
// Use the one character string cache.
- if (start + 1 == end) {
- return %_StringCharAt(string, start);
- }
+ if (start + 1 == end) return %_StringCharAt(string, start);
return %_SubString(string, start, end);
}
@@ -208,7 +204,10 @@ function StringReplace(search, replace) {
replace);
}
} else {
- return StringReplaceRegExp(subject, search, replace);
+ return %StringReplaceRegExpWithString(subject,
+ search,
+ TO_STRING_INLINE(replace),
+ lastMatchInfo);
}
}
@@ -224,7 +223,11 @@ function StringReplace(search, replace) {
// Compute the string to replace with.
if (IS_FUNCTION(replace)) {
- builder.add(replace.call(null, search, start, subject));
+ builder.add(%_CallFunction(%GetGlobalReceiver(),
+ search,
+ start,
+ subject,
+ replace));
} else {
reusableMatchInfo[CAPTURE0] = start;
reusableMatchInfo[CAPTURE1] = end;
@@ -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
// the result.
function ExpandReplacement(string, subject, matchInfo, builder) {
@@ -408,9 +402,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
lastMatchInfoOverride = override;
var func_result =
%_CallFunction(receiver, elem, match_start, subject, replace);
- if (!IS_STRING(func_result)) {
- func_result = NonStringToString(func_result);
- }
+ func_result = TO_STRING_INLINE(func_result);
res[i] = func_result;
match_start += elem.length;
}
@@ -424,9 +416,7 @@ function StringReplaceGlobalRegExpWithFunction(subject, regexp, replace) {
// Use the apply argument as backing for global RegExp properties.
lastMatchInfoOverride = elem;
var func_result = replace.apply(null, elem);
- if (!IS_STRING(func_result)) {
- func_result = NonStringToString(func_result);
- }
+ func_result = TO_STRING_INLINE(func_result);
res[i] = func_result;
}
i++;
@@ -487,8 +477,7 @@ function StringSearch(re) {
} else {
regexp = new $RegExp(re);
}
- var s = TO_STRING_INLINE(this);
- var match = DoRegExpExec(regexp, s, 0);
+ var match = DoRegExpExec(regexp, TO_STRING_INLINE(this), 0);
if (match) {
return match[CAPTURE0];
}
@@ -576,14 +565,14 @@ function StringSplit(separator, limit) {
while (true) {
if (startIndex === length) {
- result[result.length] = subject.slice(currentIndex, length);
+ result.push(subject.slice(currentIndex, length));
break;
}
var matchInfo = splitMatch(separator, subject, currentIndex, startIndex);
if (IS_NULL(matchInfo)) {
- result[result.length] = subject.slice(currentIndex, length);
+ result.push(subject.slice(currentIndex, length));
break;
}
@@ -595,17 +584,21 @@ function StringSplit(separator, limit) {
continue;
}
- result[result.length] = SubString(subject, currentIndex, matchInfo[CAPTURE0]);
+ result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0]));
if (result.length === limit) break;
- var num_captures = NUMBER_OF_CAPTURES(matchInfo);
- for (var i = 2; i < num_captures; i += 2) {
- var start = matchInfo[CAPTURE(i)];
- var end = matchInfo[CAPTURE(i + 1)];
- if (start != -1 && end != -1) {
- result[result.length] = SubString(subject, start, end);
+ var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE;
+ for (var i = REGEXP_FIRST_CAPTURE + 2; i < matchinfo_len; ) {
+ var start = matchInfo[i++];
+ var end = matchInfo[i++];
+ if (end != -1) {
+ if (start + 1 == end) {
+ result.push(%_StringCharAt(subject, start));
+ } else {
+ result.push(%_SubString(subject, start, end));
+ }
} else {
- result[result.length] = void 0;
+ result.push(void 0);
}
if (result.length === limit) break outer_loop;
}
@@ -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) {
var end = start + len;
if (end > s.length) end = s.length;
- return SubString(s, start, end);
+ return (start + 1 == end
+ ? %_StringCharAt(s, start)
+ : %_SubString(s, start, end));
}

0 comments on commit 425a221

Please sign in to comment.