Chromium Code Reviews| Index: src/string.js |
| =================================================================== |
| --- src/string.js (revision 6062) |
| +++ src/string.js (working copy) |
| @@ -159,7 +159,7 @@ |
| function StringMatch(regexp) { |
| var subject = TO_STRING_INLINE(this); |
| if (IS_REGEXP(regexp)) { |
| - if (!regexp.global) return regexp.exec(subject); |
| + if (!regexp.global) return RegExpExecNoTests(regexp, subject, 0); |
| %_Log('regexp', 'regexp-match,%0S,%1r', [subject, regexp]); |
| // lastMatchInfo is defined in regexp.js. |
| return %StringMatch(subject, regexp, lastMatchInfo); |
| @@ -247,14 +247,14 @@ |
| function ExpandReplacement(string, subject, matchInfo, builder) { |
| var next = %StringIndexOf(string, '$', 0); |
| if (next < 0) { |
| - builder.add(string); |
| + builder.addString(string); |
| return; |
| } |
| // Compute the number of captures; see ECMA-262, 15.5.4.11, p. 102. |
| var m = NUMBER_OF_CAPTURES(matchInfo) >> 1; // Includes the match. |
| - if (next > 0) builder.add(SubString(string, 0, next)); |
| + if (next > 0) builder.elements.push(SubString(string, 0, next)); |
|
Lasse Reichstein
2010/12/17 10:38:30
Consider extracting elements from builder, so you
sandholm
2010/12/17 11:50:24
Done.
|
| var length = string.length; |
| while (true) { |
| @@ -264,7 +264,7 @@ |
| var peek = %_StringCharCodeAt(string, position); |
| if (peek == 36) { // $$ |
| ++position; |
| - builder.add('$'); |
| + builder.elements.push('$'); |
| } else if (peek == 38) { // $& - match |
| ++position; |
| builder.addSpecialSlice(matchInfo[CAPTURE0], |
| @@ -301,14 +301,14 @@ |
| // digit capture references, we can only enter here when a |
| // single digit capture reference is outside the range of |
| // captures. |
| - builder.add('$'); |
| + builder.elements.push('$'); |
| --position; |
| } |
| } else { |
| - builder.add('$'); |
| + builder.elements.push('$'); |
| } |
| } else { |
| - builder.add('$'); |
| + builder.elements.push('$'); |
| } |
| // Go the the next $ in the string. |
| @@ -318,13 +318,13 @@ |
| // haven't reached the end, we need to append the suffix. |
| if (next < 0) { |
| if (position < length) { |
| - builder.add(SubString(string, position, length)); |
| + builder.elements.push(SubString(string, position, length)); |
| } |
| return; |
| } |
| // Append substring between the previous and the next $ character. |
| - builder.add(SubString(string, position, next)); |
| + builder.addString(SubString(string, position, next)); |
| } |
| }; |
| @@ -559,23 +559,23 @@ |
| var currentIndex = 0; |
| var startIndex = 0; |
| + var startMatch = 0; |
| var result = []; |
| outer_loop: |
| while (true) { |
| if (startIndex === length) { |
| - result.push(subject.slice(currentIndex, length)); |
| + result.push(SubString(subject, currentIndex, length)); |
| break; |
| } |
| - var matchInfo = splitMatch(separator, subject, currentIndex, startIndex); |
| - |
| - if (IS_NULL(matchInfo)) { |
| - result.push(subject.slice(currentIndex, length)); |
| + var matchInfo = DoRegExpExec(separator, subject, startIndex); |
| + if (IS_NULL_OR_UNDEFINED(matchInfo) |
|
Lasse Reichstein
2010/12/17 10:38:30
Why accept undefined?
sandholm
2010/12/17 11:50:24
I am just applying the same semantics as the inlin
|
| + || length === (startMatch = matchInfo[CAPTURE0])) { |
| + result.push(SubString(subject, currentIndex, length)); |
| break; |
| } |
| - |
| var endIndex = matchInfo[CAPTURE1]; |
| // We ignore a zero-length match at the currentIndex. |
| @@ -584,7 +584,12 @@ |
| continue; |
| } |
| - result.push(SubString(subject, currentIndex, matchInfo[CAPTURE0])); |
| + if (currentIndex + 1 == startMatch) { |
|
Lasse Reichstein
2010/12/17 10:38:30
Does this really pay off? It seems to be simply in
sandholm
2010/12/17 11:50:24
It is faster. I generally only inline call sites w
|
| + result.push(%_StringCharAt(subject, currentIndex)); |
| + } else { |
| + result.push(%_SubString(subject, currentIndex, startMatch)); |
| + } |
| + |
| if (result.length === limit) break; |
| var matchinfo_len = NUMBER_OF_CAPTURES(matchInfo) + REGEXP_FIRST_CAPTURE; |
| @@ -609,19 +614,6 @@ |
| } |
| -// ECMA-262 section 15.5.4.14 |
| -// Helper function used by split. This version returns the matchInfo |
| -// instead of allocating a new array with basically the same information. |
| -function splitMatch(separator, subject, current_index, start_index) { |
| - var matchInfo = DoRegExpExec(separator, subject, start_index); |
| - if (matchInfo == null) return null; |
| - // Section 15.5.4.14 paragraph two says that we do not allow zero length |
| - // matches at the end of the string. |
| - if (matchInfo[CAPTURE0] === subject.length) return null; |
| - return matchInfo; |
| -} |
| - |
| - |
| // ECMA-262 section 15.5.4.15 |
| function StringSubstring(start, end) { |
| var s = TO_STRING_INLINE(this); |
| @@ -844,24 +836,26 @@ |
| ReplaceResultBuilder.prototype.add = function(str) { |
| str = TO_STRING_INLINE(str); |
| - if (str.length > 0) { |
| - var elements = this.elements; |
| - elements[elements.length] = str; |
| - } |
| + if (str.length > 0) this.elements.push(str); |
| } |
| +ReplaceResultBuilder.prototype.addString = function(str) { |
| + if (str.length > 0) this.elements.push(str); |
| +} |
| + |
| + |
| ReplaceResultBuilder.prototype.addSpecialSlice = function(start, end) { |
| var len = end - start; |
| if (start < 0 || len <= 0) return; |
| - var elements = this.elements; |
| if (start < 0x80000 && len < 0x800) { |
| - elements[elements.length] = (start << 11) | len; |
| + this.elements.push((start << 11) | len); |
| } else { |
| // 0 < len <= String::kMaxLength and Smi::kMaxValue >= String::kMaxLength, |
| // so -len is a smi. |
| - elements[elements.length] = -len; |
| - elements[elements.length] = start; |
| + var elements = this.elements; |
| + elements.push(-len); |
| + elements.push(start); |
| } |
| } |