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

Side by Side Diff: src/runtime.cc

Issue 1515005: Revert svn r4269 and r4298. (Closed)
Patch Set: Created 10 years, 8 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 | « src/runtime.h ('k') | src/string.js » ('j') | 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-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
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
(...skipping 1210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1221 Counters::regexp_entry_runtime.Increment(); 1221 Counters::regexp_entry_runtime.Increment();
1222 Handle<Object> result = RegExpImpl::Exec(regexp, 1222 Handle<Object> result = RegExpImpl::Exec(regexp,
1223 subject, 1223 subject,
1224 index, 1224 index,
1225 last_match_info); 1225 last_match_info);
1226 if (result.is_null()) return Failure::Exception(); 1226 if (result.is_null()) return Failure::Exception();
1227 return *result; 1227 return *result;
1228 } 1228 }
1229 1229
1230 1230
1231 static Object* Runtime_RegExpInitializeObject(Arguments args) {
1232 AssertNoAllocation no_alloc;
1233 ASSERT(args.length() == 5);
1234 CONVERT_CHECKED(JSRegExp, regexp, args[0]);
1235 CONVERT_CHECKED(String, source, args[1]);
1236
1237 Object* global = args[2];
1238 if (!global->IsTrue()) global = Heap::false_value();
1239
1240 Object* ignoreCase = args[3];
1241 if (!ignoreCase->IsTrue()) ignoreCase = Heap::false_value();
1242
1243 Object* multiline = args[4];
1244 if (!multiline->IsTrue()) multiline = Heap::false_value();
1245
1246 Map* map = regexp->map();
1247 Object* constructor = map->constructor();
1248 if (constructor->IsJSFunction() &&
1249 JSFunction::cast(constructor)->initial_map() == map) {
1250 // If we still have the original map, set in-object properties directly.
1251 regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
1252 // TODO(lrn): Consider skipping write barrier on booleans as well.
1253 // Both true and false should be in oldspace at all times.
1254 regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
1255 regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
1256 regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
1257 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
1258 Smi::FromInt(0),
1259 SKIP_WRITE_BARRIER);
1260 return regexp;
1261 }
1262
1263 // Map has changed, so use generic, but slower, method.
1264 PropertyAttributes final =
1265 static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
1266 PropertyAttributes writable =
1267 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
1268 regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(),
1269 source,
1270 final);
1271 regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(),
1272 global,
1273 final);
1274 regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(),
1275 ignoreCase,
1276 final);
1277 regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(),
1278 multiline,
1279 final);
1280 regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(),
1281 Smi::FromInt(0),
1282 writable);
1283 return regexp;
1284 }
1285
1286
1287 static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) { 1231 static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
1288 HandleScope scope; 1232 HandleScope scope;
1289 ASSERT(args.length() == 1); 1233 ASSERT(args.length() == 1);
1290 CONVERT_ARG_CHECKED(JSArray, prototype, 0); 1234 CONVERT_ARG_CHECKED(JSArray, prototype, 0);
1291 // This is necessary to enable fast checks for absence of elements 1235 // This is necessary to enable fast checks for absence of elements
1292 // on Array.prototype and below. 1236 // on Array.prototype and below.
1293 prototype->set_elements(Heap::empty_fixed_array()); 1237 prototype->set_elements(Heap::empty_fixed_array());
1294 return Smi::FromInt(0); 1238 return Smi::FromInt(0);
1295 } 1239 }
1296 1240
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1616 return CharFromCode(code); 1560 return CharFromCode(code);
1617 } 1561 }
1618 1562
1619 1563
1620 static Object* Runtime_CharFromCode(Arguments args) { 1564 static Object* Runtime_CharFromCode(Arguments args) {
1621 NoHandleAllocation ha; 1565 NoHandleAllocation ha;
1622 ASSERT(args.length() == 1); 1566 ASSERT(args.length() == 1);
1623 return CharFromCode(args[0]); 1567 return CharFromCode(args[0]);
1624 } 1568 }
1625 1569
1626
1627 class FixedArrayBuilder {
1628 public:
1629 explicit FixedArrayBuilder(int initial_capacity)
1630 : array_(Factory::NewFixedArrayWithHoles(initial_capacity)),
1631 length_(0) {
1632 // Require a non-zero initial size. Ensures that doubling the size to
1633 // extend the array will work.
1634 ASSERT(initial_capacity > 0);
1635 }
1636
1637 explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
1638 : array_(backing_store),
1639 length_(0) {
1640 // Require a non-zero initial size. Ensures that doubling the size to
1641 // extend the array will work.
1642 ASSERT(backing_store->length() > 0);
1643 }
1644
1645 bool HasCapacity(int elements) {
1646 int length = array_->length();
1647 int required_length = length_ + elements;
1648 return (length >= required_length);
1649 }
1650
1651 void EnsureCapacity(int elements) {
1652 int length = array_->length();
1653 int required_length = length_ + elements;
1654 if (length < required_length) {
1655 int new_length = length;
1656 do {
1657 new_length *= 2;
1658 } while (new_length < required_length);
1659 Handle<FixedArray> extended_array =
1660 Factory::NewFixedArrayWithHoles(new_length);
1661 array_->CopyTo(0, *extended_array, 0, length_);
1662 array_ = extended_array;
1663 }
1664 }
1665
1666 void Add(Object* value) {
1667 ASSERT(length_ < capacity());
1668 array_->set(length_, value);
1669 length_++;
1670 }
1671
1672 void Add(Smi* value) {
1673 ASSERT(length_ < capacity());
1674 array_->set(length_, value);
1675 length_++;
1676 }
1677
1678 Handle<FixedArray> array() {
1679 return array_;
1680 }
1681
1682 int length() {
1683 return length_;
1684 }
1685
1686 int capacity() {
1687 return array_->length();
1688 }
1689
1690 Handle<JSArray> ToJSArray() {
1691 Handle<JSArray> result_array = Factory::NewJSArrayWithElements(array_);
1692 result_array->set_length(Smi::FromInt(length_));
1693 return result_array;
1694 }
1695
1696 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
1697 target_array->set_elements(*array_);
1698 target_array->set_length(Smi::FromInt(length_));
1699 return target_array;
1700 }
1701
1702 private:
1703 Handle<FixedArray> array_;
1704 int length_;
1705 };
1706
1707
1708 // Forward declarations. 1570 // Forward declarations.
1709 const int kStringBuilderConcatHelperLengthBits = 11; 1571 static const int kStringBuilderConcatHelperLengthBits = 11;
1710 const int kStringBuilderConcatHelperPositionBits = 19; 1572 static const int kStringBuilderConcatHelperPositionBits = 19;
1711 1573
1712 template <typename schar> 1574 template <typename schar>
1713 static inline void StringBuilderConcatHelper(String*, 1575 static inline void StringBuilderConcatHelper(String*,
1714 schar*, 1576 schar*,
1715 FixedArray*, 1577 FixedArray*,
1716 int); 1578 int);
1717 1579
1718 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> 1580 typedef BitField<int, 0, 11> StringBuilderSubstringLength;
1719 StringBuilderSubstringLength; 1581 typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
1720 typedef BitField<int,
1721 kStringBuilderConcatHelperLengthBits,
1722 kStringBuilderConcatHelperPositionBits>
1723 StringBuilderSubstringPosition;
1724
1725 1582
1726 class ReplacementStringBuilder { 1583 class ReplacementStringBuilder {
1727 public: 1584 public:
1728 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count) 1585 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
1729 : array_builder_(estimated_part_count), 1586 : subject_(subject),
1730 subject_(subject), 1587 parts_(Factory::NewFixedArray(estimated_part_count)),
1588 part_count_(0),
1731 character_count_(0), 1589 character_count_(0),
1732 is_ascii_(subject->IsAsciiRepresentation()) { 1590 is_ascii_(subject->IsAsciiRepresentation()) {
1733 // Require a non-zero initial size. Ensures that doubling the size to 1591 // Require a non-zero initial size. Ensures that doubling the size to
1734 // extend the array will work. 1592 // extend the array will work.
1735 ASSERT(estimated_part_count > 0); 1593 ASSERT(estimated_part_count > 0);
1736 } 1594 }
1737 1595
1738 static inline void AddSubjectSlice(FixedArrayBuilder* builder, 1596 void EnsureCapacity(int elements) {
1739 int from, 1597 int length = parts_->length();
1740 int to) { 1598 int required_length = part_count_ + elements;
1599 if (length < required_length) {
1600 int new_length = length;
1601 do {
1602 new_length *= 2;
1603 } while (new_length < required_length);
1604 Handle<FixedArray> extended_array =
1605 Factory::NewFixedArray(new_length);
1606 parts_->CopyTo(0, *extended_array, 0, part_count_);
1607 parts_ = extended_array;
1608 }
1609 }
1610
1611 void AddSubjectSlice(int from, int to) {
1741 ASSERT(from >= 0); 1612 ASSERT(from >= 0);
1742 int length = to - from; 1613 int length = to - from;
1743 ASSERT(length > 0); 1614 ASSERT(length > 0);
1615 // Can we encode the slice in 11 bits for length and 19 bits for
1616 // start position - as used by StringBuilderConcatHelper?
1744 if (StringBuilderSubstringLength::is_valid(length) && 1617 if (StringBuilderSubstringLength::is_valid(length) &&
1745 StringBuilderSubstringPosition::is_valid(from)) { 1618 StringBuilderSubstringPosition::is_valid(from)) {
1746 int encoded_slice = StringBuilderSubstringLength::encode(length) | 1619 int encoded_slice = StringBuilderSubstringLength::encode(length) |
1747 StringBuilderSubstringPosition::encode(from); 1620 StringBuilderSubstringPosition::encode(from);
1748 builder->Add(Smi::FromInt(encoded_slice)); 1621 AddElement(Smi::FromInt(encoded_slice));
1749 } else { 1622 } else {
1750 // Otherwise encode as two smis. 1623 // Otherwise encode as two smis.
1751 builder->Add(Smi::FromInt(-length)); 1624 AddElement(Smi::FromInt(-length));
1752 builder->Add(Smi::FromInt(from)); 1625 AddElement(Smi::FromInt(from));
1753 } 1626 }
1627 IncrementCharacterCount(length);
1754 } 1628 }
1755 1629
1756 1630
1757 void EnsureCapacity(int elements) {
1758 array_builder_.EnsureCapacity(elements);
1759 }
1760
1761
1762 void AddSubjectSlice(int from, int to) {
1763 AddSubjectSlice(&array_builder_, from, to);
1764 // Can we encode the slice in 11 bits for length and 19 bits for
1765 // start position - as used by StringBuilderConcatHelper?
1766 IncrementCharacterCount(to - from);
1767 }
1768
1769
1770 void AddString(Handle<String> string) { 1631 void AddString(Handle<String> string) {
1771 int length = string->length(); 1632 int length = string->length();
1772 ASSERT(length > 0); 1633 ASSERT(length > 0);
1773 AddElement(*string); 1634 AddElement(*string);
1774 if (!string->IsAsciiRepresentation()) { 1635 if (!string->IsAsciiRepresentation()) {
1775 is_ascii_ = false; 1636 is_ascii_ = false;
1776 } 1637 }
1777 IncrementCharacterCount(length); 1638 IncrementCharacterCount(length);
1778 } 1639 }
1779 1640
1780 1641
1781 Handle<String> ToString() { 1642 Handle<String> ToString() {
1782 if (array_builder_.length() == 0) { 1643 if (part_count_ == 0) {
1783 return Factory::empty_string(); 1644 return Factory::empty_string();
1784 } 1645 }
1785 1646
1786 Handle<String> joined_string; 1647 Handle<String> joined_string;
1787 if (is_ascii_) { 1648 if (is_ascii_) {
1788 joined_string = NewRawAsciiString(character_count_); 1649 joined_string = NewRawAsciiString(character_count_);
1789 AssertNoAllocation no_alloc; 1650 AssertNoAllocation no_alloc;
1790 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); 1651 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1791 char* char_buffer = seq->GetChars(); 1652 char* char_buffer = seq->GetChars();
1792 StringBuilderConcatHelper(*subject_, 1653 StringBuilderConcatHelper(*subject_,
1793 char_buffer, 1654 char_buffer,
1794 *array_builder_.array(), 1655 *parts_,
1795 array_builder_.length()); 1656 part_count_);
1796 } else { 1657 } else {
1797 // Non-ASCII. 1658 // Non-ASCII.
1798 joined_string = NewRawTwoByteString(character_count_); 1659 joined_string = NewRawTwoByteString(character_count_);
1799 AssertNoAllocation no_alloc; 1660 AssertNoAllocation no_alloc;
1800 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); 1661 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1801 uc16* char_buffer = seq->GetChars(); 1662 uc16* char_buffer = seq->GetChars();
1802 StringBuilderConcatHelper(*subject_, 1663 StringBuilderConcatHelper(*subject_,
1803 char_buffer, 1664 char_buffer,
1804 *array_builder_.array(), 1665 *parts_,
1805 array_builder_.length()); 1666 part_count_);
1806 } 1667 }
1807 return joined_string; 1668 return joined_string;
1808 } 1669 }
1809 1670
1810 1671
1811 void IncrementCharacterCount(int by) { 1672 void IncrementCharacterCount(int by) {
1812 if (character_count_ > String::kMaxLength - by) { 1673 if (character_count_ > String::kMaxLength - by) {
1813 V8::FatalProcessOutOfMemory("String.replace result too large."); 1674 V8::FatalProcessOutOfMemory("String.replace result too large.");
1814 } 1675 }
1815 character_count_ += by; 1676 character_count_ += by;
1816 } 1677 }
1817 1678
1818 Handle<JSArray> GetParts() { 1679 private:
1819 Handle<JSArray> result =
1820 Factory::NewJSArrayWithElements(array_builder_.array());
1821 result->set_length(Smi::FromInt(array_builder_.length()));
1822 return result;
1823 }
1824 1680
1825 private:
1826 Handle<String> NewRawAsciiString(int size) { 1681 Handle<String> NewRawAsciiString(int size) {
1827 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String); 1682 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1828 } 1683 }
1829 1684
1830 1685
1831 Handle<String> NewRawTwoByteString(int size) { 1686 Handle<String> NewRawTwoByteString(int size) {
1832 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String); 1687 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1833 } 1688 }
1834 1689
1835 1690
1836 void AddElement(Object* element) { 1691 void AddElement(Object* element) {
1837 ASSERT(element->IsSmi() || element->IsString()); 1692 ASSERT(element->IsSmi() || element->IsString());
1838 ASSERT(array_builder_.capacity() > array_builder_.length()); 1693 ASSERT(parts_->length() > part_count_);
1839 array_builder_.Add(element); 1694 parts_->set(part_count_, element);
1695 part_count_++;
1840 } 1696 }
1841 1697
1842 FixedArrayBuilder array_builder_;
1843 Handle<String> subject_; 1698 Handle<String> subject_;
1699 Handle<FixedArray> parts_;
1700 int part_count_;
1844 int character_count_; 1701 int character_count_;
1845 bool is_ascii_; 1702 bool is_ascii_;
1846 }; 1703 };
1847 1704
1848 1705
1849 class CompiledReplacement { 1706 class CompiledReplacement {
1850 public: 1707 public:
1851 CompiledReplacement() 1708 CompiledReplacement()
1852 : parts_(1), replacement_substrings_(0) {} 1709 : parts_(1), replacement_substrings_(0) {}
1853 1710
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
2241 2098
2242 ASSERT(last_match_info->HasFastElements()); 2099 ASSERT(last_match_info->HasFastElements());
2243 2100
2244 return StringReplaceRegExpWithString(subject, 2101 return StringReplaceRegExpWithString(subject,
2245 regexp, 2102 regexp,
2246 replacement, 2103 replacement,
2247 last_match_info); 2104 last_match_info);
2248 } 2105 }
2249 2106
2250 2107
2108
2251 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a 2109 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a
2252 // limit, we can fix the size of tables. 2110 // limit, we can fix the size of tables.
2253 static const int kBMMaxShift = 0xff; 2111 static const int kBMMaxShift = 0xff;
2254 // Reduce alphabet to this size. 2112 // Reduce alphabet to this size.
2255 static const int kBMAlphabetSize = 0x100; 2113 static const int kBMAlphabetSize = 0x100;
2256 // For patterns below this length, the skip length of Boyer-Moore is too short 2114 // For patterns below this length, the skip length of Boyer-Moore is too short
2257 // to compensate for the algorithmic overhead compared to simple brute force. 2115 // to compensate for the algorithmic overhead compared to simple brute force.
2258 static const int kBMMinPatternLength = 5; 2116 static const int kBMMinPatternLength = 5;
2259 2117
2260 // Holds the two buffers used by Boyer-Moore string search's Good Suffix 2118 // Holds the two buffers used by Boyer-Moore string search's Good Suffix
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after
3004 int from = offsets.at(i * 2); 2862 int from = offsets.at(i * 2);
3005 int to = offsets.at(i * 2 + 1); 2863 int to = offsets.at(i * 2 + 1);
3006 elements->set(i, *Factory::NewSubString(subject, from, to)); 2864 elements->set(i, *Factory::NewSubString(subject, from, to));
3007 } 2865 }
3008 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements); 2866 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
3009 result->set_length(Smi::FromInt(matches)); 2867 result->set_length(Smi::FromInt(matches));
3010 return *result; 2868 return *result;
3011 } 2869 }
3012 2870
3013 2871
3014 // Two smis before and after the match, for very long strings.
3015 const int kMaxBuilderEntriesPerRegExpMatch = 5;
3016
3017
3018 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
3019 Handle<JSArray> last_match_info,
3020 int match_start,
3021 int match_end) {
3022 // Fill last_match_info with a single capture.
3023 last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
3024 AssertNoAllocation no_gc;
3025 FixedArray* elements = FixedArray::cast(last_match_info->elements());
3026 RegExpImpl::SetLastCaptureCount(elements, 2);
3027 RegExpImpl::SetLastInput(elements, *subject);
3028 RegExpImpl::SetLastSubject(elements, *subject);
3029 RegExpImpl::SetCapture(elements, 0, match_start);
3030 RegExpImpl::SetCapture(elements, 1, match_end);
3031 }
3032
3033
3034 template <typename schar>
3035 static bool SearchCharMultiple(Vector<schar> subject,
3036 String* pattern,
3037 schar pattern_char,
3038 FixedArrayBuilder* builder,
3039 int* match_pos) {
3040 // Position of last match.
3041 int pos = *match_pos;
3042 int subject_length = subject.length();
3043 while (pos < subject_length) {
3044 int match_end = pos + 1;
3045 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3046 *match_pos = pos;
3047 return false;
3048 }
3049 int new_pos = SingleCharIndexOf(subject, pattern_char, match_end);
3050 if (new_pos >= 0) {
3051 // Match has been found.
3052 if (new_pos > match_end) {
3053 ReplacementStringBuilder::AddSubjectSlice(builder, match_end, new_pos);
3054 }
3055 pos = new_pos;
3056 builder->Add(pattern);
3057 } else {
3058 break;
3059 }
3060 }
3061 if (pos + 1 < subject_length) {
3062 ReplacementStringBuilder::AddSubjectSlice(builder, pos + 1, subject_length);
3063 }
3064 *match_pos = pos;
3065 return true;
3066 }
3067
3068
3069 static bool SearchCharMultiple(Handle<String> subject,
3070 Handle<String> pattern,
3071 Handle<JSArray> last_match_info,
3072 FixedArrayBuilder* builder) {
3073 ASSERT(subject->IsFlat());
3074 ASSERT_EQ(1, pattern->length());
3075 uc16 pattern_char = pattern->Get(0);
3076 // Treating position before first as initial "previous match position".
3077 int match_pos = -1;
3078
3079 for (;;) { // Break when search complete.
3080 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3081 AssertNoAllocation no_gc;
3082 if (subject->IsAsciiRepresentation()) {
3083 if (pattern_char > String::kMaxAsciiCharCode) {
3084 break;
3085 }
3086 Vector<const char> subject_vector = subject->ToAsciiVector();
3087 char pattern_ascii_char = static_cast<char>(pattern_char);
3088 bool complete = SearchCharMultiple<const char>(subject_vector,
3089 *pattern,
3090 pattern_ascii_char,
3091 builder,
3092 &match_pos);
3093 if (complete) break;
3094 } else {
3095 Vector<const uc16> subject_vector = subject->ToUC16Vector();
3096 bool complete = SearchCharMultiple<const uc16>(subject_vector,
3097 *pattern,
3098 pattern_char,
3099 builder,
3100 &match_pos);
3101 if (complete) break;
3102 }
3103 }
3104
3105 if (match_pos >= 0) {
3106 SetLastMatchInfoNoCaptures(subject,
3107 last_match_info,
3108 match_pos,
3109 match_pos + 1);
3110 return true;
3111 }
3112 return false; // No matches at all.
3113 }
3114
3115
3116 template <typename schar, typename pchar>
3117 static bool SearchStringMultiple(Vector<schar> subject,
3118 String* pattern,
3119 Vector<pchar> pattern_string,
3120 FixedArrayBuilder* builder,
3121 int* match_pos) {
3122 int pos = *match_pos;
3123 int subject_length = subject.length();
3124 int pattern_length = pattern_string.length();
3125 int max_search_start = subject_length - pattern_length;
3126 bool is_ascii = (sizeof(schar) == 1);
3127 StringSearchStrategy strategy =
3128 InitializeStringSearch(pattern_string, is_ascii);
3129 switch (strategy) {
3130 case SEARCH_FAIL: return false;
3131 case SEARCH_SHORT:
3132 while (pos <= max_search_start) {
3133 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3134 *match_pos = pos;
3135 return false;
3136 }
3137 // Position of end of previous match.
3138 int match_end = pos + pattern_length;
3139 int new_pos = SimpleIndexOf(subject, pattern_string, match_end);
3140 if (new_pos >= 0) {
3141 // A match.
3142 if (new_pos > match_end) {
3143 ReplacementStringBuilder::AddSubjectSlice(builder,
3144 match_end,
3145 new_pos);
3146 }
3147 pos = new_pos;
3148 builder->Add(pattern);
3149 } else {
3150 break;
3151 }
3152 }
3153 break;
3154 case SEARCH_LONG:
3155 while (pos <= max_search_start) {
3156 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3157 *match_pos = pos;
3158 return false;
3159 }
3160 int new_pos = ComplexIndexOf(subject,
3161 pattern_string,
3162 pos + pattern_length);
3163 if (new_pos >= 0) {
3164 // A match has been found.
3165 if (new_pos > pos) {
3166 ReplacementStringBuilder::AddSubjectSlice(builder, pos, new_pos);
3167 }
3168 pos = new_pos;
3169 builder->Add(pattern);
3170 } else {
3171 break;
3172 }
3173 }
3174 break;
3175 }
3176 if (pos < max_search_start) {
3177 ReplacementStringBuilder::AddSubjectSlice(builder,
3178 pos + pattern_length,
3179 subject_length);
3180 }
3181 *match_pos = pos;
3182 return true;
3183 }
3184
3185
3186 static bool SearchStringMultiple(Handle<String> subject,
3187 Handle<String> pattern,
3188 Handle<JSArray> last_match_info,
3189 FixedArrayBuilder* builder) {
3190 ASSERT(subject->IsFlat());
3191 ASSERT(pattern->IsFlat());
3192 ASSERT(pattern->length() > 1);
3193
3194 // Treating as if a previous match was before first character.
3195 int match_pos = -pattern->length();
3196
3197 for (;;) { // Break when search complete.
3198 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3199 AssertNoAllocation no_gc;
3200 if (subject->IsAsciiRepresentation()) {
3201 Vector<const char> subject_vector = subject->ToAsciiVector();
3202 if (pattern->IsAsciiRepresentation()) {
3203 if (SearchStringMultiple(subject_vector,
3204 *pattern,
3205 pattern->ToAsciiVector(),
3206 builder,
3207 &match_pos)) break;
3208 } else {
3209 if (SearchStringMultiple(subject_vector,
3210 *pattern,
3211 pattern->ToUC16Vector(),
3212 builder,
3213 &match_pos)) break;
3214 }
3215 } else {
3216 Vector<const uc16> subject_vector = subject->ToUC16Vector();
3217 if (pattern->IsAsciiRepresentation()) {
3218 if (SearchStringMultiple(subject_vector,
3219 *pattern,
3220 pattern->ToAsciiVector(),
3221 builder,
3222 &match_pos)) break;
3223 } else {
3224 if (SearchStringMultiple(subject_vector,
3225 *pattern,
3226 pattern->ToUC16Vector(),
3227 builder,
3228 &match_pos)) break;
3229 }
3230 }
3231 }
3232
3233 if (match_pos >= 0) {
3234 SetLastMatchInfoNoCaptures(subject,
3235 last_match_info,
3236 match_pos,
3237 match_pos + pattern->length());
3238 return true;
3239 }
3240 return false; // No matches at all.
3241 }
3242
3243
3244 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3245 Handle<String> subject,
3246 Handle<JSRegExp> regexp,
3247 Handle<JSArray> last_match_array,
3248 FixedArrayBuilder* builder) {
3249 ASSERT(subject->IsFlat());
3250 int match_start = -1;
3251 int match_end = 0;
3252 int pos = 0;
3253 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3254 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3255
3256 OffsetsVector registers(required_registers);
3257 Vector<int> register_vector(registers.vector(), registers.length());
3258 int subject_length = subject->length();
3259
3260 for (;;) { // Break on failure, return on exception.
3261 RegExpImpl::IrregexpResult result =
3262 RegExpImpl::IrregexpExecOnce(regexp,
3263 subject,
3264 pos,
3265 register_vector);
3266 if (result == RegExpImpl::RE_SUCCESS) {
3267 match_start = register_vector[0];
3268 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3269 if (match_end < match_start) {
3270 ReplacementStringBuilder::AddSubjectSlice(builder,
3271 match_end,
3272 match_start);
3273 }
3274 match_end = register_vector[1];
3275 HandleScope loop_scope;
3276 builder->Add(*Factory::NewSubString(subject, match_start, match_end));
3277 if (match_start != match_end) {
3278 pos = match_end;
3279 } else {
3280 pos = match_end + 1;
3281 if (pos > subject_length) break;
3282 }
3283 } else if (result == RegExpImpl::RE_FAILURE) {
3284 break;
3285 } else {
3286 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3287 return result;
3288 }
3289 }
3290
3291 if (match_start >= 0) {
3292 if (match_end < subject_length) {
3293 ReplacementStringBuilder::AddSubjectSlice(builder,
3294 match_end,
3295 subject_length);
3296 }
3297 SetLastMatchInfoNoCaptures(subject,
3298 last_match_array,
3299 match_start,
3300 match_end);
3301 return RegExpImpl::RE_SUCCESS;
3302 } else {
3303 return RegExpImpl::RE_FAILURE; // No matches at all.
3304 }
3305 }
3306
3307
3308 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3309 Handle<String> subject,
3310 Handle<JSRegExp> regexp,
3311 Handle<JSArray> last_match_array,
3312 FixedArrayBuilder* builder) {
3313
3314 ASSERT(subject->IsFlat());
3315 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3316 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3317
3318 OffsetsVector registers(required_registers);
3319 Vector<int> register_vector(registers.vector(), registers.length());
3320
3321 RegExpImpl::IrregexpResult result =
3322 RegExpImpl::IrregexpExecOnce(regexp,
3323 subject,
3324 0,
3325 register_vector);
3326
3327 int capture_count = regexp->CaptureCount();
3328 int subject_length = subject->length();
3329
3330 // Position to search from.
3331 int pos = 0;
3332 // End of previous match. Differs from pos if match was empty.
3333 int match_end = 0;
3334 if (result == RegExpImpl::RE_SUCCESS) {
3335 // Need to keep a copy of the previous match for creating last_match_info
3336 // at the end, so we have two vectors that we swap between.
3337 OffsetsVector registers2(required_registers);
3338 Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3339
3340 do {
3341 int match_start = register_vector[0];
3342 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3343 if (match_end < match_start) {
3344 ReplacementStringBuilder::AddSubjectSlice(builder,
3345 match_end,
3346 match_start);
3347 }
3348 match_end = register_vector[1];
3349
3350 {
3351 // Avoid accumulating new handles inside loop.
3352 HandleScope temp_scope;
3353 // Arguments array to replace function is match, captures, index and
3354 // subject, i.e., 3 + capture count in total.
3355 Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
3356 elements->set(0, *Factory::NewSubString(subject,
3357 match_start,
3358 match_end));
3359 for (int i = 1; i <= capture_count; i++) {
3360 Handle<String> substring =
3361 Factory::NewSubString(subject,
3362 register_vector[i * 2],
3363 register_vector[i * 2 + 1]);
3364 elements->set(i, *substring);
3365 }
3366 elements->set(capture_count + 1, Smi::FromInt(match_start));
3367 elements->set(capture_count + 2, *subject);
3368 builder->Add(*Factory::NewJSArrayWithElements(elements));
3369 }
3370 // Swap register vectors, so the last successful match is in
3371 // prev_register_vector.
3372 Vector<int> tmp = prev_register_vector;
3373 prev_register_vector = register_vector;
3374 register_vector = tmp;
3375
3376 if (match_end > match_start) {
3377 pos = match_end;
3378 } else {
3379 pos = match_end + 1;
3380 if (pos > subject_length) {
3381 break;
3382 }
3383 }
3384
3385 result = RegExpImpl::IrregexpExecOnce(regexp,
3386 subject,
3387 pos,
3388 register_vector);
3389 } while (result == RegExpImpl::RE_SUCCESS);
3390
3391 if (result != RegExpImpl::RE_EXCEPTION) {
3392 // Finished matching, with at least one match.
3393 if (match_end < subject_length) {
3394 ReplacementStringBuilder::AddSubjectSlice(builder,
3395 match_end,
3396 subject_length);
3397 }
3398
3399 int last_match_capture_count = (capture_count + 1) * 2;
3400 int last_match_array_size =
3401 last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3402 last_match_array->EnsureSize(last_match_array_size);
3403 AssertNoAllocation no_gc;
3404 FixedArray* elements = FixedArray::cast(last_match_array->elements());
3405 RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3406 RegExpImpl::SetLastSubject(elements, *subject);
3407 RegExpImpl::SetLastInput(elements, *subject);
3408 for (int i = 0; i < last_match_capture_count; i++) {
3409 RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3410 }
3411 return RegExpImpl::RE_SUCCESS;
3412 }
3413 }
3414 // No matches at all, return failure or exception result directly.
3415 return result;
3416 }
3417
3418
3419 static Object* Runtime_RegExpExecMultiple(Arguments args) {
3420 ASSERT(args.length() == 4);
3421 HandleScope handles;
3422
3423 CONVERT_ARG_CHECKED(String, subject, 1);
3424 if (!subject->IsFlat()) { FlattenString(subject); }
3425 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3426 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3427 CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3428
3429 ASSERT(last_match_info->HasFastElements());
3430 ASSERT(regexp->GetFlags().is_global());
3431 Handle<FixedArray> result_elements;
3432 if (result_array->HasFastElements()) {
3433 result_elements =
3434 Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3435 } else {
3436 result_elements = Factory::NewFixedArrayWithHoles(16);
3437 }
3438 FixedArrayBuilder builder(result_elements);
3439
3440 if (regexp->TypeTag() == JSRegExp::ATOM) {
3441 Handle<String> pattern(
3442 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
3443 int pattern_length = pattern->length();
3444 if (pattern_length == 1) {
3445 if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
3446 return *builder.ToJSArray(result_array);
3447 }
3448 return Heap::null_value();
3449 }
3450
3451 if (!pattern->IsFlat()) FlattenString(pattern);
3452 if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
3453 return *builder.ToJSArray(result_array);
3454 }
3455 return Heap::null_value();
3456 }
3457
3458 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
3459
3460 RegExpImpl::IrregexpResult result;
3461 if (regexp->CaptureCount() == 0) {
3462 result = SearchRegExpNoCaptureMultiple(subject,
3463 regexp,
3464 last_match_info,
3465 &builder);
3466 } else {
3467 result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
3468 }
3469 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
3470 if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
3471 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3472 return Failure::Exception();
3473 }
3474
3475
3476 static Object* Runtime_NumberToRadixString(Arguments args) { 2872 static Object* Runtime_NumberToRadixString(Arguments args) {
3477 NoHandleAllocation ha; 2873 NoHandleAllocation ha;
3478 ASSERT(args.length() == 2); 2874 ASSERT(args.length() == 2);
3479 2875
3480 // Fast case where the result is a one character string. 2876 // Fast case where the result is a one character string.
3481 if (args[0]->IsSmi() && args[1]->IsSmi()) { 2877 if (args[0]->IsSmi() && args[1]->IsSmi()) {
3482 int value = Smi::cast(args[0])->value(); 2878 int value = Smi::cast(args[0])->value();
3483 int radix = Smi::cast(args[1])->value(); 2879 int radix = Smi::cast(args[1])->value();
3484 if (value >= 0 && value < radix) { 2880 if (value >= 0 && value < radix) {
3485 RUNTIME_ASSERT(radix <= 36); 2881 RUNTIME_ASSERT(radix <= 36);
(...skipping 6546 matching lines...) Expand 10 before | Expand all | Expand 10 after
10032 } else { 9428 } else {
10033 // Handle last resort GC and make sure to allow future allocations 9429 // Handle last resort GC and make sure to allow future allocations
10034 // to grow the heap without causing GCs (if possible). 9430 // to grow the heap without causing GCs (if possible).
10035 Counters::gc_last_resort_from_js.Increment(); 9431 Counters::gc_last_resort_from_js.Increment();
10036 Heap::CollectAllGarbage(false); 9432 Heap::CollectAllGarbage(false);
10037 } 9433 }
10038 } 9434 }
10039 9435
10040 9436
10041 } } // namespace v8::internal 9437 } } // namespace v8::internal
OLDNEW
« 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