Chromium Code Reviews| Index: src/runtime.cc |
| diff --git a/src/runtime.cc b/src/runtime.cc |
| index 0b80effbf21e86138f7e66ea6290998d3922b7de..d2f73f0c445cdad076fe013d8c3d1cfe7c6a0d02 100644 |
| --- a/src/runtime.cc |
| +++ b/src/runtime.cc |
| @@ -3795,7 +3795,7 @@ static bool SearchStringMultiple(Isolate* isolate, |
| } |
| -static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple( |
| +static int SearchRegExpNoCaptureMultiple( |
|
Erik Corry
2012/05/11 11:01:00
I wonder if we can unify this and SearchRegExpMult
Yang
2012/05/16 14:58:47
I'll try this in another CL.
|
| Isolate* isolate, |
| Handle<String> subject, |
| Handle<JSRegExp> regexp, |
| @@ -3808,41 +3808,53 @@ static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple( |
| int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
| if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; |
| - OffsetsVector registers(required_registers, isolate); |
| + OffsetsVector registers(OffsetsVector::kStaticOffsetsVectorSize, isolate); |
| + static const int max_result_sets = |
| + OffsetsVector::kStaticOffsetsVectorSize / 2; |
| Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| int subject_length = subject->length(); |
| bool first = true; |
| - |
| for (;;) { // Break on failure, return on exception. |
| - RegExpImpl::IrregexpResult result = |
| + int result = |
|
Erik Corry
2012/05/11 11:01:00
How about giving this variable a name like number_
Yang
2012/05/16 14:58:47
Done.
|
| RegExpImpl::IrregexpExecOnce(regexp, |
| subject, |
| pos, |
| register_vector); |
| - if (result == RegExpImpl::RE_SUCCESS) { |
| - match_start = register_vector[0]; |
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| - if (match_end < match_start) { |
| - ReplacementStringBuilder::AddSubjectSlice(builder, |
| - match_end, |
| - match_start); |
| - } |
| - match_end = register_vector[1]; |
| - HandleScope loop_scope(isolate); |
| - if (!first) { |
| - builder->Add(*isolate->factory()->NewProperSubString(subject, |
| - match_start, |
| - match_end)); |
| - } else { |
| - builder->Add(*isolate->factory()->NewSubString(subject, |
| - match_start, |
| - match_end)); |
| + if (result >= RegExpImpl::RE_SUCCESS) { |
| + for (int result_index = 0; result_index < result; result_index++) { |
| + int32_t* current_result_set = ®ister_vector[result_index * 2]; |
| + match_start = current_result_set[0]; |
| + builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| + if (match_end < match_start) { |
| + ReplacementStringBuilder::AddSubjectSlice(builder, |
| + match_end, |
| + match_start); |
| + } |
| + match_end = current_result_set[1]; |
| + HandleScope loop_scope(isolate); |
| + if (!first) { |
| + builder->Add(*isolate->factory()->NewProperSubString(subject, |
| + match_start, |
| + match_end)); |
| + } else { |
| + builder->Add(*isolate->factory()->NewSubString(subject, |
| + match_start, |
| + match_end)); |
| + } |
| + first = false; |
| } |
| + |
| + // If we did not get the maximum number of resultsets, we can stop here |
| + // since there are no matches left. |
| + if (result < max_result_sets) break; |
| + |
| if (match_start != match_end) { |
|
Erik Corry
2012/05/11 11:01:00
I don't see this logic replicated in the regexp-ma
|
| pos = match_end; |
| } else { |
| pos = match_end + 1; |
| - if (pos > subject_length) break; |
| + if (pos > subject_length) { |
|
Erik Corry
2012/05/11 11:01:00
unneeded edit
|
| + break; |
| + } |
| } |
| } else if (result == RegExpImpl::RE_FAILURE) { |
| break; |
| @@ -3850,7 +3862,6 @@ static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple( |
| ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| return result; |
| } |
| - first = false; |
| } |
| if (match_start >= 0) { |
| @@ -3872,7 +3883,7 @@ static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple( |
| // 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( |
| +static int SearchRegExpMultiple( |
| Isolate* isolate, |
| Handle<String> subject, |
| Handle<JSRegExp> regexp, |
| @@ -3880,17 +3891,19 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple( |
| FixedArrayBuilder* builder) { |
| ASSERT(subject->IsFlat()); |
| - int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject); |
| - if (required_registers < 0) return RegExpImpl::RE_EXCEPTION; |
| + int registers_per_result_set = RegExpImpl::IrregexpPrepare(regexp, subject); |
| + if (registers_per_result_set < 0) return RegExpImpl::RE_EXCEPTION; |
| - OffsetsVector registers(required_registers, isolate); |
| + int num_registers = Min(OffsetsVector::kStaticOffsetsVectorSize, |
| + registers_per_result_set); |
| + int max_result_sets = num_registers / registers_per_result_set; |
| + OffsetsVector registers(OffsetsVector::kStaticOffsetsVectorSize, isolate); |
| Vector<int32_t> register_vector(registers.vector(), registers.length()); |
| - RegExpImpl::IrregexpResult result = |
| - RegExpImpl::IrregexpExecOnce(regexp, |
| - subject, |
| - 0, |
| - register_vector); |
| + int result = RegExpImpl::IrregexpExecOnce(regexp, |
| + subject, |
| + 0, |
| + register_vector); |
| int capture_count = regexp->CaptureCount(); |
| int subject_length = subject->length(); |
| @@ -3899,60 +3912,71 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple( |
| int pos = 0; |
| // End of previous match. Differs from pos if match was empty. |
| int match_end = 0; |
| - if (result == RegExpImpl::RE_SUCCESS) { |
| + if (result >= RegExpImpl::RE_SUCCESS) { |
| bool first = true; |
| do { |
| - int match_start = register_vector[0]; |
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| - if (match_end < match_start) { |
| - ReplacementStringBuilder::AddSubjectSlice(builder, |
| - match_end, |
| - match_start); |
| - } |
| - match_end = register_vector[1]; |
| - |
| - { |
| - // Avoid accumulating new handles inside loop. |
| - HandleScope temp_scope(isolate); |
| - // Arguments array to replace function is match, captures, index and |
| - // subject, i.e., 3 + capture count in total. |
| - Handle<FixedArray> elements = |
| - isolate->factory()->NewFixedArray(3 + capture_count); |
| - Handle<String> match; |
| - if (!first) { |
| - match = isolate->factory()->NewProperSubString(subject, |
| - match_start, |
| - match_end); |
| - } else { |
| - match = isolate->factory()->NewSubString(subject, |
| - match_start, |
| - match_end); |
| + int match_start = 0; |
| + for (int result_index = 0; result_index < result; result_index++) { |
| + int32_t* current_result_set = |
| + ®ister_vector[result_index * registers_per_result_set]; |
| + match_start = current_result_set[0]; |
| + builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
| + if (match_end < match_start) { |
| + ReplacementStringBuilder::AddSubjectSlice(builder, |
| + match_end, |
| + match_start); |
| } |
| - elements->set(0, *match); |
| - for (int i = 1; i <= capture_count; i++) { |
| - int start = register_vector[i * 2]; |
| - if (start >= 0) { |
| - int end = register_vector[i * 2 + 1]; |
| - ASSERT(start <= end); |
| - Handle<String> substring; |
| - if (!first) { |
| - substring = isolate->factory()->NewProperSubString(subject, |
| - start, |
| - end); |
| + match_end = current_result_set[1]; |
| + |
| + { |
| + // Avoid accumulating new handles inside loop. |
| + HandleScope temp_scope(isolate); |
| + // Arguments array to replace function is match, captures, index and |
| + // subject, i.e., 3 + capture count in total. |
| + Handle<FixedArray> elements = |
| + isolate->factory()->NewFixedArray(3 + capture_count); |
| + Handle<String> match; |
| + if (!first) { |
| + match = isolate->factory()->NewProperSubString(subject, |
|
Erik Corry
2012/05/11 11:01:00
Not sure why we need NewProperSubString here.
Yang
2012/05/16 14:58:47
For every substring save for the first one we know
|
| + match_start, |
| + match_end); |
| + } else { |
| + match = isolate->factory()->NewSubString(subject, |
| + match_start, |
| + match_end); |
| + } |
| + elements->set(0, *match); |
| + for (int i = 1; i <= capture_count; i++) { |
|
Erik Corry
2012/05/11 11:01:00
I think you could just start this loop at 0 and re
Yang
2012/05/16 14:58:47
After removing the call to NewSubString here (firs
|
| + int start = current_result_set[i * 2]; |
| + if (start >= 0) { |
| + int end = current_result_set[i * 2 + 1]; |
| + ASSERT(start <= end); |
| + Handle<String> substring; |
| + if (!first) { |
| + substring = isolate->factory()->NewProperSubString(subject, |
| + start, |
| + end); |
| + } else { |
| + substring = isolate->factory()->NewSubString(subject, |
| + start, |
| + end); |
| + } |
| + elements->set(i, *substring); |
| } else { |
| - substring = isolate->factory()->NewSubString(subject, start, end); |
| + ASSERT(current_result_set[i * 2 + 1] < 0); |
| + elements->set(i, isolate->heap()->undefined_value()); |
| } |
| - elements->set(i, *substring); |
| - } else { |
| - ASSERT(register_vector[i * 2 + 1] < 0); |
| - elements->set(i, isolate->heap()->undefined_value()); |
| } |
| + elements->set(capture_count + 1, Smi::FromInt(match_start)); |
| + elements->set(capture_count + 2, *subject); |
| + builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
| } |
| - elements->set(capture_count + 1, Smi::FromInt(match_start)); |
| - elements->set(capture_count + 2, *subject); |
| - builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
| } |
| + // If we did not get the maximum number of resultsets, we can stop here |
| + // since there are no matches left. |
| + if (result < max_result_sets) break; |
| + |
| if (match_end > match_start) { |
| pos = match_end; |
| } else { |
| @@ -3967,7 +3991,7 @@ static RegExpImpl::IrregexpResult SearchRegExpMultiple( |
| pos, |
| register_vector); |
| first = false; |
| - } while (result == RegExpImpl::RE_SUCCESS); |
| + } while (result >= RegExpImpl::RE_SUCCESS); |
| if (result != RegExpImpl::RE_EXCEPTION) { |
| // Finished matching, with at least one match. |
| @@ -4035,7 +4059,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { |
| ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP); |
| - RegExpImpl::IrregexpResult result; |
| + int result; |
| if (regexp->CaptureCount() == 0) { |
| result = SearchRegExpNoCaptureMultiple(isolate, |
| subject, |
| @@ -4049,7 +4073,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { |
| last_match_info, |
| &builder); |
| } |
| - if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); |
| + if (result >= RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array); |
| if (result == RegExpImpl::RE_FAILURE) return isolate->heap()->null_value(); |
| ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION); |
| return Failure::Exception(); |