Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(150)

Unified Diff: src/runtime.cc

Issue 10837290: Cache results in SearchRegExpMultiple. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.cc ('k') | test/mjsunit/regexp-results-cache.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
}
« no previous file with comments | « src/heap.cc ('k') | test/mjsunit/regexp-results-cache.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698