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

Side by Side Diff: src/runtime.cc

Issue 1574003: Reapply svn r4269 plus fixes for issues 665 and 667. (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 1549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 return CharFromCode(code); 1560 return CharFromCode(code);
1561 } 1561 }
1562 1562
1563 1563
1564 static Object* Runtime_CharFromCode(Arguments args) { 1564 static Object* Runtime_CharFromCode(Arguments args) {
1565 NoHandleAllocation ha; 1565 NoHandleAllocation ha;
1566 ASSERT(args.length() == 1); 1566 ASSERT(args.length() == 1);
1567 return CharFromCode(args[0]); 1567 return CharFromCode(args[0]);
1568 } 1568 }
1569 1569
1570
1571 class FixedArrayBuilder {
1572 public:
1573 explicit FixedArrayBuilder(int initial_capacity)
1574 : array_(Factory::NewFixedArrayWithHoles(initial_capacity)),
1575 length_(0) {
1576 // Require a non-zero initial size. Ensures that doubling the size to
1577 // extend the array will work.
1578 ASSERT(initial_capacity > 0);
1579 }
1580
1581 explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
1582 : array_(backing_store),
1583 length_(0) {
1584 // Require a non-zero initial size. Ensures that doubling the size to
1585 // extend the array will work.
1586 ASSERT(backing_store->length() > 0);
1587 }
1588
1589 bool HasCapacity(int elements) {
1590 int length = array_->length();
1591 int required_length = length_ + elements;
1592 return (length >= required_length);
1593 }
1594
1595 void EnsureCapacity(int elements) {
1596 int length = array_->length();
1597 int required_length = length_ + elements;
1598 if (length < required_length) {
1599 int new_length = length;
1600 do {
1601 new_length *= 2;
1602 } while (new_length < required_length);
1603 Handle<FixedArray> extended_array =
1604 Factory::NewFixedArrayWithHoles(new_length);
1605 array_->CopyTo(0, *extended_array, 0, length_);
1606 array_ = extended_array;
1607 }
1608 }
1609
1610 void Add(Object* value) {
1611 ASSERT(length_ < capacity());
1612 array_->set(length_, value);
1613 length_++;
1614 }
1615
1616 void Add(Smi* value) {
1617 ASSERT(length_ < capacity());
1618 array_->set(length_, value);
1619 length_++;
1620 }
1621
1622 Handle<FixedArray> array() {
1623 return array_;
1624 }
1625
1626 int length() {
1627 return length_;
1628 }
1629
1630 int capacity() {
1631 return array_->length();
1632 }
1633
1634 Handle<JSArray> ToJSArray() {
1635 Handle<JSArray> result_array = Factory::NewJSArrayWithElements(array_);
1636 result_array->set_length(Smi::FromInt(length_));
1637 return result_array;
1638 }
1639
1640 Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
1641 target_array->set_elements(*array_);
1642 target_array->set_length(Smi::FromInt(length_));
1643 return target_array;
1644 }
1645
1646 private:
1647 Handle<FixedArray> array_;
1648 int length_;
1649 };
1650
1651
1570 // Forward declarations. 1652 // Forward declarations.
1571 static const int kStringBuilderConcatHelperLengthBits = 11; 1653 const int kStringBuilderConcatHelperLengthBits = 11;
1572 static const int kStringBuilderConcatHelperPositionBits = 19; 1654 const int kStringBuilderConcatHelperPositionBits = 19;
1573 1655
1574 template <typename schar> 1656 template <typename schar>
1575 static inline void StringBuilderConcatHelper(String*, 1657 static inline void StringBuilderConcatHelper(String*,
1576 schar*, 1658 schar*,
1577 FixedArray*, 1659 FixedArray*,
1578 int); 1660 int);
1579 1661
1580 typedef BitField<int, 0, 11> StringBuilderSubstringLength; 1662 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
1581 typedef BitField<int, 11, 19> StringBuilderSubstringPosition; 1663 StringBuilderSubstringLength;
1664 typedef BitField<int,
1665 kStringBuilderConcatHelperLengthBits,
1666 kStringBuilderConcatHelperPositionBits>
1667 StringBuilderSubstringPosition;
1668
1582 1669
1583 class ReplacementStringBuilder { 1670 class ReplacementStringBuilder {
1584 public: 1671 public:
1585 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count) 1672 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
1586 : subject_(subject), 1673 : array_builder_(estimated_part_count),
1587 parts_(Factory::NewFixedArray(estimated_part_count)), 1674 subject_(subject),
1588 part_count_(0),
1589 character_count_(0), 1675 character_count_(0),
1590 is_ascii_(subject->IsAsciiRepresentation()) { 1676 is_ascii_(subject->IsAsciiRepresentation()) {
1591 // Require a non-zero initial size. Ensures that doubling the size to 1677 // Require a non-zero initial size. Ensures that doubling the size to
1592 // extend the array will work. 1678 // extend the array will work.
1593 ASSERT(estimated_part_count > 0); 1679 ASSERT(estimated_part_count > 0);
1594 } 1680 }
1595 1681
1596 void EnsureCapacity(int elements) { 1682 static inline void AddSubjectSlice(FixedArrayBuilder* builder,
1597 int length = parts_->length(); 1683 int from,
1598 int required_length = part_count_ + elements; 1684 int to) {
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) {
1612 ASSERT(from >= 0); 1685 ASSERT(from >= 0);
1613 int length = to - from; 1686 int length = to - from;
1614 ASSERT(length > 0); 1687 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?
1617 if (StringBuilderSubstringLength::is_valid(length) && 1688 if (StringBuilderSubstringLength::is_valid(length) &&
1618 StringBuilderSubstringPosition::is_valid(from)) { 1689 StringBuilderSubstringPosition::is_valid(from)) {
1619 int encoded_slice = StringBuilderSubstringLength::encode(length) | 1690 int encoded_slice = StringBuilderSubstringLength::encode(length) |
1620 StringBuilderSubstringPosition::encode(from); 1691 StringBuilderSubstringPosition::encode(from);
1621 AddElement(Smi::FromInt(encoded_slice)); 1692 builder->Add(Smi::FromInt(encoded_slice));
1622 } else { 1693 } else {
1623 // Otherwise encode as two smis. 1694 // Otherwise encode as two smis.
1624 AddElement(Smi::FromInt(-length)); 1695 builder->Add(Smi::FromInt(-length));
1625 AddElement(Smi::FromInt(from)); 1696 builder->Add(Smi::FromInt(from));
1626 } 1697 }
1627 IncrementCharacterCount(length);
1628 } 1698 }
1629 1699
1630 1700
1701 void EnsureCapacity(int elements) {
1702 array_builder_.EnsureCapacity(elements);
1703 }
1704
1705
1706 void AddSubjectSlice(int from, int to) {
1707 AddSubjectSlice(&array_builder_, from, to);
1708 // Can we encode the slice in 11 bits for length and 19 bits for
1709 // start position - as used by StringBuilderConcatHelper?
1710 IncrementCharacterCount(to - from);
1711 }
1712
1713
1631 void AddString(Handle<String> string) { 1714 void AddString(Handle<String> string) {
1632 int length = string->length(); 1715 int length = string->length();
1633 ASSERT(length > 0); 1716 ASSERT(length > 0);
1634 AddElement(*string); 1717 AddElement(*string);
1635 if (!string->IsAsciiRepresentation()) { 1718 if (!string->IsAsciiRepresentation()) {
1636 is_ascii_ = false; 1719 is_ascii_ = false;
1637 } 1720 }
1638 IncrementCharacterCount(length); 1721 IncrementCharacterCount(length);
1639 } 1722 }
1640 1723
1641 1724
1642 Handle<String> ToString() { 1725 Handle<String> ToString() {
1643 if (part_count_ == 0) { 1726 if (array_builder_.length() == 0) {
1644 return Factory::empty_string(); 1727 return Factory::empty_string();
1645 } 1728 }
1646 1729
1647 Handle<String> joined_string; 1730 Handle<String> joined_string;
1648 if (is_ascii_) { 1731 if (is_ascii_) {
1649 joined_string = NewRawAsciiString(character_count_); 1732 joined_string = NewRawAsciiString(character_count_);
1650 AssertNoAllocation no_alloc; 1733 AssertNoAllocation no_alloc;
1651 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); 1734 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1652 char* char_buffer = seq->GetChars(); 1735 char* char_buffer = seq->GetChars();
1653 StringBuilderConcatHelper(*subject_, 1736 StringBuilderConcatHelper(*subject_,
1654 char_buffer, 1737 char_buffer,
1655 *parts_, 1738 *array_builder_.array(),
1656 part_count_); 1739 array_builder_.length());
1657 } else { 1740 } else {
1658 // Non-ASCII. 1741 // Non-ASCII.
1659 joined_string = NewRawTwoByteString(character_count_); 1742 joined_string = NewRawTwoByteString(character_count_);
1660 AssertNoAllocation no_alloc; 1743 AssertNoAllocation no_alloc;
1661 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); 1744 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1662 uc16* char_buffer = seq->GetChars(); 1745 uc16* char_buffer = seq->GetChars();
1663 StringBuilderConcatHelper(*subject_, 1746 StringBuilderConcatHelper(*subject_,
1664 char_buffer, 1747 char_buffer,
1665 *parts_, 1748 *array_builder_.array(),
1666 part_count_); 1749 array_builder_.length());
1667 } 1750 }
1668 return joined_string; 1751 return joined_string;
1669 } 1752 }
1670 1753
1671 1754
1672 void IncrementCharacterCount(int by) { 1755 void IncrementCharacterCount(int by) {
1673 if (character_count_ > String::kMaxLength - by) { 1756 if (character_count_ > String::kMaxLength - by) {
1674 V8::FatalProcessOutOfMemory("String.replace result too large."); 1757 V8::FatalProcessOutOfMemory("String.replace result too large.");
1675 } 1758 }
1676 character_count_ += by; 1759 character_count_ += by;
1677 } 1760 }
1678 1761
1762 Handle<JSArray> GetParts() {
1763 Handle<JSArray> result =
1764 Factory::NewJSArrayWithElements(array_builder_.array());
1765 result->set_length(Smi::FromInt(array_builder_.length()));
1766 return result;
1767 }
1768
1679 private: 1769 private:
1680
1681 Handle<String> NewRawAsciiString(int size) { 1770 Handle<String> NewRawAsciiString(int size) {
1682 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String); 1771 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1683 } 1772 }
1684 1773
1685 1774
1686 Handle<String> NewRawTwoByteString(int size) { 1775 Handle<String> NewRawTwoByteString(int size) {
1687 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String); 1776 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1688 } 1777 }
1689 1778
1690 1779
1691 void AddElement(Object* element) { 1780 void AddElement(Object* element) {
1692 ASSERT(element->IsSmi() || element->IsString()); 1781 ASSERT(element->IsSmi() || element->IsString());
1693 ASSERT(parts_->length() > part_count_); 1782 ASSERT(array_builder_.capacity() > array_builder_.length());
1694 parts_->set(part_count_, element); 1783 array_builder_.Add(element);
1695 part_count_++;
1696 } 1784 }
1697 1785
1786 FixedArrayBuilder array_builder_;
1698 Handle<String> subject_; 1787 Handle<String> subject_;
1699 Handle<FixedArray> parts_;
1700 int part_count_;
1701 int character_count_; 1788 int character_count_;
1702 bool is_ascii_; 1789 bool is_ascii_;
1703 }; 1790 };
1704 1791
1705 1792
1706 class CompiledReplacement { 1793 class CompiledReplacement {
1707 public: 1794 public:
1708 CompiledReplacement() 1795 CompiledReplacement()
1709 : parts_(1), replacement_substrings_(0) {} 1796 : parts_(1), replacement_substrings_(0) {}
1710 1797
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
2098 2185
2099 ASSERT(last_match_info->HasFastElements()); 2186 ASSERT(last_match_info->HasFastElements());
2100 2187
2101 return StringReplaceRegExpWithString(subject, 2188 return StringReplaceRegExpWithString(subject,
2102 regexp, 2189 regexp,
2103 replacement, 2190 replacement,
2104 last_match_info); 2191 last_match_info);
2105 } 2192 }
2106 2193
2107 2194
2108
2109 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a 2195 // Cap on the maximal shift in the Boyer-Moore implementation. By setting a
2110 // limit, we can fix the size of tables. 2196 // limit, we can fix the size of tables.
2111 static const int kBMMaxShift = 0xff; 2197 static const int kBMMaxShift = 0xff;
2112 // Reduce alphabet to this size. 2198 // Reduce alphabet to this size.
2113 static const int kBMAlphabetSize = 0x100; 2199 static const int kBMAlphabetSize = 0x100;
2114 // For patterns below this length, the skip length of Boyer-Moore is too short 2200 // For patterns below this length, the skip length of Boyer-Moore is too short
2115 // to compensate for the algorithmic overhead compared to simple brute force. 2201 // to compensate for the algorithmic overhead compared to simple brute force.
2116 static const int kBMMinPatternLength = 5; 2202 static const int kBMMinPatternLength = 5;
2117 2203
2118 // Holds the two buffers used by Boyer-Moore string search's Good Suffix 2204 // 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
2862 int from = offsets.at(i * 2); 2948 int from = offsets.at(i * 2);
2863 int to = offsets.at(i * 2 + 1); 2949 int to = offsets.at(i * 2 + 1);
2864 elements->set(i, *Factory::NewSubString(subject, from, to)); 2950 elements->set(i, *Factory::NewSubString(subject, from, to));
2865 } 2951 }
2866 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements); 2952 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
2867 result->set_length(Smi::FromInt(matches)); 2953 result->set_length(Smi::FromInt(matches));
2868 return *result; 2954 return *result;
2869 } 2955 }
2870 2956
2871 2957
2958 // Two smis before and after the match, for very long strings.
2959 const int kMaxBuilderEntriesPerRegExpMatch = 5;
2960
2961
2962 static void SetLastMatchInfoNoCaptures(Handle<String> subject,
2963 Handle<JSArray> last_match_info,
2964 int match_start,
2965 int match_end) {
2966 // Fill last_match_info with a single capture.
2967 last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
2968 AssertNoAllocation no_gc;
2969 FixedArray* elements = FixedArray::cast(last_match_info->elements());
2970 RegExpImpl::SetLastCaptureCount(elements, 2);
2971 RegExpImpl::SetLastInput(elements, *subject);
2972 RegExpImpl::SetLastSubject(elements, *subject);
2973 RegExpImpl::SetCapture(elements, 0, match_start);
2974 RegExpImpl::SetCapture(elements, 1, match_end);
2975 }
2976
2977
2978 template <typename schar>
2979 static bool SearchCharMultiple(Vector<schar> subject,
2980 String* pattern,
2981 schar pattern_char,
2982 FixedArrayBuilder* builder,
2983 int* match_pos) {
2984 // Position of last match.
2985 int pos = *match_pos;
2986 int subject_length = subject.length();
2987 while (pos < subject_length) {
2988 int match_end = pos + 1;
2989 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
2990 *match_pos = pos;
2991 return false;
2992 }
2993 int new_pos = SingleCharIndexOf(subject, pattern_char, match_end);
2994 if (new_pos >= 0) {
2995 // Match has been found.
2996 if (new_pos > match_end) {
2997 ReplacementStringBuilder::AddSubjectSlice(builder, match_end, new_pos);
2998 }
2999 pos = new_pos;
3000 builder->Add(pattern);
3001 } else {
3002 break;
3003 }
3004 }
3005 if (pos + 1 < subject_length) {
3006 ReplacementStringBuilder::AddSubjectSlice(builder, pos + 1, subject_length);
3007 }
3008 *match_pos = pos;
3009 return true;
3010 }
3011
3012
3013 static bool SearchCharMultiple(Handle<String> subject,
3014 Handle<String> pattern,
3015 Handle<JSArray> last_match_info,
3016 FixedArrayBuilder* builder) {
3017 ASSERT(subject->IsFlat());
3018 ASSERT_EQ(1, pattern->length());
3019 uc16 pattern_char = pattern->Get(0);
3020 // Treating position before first as initial "previous match position".
3021 int match_pos = -1;
3022
3023 for (;;) { // Break when search complete.
3024 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3025 AssertNoAllocation no_gc;
3026 if (subject->IsAsciiRepresentation()) {
3027 if (pattern_char > String::kMaxAsciiCharCode) {
3028 break;
3029 }
3030 Vector<const char> subject_vector = subject->ToAsciiVector();
3031 char pattern_ascii_char = static_cast<char>(pattern_char);
3032 bool complete = SearchCharMultiple<const char>(subject_vector,
3033 *pattern,
3034 pattern_ascii_char,
3035 builder,
3036 &match_pos);
3037 if (complete) break;
3038 } else {
3039 Vector<const uc16> subject_vector = subject->ToUC16Vector();
3040 bool complete = SearchCharMultiple<const uc16>(subject_vector,
3041 *pattern,
3042 pattern_char,
3043 builder,
3044 &match_pos);
3045 if (complete) break;
3046 }
3047 }
3048
3049 if (match_pos >= 0) {
3050 SetLastMatchInfoNoCaptures(subject,
3051 last_match_info,
3052 match_pos,
3053 match_pos + 1);
3054 return true;
3055 }
3056 return false; // No matches at all.
3057 }
3058
3059
3060 template <typename schar, typename pchar>
3061 static bool SearchStringMultiple(Vector<schar> subject,
3062 String* pattern,
3063 Vector<pchar> pattern_string,
3064 FixedArrayBuilder* builder,
3065 int* match_pos) {
3066 int pos = *match_pos;
3067 int subject_length = subject.length();
3068 int pattern_length = pattern_string.length();
3069 int max_search_start = subject_length - pattern_length;
3070 bool is_ascii = (sizeof(schar) == 1);
3071 StringSearchStrategy strategy =
3072 InitializeStringSearch(pattern_string, is_ascii);
3073 switch (strategy) {
3074 case SEARCH_FAIL: return false;
3075 case SEARCH_SHORT:
3076 while (pos <= max_search_start) {
3077 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3078 *match_pos = pos;
3079 return false;
3080 }
3081 // Position of end of previous match.
3082 int match_end = pos + pattern_length;
3083 int new_pos = SimpleIndexOf(subject, pattern_string, match_end);
3084 if (new_pos >= 0) {
3085 // A match.
3086 if (new_pos > match_end) {
3087 ReplacementStringBuilder::AddSubjectSlice(builder,
3088 match_end,
3089 new_pos);
3090 }
3091 pos = new_pos;
3092 builder->Add(pattern);
3093 } else {
3094 break;
3095 }
3096 }
3097 break;
3098 case SEARCH_LONG:
3099 while (pos <= max_search_start) {
3100 if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
3101 *match_pos = pos;
3102 return false;
3103 }
3104 int new_pos = ComplexIndexOf(subject,
3105 pattern_string,
3106 pos + pattern_length);
3107 if (new_pos >= 0) {
3108 // A match has been found.
3109 if (new_pos > pos) {
3110 ReplacementStringBuilder::AddSubjectSlice(builder, pos, new_pos);
3111 }
3112 pos = new_pos;
3113 builder->Add(pattern);
3114 } else {
3115 break;
3116 }
3117 }
3118 break;
3119 }
3120 if (pos < max_search_start) {
3121 ReplacementStringBuilder::AddSubjectSlice(builder,
3122 pos + pattern_length,
3123 subject_length);
3124 }
3125 *match_pos = pos;
3126 return true;
3127 }
3128
3129
3130 static bool SearchStringMultiple(Handle<String> subject,
3131 Handle<String> pattern,
3132 Handle<JSArray> last_match_info,
3133 FixedArrayBuilder* builder) {
3134 ASSERT(subject->IsFlat());
3135 ASSERT(pattern->IsFlat());
3136 ASSERT(pattern->length() > 1);
3137
3138 // Treating as if a previous match was before first character.
3139 int match_pos = -pattern->length();
3140
3141 for (;;) { // Break when search complete.
3142 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3143 AssertNoAllocation no_gc;
3144 if (subject->IsAsciiRepresentation()) {
3145 Vector<const char> subject_vector = subject->ToAsciiVector();
3146 if (pattern->IsAsciiRepresentation()) {
3147 if (SearchStringMultiple(subject_vector,
3148 *pattern,
3149 pattern->ToAsciiVector(),
3150 builder,
3151 &match_pos)) break;
3152 } else {
3153 if (SearchStringMultiple(subject_vector,
3154 *pattern,
3155 pattern->ToUC16Vector(),
3156 builder,
3157 &match_pos)) break;
3158 }
3159 } else {
3160 Vector<const uc16> subject_vector = subject->ToUC16Vector();
3161 if (pattern->IsAsciiRepresentation()) {
3162 if (SearchStringMultiple(subject_vector,
3163 *pattern,
3164 pattern->ToAsciiVector(),
3165 builder,
3166 &match_pos)) break;
3167 } else {
3168 if (SearchStringMultiple(subject_vector,
3169 *pattern,
3170 pattern->ToUC16Vector(),
3171 builder,
3172 &match_pos)) break;
3173 }
3174 }
3175 }
3176
3177 if (match_pos >= 0) {
3178 SetLastMatchInfoNoCaptures(subject,
3179 last_match_info,
3180 match_pos,
3181 match_pos + pattern->length());
3182 return true;
3183 }
3184 return false; // No matches at all.
3185 }
3186
3187
3188 static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
3189 Handle<String> subject,
3190 Handle<JSRegExp> regexp,
3191 Handle<JSArray> last_match_array,
3192 FixedArrayBuilder* builder) {
3193 ASSERT(subject->IsFlat());
3194 int match_start = -1;
3195 int match_end = 0;
3196 int pos = 0;
3197 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3198 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3199
3200 OffsetsVector registers(required_registers);
3201 Vector<int> register_vector(registers.vector(), registers.length());
3202 int subject_length = subject->length();
3203
3204 for (;;) { // Break on failure, return on exception.
3205 RegExpImpl::IrregexpResult result =
3206 RegExpImpl::IrregexpExecOnce(regexp,
3207 subject,
3208 pos,
3209 register_vector);
3210 if (result == RegExpImpl::RE_SUCCESS) {
3211 match_start = register_vector[0];
3212 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3213 if (match_end < match_start) {
3214 ReplacementStringBuilder::AddSubjectSlice(builder,
3215 match_end,
3216 match_start);
3217 }
3218 match_end = register_vector[1];
3219 HandleScope loop_scope;
3220 builder->Add(*Factory::NewSubString(subject, match_start, match_end));
3221 if (match_start != match_end) {
3222 pos = match_end;
3223 } else {
3224 pos = match_end + 1;
3225 if (pos > subject_length) break;
3226 }
3227 } else if (result == RegExpImpl::RE_FAILURE) {
3228 break;
3229 } else {
3230 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3231 return result;
3232 }
3233 }
3234
3235 if (match_start >= 0) {
3236 if (match_end < subject_length) {
3237 ReplacementStringBuilder::AddSubjectSlice(builder,
3238 match_end,
3239 subject_length);
3240 }
3241 SetLastMatchInfoNoCaptures(subject,
3242 last_match_array,
3243 match_start,
3244 match_end);
3245 return RegExpImpl::RE_SUCCESS;
3246 } else {
3247 return RegExpImpl::RE_FAILURE; // No matches at all.
3248 }
3249 }
3250
3251
3252 static RegExpImpl::IrregexpResult SearchRegExpMultiple(
3253 Handle<String> subject,
3254 Handle<JSRegExp> regexp,
3255 Handle<JSArray> last_match_array,
3256 FixedArrayBuilder* builder) {
3257
3258 ASSERT(subject->IsFlat());
3259 int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
3260 if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
3261
3262 OffsetsVector registers(required_registers);
3263 Vector<int> register_vector(registers.vector(), registers.length());
3264
3265 RegExpImpl::IrregexpResult result =
3266 RegExpImpl::IrregexpExecOnce(regexp,
3267 subject,
3268 0,
3269 register_vector);
3270
3271 int capture_count = regexp->CaptureCount();
3272 int subject_length = subject->length();
3273
3274 // Position to search from.
3275 int pos = 0;
3276 // End of previous match. Differs from pos if match was empty.
3277 int match_end = 0;
3278 if (result == RegExpImpl::RE_SUCCESS) {
3279 // Need to keep a copy of the previous match for creating last_match_info
3280 // at the end, so we have two vectors that we swap between.
3281 OffsetsVector registers2(required_registers);
3282 Vector<int> prev_register_vector(registers2.vector(), registers2.length());
3283
3284 do {
3285 int match_start = register_vector[0];
3286 builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
3287 if (match_end < match_start) {
3288 ReplacementStringBuilder::AddSubjectSlice(builder,
3289 match_end,
3290 match_start);
3291 }
3292 match_end = register_vector[1];
3293
3294 {
3295 // Avoid accumulating new handles inside loop.
3296 HandleScope temp_scope;
3297 // Arguments array to replace function is match, captures, index and
3298 // subject, i.e., 3 + capture count in total.
3299 Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
3300 elements->set(0, *Factory::NewSubString(subject,
3301 match_start,
3302 match_end));
3303 for (int i = 1; i <= capture_count; i++) {
3304 int start = register_vector[i * 2];
3305 if (start >= 0) {
3306 int end = register_vector[i * 2 + 1];
3307 ASSERT(start <= end);
3308 Handle<String> substring = Factory::NewSubString(subject, start, end );
3309 elements->set(i, *substring);
3310 } else {
3311 ASSERT(register_vector[i * 2 + 1] < 0);
3312 elements->set(i, Heap::undefined_value());
3313 }
3314 }
3315 elements->set(capture_count + 1, Smi::FromInt(match_start));
3316 elements->set(capture_count + 2, *subject);
3317 builder->Add(*Factory::NewJSArrayWithElements(elements));
3318 }
3319 // Swap register vectors, so the last successful match is in
3320 // prev_register_vector.
3321 Vector<int> tmp = prev_register_vector;
3322 prev_register_vector = register_vector;
3323 register_vector = tmp;
3324
3325 if (match_end > match_start) {
3326 pos = match_end;
3327 } else {
3328 pos = match_end + 1;
3329 if (pos > subject_length) {
3330 break;
3331 }
3332 }
3333
3334 result = RegExpImpl::IrregexpExecOnce(regexp,
3335 subject,
3336 pos,
3337 register_vector);
3338 } while (result == RegExpImpl::RE_SUCCESS);
3339
3340 if (result != RegExpImpl::RE_EXCEPTION) {
3341 // Finished matching, with at least one match.
3342 if (match_end < subject_length) {
3343 ReplacementStringBuilder::AddSubjectSlice(builder,
3344 match_end,
3345 subject_length);
3346 }
3347
3348 int last_match_capture_count = (capture_count + 1) * 2;
3349 int last_match_array_size =
3350 last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3351 last_match_array->EnsureSize(last_match_array_size);
3352 AssertNoAllocation no_gc;
3353 FixedArray* elements = FixedArray::cast(last_match_array->elements());
3354 RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3355 RegExpImpl::SetLastSubject(elements, *subject);
3356 RegExpImpl::SetLastInput(elements, *subject);
3357 for (int i = 0; i < last_match_capture_count; i++) {
3358 RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3359 }
3360 return RegExpImpl::RE_SUCCESS;
3361 }
3362 }
3363 // No matches at all, return failure or exception result directly.
3364 return result;
3365 }
3366
3367
3368 static Object* Runtime_RegExpExecMultiple(Arguments args) {
3369 ASSERT(args.length() == 4);
3370 HandleScope handles;
3371
3372 CONVERT_ARG_CHECKED(String, subject, 1);
3373 if (!subject->IsFlat()) { FlattenString(subject); }
3374 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3375 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3376 CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3377
3378 ASSERT(last_match_info->HasFastElements());
3379 ASSERT(regexp->GetFlags().is_global());
3380 Handle<FixedArray> result_elements;
3381 if (result_array->HasFastElements()) {
3382 result_elements =
3383 Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3384 } else {
3385 result_elements = Factory::NewFixedArrayWithHoles(16);
3386 }
3387 FixedArrayBuilder builder(result_elements);
3388
3389 if (regexp->TypeTag() == JSRegExp::ATOM) {
3390 Handle<String> pattern(
3391 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
3392 int pattern_length = pattern->length();
3393 if (pattern_length == 1) {
3394 if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
3395 return *builder.ToJSArray(result_array);
3396 }
3397 return Heap::null_value();
3398 }
3399
3400 if (!pattern->IsFlat()) FlattenString(pattern);
3401 if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
3402 return *builder.ToJSArray(result_array);
3403 }
3404 return Heap::null_value();
3405 }
3406
3407 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
3408
3409 RegExpImpl::IrregexpResult result;
3410 if (regexp->CaptureCount() == 0) {
3411 result = SearchRegExpNoCaptureMultiple(subject,
3412 regexp,
3413 last_match_info,
3414 &builder);
3415 } else {
3416 result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
3417 }
3418 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
3419 if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
3420 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3421 return Failure::Exception();
3422 }
3423
3424
2872 static Object* Runtime_NumberToRadixString(Arguments args) { 3425 static Object* Runtime_NumberToRadixString(Arguments args) {
2873 NoHandleAllocation ha; 3426 NoHandleAllocation ha;
2874 ASSERT(args.length() == 2); 3427 ASSERT(args.length() == 2);
2875 3428
2876 // Fast case where the result is a one character string. 3429 // Fast case where the result is a one character string.
2877 if (args[0]->IsSmi() && args[1]->IsSmi()) { 3430 if (args[0]->IsSmi() && args[1]->IsSmi()) {
2878 int value = Smi::cast(args[0])->value(); 3431 int value = Smi::cast(args[0])->value();
2879 int radix = Smi::cast(args[1])->value(); 3432 int radix = Smi::cast(args[1])->value();
2880 if (value >= 0 && value < radix) { 3433 if (value >= 0 && value < radix) {
2881 RUNTIME_ASSERT(radix <= 36); 3434 RUNTIME_ASSERT(radix <= 36);
(...skipping 6546 matching lines...) Expand 10 before | Expand all | Expand 10 after
9428 } else { 9981 } else {
9429 // Handle last resort GC and make sure to allow future allocations 9982 // Handle last resort GC and make sure to allow future allocations
9430 // to grow the heap without causing GCs (if possible). 9983 // to grow the heap without causing GCs (if possible).
9431 Counters::gc_last_resort_from_js.Increment(); 9984 Counters::gc_last_resort_from_js.Increment();
9432 Heap::CollectAllGarbage(false); 9985 Heap::CollectAllGarbage(false);
9433 } 9986 }
9434 } 9987 }
9435 9988
9436 9989
9437 } } // namespace v8::internal 9990 } } // 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