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

Side by Side Diff: src/runtime.cc

Issue 42221: Added handle scope to inner loop of replace to avoid unbounded handle creation. (Closed)
Patch Set: Created 11 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
Erik Corry 2009/03/16 09:48:09 2009?
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution. 11 // with the distribution.
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1128 : subject_(subject), 1128 : subject_(subject),
1129 parts_(Factory::NewFixedArray(estimated_part_count)), 1129 parts_(Factory::NewFixedArray(estimated_part_count)),
1130 part_count_(0), 1130 part_count_(0),
1131 character_count_(0), 1131 character_count_(0),
1132 is_ascii_(StringShape(*subject).IsAsciiRepresentation()) { 1132 is_ascii_(StringShape(*subject).IsAsciiRepresentation()) {
1133 // Require a non-zero initial size. Ensures that doubling the size to 1133 // Require a non-zero initial size. Ensures that doubling the size to
1134 // extend the array will work. 1134 // extend the array will work.
1135 ASSERT(estimated_part_count > 0); 1135 ASSERT(estimated_part_count > 0);
1136 } 1136 }
1137 1137
1138 void EnsureCapacity(int elements) {
1139 int length = parts_->length();
1140 int required_length = part_count_ + elements;
1141 if (length < required_length) {
1142 int new_length = length;
1143 do {
1144 new_length *= 2;
1145 } while (new_length < required_length);
1146 Handle<FixedArray> extended_array =
1147 Factory::NewFixedArray(new_length);
1148 parts_->CopyTo(0, *extended_array, 0, part_count_);
1149 parts_ = extended_array;
1150 }
1151 }
1152
1138 void AddSubjectSlice(int from, int to) { 1153 void AddSubjectSlice(int from, int to) {
1139 ASSERT(from >= 0); 1154 ASSERT(from >= 0);
1140 int length = to - from; 1155 int length = to - from;
1141 ASSERT(length >= 0); 1156 ASSERT(length > 0);
1142 if (length > 0) { 1157 // Can we encode the slice in 11 bits for length and 19 bits for
1143 // Can we encode the slice in 11 bits for length and 19 bits for 1158 // start position - as used by StringBuilderConcatHelper?
1144 // start position - as used by StringBuilderConcatHelper? 1159 if (StringBuilderSubstringLength::is_valid(length) &&
1145 if (StringBuilderSubstringLength::is_valid(length) && 1160 StringBuilderSubstringPosition::is_valid(from)) {
1146 StringBuilderSubstringPosition::is_valid(from)) { 1161 int encoded_slice = StringBuilderSubstringLength::encode(length) |
1147 int encoded_slice = StringBuilderSubstringLength::encode(length) | 1162 StringBuilderSubstringPosition::encode(from);
1148 StringBuilderSubstringPosition::encode(from); 1163 AddElement(Handle<Object>(Smi::FromInt(encoded_slice)));
1149 AddElement(Handle<Object>(Smi::FromInt(encoded_slice))); 1164 } else {
1150 } else { 1165 Handle<String> slice = Factory::NewStringSlice(subject_, from, to);
1151 Handle<String> slice = Factory::NewStringSlice(subject_, from, to); 1166 AddElement(slice);
1152 AddElement(slice);
1153 }
1154 IncrementCharacterCount(length);
1155 } 1167 }
1168 IncrementCharacterCount(length);
1156 } 1169 }
1157 1170
1158 1171
1159 void AddString(Handle<String> string) { 1172 void AddString(Handle<String> string) {
1160 StringShape shape(*string); 1173 StringShape shape(*string);
1161 int length = string->length(shape); 1174 int length = string->length(shape);
1162 if (length > 0) { 1175 ASSERT(length > 0);
1163 AddElement(string); 1176 AddElement(string);
1164 if (!shape.IsAsciiRepresentation()) { 1177 if (!shape.IsAsciiRepresentation()) {
1165 is_ascii_ = false; 1178 is_ascii_ = false;
1166 }
1167 IncrementCharacterCount(length);
1168 } 1179 }
1180 IncrementCharacterCount(length);
1169 } 1181 }
1170 1182
1171 1183
1172 Handle<String> ToString() { 1184 Handle<String> ToString() {
1173 if (part_count_ == 0) { 1185 if (part_count_ == 0) {
1174 return Factory::empty_string(); 1186 return Factory::empty_string();
1175 } 1187 }
1176 1188
1177 Handle<String> joined_string; 1189 Handle<String> joined_string;
1178 if (is_ascii_) { 1190 if (is_ascii_) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 1228
1217 1229
1218 Handle<String> NewRawTwoByteString(int size) { 1230 Handle<String> NewRawTwoByteString(int size) {
1219 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String); 1231 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1220 } 1232 }
1221 1233
1222 1234
1223 void AddElement(Handle<Object> element) { 1235 void AddElement(Handle<Object> element) {
1224 ASSERT(element->IsSmi() || element->IsString()); 1236 ASSERT(element->IsSmi() || element->IsString());
1225 // Extend parts_ array if necessary. 1237 // Extend parts_ array if necessary.
1226 if (parts_->length() == part_count_) {
1227 Handle<FixedArray> extended_array =
1228 Factory::NewFixedArray(part_count_ * 2);
1229 parts_->CopyTo(0, *extended_array, 0, part_count_);
1230 parts_ = extended_array;
1231 }
1232 parts_->set(part_count_, *element); 1238 parts_->set(part_count_, *element);
1233 part_count_++; 1239 part_count_++;
1234 } 1240 }
1235 1241
1236 Handle<String> subject_; 1242 Handle<String> subject_;
1237 Handle<FixedArray> parts_; 1243 Handle<FixedArray> parts_;
1238 int part_count_; 1244 int part_count_;
1239 int character_count_; 1245 int character_count_;
1240 bool is_ascii_; 1246 bool is_ascii_;
1241 }; 1247 };
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1467 1473
1468 1474
1469 void CompiledReplacement::Apply(ReplacementStringBuilder* builder, 1475 void CompiledReplacement::Apply(ReplacementStringBuilder* builder,
1470 int match_from, 1476 int match_from,
1471 int match_to, 1477 int match_to,
1472 Handle<JSArray> last_match_info) { 1478 Handle<JSArray> last_match_info) {
1473 for (int i = 0, n = parts_.length(); i < n; i++) { 1479 for (int i = 0, n = parts_.length(); i < n; i++) {
1474 ReplacementPart part = parts_[i]; 1480 ReplacementPart part = parts_[i];
1475 switch (part.tag) { 1481 switch (part.tag) {
1476 case SUBJECT_PREFIX: 1482 case SUBJECT_PREFIX:
1477 builder->AddSubjectSlice(0, match_from); 1483 if (match_from > 0) builder->AddSubjectSlice(0, match_from);
1478 break; 1484 break;
1479 case SUBJECT_SUFFIX: { 1485 case SUBJECT_SUFFIX: {
1480 int subject_length = part.data; 1486 int subject_length = part.data;
1481 builder->AddSubjectSlice(match_to, subject_length); 1487 if (match_to < subject_length) {
1488 builder->AddSubjectSlice(match_to, subject_length);
1489 }
1482 break; 1490 break;
1483 } 1491 }
1484 case SUBJECT_CAPTURE: { 1492 case SUBJECT_CAPTURE: {
1485 int capture = part.data; 1493 int capture = part.data;
1486 FixedArray* match_info = last_match_info->elements(); 1494 FixedArray* match_info = last_match_info->elements();
1487 int from = RegExpImpl::GetCapture(match_info, capture * 2); 1495 int from = RegExpImpl::GetCapture(match_info, capture * 2);
1488 int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1); 1496 int to = RegExpImpl::GetCapture(match_info, capture * 2 + 1);
1489 if (from >= 0 && to > from) { 1497 if (from >= 0 && to > from) {
1490 builder->AddSubjectSlice(from, to); 1498 builder->AddSubjectSlice(from, to);
1491 } 1499 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 // Guessing the number of parts that the final result string is built 1550 // Guessing the number of parts that the final result string is built
1543 // from. Global regexps can match any number of times, so we guess 1551 // from. Global regexps can match any number of times, so we guess
1544 // conservatively. 1552 // conservatively.
1545 int expected_parts = 1553 int expected_parts =
1546 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1; 1554 (compiled_replacement.parts() + 1) * (is_global ? 4 : 1) + 1;
1547 ReplacementStringBuilder builder(subject_handle, expected_parts); 1555 ReplacementStringBuilder builder(subject_handle, expected_parts);
1548 1556
1549 // Index of end of last match. 1557 // Index of end of last match.
1550 int prev = 0; 1558 int prev = 0;
1551 1559
1560 // Number of parts added by compiled replacement plus preceeding string
1561 // and possibly suffix after last match.
1562 const int parts_added_per_loop = compiled_replacement.parts() + 2;
1563 bool matched;
1552 do { 1564 do {
1553 ASSERT(last_match_info_handle->HasFastElements()); 1565 ASSERT(last_match_info_handle->HasFastElements());
1566 // Increase the capacity of the builder before entering local handle-scope,
1567 // so its internal buffer can safely allocate a new handle if it grows.
1568 builder.EnsureCapacity(parts_added_per_loop);
1569
1570 HandleScope loop_scope;
1554 int start, end; 1571 int start, end;
1555 { 1572 {
1556 AssertNoAllocation match_info_array_is_not_in_a_handle; 1573 AssertNoAllocation match_info_array_is_not_in_a_handle;
1557 FixedArray* match_info_array = last_match_info_handle->elements(); 1574 FixedArray* match_info_array = last_match_info_handle->elements();
1558 1575
1559 ASSERT_EQ(capture_count * 2 + 2, 1576 ASSERT_EQ(capture_count * 2 + 2,
1560 RegExpImpl::GetLastCaptureCount(match_info_array)); 1577 RegExpImpl::GetLastCaptureCount(match_info_array));
1561 start = RegExpImpl::GetCapture(match_info_array, 0); 1578 start = RegExpImpl::GetCapture(match_info_array, 0);
1562 end = RegExpImpl::GetCapture(match_info_array, 1); 1579 end = RegExpImpl::GetCapture(match_info_array, 1);
1563 } 1580 }
(...skipping 17 matching lines...) Expand all
1581 if (next > length) break; 1598 if (next > length) break;
1582 } 1599 }
1583 1600
1584 match = RegExpImpl::Exec(regexp_handle, 1601 match = RegExpImpl::Exec(regexp_handle,
1585 subject_handle, 1602 subject_handle,
1586 next, 1603 next,
1587 last_match_info_handle); 1604 last_match_info_handle);
1588 if (match.is_null()) { 1605 if (match.is_null()) {
1589 return Failure::Exception(); 1606 return Failure::Exception();
1590 } 1607 }
1591 } while (!match->IsNull()); 1608 matched = !match->IsNull();
1609 } while (matched);
1592 1610
1593 if (prev < length) { 1611 if (prev < length) {
1594 builder.AddSubjectSlice(prev, length); 1612 builder.AddSubjectSlice(prev, length);
1595 } 1613 }
1596 1614
1597 return *(builder.ToString()); 1615 return *(builder.ToString());
1598 } 1616 }
1599 1617
1600 1618
1601 static Object* Runtime_StringReplaceRegExpWithString(Arguments args) { 1619 static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
(...skipping 5054 matching lines...) Expand 10 before | Expand all | Expand 10 after
6656 } else { 6674 } else {
6657 // Handle last resort GC and make sure to allow future allocations 6675 // Handle last resort GC and make sure to allow future allocations
6658 // to grow the heap without causing GCs (if possible). 6676 // to grow the heap without causing GCs (if possible).
6659 Counters::gc_last_resort_from_js.Increment(); 6677 Counters::gc_last_resort_from_js.Increment();
6660 Heap::CollectAllGarbage(); 6678 Heap::CollectAllGarbage();
6661 } 6679 }
6662 } 6680 }
6663 6681
6664 6682
6665 } } // namespace v8::internal 6683 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698