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

Unified Diff: src/runtime.cc

Issue 1014005: Attempt at pre-calculating replace regexp matches. (Closed)
Patch Set: Reuse result array. Avoid using apply. Created 10 years, 9 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/runtime.h ('k') | src/string.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 492bca79469cf16d8d5d3abc29612bc72b65e4b4..fc3a9a5570a0f25f008a2304d51bfbde9e163cdc 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1226,6 +1226,129 @@ static Object* Runtime_RegExpExec(Arguments args) {
return *result;
}
+static Object* Runtime_RegExpExecMultiple(Arguments args) {
+ HandleScope scope;
+ ASSERT(args.length() == 4);
+
+ CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
+ CONVERT_ARG_CHECKED(String, subject, 1);
+ CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
+ CONVERT_ARG_CHECKED(JSArray, result_array, 3);
+ RUNTIME_ASSERT(last_match_info->HasFastElements());
+ RUNTIME_ASSERT(result_array->HasFastElements());
+ RUNTIME_ASSERT(regexp->GetFlags().is_global());
+
+ ZoneScope zone(DELETE_ON_EXIT);
+ // TODO(lrn): Be much smarter about calling the regexp exec
+ // function in a loop! And split execution into Atom and Irregexp
+ // parts (atoms never have captures and can call StringMatch directly).
+ ZoneList<Smi*> captures(256);
+ // Number of captures per regexp match (excluding the match itself).
+
+ int capture_count =
+ RegExpImpl::RegExpNumberOfCaptures(FixedArray::cast(regexp->data()));
+ int subject_length = subject->length();
+
+ // Execute regexp once. If absolutely no match, we exit fast.
+ // Otherwise prepare to repeat execution.
+ Handle<Object> result =
+ RegExpImpl::Exec(regexp, subject, 0, last_match_info);
+ if (result.is_null()) {
+ return Failure::Exception();
+ }
+ if (result->IsNull()) {
+ // No match at all, return null.
+ return Smi::FromInt(0);
+ }
+
+ ASSERT_EQ(*last_match_info, *result);
+ ASSERT(last_match_info->HasFastElements());
+
+ // Include the match itself as a capture.
+ int capture_reg_count = (capture_count + 1) * 2;
+
+ ASSERT_EQ(capture_reg_count,
+ Smi::cast(FixedArray::cast(last_match_info->elements())->
+ get(RegExpImpl::kLastCaptureCount))->value());
+
+ int index;
+ int matches = 0;
+ do {
+ {
+ AssertNoAllocation no_gc;
+ ASSERT(last_match_info->HasFastElements());
+
+ FixedArray* match_array = FixedArray::cast(last_match_info->elements());
+ Smi* match_start =
+ Smi::cast(match_array->get(RegExpImpl::kFirstCapture));
+ Smi* match_end =
+ Smi::cast(match_array->get(RegExpImpl::kFirstCapture + 1));
+ captures.Add(match_start);
+ captures.Add(match_end);
+ // TODO(lrn): Expand, if necessary, captures list in one go and
+ // use memcpy to copy captures.
+ for (int i = 2; i < capture_reg_count; i++) {
+ captures.Add(
+ Smi::cast(match_array->get(RegExpImpl::kFirstCapture + i)));
+ }
+ matches++;
+ index = match_end->value();
+ if (match_start == match_end) {
+ index++;
+ if (index > subject_length) {
+ break;
+ }
+ }
+ }
+ result = RegExpImpl::Exec(regexp, subject, index, last_match_info);
+ if (result.is_null()) {
+ return Failure::Exception();
+ }
+ } while (!result->IsNull());
+
+ // Done collecting match indices. Now create a result array on the format:
+ // - Smi number of captures (not including match) per match
+ // - for each match:
+ // - smi index of match
+ // - match substring
+ // - for each capture
+ // - captured substring, or undefined if capture is not participating.
+ int array_length = 1 + (2 + capture_count) * matches;
+ result_array->Resize(array_length);
+ result_array->set_length(Smi::FromInt(array_length));
+ Handle<FixedArray> elements(FixedArray::cast(result_array->elements()));
+
+ elements->set(0, Smi::FromInt(capture_count));
+ int capture_index = 0;
+ int result_index = 1;
+ for (int i = 0; i < matches; i++) {
+ Smi* from = captures.at(capture_index);
+ Smi* to = captures.at(capture_index + 1);
+ elements->set(result_index, from);
+ elements->set(result_index + 1, *Factory::NewSubString(subject,
+ from->value(),
+ to->value()));
+ result_index += 2;
+ capture_index += 2;
+ for (int j = 0; j < capture_count; j++) {
+ int from = captures.at(capture_index)->value();
+ if (from >= 0) {
+ int to = captures.at(capture_index + 1)->value();
+ ASSERT(to >= 0);
+ elements->set(result_index,
+ *Factory::NewSubString(subject, from, to));
+ } else {
+ ASSERT(captures.at(capture_index + 1)->value() < 0);
+ elements->set(result_index, Heap::undefined_value());
+ }
+ capture_index += 2;
+ result_index++;
+ }
+ }
+
+ return Smi::FromInt(matches);
+}
+
static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
HandleScope scope;
@@ -5073,7 +5196,7 @@ static Object* FlatStringCompare(String* x, String* y) {
Vector<const char> x_chars = x->ToAsciiVector();
if (y->IsAsciiRepresentation()) {
Vector<const char> y_chars = y->ToAsciiVector();
- r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
+ r = memcmp(x_chars.start(), y_chars.start(), prefix_length);
} else {
Vector<const uc16> y_chars = y->ToUC16Vector();
r = CompareChars(x_chars.start(), y_chars.start(), prefix_length);
@@ -5121,10 +5244,8 @@ static Object* Runtime_StringCompare(Arguments args) {
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
- Object* obj = Heap::PrepareForCompare(x);
- if (obj->IsFailure()) return obj;
- obj = Heap::PrepareForCompare(y);
- if (obj->IsFailure()) return obj;
+ x->TryFlatten();
+ y->TryFlatten();
return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
: StringInputBufferCompare(x, y);
@@ -5325,21 +5446,12 @@ static Object* Runtime_Math_round(Arguments args) {
NoHandleAllocation ha;
ASSERT(args.length() == 1);
Counters::math_round.Increment();
- CONVERT_DOUBLE_CHECKED(x, args[0]);
-
- if (x > 0 && x < Smi::kMaxValue) {
- return Smi::FromInt(static_cast<int>(x + 0.5));
- }
+ CONVERT_DOUBLE_CHECKED(x, args[0]);
if (signbit(x) && x >= -0.5) return Heap::minus_zero_value();
-
- // if the magnitude is big enough, there's no place for fraction part. If we
- // try to add 0.5 to this number, 1.0 will be added instead.
- if (x >= 9007199254740991.0 || x <= -9007199254740991.0) {
- return args[0];
- }
-
- return Heap::NumberFromDouble(floor(x + 0.5));
+ double integer = ceil(x);
+ if (integer - x > 0.5) { integer -= 1.0; }
+ return Heap::NumberFromDouble(integer);
}
« no previous file with comments | « src/runtime.h ('k') | src/string.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698