Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index 3e07b998230373201759e445fe14693343f033d9..7689a1acae5591abf2b23adba008e6d451675f4e 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2769,6 +2769,164 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder, |
} |
+void FindAsciiStringIndices(Vector<const char> subject, |
+ char pattern, |
Yang
2011/09/07 13:33:40
Moved up from further below.
|
+ ZoneList<int>* indices, |
+ unsigned int limit) { |
+ ASSERT(limit > 0); |
+ // Collect indices of pattern in subject using memchr. |
+ // Stop after finding at most limit values. |
+ const char* subject_start = reinterpret_cast<const char*>(subject.start()); |
+ const char* subject_end = subject_start + subject.length(); |
+ const char* pos = subject_start; |
+ while (limit > 0) { |
+ pos = reinterpret_cast<const char*>( |
+ memchr(pos, pattern, subject_end - pos)); |
+ if (pos == NULL) return; |
+ indices->Add(static_cast<int>(pos - subject_start)); |
+ pos++; |
+ limit--; |
+ } |
+} |
+ |
+ |
+template <typename SubjectChar, typename PatternChar> |
+void FindStringIndices(Isolate* isolate, |
+ Vector<const SubjectChar> subject, |
Yang
2011/09/07 13:33:40
Moved up from further below.
|
+ Vector<const PatternChar> pattern, |
+ ZoneList<int>* indices, |
+ unsigned int limit) { |
+ ASSERT(limit > 0); |
+ // Collect indices of pattern in subject. |
+ // Stop after finding at most limit values. |
+ int pattern_length = pattern.length(); |
+ int index = 0; |
+ StringSearch<PatternChar, SubjectChar> search(isolate, pattern); |
+ while (limit > 0) { |
+ index = search.Search(subject, index); |
+ if (index < 0) return; |
+ indices->Add(index); |
+ index += pattern_length; |
+ limit--; |
+ } |
+} |
+ |
+ |
+void FindStringIndicesDispatch(Isolate* isolate, |
+ String* subject, |
+ String* pattern, |
+ ZoneList<int>* indices, |
+ unsigned int limit) { |
+ { |
Yang
2011/09/07 13:33:40
Refactored code from Runtime_StringSplit.
|
+ AssertNoAllocation no_gc; |
+ String::FlatContent subject_content = subject->GetFlatContent(); |
+ String::FlatContent pattern_content = pattern->GetFlatContent(); |
+ ASSERT(subject_content.IsFlat()); |
+ ASSERT(pattern_content.IsFlat()); |
+ if (subject_content.IsAscii()) { |
+ Vector<const char> subject_vector = subject_content.ToAsciiVector(); |
+ if (pattern_content.IsAscii()) { |
+ Vector<const char> pattern_vector = pattern_content.ToAsciiVector(); |
+ if (pattern_vector.length() == 1) { |
+ FindAsciiStringIndices(subject_vector, |
+ pattern_vector[0], |
+ indices, |
+ limit); |
+ } else { |
+ FindStringIndices(isolate, |
+ subject_vector, |
+ pattern_vector, |
+ indices, |
+ limit); |
+ } |
+ } else { |
+ FindStringIndices(isolate, |
+ subject_vector, |
+ pattern_content.ToUC16Vector(), |
+ indices, |
+ limit); |
+ } |
+ } else { |
+ Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); |
+ if (pattern->IsAsciiRepresentation()) { |
+ FindStringIndices(isolate, |
+ subject_vector, |
+ pattern_content.ToAsciiVector(), |
+ indices, |
+ limit); |
+ } else { |
+ FindStringIndices(isolate, |
+ subject_vector, |
+ pattern_content.ToUC16Vector(), |
+ indices, |
+ limit); |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+template<typename ResultSeqString> |
+MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString( |
+ Isolate* isolate, |
+ Handle<String> subject, |
+ Handle<JSRegExp> pattern_regexp, |
+ Handle<String> replacement = Handle<String>::null()) { |
Lasse Reichstein
2011/09/07 13:50:53
Don't use an optional argument, just pass the null
|
+ ASSERT(subject->IsFlat()); |
+ ASSERT(replacement->IsFlat()); |
+ |
+ ZoneScope zone_space(isolate, DELETE_ON_EXIT); |
+ ZoneList<int> indices(8); |
+ String* pattern = |
+ String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); |
Lasse Reichstein
2011/09/07 13:50:53
Assert that the regexp is atomic.
|
+ int subject_len = subject->length(); |
+ int pattern_len = pattern->length(); |
+ int replacement_len = (replacement.is_null()) ? 0 : replacement->length(); |
+ |
+ FindStringIndicesDispatch(isolate, *subject, pattern, &indices, 0xffffffff); |
+ |
+ int matches = indices.length(); |
+ if (matches == 0) return *subject; |
+ |
+ int result_len = (replacement_len - pattern_len) * matches + subject_len; |
+ int subject_pos = 0; |
+ int result_pos = 0; |
+ |
+ Handle<ResultSeqString> result; |
+ if (ResultSeqString::kHasAsciiEncoding) { |
+ result = Handle<ResultSeqString>::cast( |
+ isolate->factory()->NewRawAsciiString(result_len)); |
+ } else { |
+ result = Handle<ResultSeqString>::cast( |
+ isolate->factory()->NewRawTwoByteString(result_len)); |
+ } |
+ |
+ for(int i = 0; i < matches; i++) { |
+ // Copy non-matched subject content. |
+ String::WriteToFlat(*subject, |
Lasse Reichstein
2011/09/07 13:50:53
Would it be worth it to check that that subject_po
|
+ result->GetChars() + result_pos, |
+ subject_pos, |
+ indices.at(i)); |
+ result_pos += indices.at(i) - subject_pos; |
+ // Replace match. |
Lasse Reichstein
2011/09/07 13:50:53
Move comment down one line.
|
+ |
+ if (replacement_len > 0) { |
+ String::WriteToFlat(*replacement, |
+ result->GetChars() + result_pos, |
+ 0, |
+ replacement_len); |
+ result_pos += replacement_len; |
+ } |
+ |
+ subject_pos = indices.at(i) + pattern_len; |
+ } |
+ String::WriteToFlat(*subject, |
+ result->GetChars() + result_pos, |
+ subject_pos, |
+ subject_len); |
+ return *result; |
+} |
+ |
MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( |
Isolate* isolate, |
@@ -2808,6 +2966,20 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString( |
bool is_global = regexp_handle->GetFlags().is_global(); |
+ // Shortcut for simple non-regexp global replacements |
+ if (is_global && |
+ regexp->TypeTag() == JSRegExp::ATOM && |
+ compiled_replacement.parts() == 1) { |
+ if (subject_handle->HasOnlyAsciiChars() && |
+ replacement_handle->HasOnlyAsciiChars()) { |
+ return StringReplaceStringWithString<SeqAsciiString>( |
+ isolate, subject_handle, regexp_handle, replacement_handle); |
+ } else { |
+ return StringReplaceStringWithString<SeqTwoByteString>( |
+ isolate, subject_handle, regexp_handle, replacement_handle); |
+ } |
+ } |
+ |
// Guessing the number of parts that the final result string is built |
// from. Global regexps can match any number of times, so we guess |
// conservatively. |
@@ -2893,6 +3065,19 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString( |
Handle<String> subject_handle(subject); |
Handle<JSRegExp> regexp_handle(regexp); |
+ |
+ // Shortcut for simple non-regexp global replacements |
+ if (regexp_handle->GetFlags().is_global() && |
+ regexp_handle->TypeTag() == JSRegExp::ATOM) { |
+ if (subject_handle->HasOnlyAsciiChars()) { |
+ return StringReplaceStringWithString<SeqAsciiString>( |
+ isolate, subject_handle, regexp_handle); |
+ } else { |
+ return StringReplaceStringWithString<SeqTwoByteString>( |
+ isolate, subject_handle, regexp_handle); |
+ } |
+ } |
+ |
Handle<JSArray> last_match_info_handle(last_match_info); |
Handle<Object> match = RegExpImpl::Exec(regexp_handle, |
subject_handle, |
@@ -5930,49 +6115,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringTrim) { |
} |
-void FindAsciiStringIndices(Vector<const char> subject, |
- char pattern, |
- ZoneList<int>* indices, |
- unsigned int limit) { |
- ASSERT(limit > 0); |
- // Collect indices of pattern in subject using memchr. |
- // Stop after finding at most limit values. |
- const char* subject_start = reinterpret_cast<const char*>(subject.start()); |
- const char* subject_end = subject_start + subject.length(); |
- const char* pos = subject_start; |
- while (limit > 0) { |
- pos = reinterpret_cast<const char*>( |
- memchr(pos, pattern, subject_end - pos)); |
- if (pos == NULL) return; |
- indices->Add(static_cast<int>(pos - subject_start)); |
- pos++; |
- limit--; |
- } |
-} |
- |
- |
-template <typename SubjectChar, typename PatternChar> |
-void FindStringIndices(Isolate* isolate, |
- Vector<const SubjectChar> subject, |
- Vector<const PatternChar> pattern, |
- ZoneList<int>* indices, |
- unsigned int limit) { |
- ASSERT(limit > 0); |
- // Collect indices of pattern in subject. |
- // Stop after finding at most limit values. |
- int pattern_length = pattern.length(); |
- int index = 0; |
- StringSearch<PatternChar, SubjectChar> search(isolate, pattern); |
- while (limit > 0) { |
- index = search.Search(subject, index); |
- if (index < 0) return; |
- indices->Add(index); |
- index += pattern_length; |
- limit--; |
- } |
-} |
- |
- |
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
ASSERT(args.length() == 3); |
HandleScope handle_scope(isolate); |
@@ -6012,53 +6154,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
ZoneList<int> indices(initial_capacity); |
if (!pattern->IsFlat()) FlattenString(pattern); |
- // No allocation block. |
- { |
- AssertNoAllocation no_gc; |
- String::FlatContent subject_content = subject->GetFlatContent(); |
- String::FlatContent pattern_content = pattern->GetFlatContent(); |
- ASSERT(subject_content.IsFlat()); |
- ASSERT(pattern_content.IsFlat()); |
- if (subject_content.IsAscii()) { |
- Vector<const char> subject_vector = subject_content.ToAsciiVector(); |
- if (pattern_content.IsAscii()) { |
- Vector<const char> pattern_vector = pattern_content.ToAsciiVector(); |
- if (pattern_vector.length() == 1) { |
- FindAsciiStringIndices(subject_vector, |
- pattern_vector[0], |
- &indices, |
- limit); |
- } else { |
- FindStringIndices(isolate, |
- subject_vector, |
- pattern_vector, |
- &indices, |
- limit); |
- } |
- } else { |
- FindStringIndices(isolate, |
- subject_vector, |
- pattern_content.ToUC16Vector(), |
- &indices, |
- limit); |
- } |
- } else { |
- Vector<const uc16> subject_vector = subject_content.ToUC16Vector(); |
- if (pattern->IsAsciiRepresentation()) { |
- FindStringIndices(isolate, |
- subject_vector, |
- pattern_content.ToAsciiVector(), |
- &indices, |
- limit); |
- } else { |
- FindStringIndices(isolate, |
- subject_vector, |
- pattern_content.ToUC16Vector(), |
- &indices, |
- limit); |
- } |
- } |
- } |
+ FindStringIndicesDispatch(isolate, *subject, *pattern, &indices, limit); |
if (static_cast<uint32_t>(indices.length()) < limit) { |
indices.Add(subject_length); |