Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index d4d18c41679fc1d1b670b9298a01df2219b9c1ce..7212953f7f1a51b10e1b4cc94215f7a30c94258e 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -2412,18 +2412,19 @@ class FixedArrayBuilder { |
return array_->length(); |
} |
- Handle<JSArray> ToJSArray() { |
- Handle<JSArray> result_array = FACTORY->NewJSArrayWithElements(array_); |
- result_array->set_length(Smi::FromInt(length_)); |
- return result_array; |
- } |
- |
Handle<JSArray> ToJSArray(Handle<JSArray> target_array) { |
FACTORY->SetContent(target_array, array_); |
target_array->set_length(Smi::FromInt(length_)); |
return target_array; |
} |
+ |
+ static int GetFinalLength(Handle<FixedArray> array) { |
ulan
2012/08/31 08:52:51
It can be removed now.
|
+ // Get final length from last element. |
+ return Smi::cast(array->get(array->length() - 1))->value(); |
+ } |
+ |
+ |
private: |
Handle<FixedArray> array_; |
int length_; |
@@ -2542,10 +2543,6 @@ class ReplacementStringBuilder { |
character_count_ += by; |
} |
- Handle<JSArray> GetParts() { |
- return array_builder_.ToJSArray(); |
- } |
- |
private: |
Handle<SeqAsciiString> NewRawAsciiString(int length) { |
return heap_->isolate()->factory()->NewRawAsciiString(length); |
@@ -3666,21 +3663,57 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringMatch) { |
// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain |
// separate last match info. See comment on that function. |
template<bool has_capture> |
-static int SearchRegExpMultiple( |
+static MaybeObject* SearchRegExpMultiple( |
Isolate* isolate, |
Handle<String> subject, |
Handle<JSRegExp> regexp, |
Handle<JSArray> last_match_array, |
- FixedArrayBuilder* builder) { |
+ Handle<JSArray> result_array) { |
ASSERT(subject->IsFlat()); |
ASSERT_NE(has_capture, regexp->CaptureCount() == 0); |
- RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); |
- if (global_cache.HasException()) return RegExpImpl::RE_EXCEPTION; |
- |
int capture_count = regexp->CaptureCount(); |
int subject_length = subject->length(); |
+ static const int kMinLengthToCache = 0x1000; |
+ |
+ if (subject_length > kMinLengthToCache) { |
+ Handle<Object> cached_answer(RegExpResultsCache::Lookup( |
+ isolate->heap(), |
+ *subject, |
+ regexp->data(), |
+ RegExpResultsCache::REGEXP_MULTIPLE_INDICES)); |
+ if (*cached_answer != Smi::FromInt(0)) { |
+ Handle<FixedArray> cached_fixed_array = |
+ Handle<FixedArray>(FixedArray::cast(*cached_answer)); |
+ // The cache FixedArray is a COW-array and can therefore be reused. |
+ isolate->factory()->SetContent(result_array, cached_fixed_array); |
+ // The actual length of the result array is stored in the last element of |
+ // the backing store (the backing FixedArray may have a larger capacity). |
+ Object* cached_fixed_array_last_element = |
+ cached_fixed_array->get(cached_fixed_array->length() - 1); |
+ Smi* js_array_length = Smi::cast(cached_fixed_array_last_element); |
+ result_array->set_length(js_array_length); |
+ RegExpImpl::SetLastMatchInfo( |
+ last_match_array, subject, capture_count, NULL); |
+ return *result_array; |
+ } |
+ } |
+ |
+ RegExpImpl::GlobalCache global_cache(regexp, subject, true, isolate); |
+ if (global_cache.HasException()) return Failure::Exception(); |
+ |
+ Handle<FixedArray> result_elements; |
+ if (result_array->HasFastObjectElements()) { |
+ result_elements = |
+ Handle<FixedArray>(FixedArray::cast(result_array->elements())); |
+ } |
+ if (result_elements.is_null() || result_elements->length() < 16) { |
+ result_elements = isolate->factory()->NewFixedArrayWithHoles(16); |
+ } |
+ |
+ FixedArrayBuilder builder(result_elements); |
+ |
// Position to search from. |
int match_start = -1; |
int match_end = 0; |
@@ -3693,9 +3726,9 @@ static int SearchRegExpMultiple( |
int32_t* current_match = global_cache.FetchNext(); |
if (current_match == NULL) break; |
match_start = current_match[0]; |
- builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
+ builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch); |
if (match_end < match_start) { |
- ReplacementStringBuilder::AddSubjectSlice(builder, |
+ ReplacementStringBuilder::AddSubjectSlice(&builder, |
match_end, |
match_start); |
} |
@@ -3737,19 +3770,19 @@ static int SearchRegExpMultiple( |
} |
elements->set(capture_count + 1, Smi::FromInt(match_start)); |
elements->set(capture_count + 2, *subject); |
- builder->Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
+ builder.Add(*isolate->factory()->NewJSArrayWithElements(elements)); |
} else { |
- builder->Add(*match); |
+ builder.Add(*match); |
} |
} |
} |
- if (global_cache.HasException()) return RegExpImpl::RE_EXCEPTION; |
+ if (global_cache.HasException()) return Failure::Exception(); |
if (match_start >= 0) { |
// Finished matching, with at least one match. |
if (match_end < subject_length) { |
- ReplacementStringBuilder::AddSubjectSlice(builder, |
+ ReplacementStringBuilder::AddSubjectSlice(&builder, |
match_end, |
subject_length); |
} |
@@ -3757,9 +3790,23 @@ static int SearchRegExpMultiple( |
RegExpImpl::SetLastMatchInfo( |
last_match_array, subject, capture_count, NULL); |
- return RegExpImpl::RE_SUCCESS; |
+ if (subject_length > kMinLengthToCache) { |
+ // Store the length of the result array into the last element of the |
+ // backing FixedArray. |
+ builder.EnsureCapacity(1); |
+ Handle<FixedArray> fixed_array = builder.array(); |
+ fixed_array->set(fixed_array->length() - 1, |
+ Smi::FromInt(builder.length())); |
+ // Cache the result and turn the FixedArray into a COW array. |
+ RegExpResultsCache::Enter(isolate->heap(), |
+ *subject, |
+ regexp->data(), |
+ *fixed_array, |
+ RegExpResultsCache::REGEXP_MULTIPLE_INDICES); |
+ } |
+ return *builder.ToJSArray(result_array); |
} else { |
- return RegExpImpl::RE_FAILURE; // No matches at all. |
+ return isolate->heap()->null_value(); // No matches at all. |
} |
} |
@@ -3779,29 +3826,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_RegExpExecMultiple) { |
ASSERT(last_match_info->HasFastObjectElements()); |
ASSERT(regexp->GetFlags().is_global()); |
- Handle<FixedArray> result_elements; |
- if (result_array->HasFastObjectElements()) { |
- result_elements = |
- Handle<FixedArray>(FixedArray::cast(result_array->elements())); |
- } |
- if (result_elements.is_null() || result_elements->length() < 16) { |
- result_elements = isolate->factory()->NewFixedArrayWithHoles(16); |
- } |
- FixedArrayBuilder builder(result_elements); |
- int result; |
if (regexp->CaptureCount() == 0) { |
- result = SearchRegExpMultiple<false>( |
- isolate, subject, regexp, last_match_info, &builder); |
+ return SearchRegExpMultiple<false>( |
+ isolate, subject, regexp, last_match_info, result_array); |
} else { |
- result = SearchRegExpMultiple<true>( |
- isolate, subject, regexp, last_match_info, &builder); |
+ return SearchRegExpMultiple<true>( |
+ isolate, subject, regexp, last_match_info, 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(); |
} |
@@ -6118,11 +6150,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
RUNTIME_ASSERT(pattern_length > 0); |
if (limit == 0xffffffffu) { |
- Handle<Object> cached_answer(StringSplitCache::Lookup( |
- isolate->heap()->string_split_cache(), |
+ Handle<Object> cached_answer(RegExpResultsCache::Lookup( |
+ isolate->heap(), |
*subject, |
- *pattern)); |
+ *pattern, |
+ RegExpResultsCache::STRING_SPLIT_SUBSTRINGS)); |
if (*cached_answer != Smi::FromInt(0)) { |
+ // The cache FixedArray is a COW-array and can therefore be reused. |
Handle<JSArray> result = |
isolate->factory()->NewJSArrayWithElements( |
Handle<FixedArray>::cast(cached_answer)); |
@@ -6182,11 +6216,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringSplit) { |
if (limit == 0xffffffffu) { |
if (result->HasFastObjectElements()) { |
- StringSplitCache::Enter(isolate->heap(), |
- isolate->heap()->string_split_cache(), |
- *subject, |
- *pattern, |
- *elements); |
+ RegExpResultsCache::Enter(isolate->heap(), |
+ *subject, |
+ *pattern, |
+ *elements, |
+ RegExpResultsCache::STRING_SPLIT_SUBSTRINGS); |
} |
} |