Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |