| Index: src/runtime.cc
|
| diff --git a/src/runtime.cc b/src/runtime.cc
|
| index 7d104fa3b4123eff2aedbed7af388e454f1458ac..b34981521935bc717b5cfedb09bd14c402df6136 100644
|
| --- a/src/runtime.cc
|
| +++ b/src/runtime.cc
|
| @@ -1228,62 +1228,6 @@ static Object* Runtime_RegExpExec(Arguments args) {
|
| }
|
|
|
|
|
| -static Object* Runtime_RegExpInitializeObject(Arguments args) {
|
| - AssertNoAllocation no_alloc;
|
| - ASSERT(args.length() == 5);
|
| - CONVERT_CHECKED(JSRegExp, regexp, args[0]);
|
| - CONVERT_CHECKED(String, source, args[1]);
|
| -
|
| - Object* global = args[2];
|
| - if (!global->IsTrue()) global = Heap::false_value();
|
| -
|
| - Object* ignoreCase = args[3];
|
| - if (!ignoreCase->IsTrue()) ignoreCase = Heap::false_value();
|
| -
|
| - Object* multiline = args[4];
|
| - if (!multiline->IsTrue()) multiline = Heap::false_value();
|
| -
|
| - Map* map = regexp->map();
|
| - Object* constructor = map->constructor();
|
| - if (constructor->IsJSFunction() &&
|
| - JSFunction::cast(constructor)->initial_map() == map) {
|
| - // If we still have the original map, set in-object properties directly.
|
| - regexp->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, source);
|
| - // TODO(lrn): Consider skipping write barrier on booleans as well.
|
| - // Both true and false should be in oldspace at all times.
|
| - regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, global);
|
| - regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, ignoreCase);
|
| - regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, multiline);
|
| - regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
|
| - Smi::FromInt(0),
|
| - SKIP_WRITE_BARRIER);
|
| - return regexp;
|
| - }
|
| -
|
| - // Map has changed, so use generic, but slower, method.
|
| - PropertyAttributes final =
|
| - static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE);
|
| - PropertyAttributes writable =
|
| - static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
|
| - regexp->IgnoreAttributesAndSetLocalProperty(Heap::source_symbol(),
|
| - source,
|
| - final);
|
| - regexp->IgnoreAttributesAndSetLocalProperty(Heap::global_symbol(),
|
| - global,
|
| - final);
|
| - regexp->IgnoreAttributesAndSetLocalProperty(Heap::ignore_case_symbol(),
|
| - ignoreCase,
|
| - final);
|
| - regexp->IgnoreAttributesAndSetLocalProperty(Heap::multiline_symbol(),
|
| - multiline,
|
| - final);
|
| - regexp->IgnoreAttributesAndSetLocalProperty(Heap::last_index_symbol(),
|
| - Smi::FromInt(0),
|
| - writable);
|
| - return regexp;
|
| -}
|
| -
|
| -
|
| static Object* Runtime_FinishArrayPrototypeSetup(Arguments args) {
|
| HandleScope scope;
|
| ASSERT(args.length() == 1);
|
| @@ -1623,91 +1567,9 @@ static Object* Runtime_CharFromCode(Arguments args) {
|
| return CharFromCode(args[0]);
|
| }
|
|
|
| -
|
| -class FixedArrayBuilder {
|
| - public:
|
| - explicit FixedArrayBuilder(int initial_capacity)
|
| - : array_(Factory::NewFixedArrayWithHoles(initial_capacity)),
|
| - length_(0) {
|
| - // Require a non-zero initial size. Ensures that doubling the size to
|
| - // extend the array will work.
|
| - ASSERT(initial_capacity > 0);
|
| - }
|
| -
|
| - explicit FixedArrayBuilder(Handle<FixedArray> backing_store)
|
| - : array_(backing_store),
|
| - length_(0) {
|
| - // Require a non-zero initial size. Ensures that doubling the size to
|
| - // extend the array will work.
|
| - ASSERT(backing_store->length() > 0);
|
| - }
|
| -
|
| - bool HasCapacity(int elements) {
|
| - int length = array_->length();
|
| - int required_length = length_ + elements;
|
| - return (length >= required_length);
|
| - }
|
| -
|
| - void EnsureCapacity(int elements) {
|
| - int length = array_->length();
|
| - int required_length = length_ + elements;
|
| - if (length < required_length) {
|
| - int new_length = length;
|
| - do {
|
| - new_length *= 2;
|
| - } while (new_length < required_length);
|
| - Handle<FixedArray> extended_array =
|
| - Factory::NewFixedArrayWithHoles(new_length);
|
| - array_->CopyTo(0, *extended_array, 0, length_);
|
| - array_ = extended_array;
|
| - }
|
| - }
|
| -
|
| - void Add(Object* value) {
|
| - ASSERT(length_ < capacity());
|
| - array_->set(length_, value);
|
| - length_++;
|
| - }
|
| -
|
| - void Add(Smi* value) {
|
| - ASSERT(length_ < capacity());
|
| - array_->set(length_, value);
|
| - length_++;
|
| - }
|
| -
|
| - Handle<FixedArray> array() {
|
| - return array_;
|
| - }
|
| -
|
| - int length() {
|
| - return length_;
|
| - }
|
| -
|
| - int capacity() {
|
| - return array_->length();
|
| - }
|
| -
|
| - Handle<JSArray> ToJSArray() {
|
| - Handle<JSArray> result_array = Factory::NewJSArrayWithElements(array_);
|
| - result_array->set_length(Smi::FromInt(length_));
|
| - return result_array;
|
| - }
|
| -
|
| - Handle<JSArray> ToJSArray(Handle<JSArray> target_array) {
|
| - target_array->set_elements(*array_);
|
| - target_array->set_length(Smi::FromInt(length_));
|
| - return target_array;
|
| - }
|
| -
|
| - private:
|
| - Handle<FixedArray> array_;
|
| - int length_;
|
| -};
|
| -
|
| -
|
| // Forward declarations.
|
| -const int kStringBuilderConcatHelperLengthBits = 11;
|
| -const int kStringBuilderConcatHelperPositionBits = 19;
|
| +static const int kStringBuilderConcatHelperLengthBits = 11;
|
| +static const int kStringBuilderConcatHelperPositionBits = 19;
|
|
|
| template <typename schar>
|
| static inline void StringBuilderConcatHelper(String*,
|
| @@ -1715,19 +1577,15 @@ static inline void StringBuilderConcatHelper(String*,
|
| FixedArray*,
|
| int);
|
|
|
| -typedef BitField<int, 0, kStringBuilderConcatHelperLengthBits>
|
| - StringBuilderSubstringLength;
|
| -typedef BitField<int,
|
| - kStringBuilderConcatHelperLengthBits,
|
| - kStringBuilderConcatHelperPositionBits>
|
| - StringBuilderSubstringPosition;
|
| -
|
| +typedef BitField<int, 0, 11> StringBuilderSubstringLength;
|
| +typedef BitField<int, 11, 19> StringBuilderSubstringPosition;
|
|
|
| class ReplacementStringBuilder {
|
| public:
|
| ReplacementStringBuilder(Handle<String> subject, int estimated_part_count)
|
| - : array_builder_(estimated_part_count),
|
| - subject_(subject),
|
| + : subject_(subject),
|
| + parts_(Factory::NewFixedArray(estimated_part_count)),
|
| + part_count_(0),
|
| character_count_(0),
|
| is_ascii_(subject->IsAsciiRepresentation()) {
|
| // Require a non-zero initial size. Ensures that doubling the size to
|
| @@ -1735,35 +1593,38 @@ class ReplacementStringBuilder {
|
| ASSERT(estimated_part_count > 0);
|
| }
|
|
|
| - static inline void AddSubjectSlice(FixedArrayBuilder* builder,
|
| - int from,
|
| - int to) {
|
| + void EnsureCapacity(int elements) {
|
| + int length = parts_->length();
|
| + int required_length = part_count_ + elements;
|
| + if (length < required_length) {
|
| + int new_length = length;
|
| + do {
|
| + new_length *= 2;
|
| + } while (new_length < required_length);
|
| + Handle<FixedArray> extended_array =
|
| + Factory::NewFixedArray(new_length);
|
| + parts_->CopyTo(0, *extended_array, 0, part_count_);
|
| + parts_ = extended_array;
|
| + }
|
| + }
|
| +
|
| + void AddSubjectSlice(int from, int to) {
|
| ASSERT(from >= 0);
|
| int length = to - from;
|
| ASSERT(length > 0);
|
| + // Can we encode the slice in 11 bits for length and 19 bits for
|
| + // start position - as used by StringBuilderConcatHelper?
|
| if (StringBuilderSubstringLength::is_valid(length) &&
|
| StringBuilderSubstringPosition::is_valid(from)) {
|
| int encoded_slice = StringBuilderSubstringLength::encode(length) |
|
| StringBuilderSubstringPosition::encode(from);
|
| - builder->Add(Smi::FromInt(encoded_slice));
|
| + AddElement(Smi::FromInt(encoded_slice));
|
| } else {
|
| // Otherwise encode as two smis.
|
| - builder->Add(Smi::FromInt(-length));
|
| - builder->Add(Smi::FromInt(from));
|
| + AddElement(Smi::FromInt(-length));
|
| + AddElement(Smi::FromInt(from));
|
| }
|
| - }
|
| -
|
| -
|
| - void EnsureCapacity(int elements) {
|
| - array_builder_.EnsureCapacity(elements);
|
| - }
|
| -
|
| -
|
| - void AddSubjectSlice(int from, int to) {
|
| - AddSubjectSlice(&array_builder_, from, to);
|
| - // Can we encode the slice in 11 bits for length and 19 bits for
|
| - // start position - as used by StringBuilderConcatHelper?
|
| - IncrementCharacterCount(to - from);
|
| + IncrementCharacterCount(length);
|
| }
|
|
|
|
|
| @@ -1779,7 +1640,7 @@ class ReplacementStringBuilder {
|
|
|
|
|
| Handle<String> ToString() {
|
| - if (array_builder_.length() == 0) {
|
| + if (part_count_ == 0) {
|
| return Factory::empty_string();
|
| }
|
|
|
| @@ -1791,8 +1652,8 @@ class ReplacementStringBuilder {
|
| char* char_buffer = seq->GetChars();
|
| StringBuilderConcatHelper(*subject_,
|
| char_buffer,
|
| - *array_builder_.array(),
|
| - array_builder_.length());
|
| + *parts_,
|
| + part_count_);
|
| } else {
|
| // Non-ASCII.
|
| joined_string = NewRawTwoByteString(character_count_);
|
| @@ -1801,8 +1662,8 @@ class ReplacementStringBuilder {
|
| uc16* char_buffer = seq->GetChars();
|
| StringBuilderConcatHelper(*subject_,
|
| char_buffer,
|
| - *array_builder_.array(),
|
| - array_builder_.length());
|
| + *parts_,
|
| + part_count_);
|
| }
|
| return joined_string;
|
| }
|
| @@ -1815,14 +1676,8 @@ class ReplacementStringBuilder {
|
| character_count_ += by;
|
| }
|
|
|
| - Handle<JSArray> GetParts() {
|
| - Handle<JSArray> result =
|
| - Factory::NewJSArrayWithElements(array_builder_.array());
|
| - result->set_length(Smi::FromInt(array_builder_.length()));
|
| - return result;
|
| - }
|
| -
|
| private:
|
| +
|
| Handle<String> NewRawAsciiString(int size) {
|
| CALL_HEAP_FUNCTION(Heap::AllocateRawAsciiString(size), String);
|
| }
|
| @@ -1835,12 +1690,14 @@ class ReplacementStringBuilder {
|
|
|
| void AddElement(Object* element) {
|
| ASSERT(element->IsSmi() || element->IsString());
|
| - ASSERT(array_builder_.capacity() > array_builder_.length());
|
| - array_builder_.Add(element);
|
| + ASSERT(parts_->length() > part_count_);
|
| + parts_->set(part_count_, element);
|
| + part_count_++;
|
| }
|
|
|
| - FixedArrayBuilder array_builder_;
|
| Handle<String> subject_;
|
| + Handle<FixedArray> parts_;
|
| + int part_count_;
|
| int character_count_;
|
| bool is_ascii_;
|
| };
|
| @@ -2248,6 +2105,7 @@ static Object* Runtime_StringReplaceRegExpWithString(Arguments args) {
|
| }
|
|
|
|
|
| +
|
| // Cap on the maximal shift in the Boyer-Moore implementation. By setting a
|
| // limit, we can fix the size of tables.
|
| static const int kBMMaxShift = 0xff;
|
| @@ -3011,468 +2869,6 @@ static Object* Runtime_StringMatch(Arguments args) {
|
| }
|
|
|
|
|
| -// Two smis before and after the match, for very long strings.
|
| -const int kMaxBuilderEntriesPerRegExpMatch = 5;
|
| -
|
| -
|
| -static void SetLastMatchInfoNoCaptures(Handle<String> subject,
|
| - Handle<JSArray> last_match_info,
|
| - int match_start,
|
| - int match_end) {
|
| - // Fill last_match_info with a single capture.
|
| - last_match_info->EnsureSize(2 + RegExpImpl::kLastMatchOverhead);
|
| - AssertNoAllocation no_gc;
|
| - FixedArray* elements = FixedArray::cast(last_match_info->elements());
|
| - RegExpImpl::SetLastCaptureCount(elements, 2);
|
| - RegExpImpl::SetLastInput(elements, *subject);
|
| - RegExpImpl::SetLastSubject(elements, *subject);
|
| - RegExpImpl::SetCapture(elements, 0, match_start);
|
| - RegExpImpl::SetCapture(elements, 1, match_end);
|
| -}
|
| -
|
| -
|
| -template <typename schar>
|
| -static bool SearchCharMultiple(Vector<schar> subject,
|
| - String* pattern,
|
| - schar pattern_char,
|
| - FixedArrayBuilder* builder,
|
| - int* match_pos) {
|
| - // Position of last match.
|
| - int pos = *match_pos;
|
| - int subject_length = subject.length();
|
| - while (pos < subject_length) {
|
| - int match_end = pos + 1;
|
| - if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
|
| - *match_pos = pos;
|
| - return false;
|
| - }
|
| - int new_pos = SingleCharIndexOf(subject, pattern_char, match_end);
|
| - if (new_pos >= 0) {
|
| - // Match has been found.
|
| - if (new_pos > match_end) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder, match_end, new_pos);
|
| - }
|
| - pos = new_pos;
|
| - builder->Add(pattern);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - if (pos + 1 < subject_length) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder, pos + 1, subject_length);
|
| - }
|
| - *match_pos = pos;
|
| - return true;
|
| -}
|
| -
|
| -
|
| -static bool SearchCharMultiple(Handle<String> subject,
|
| - Handle<String> pattern,
|
| - Handle<JSArray> last_match_info,
|
| - FixedArrayBuilder* builder) {
|
| - ASSERT(subject->IsFlat());
|
| - ASSERT_EQ(1, pattern->length());
|
| - uc16 pattern_char = pattern->Get(0);
|
| - // Treating position before first as initial "previous match position".
|
| - int match_pos = -1;
|
| -
|
| - for (;;) { // Break when search complete.
|
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
|
| - AssertNoAllocation no_gc;
|
| - if (subject->IsAsciiRepresentation()) {
|
| - if (pattern_char > String::kMaxAsciiCharCode) {
|
| - break;
|
| - }
|
| - Vector<const char> subject_vector = subject->ToAsciiVector();
|
| - char pattern_ascii_char = static_cast<char>(pattern_char);
|
| - bool complete = SearchCharMultiple<const char>(subject_vector,
|
| - *pattern,
|
| - pattern_ascii_char,
|
| - builder,
|
| - &match_pos);
|
| - if (complete) break;
|
| - } else {
|
| - Vector<const uc16> subject_vector = subject->ToUC16Vector();
|
| - bool complete = SearchCharMultiple<const uc16>(subject_vector,
|
| - *pattern,
|
| - pattern_char,
|
| - builder,
|
| - &match_pos);
|
| - if (complete) break;
|
| - }
|
| - }
|
| -
|
| - if (match_pos >= 0) {
|
| - SetLastMatchInfoNoCaptures(subject,
|
| - last_match_info,
|
| - match_pos,
|
| - match_pos + 1);
|
| - return true;
|
| - }
|
| - return false; // No matches at all.
|
| -}
|
| -
|
| -
|
| -template <typename schar, typename pchar>
|
| -static bool SearchStringMultiple(Vector<schar> subject,
|
| - String* pattern,
|
| - Vector<pchar> pattern_string,
|
| - FixedArrayBuilder* builder,
|
| - int* match_pos) {
|
| - int pos = *match_pos;
|
| - int subject_length = subject.length();
|
| - int pattern_length = pattern_string.length();
|
| - int max_search_start = subject_length - pattern_length;
|
| - bool is_ascii = (sizeof(schar) == 1);
|
| - StringSearchStrategy strategy =
|
| - InitializeStringSearch(pattern_string, is_ascii);
|
| - switch (strategy) {
|
| - case SEARCH_FAIL: return false;
|
| - case SEARCH_SHORT:
|
| - while (pos <= max_search_start) {
|
| - if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
|
| - *match_pos = pos;
|
| - return false;
|
| - }
|
| - // Position of end of previous match.
|
| - int match_end = pos + pattern_length;
|
| - int new_pos = SimpleIndexOf(subject, pattern_string, match_end);
|
| - if (new_pos >= 0) {
|
| - // A match.
|
| - if (new_pos > match_end) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - match_end,
|
| - new_pos);
|
| - }
|
| - pos = new_pos;
|
| - builder->Add(pattern);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - break;
|
| - case SEARCH_LONG:
|
| - while (pos <= max_search_start) {
|
| - if (!builder->HasCapacity(kMaxBuilderEntriesPerRegExpMatch)) {
|
| - *match_pos = pos;
|
| - return false;
|
| - }
|
| - int new_pos = ComplexIndexOf(subject,
|
| - pattern_string,
|
| - pos + pattern_length);
|
| - if (new_pos >= 0) {
|
| - // A match has been found.
|
| - if (new_pos > pos) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder, pos, new_pos);
|
| - }
|
| - pos = new_pos;
|
| - builder->Add(pattern);
|
| - } else {
|
| - break;
|
| - }
|
| - }
|
| - break;
|
| - }
|
| - if (pos < max_search_start) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - pos + pattern_length,
|
| - subject_length);
|
| - }
|
| - *match_pos = pos;
|
| - return true;
|
| -}
|
| -
|
| -
|
| -static bool SearchStringMultiple(Handle<String> subject,
|
| - Handle<String> pattern,
|
| - Handle<JSArray> last_match_info,
|
| - FixedArrayBuilder* builder) {
|
| - ASSERT(subject->IsFlat());
|
| - ASSERT(pattern->IsFlat());
|
| - ASSERT(pattern->length() > 1);
|
| -
|
| - // Treating as if a previous match was before first character.
|
| - int match_pos = -pattern->length();
|
| -
|
| - for (;;) { // Break when search complete.
|
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
|
| - AssertNoAllocation no_gc;
|
| - if (subject->IsAsciiRepresentation()) {
|
| - Vector<const char> subject_vector = subject->ToAsciiVector();
|
| - if (pattern->IsAsciiRepresentation()) {
|
| - if (SearchStringMultiple(subject_vector,
|
| - *pattern,
|
| - pattern->ToAsciiVector(),
|
| - builder,
|
| - &match_pos)) break;
|
| - } else {
|
| - if (SearchStringMultiple(subject_vector,
|
| - *pattern,
|
| - pattern->ToUC16Vector(),
|
| - builder,
|
| - &match_pos)) break;
|
| - }
|
| - } else {
|
| - Vector<const uc16> subject_vector = subject->ToUC16Vector();
|
| - if (pattern->IsAsciiRepresentation()) {
|
| - if (SearchStringMultiple(subject_vector,
|
| - *pattern,
|
| - pattern->ToAsciiVector(),
|
| - builder,
|
| - &match_pos)) break;
|
| - } else {
|
| - if (SearchStringMultiple(subject_vector,
|
| - *pattern,
|
| - pattern->ToUC16Vector(),
|
| - builder,
|
| - &match_pos)) break;
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (match_pos >= 0) {
|
| - SetLastMatchInfoNoCaptures(subject,
|
| - last_match_info,
|
| - match_pos,
|
| - match_pos + pattern->length());
|
| - return true;
|
| - }
|
| - return false; // No matches at all.
|
| -}
|
| -
|
| -
|
| -static RegExpImpl::IrregexpResult SearchRegExpNoCaptureMultiple(
|
| - Handle<String> subject,
|
| - Handle<JSRegExp> regexp,
|
| - Handle<JSArray> last_match_array,
|
| - FixedArrayBuilder* builder) {
|
| - ASSERT(subject->IsFlat());
|
| - int match_start = -1;
|
| - int match_end = 0;
|
| - int pos = 0;
|
| - int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
|
| - if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
|
| -
|
| - OffsetsVector registers(required_registers);
|
| - Vector<int> register_vector(registers.vector(), registers.length());
|
| - int subject_length = subject->length();
|
| -
|
| - for (;;) { // Break on failure, return on exception.
|
| - RegExpImpl::IrregexpResult result =
|
| - RegExpImpl::IrregexpExecOnce(regexp,
|
| - subject,
|
| - pos,
|
| - register_vector);
|
| - if (result == RegExpImpl::RE_SUCCESS) {
|
| - match_start = register_vector[0];
|
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
|
| - if (match_end < match_start) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - match_end,
|
| - match_start);
|
| - }
|
| - match_end = register_vector[1];
|
| - HandleScope loop_scope;
|
| - builder->Add(*Factory::NewSubString(subject, match_start, match_end));
|
| - if (match_start != match_end) {
|
| - pos = match_end;
|
| - } else {
|
| - pos = match_end + 1;
|
| - if (pos > subject_length) break;
|
| - }
|
| - } else if (result == RegExpImpl::RE_FAILURE) {
|
| - break;
|
| - } else {
|
| - ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
|
| - return result;
|
| - }
|
| - }
|
| -
|
| - if (match_start >= 0) {
|
| - if (match_end < subject_length) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - match_end,
|
| - subject_length);
|
| - }
|
| - SetLastMatchInfoNoCaptures(subject,
|
| - last_match_array,
|
| - match_start,
|
| - match_end);
|
| - return RegExpImpl::RE_SUCCESS;
|
| - } else {
|
| - return RegExpImpl::RE_FAILURE; // No matches at all.
|
| - }
|
| -}
|
| -
|
| -
|
| -static RegExpImpl::IrregexpResult SearchRegExpMultiple(
|
| - Handle<String> subject,
|
| - Handle<JSRegExp> regexp,
|
| - Handle<JSArray> last_match_array,
|
| - FixedArrayBuilder* builder) {
|
| -
|
| - ASSERT(subject->IsFlat());
|
| - int required_registers = RegExpImpl::IrregexpPrepare(regexp, subject);
|
| - if (required_registers < 0) return RegExpImpl::RE_EXCEPTION;
|
| -
|
| - OffsetsVector registers(required_registers);
|
| - Vector<int> register_vector(registers.vector(), registers.length());
|
| -
|
| - RegExpImpl::IrregexpResult result =
|
| - RegExpImpl::IrregexpExecOnce(regexp,
|
| - subject,
|
| - 0,
|
| - register_vector);
|
| -
|
| - int capture_count = regexp->CaptureCount();
|
| - int subject_length = subject->length();
|
| -
|
| - // Position to search from.
|
| - int pos = 0;
|
| - // End of previous match. Differs from pos if match was empty.
|
| - int match_end = 0;
|
| - if (result == RegExpImpl::RE_SUCCESS) {
|
| - // Need to keep a copy of the previous match for creating last_match_info
|
| - // at the end, so we have two vectors that we swap between.
|
| - OffsetsVector registers2(required_registers);
|
| - Vector<int> prev_register_vector(registers2.vector(), registers2.length());
|
| -
|
| - do {
|
| - int match_start = register_vector[0];
|
| - builder->EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
|
| - if (match_end < match_start) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - match_end,
|
| - match_start);
|
| - }
|
| - match_end = register_vector[1];
|
| -
|
| - {
|
| - // Avoid accumulating new handles inside loop.
|
| - HandleScope temp_scope;
|
| - // Arguments array to replace function is match, captures, index and
|
| - // subject, i.e., 3 + capture count in total.
|
| - Handle<FixedArray> elements = Factory::NewFixedArray(3 + capture_count);
|
| - elements->set(0, *Factory::NewSubString(subject,
|
| - match_start,
|
| - match_end));
|
| - for (int i = 1; i <= capture_count; i++) {
|
| - Handle<String> substring =
|
| - Factory::NewSubString(subject,
|
| - register_vector[i * 2],
|
| - register_vector[i * 2 + 1]);
|
| - elements->set(i, *substring);
|
| - }
|
| - elements->set(capture_count + 1, Smi::FromInt(match_start));
|
| - elements->set(capture_count + 2, *subject);
|
| - builder->Add(*Factory::NewJSArrayWithElements(elements));
|
| - }
|
| - // Swap register vectors, so the last successful match is in
|
| - // prev_register_vector.
|
| - Vector<int> tmp = prev_register_vector;
|
| - prev_register_vector = register_vector;
|
| - register_vector = tmp;
|
| -
|
| - if (match_end > match_start) {
|
| - pos = match_end;
|
| - } else {
|
| - pos = match_end + 1;
|
| - if (pos > subject_length) {
|
| - break;
|
| - }
|
| - }
|
| -
|
| - result = RegExpImpl::IrregexpExecOnce(regexp,
|
| - subject,
|
| - pos,
|
| - register_vector);
|
| - } while (result == RegExpImpl::RE_SUCCESS);
|
| -
|
| - if (result != RegExpImpl::RE_EXCEPTION) {
|
| - // Finished matching, with at least one match.
|
| - if (match_end < subject_length) {
|
| - ReplacementStringBuilder::AddSubjectSlice(builder,
|
| - match_end,
|
| - subject_length);
|
| - }
|
| -
|
| - int last_match_capture_count = (capture_count + 1) * 2;
|
| - int last_match_array_size =
|
| - last_match_capture_count + RegExpImpl::kLastMatchOverhead;
|
| - last_match_array->EnsureSize(last_match_array_size);
|
| - AssertNoAllocation no_gc;
|
| - FixedArray* elements = FixedArray::cast(last_match_array->elements());
|
| - RegExpImpl::SetLastCaptureCount(elements, last_match_capture_count);
|
| - RegExpImpl::SetLastSubject(elements, *subject);
|
| - RegExpImpl::SetLastInput(elements, *subject);
|
| - for (int i = 0; i < last_match_capture_count; i++) {
|
| - RegExpImpl::SetCapture(elements, i, prev_register_vector[i]);
|
| - }
|
| - return RegExpImpl::RE_SUCCESS;
|
| - }
|
| - }
|
| - // No matches at all, return failure or exception result directly.
|
| - return result;
|
| -}
|
| -
|
| -
|
| -static Object* Runtime_RegExpExecMultiple(Arguments args) {
|
| - ASSERT(args.length() == 4);
|
| - HandleScope handles;
|
| -
|
| - CONVERT_ARG_CHECKED(String, subject, 1);
|
| - if (!subject->IsFlat()) { FlattenString(subject); }
|
| - CONVERT_ARG_CHECKED(JSRegExp, regexp, 0);
|
| - CONVERT_ARG_CHECKED(JSArray, last_match_info, 2);
|
| - CONVERT_ARG_CHECKED(JSArray, result_array, 3);
|
| -
|
| - ASSERT(last_match_info->HasFastElements());
|
| - ASSERT(regexp->GetFlags().is_global());
|
| - Handle<FixedArray> result_elements;
|
| - if (result_array->HasFastElements()) {
|
| - result_elements =
|
| - Handle<FixedArray>(FixedArray::cast(result_array->elements()));
|
| - } else {
|
| - result_elements = Factory::NewFixedArrayWithHoles(16);
|
| - }
|
| - FixedArrayBuilder builder(result_elements);
|
| -
|
| - if (regexp->TypeTag() == JSRegExp::ATOM) {
|
| - Handle<String> pattern(
|
| - String::cast(regexp->DataAt(JSRegExp::kAtomPatternIndex)));
|
| - int pattern_length = pattern->length();
|
| - if (pattern_length == 1) {
|
| - if (SearchCharMultiple(subject, pattern, last_match_info, &builder)) {
|
| - return *builder.ToJSArray(result_array);
|
| - }
|
| - return Heap::null_value();
|
| - }
|
| -
|
| - if (!pattern->IsFlat()) FlattenString(pattern);
|
| - if (SearchStringMultiple(subject, pattern, last_match_info, &builder)) {
|
| - return *builder.ToJSArray(result_array);
|
| - }
|
| - return Heap::null_value();
|
| - }
|
| -
|
| - ASSERT_EQ(regexp->TypeTag(), JSRegExp::IRREGEXP);
|
| -
|
| - RegExpImpl::IrregexpResult result;
|
| - if (regexp->CaptureCount() == 0) {
|
| - result = SearchRegExpNoCaptureMultiple(subject,
|
| - regexp,
|
| - last_match_info,
|
| - &builder);
|
| - } else {
|
| - result = SearchRegExpMultiple(subject, regexp, last_match_info, &builder);
|
| - }
|
| - if (result == RegExpImpl::RE_SUCCESS) return *builder.ToJSArray(result_array);
|
| - if (result == RegExpImpl::RE_FAILURE) return Heap::null_value();
|
| - ASSERT_EQ(result, RegExpImpl::RE_EXCEPTION);
|
| - return Failure::Exception();
|
| -}
|
| -
|
| -
|
| static Object* Runtime_NumberToRadixString(Arguments args) {
|
| NoHandleAllocation ha;
|
| ASSERT(args.length() == 2);
|
|
|