Index: src/runtime.cc |
=================================================================== |
--- src/runtime.cc (revision 11415) |
+++ src/runtime.cc (working copy) |
@@ -2882,12 +2882,19 @@ |
} |
+static void SetLastMatchInfoNoCaptures(Handle<String> subject, |
ulan
2012/04/23 16:59:23
Why not just move the implementation here, instead
Erik Corry
2012/04/23 18:54:02
Because then it would be hard to review.
Done.
|
+ Handle<JSArray> last_match_info, |
+ int match_start, |
+ int match_end); |
+ |
+ |
template<typename ResultSeqString> |
-MUST_USE_RESULT static MaybeObject* StringReplaceStringWithString( |
+MUST_USE_RESULT static MaybeObject* StringReplaceAtomRegExpWithString( |
Isolate* isolate, |
Handle<String> subject, |
Handle<JSRegExp> pattern_regexp, |
- Handle<String> replacement) { |
+ Handle<String> replacement, |
+ Handle<JSArray> last_match_info) { |
ASSERT(subject->IsFlat()); |
ASSERT(replacement->IsFlat()); |
@@ -2946,6 +2953,12 @@ |
subject_pos, |
subject_len); |
} |
+ |
+ SetLastMatchInfoNoCaptures(subject, |
+ last_match_info, |
+ indices.at(matches - 1), |
+ indices.at(matches - 1) + pattern_len); |
+ |
return *result; |
} |
@@ -2994,11 +3007,19 @@ |
compiled_replacement.simple_hint()) { |
if (subject_handle->HasOnlyAsciiChars() && |
replacement_handle->HasOnlyAsciiChars()) { |
- return StringReplaceStringWithString<SeqAsciiString>( |
- isolate, subject_handle, regexp_handle, replacement_handle); |
+ return StringReplaceAtomRegExpWithString<SeqAsciiString>( |
+ isolate, |
+ subject_handle, |
+ regexp_handle, |
+ replacement_handle, |
+ last_match_info_handle); |
} else { |
- return StringReplaceStringWithString<SeqTwoByteString>( |
- isolate, subject_handle, regexp_handle, replacement_handle); |
+ return StringReplaceAtomRegExpWithString<SeqTwoByteString>( |
+ isolate, |
+ subject_handle, |
+ regexp_handle, |
+ replacement_handle, |
+ last_match_info_handle); |
} |
} |
@@ -3087,21 +3108,29 @@ |
Handle<String> subject_handle(subject); |
Handle<JSRegExp> regexp_handle(regexp); |
+ Handle<JSArray> last_match_info_handle(last_match_info); |
// Shortcut for simple non-regexp global replacements |
if (regexp_handle->GetFlags().is_global() && |
regexp_handle->TypeTag() == JSRegExp::ATOM) { |
Handle<String> empty_string_handle(HEAP->empty_string()); |
if (subject_handle->HasOnlyAsciiChars()) { |
- return StringReplaceStringWithString<SeqAsciiString>( |
- isolate, subject_handle, regexp_handle, empty_string_handle); |
+ return StringReplaceAtomRegExpWithString<SeqAsciiString>( |
+ isolate, |
+ subject_handle, |
+ regexp_handle, |
+ empty_string_handle, |
+ last_match_info_handle); |
} else { |
- return StringReplaceStringWithString<SeqTwoByteString>( |
- isolate, subject_handle, regexp_handle, empty_string_handle); |
+ return StringReplaceAtomRegExpWithString<SeqTwoByteString>( |
+ isolate, |
+ subject_handle, |
+ regexp_handle, |
+ empty_string_handle, |
+ last_match_info_handle); |
} |
} |
- Handle<JSArray> last_match_info_handle(last_match_info); |
Handle<Object> match = RegExpImpl::Exec(regexp_handle, |
subject_handle, |
0, |
@@ -3121,6 +3150,10 @@ |
end = RegExpImpl::GetCapture(match_info_array, 1); |
} |
+ bool global = regexp_handle->GetFlags().is_global(); |
+ |
+ if (start == end && !global) return *subject_handle; |
+ |
int length = subject_handle->length(); |
int new_length = length - (end - start); |
if (new_length == 0) { |
@@ -3136,7 +3169,7 @@ |
} |
// If the regexp isn't global, only match once. |
- if (!regexp_handle->GetFlags().is_global()) { |
+ if (!global) { |
if (start > 0) { |
String::WriteToFlat(*subject_handle, |
answer->GetChars(), |
@@ -3838,6 +3871,8 @@ |
} |
+// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain |
+// separate last match info. See comment on that function. |
static RegExpImpl::IrregexpResult SearchRegExpMultiple( |
Isolate* isolate, |
Handle<String> subject, |
@@ -3866,10 +3901,6 @@ |
// End of previous match. Differs from pos if match was empty. |
int match_end = 0; |
if (result == RegExpImpl::RE_SUCCESS) { |
- // Need to keep a copy of the previous match for creating last_match_info |
- // at the end, so we have two vectors that we swap between. |
- OffsetsVector registers2(required_registers, isolate); |
- Vector<int> prev_register_vector(registers2.vector(), registers2.length()); |
bool first = true; |
do { |
int match_start = register_vector[0]; |
@@ -3922,11 +3953,6 @@ |
elements->set(capture_count + 2, *subject); |
builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
} |
- // Swap register vectors, so the last successful match is in |
- // prev_register_vector. |
- Vector<int32_t> tmp = prev_register_vector; |
- prev_register_vector = register_vector; |
- register_vector = tmp; |
if (match_end > match_start) { |
pos = match_end; |
@@ -3958,12 +3984,12 @@ |
last_match_array->EnsureSize(last_match_array_size); |
AssertNoAllocation no_gc; |
FixedArray* elements = FixedArray::cast(last_match_array->elements()); |
+ // We have to set this even though the rest of the last match array is |
+ // ignored. |
RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count); |
+ // These are also read without consulting the override. |
RegExpImpl::SetLastSubject(elements, *subject); |
RegExpImpl::SetLastInput(elements, *subject); |
- for (int i = 0; i < last_match_capture_count; i++) { |
- RegExpImpl::SetCapture(elements, i, prev_register_vector[i]); |
- } |
return RegExpImpl::RE_SUCCESS; |
} |
} |
@@ -3972,6 +3998,9 @@ |
} |
+// This is only called for StringReplaceGlobalRegExpWithFunction. This sets |
+// lastMatchInfoOverride to maintain the last match info, so we don't need to |
+// set any other last match array info. |
RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { |
ASSERT(args.length() == 4); |
HandleScope handles(isolate); |