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

Side by Side Diff: src/runtime.cc

Issue 1513004: Revert svn r4269. (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
1652 // Forward declarations. 1570 // Forward declarations.
1653 const int kStringBuilderConcatHelperLengthBits = 11; 1571 static const int kStringBuilderConcatHelperLengthBits = 11;
1654 const int kStringBuilderConcatHelperPositionBits = 19; 1572 static const int kStringBuilderConcatHelperPositionBits = 19;
1655 1573
1656 template <typename schar> 1574 template <typename schar>
1657 static inline void StringBuilderConcatHelper(String*, 1575 static inline void StringBuilderConcatHelper(String*,
1658 schar*, 1576 schar*,
1659 FixedArray*, 1577 FixedArray*,
1660 int); 1578 int);
1661 1579
1662 typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits> 1580 typedef BitField<int, 0, 11> StringBuilderSubstringLength;
1663 StringBuilderSubstringLength; 1581 typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
1664 typedef BitField<int,
1665 kStringBuilderConcatHelperLengthBits,
1666 kStringBuilderConcatHelperPositionBits>
1667 StringBuilderSubstringPosition;
1668
1669 1582
1670 class ReplacementStringBuilder { 1583 class ReplacementStringBuilder {
1671 public: 1584 public:
1672 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count) 1585 ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
1673 : array_builder_(estimated_part_count), 1586 : subject_(subject),
1674 subject_(subject), 1587 parts_(Factory::NewFixedArray(estimated_part_count)),
1588 part_count_(0),
1675 character_count_(0), 1589 character_count_(0),
1676 is_ascii_(subject->IsAsciiRepresentation()) { 1590 is_ascii_(subject->IsAsciiRepresentation()) {
1677 // 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
1678 // extend the array will work. 1592 // extend the array will work.
1679 ASSERT(estimated_part_count > 0); 1593 ASSERT(estimated_part_count > 0);
1680 } 1594 }
1681 1595
1682 static inline void AddSubjectSlice(FixedArrayBuilder* builder, 1596 void EnsureCapacity(int elements) {
1683 int from, 1597 int length = parts_->length();
1684 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) {
1685 ASSERT(from >= 0); 1612 ASSERT(from >= 0);
1686 int length = to - from; 1613 int length = to - from;
1687 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?
1688 if (StringBuilderSubstringLength::is_valid(length) && 1617 if (StringBuilderSubstringLength::is_valid(length) &&
1689 StringBuilderSubstringPosition::is_valid(from)) { 1618 StringBuilderSubstringPosition::is_valid(from)) {
1690 int encoded_slice = StringBuilderSubstringLength::encode(length) | 1619 int encoded_slice = StringBuilderSubstringLength::encode(length) |
1691 StringBuilderSubstringPosition::encode(from); 1620 StringBuilderSubstringPosition::encode(from);
1692 builder->Add(Smi::FromInt(encoded_slice)); 1621 AddElement(Smi::FromInt(encoded_slice));
1693 } else { 1622 } else {
1694 // Otherwise encode as two smis. 1623 // Otherwise encode as two smis.
1695 builder->Add(Smi::FromInt(-length)); 1624 AddElement(Smi::FromInt(-length));
1696 builder->Add(Smi::FromInt(from)); 1625 AddElement(Smi::FromInt(from));
1697 } 1626 }
1627 IncrementCharacterCount(length);
1698 } 1628 }
1699 1629
1700 1630
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
1714 void AddString(Handle<String> string) { 1631 void AddString(Handle<String> string) {
1715 int length = string->length(); 1632 int length = string->length();
1716 ASSERT(length > 0); 1633 ASSERT(length > 0);
1717 AddElement(*string); 1634 AddElement(*string);
1718 if (!string->IsAsciiRepresentation()) { 1635 if (!string->IsAsciiRepresentation()) {
1719 is_ascii_ = false; 1636 is_ascii_ = false;
1720 } 1637 }
1721 IncrementCharacterCount(length); 1638 IncrementCharacterCount(length);
1722 } 1639 }
1723 1640
1724 1641
1725 Handle<String> ToString() { 1642 Handle<String> ToString() {
1726 if (array_builder_.length() == 0) { 1643 if (part_count_ == 0) {
1727 return Factory::empty_string(); 1644 return Factory::empty_string();
1728 } 1645 }
1729 1646
1730 Handle<String> joined_string; 1647 Handle<String> joined_string;
1731 if (is_ascii_) { 1648 if (is_ascii_) {
1732 joined_string = NewRawAsciiString(character_count_); 1649 joined_string = NewRawAsciiString(character_count_);
1733 AssertNoAllocation no_alloc; 1650 AssertNoAllocation no_alloc;
1734 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string); 1651 SeqAsciiString* seq = SeqAsciiString::cast(*joined_string);
1735 char* char_buffer = seq->GetChars(); 1652 char* char_buffer = seq->GetChars();
1736 StringBuilderConcatHelper(*subject_, 1653 StringBuilderConcatHelper(*subject_,
1737 char_buffer, 1654 char_buffer,
1738 *array_builder_.array(), 1655 *parts_,
1739 array_builder_.length()); 1656 part_count_);
1740 } else { 1657 } else {
1741 // Non-ASCII. 1658 // Non-ASCII.
1742 joined_string = NewRawTwoByteString(character_count_); 1659 joined_string = NewRawTwoByteString(character_count_);
1743 AssertNoAllocation no_alloc; 1660 AssertNoAllocation no_alloc;
1744 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string); 1661 SeqTwoByteString* seq = SeqTwoByteString::cast(*joined_string);
1745 uc16* char_buffer = seq->GetChars(); 1662 uc16* char_buffer = seq->GetChars();
1746 StringBuilderConcatHelper(*subject_, 1663 StringBuilderConcatHelper(*subject_,
1747 char_buffer, 1664 char_buffer,
1748 *array_builder_.array(), 1665 *parts_,
1749 array_builder_.length()); 1666 part_count_);
1750 } 1667 }
1751 return joined_string; 1668 return joined_string;
1752 } 1669 }
1753 1670
1754 1671
1755 void IncrementCharacterCount(int by) { 1672 void IncrementCharacterCount(int by) {
1756 if (character_count_ > String::kMaxLength - by) { 1673 if (character_count_ > String::kMaxLength - by) {
1757 V8::FatalProcessOutOfMemory("String.replace result too large."); 1674 V8::FatalProcessOutOfMemory("String.replace result too large.");
1758 } 1675 }
1759 character_count_ += by; 1676 character_count_ += by;
1760 } 1677 }
1761 1678
1762 Handle<JSArray> GetParts() { 1679 private:
1763 Handle<JSArray> result =
1764 Factory::NewJSArrayWithElements(array_builder_.array());
1765 result->set_length(Smi::FromInt(array_builder_.length()));
1766 return result;
1767 }
1768 1680
1769 private:
1770 Handle<String> NewRawAsciiString(int size) { 1681 Handle<String> NewRawAsciiString(int size) {
1771 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String); 1682 CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
1772 } 1683 }
1773 1684
1774 1685
1775 Handle<String> NewRawTwoByteString(int size) { 1686 Handle<String> NewRawTwoByteString(int size) {
1776 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String); 1687 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(size), String);
1777 } 1688 }
1778 1689
1779 1690
1780 void AddElement(Object* element) { 1691 void AddElement(Object* element) {
1781 ASSERT(element->IsSmi() || element->IsString()); 1692 ASSERT(element->IsSmi() || element->IsString());
1782 ASSERT(array_builder_.capacity() > array_builder_.length()); 1693 ASSERT(parts_->length() > part_count_);
1783 array_builder_.Add(element); 1694 parts_->set(part_count_, element);
1695 part_count_++;
1784 } 1696 }
1785 1697
1786 FixedArrayBuilder array_builder_;
1787 Handle<String> subject_; 1698 Handle<String> subject_;
1699 Handle<FixedArray> parts_;
1700 int part_count_;
1788 int character_count_; 1701 int character_count_;
1789 bool is_ascii_; 1702 bool is_ascii_;
1790 }; 1703 };
1791 1704
1792 1705
1793 class CompiledReplacement { 1706 class CompiledReplacement {
1794 public: 1707 public:
1795 CompiledReplacement() 1708 CompiledReplacement()
1796 : parts_(1), replacement_substrings_(0) {} 1709 : parts_(1), replacement_substrings_(0) {}
1797 1710
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
2185 2098
2186 ASSERT(last_match_info->HasFastElements()); 2099 ASSERT(last_match_info->HasFastElements());
2187 2100
2188 return StringReplaceRegExpWithString(subject, 2101 return StringReplaceRegExpWithString(subject,
2189 regexp, 2102 regexp,
2190 replacement, 2103 replacement,
2191 last_match_info); 2104 last_match_info);
2192 } 2105 }
2193 2106
2194 2107
2108
2195 // 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
2196 // limit, we can fix the size of tables. 2110 // limit, we can fix the size of tables.
2197 static const int kBMMaxShift = 0xff; 2111 static const int kBMMaxShift = 0xff;
2198 // Reduce alphabet to this size. 2112 // Reduce alphabet to this size.
2199 static const int kBMAlphabetSize = 0x100; 2113 static const int kBMAlphabetSize = 0x100;
2200 // 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
2201 // to compensate for the algorithmic overhead compared to simple brute force. 2115 // to compensate for the algorithmic overhead compared to simple brute force.
2202 static const int kBMMinPatternLength = 5; 2116 static const int kBMMinPatternLength = 5;
2203 2117
2204 // 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
2948 int from = offsets.at(i * 2); 2862 int from = offsets.at(i * 2);
2949 int to = offsets.at(i * 2 + 1); 2863 int to = offsets.at(i * 2 + 1);
2950 elements->set(i, *Factory::NewSubString(subject, from, to)); 2864 elements->set(i, *Factory::NewSubString(subject, from, to));
2951 } 2865 }
2952 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements); 2866 Handle<JSArray> result = Factory::NewJSArrayWithElements(elements);
2953 result->set_length(Smi::FromInt(matches)); 2867 result->set_length(Smi::FromInt(matches));
2954 return *result; 2868 return *result;
2955 } 2869 }
2956 2870
2957 2871
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 Handle<String> substring =
3305 Factory::NewSubString(subject,
3306 register_vector[i * 2],
3307 register_vector[i * 2 + 1]);
3308 elements->set(i, *substring);
3309 }
3310 elements->set(capture_count + 1, Smi::FromInt(match_start));
3311 elements->set(capture_count + 2, *subject);
3312 builder->Add(*Factory::NewJSArrayWithElements(elements));
3313 }
3314 // Swap register vectors, so the last successful match is in
3315 // prev_register_vector.
3316 Vector<int> tmp = prev_register_vector;
3317 prev_register_vector = register_vector;
3318 register_vector = tmp;
3319
3320 if (match_end > match_start) {
3321 pos = match_end;
3322 } else {
3323 pos = match_end + 1;
3324 if (pos > subject_length) {
3325 break;
3326 }
3327 }
3328
3329 result = RegExpImpl::IrregexpExecOnce(regexp,
3330 subject,
3331 pos,
3332 register_vector);
3333 } while (result == RegExpImpl::RE_SUCCESS);
3334
3335 if (result != RegExpImpl::RE_EXCEPTION) {
3336 // Finished matching, with at least one match.
3337 if (match_end < subject_length) {
3338 ReplacementStringBuilder::AddSubjectSlice(builder,
3339 match_end,
3340 subject_length);
3341 }
3342
3343 int last_match_capture_count = (capture_count + 1) * 2;
3344 int last_match_array_size =
3345 last_match_capture_count + RegExpImpl::kLastMatchOverhead;
3346 last_match_array->EnsureSize(last_match_array_size);
3347 AssertNoAllocation no_gc;
3348 FixedArray* elements = FixedArray::cast(last_match_array->elements());
3349 RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
3350 RegExpImpl::SetLastSubject(elements, *subject);
3351 RegExpImpl::SetLastInput(elements, *subject);
3352 for (int i = 0; i < last_match_capture_count; i++) {
3353 RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
3354 }
3355 return RegExpImpl::RE_SUCCESS;
3356 }
3357 }
3358 // No matches at all, return failure or exception result directly.
3359 return result;
3360 }
3361
3362
3363 static Object* Runtime_RegExpExecMultiple(Arguments args) {
3364 ASSERT(args.length() == 4);
3365 HandleScope handles;
3366
3367 CONVERT_ARG_CHECKED(String, subject, 1);
3368 if (!subject->IsFlat()) { FlattenString(subject); }
3369 CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
3370 CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
3371 CONVERT_ARG_CHECKED(JSArray, result_array, 3);
3372
3373 ASSERT(last_match_info->HasFastElements());
3374 ASSERT(regexp->GetFlags().is_global());
3375 Handle<FixedArray> result_elements;
3376 if (result_array->HasFastElements()) {
3377 result_elements =
3378 Handle<FixedArray>(FixedArray::cast(result_array->elements()));
3379 } else {
3380 result_elements = Factory::NewFixedArrayWithHoles(16);
3381 }
3382 FixedArrayBuilder builder(result_elements);
3383
3384 if (regexp->TypeTag() == JSRegExp::ATOM) {
3385 Handle<String> pattern(
3386 String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
3387 int pattern_length = pattern->length();
3388 if (pattern_length == 1) {
3389 if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
3390 return *builder.ToJSArray(result_array);
3391 }
3392 return Heap::null_value();
3393 }
3394
3395 if (!pattern->IsFlat()) FlattenString(pattern);
3396 if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
3397 return *builder.ToJSArray(result_array);
3398 }
3399 return Heap::null_value();
3400 }
3401
3402 ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
3403
3404 RegExpImpl::IrregexpResult result;
3405 if (regexp->CaptureCount() == 0) {
3406 result = SearchRegExpNoCaptureMultiple(subject,
3407 regexp,
3408 last_match_info,
3409 &builder);
3410 } else {
3411 result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
3412 }
3413 if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
3414 if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
3415 ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
3416 return Failure::Exception();
3417 }
3418
3419
3420 static Object* Runtime_NumberToRadixString(Arguments args) { 2872 static Object* Runtime_NumberToRadixString(Arguments args) {
3421 NoHandleAllocation ha; 2873 NoHandleAllocation ha;
3422 ASSERT(args.length() == 2); 2874 ASSERT(args.length() == 2);
3423 2875
3424 // Fast case where the result is a one character string. 2876 // Fast case where the result is a one character string.
3425 if (args[0]->IsSmi() && args[1]->IsSmi()) { 2877 if (args[0]->IsSmi() && args[1]->IsSmi()) {
3426 int value = Smi::cast(args[0])->value(); 2878 int value = Smi::cast(args[0])->value();
3427 int radix = Smi::cast(args[1])->value(); 2879 int radix = Smi::cast(args[1])->value();
3428 if (value >= 0 && value < radix) { 2880 if (value >= 0 && value < radix) {
3429 RUNTIME_ASSERT(radix <= 36); 2881 RUNTIME_ASSERT(radix <= 36);
(...skipping 6546 matching lines...) Expand 10 before | Expand all | Expand 10 after
9976 } else { 9428 } else {
9977 // Handle last resort GC and make sure to allow future allocations 9429 // Handle last resort GC and make sure to allow future allocations
9978 // to grow the heap without causing GCs (if possible). 9430 // to grow the heap without causing GCs (if possible).
9979 Counters::gc_last_resort_from_js.Increment(); 9431 Counters::gc_last_resort_from_js.Increment();
9980 Heap::CollectAllGarbage(false); 9432 Heap::CollectAllGarbage(false);
9981 } 9433 }
9982 } 9434 }
9983 9435
9984 9436
9985 } } // 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