Chromium Code Reviews| 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); |