1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2014 the V8 project authors. All rights reserved.
2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be
3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file.
4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
5014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/runtime/runtime-utils.h"
6958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/arguments.h"
8014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/conversions-inl.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate-inl.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/messages.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/jsregexp-inl.h"
12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/regexp/jsregexp.h"
13c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/regexp/regexp-utils.h"
14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/string-builder.h"
15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/string-search.h"
16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 {
18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal {
19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierclass CompiledReplacement {
21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier public:
22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  explicit CompiledReplacement(Zone* zone)
23958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      : parts_(1, zone), replacement_substrings_(0, zone), zone_(zone) {}
24958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Return whether the replacement is simple.
26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool Compile(Handle<String> replacement, int capture_count,
27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier               int subject_length);
28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
29958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Use Apply only if Compile returned false.
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  void Apply(ReplacementStringBuilder* builder, int match_from, int match_to,
31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier             int32_t* match);
32958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
33958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Number of distinct parts of the replacement pattern.
34958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int parts() { return parts_.length(); }
35958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
36958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Zone* zone() const { return zone_; }
37958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier private:
39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  enum PartType {
40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SUBJECT_PREFIX = 1,
41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SUBJECT_SUFFIX,
42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    SUBJECT_CAPTURE,
43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    REPLACEMENT_SUBSTRING,
44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    REPLACEMENT_STRING,
45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    NUMBER_OF_PART_TYPES
46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
47958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
48958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  struct ReplacementPart {
49958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart SubjectMatch() {
50958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(SUBJECT_CAPTURE, 0);
51958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart SubjectCapture(int capture_index) {
53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(SUBJECT_CAPTURE, capture_index);
54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
55958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart SubjectPrefix() {
56958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(SUBJECT_PREFIX, 0);
57958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart SubjectSuffix(int subject_length) {
59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(SUBJECT_SUFFIX, subject_length);
60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart ReplacementString() {
62958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(REPLACEMENT_STRING, 0);
63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
64958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    static inline ReplacementPart ReplacementSubString(int from, int to) {
65958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(from >= 0);
66958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(to > from);
67958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return ReplacementPart(-from, to);
68958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
69958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
70958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // If tag <= 0 then it is the negation of a start index of a substring of
71958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the replacement pattern, otherwise it's a value from PartType.
72958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ReplacementPart(int tag, int data) : tag(tag), data(data) {
73958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Must be non-positive or a PartType value.
74958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(tag < NUMBER_OF_PART_TYPES);
75958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
76958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Either a value of PartType or a non-positive number that is
77958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // the negation of an index into the replacement string.
78958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int tag;
79958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // The data value's interpretation depends on the value of tag:
80958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag == SUBJECT_PREFIX ||
81958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag == SUBJECT_SUFFIX:  data is unused.
82958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag == SUBJECT_CAPTURE: data is the number of the capture.
83958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag == REPLACEMENT_SUBSTRING ||
84958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag == REPLACEMENT_STRING:    data is index into array of substrings
85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //                               of the replacement string.
86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // tag <= 0: Temporary representation of the substring of the replacement
87958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //           string ranging over -tag .. data.
88958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //           Is replaced by REPLACEMENT_{SUB,}STRING when we create the
89958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    //           substring objects.
90958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int data;
91958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  };
92958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
93958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  template <typename Char>
94958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool ParseReplacementPattern(ZoneList<ReplacementPart>* parts,
95958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               Vector<Char> characters, int capture_count,
96958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               int subject_length, Zone* zone) {
97958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int length = characters.length();
98958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int last = 0;
99958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    for (int i = 0; i < length; i++) {
100958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Char c = characters[i];
101958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (c == '$') {
102958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        int next_index = i + 1;
103958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (next_index == length) {  // No next character!
104958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          break;
105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
106958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Char c2 = characters[next_index];
107958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        switch (c2) {
108958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '$':
109958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (i > last) {
110958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              // There is a substring before. Include the first "$".
111958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              parts->Add(
112958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  ReplacementPart::ReplacementSubString(last, next_index),
113958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  zone);
114958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              last = next_index + 1;  // Continue after the second "$".
115958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            } else {
116958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              // Let the next substring start with the second "$".
117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              last = next_index;
118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '`':
122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (i > last) {
123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            parts->Add(ReplacementPart::SubjectPrefix(), zone);
126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            last = i + 1;
128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '\'':
130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (i > last) {
131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            parts->Add(ReplacementPart::SubjectSuffix(subject_length), zone);
134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            last = i + 1;
136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
137958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '&':
138958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (i > last) {
139958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              parts->Add(ReplacementPart::ReplacementSubString(last, i), zone);
140958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
141958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            parts->Add(ReplacementPart::SubjectMatch(), zone);
142958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
143958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            last = i + 1;
144958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
145958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '0':
146958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '1':
147958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '2':
148958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '3':
149958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '4':
150958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '5':
151958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '6':
152958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '7':
153958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '8':
154958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          case '9': {
155958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int capture_ref = c2 - '0';
156958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (capture_ref > capture_count) {
157958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              i = next_index;
158958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              continue;
159958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
160958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int second_digit_index = next_index + 1;
161958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (second_digit_index < length) {
162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              // Peek ahead to see if we have two digits.
163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              Char c3 = characters[second_digit_index];
164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              if ('0' <= c3 && c3 <= '9') {  // Double digits.
165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                int double_digit_ref = capture_ref * 10 + c3 - '0';
166958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                if (double_digit_ref <= capture_count) {
167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  next_index = second_digit_index;
168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                  capture_ref = double_digit_ref;
169958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                }
170958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              }
171958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
172958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            if (capture_ref > 0) {
173958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              if (i > last) {
174958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                parts->Add(ReplacementPart::ReplacementSubString(last, i),
175958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           zone);
176958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              }
177958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              DCHECK(capture_ref <= capture_count);
178958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              parts->Add(ReplacementPart::SubjectCapture(capture_ref), zone);
179958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier              last = next_index + 1;
180958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            }
181958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
182958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
183958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          }
184958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          default:
185958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            i = next_index;
186958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            break;
187958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
188958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
189958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
190958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (length > last) {
191958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (last == 0) {
192958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Replacement is simple.  Do not use Apply to do the replacement.
193958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        return true;
194958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
195958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        parts->Add(ReplacementPart::ReplacementSubString(last, length), zone);
196958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
197958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
198958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return false;
199958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
200958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
201958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneList<ReplacementPart> parts_;
202958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ZoneList<Handle<String> > replacement_substrings_;
203958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Zone* zone_;
204958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier};
205958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
206958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
207958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierbool CompiledReplacement::Compile(Handle<String> replacement, int capture_count,
208958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                  int subject_length) {
209958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
210958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DisallowHeapAllocation no_gc;
211958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    String::FlatContent content = replacement->GetFlatContent();
212958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(content.IsFlat());
213958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    bool simple = false;
214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (content.IsOneByte()) {
215958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      simple = ParseReplacementPattern(&parts_, content.ToOneByteVector(),
216958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       capture_count, subject_length, zone());
217958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
218958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      DCHECK(content.IsTwoByte());
219958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      simple = ParseReplacementPattern(&parts_, content.ToUC16Vector(),
220958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       capture_count, subject_length, zone());
221958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
222958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (simple) return true;
223958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
224958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
225958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Isolate* isolate = replacement->GetIsolate();
226958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Find substrings of replacement string and create them as String objects.
227958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int substring_index = 0;
228958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0, n = parts_.length(); i < n; i++) {
229958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int tag = parts_[i].tag;
230958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (tag <= 0) {  // A replacement string slice.
231958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int from = -tag;
232958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      int to = parts_[i].data;
233958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      replacement_substrings_.Add(
234958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate->factory()->NewSubString(replacement, from, to), zone());
235958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      parts_[i].tag = REPLACEMENT_SUBSTRING;
236958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      parts_[i].data = substring_index;
237958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      substring_index++;
238958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else if (tag == REPLACEMENT_STRING) {
239958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      replacement_substrings_.Add(replacement, zone());
240958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      parts_[i].data = substring_index;
241958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      substring_index++;
242958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
243958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
244958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return false;
245958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
246958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
247958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
248958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid CompiledReplacement::Apply(ReplacementStringBuilder* builder,
249958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                int match_from, int match_to, int32_t* match) {
250958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_LT(0, parts_.length());
251958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0, n = parts_.length(); i < n; i++) {
252958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    ReplacementPart part = parts_[i];
253958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    switch (part.tag) {
254958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case SUBJECT_PREFIX:
255958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (match_from > 0) builder->AddSubjectSlice(0, match_from);
256958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
257958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case SUBJECT_SUFFIX: {
258958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        int subject_length = part.data;
259958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (match_to < subject_length) {
260958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          builder->AddSubjectSlice(match_to, subject_length);
261958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
262958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
263958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
264958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case SUBJECT_CAPTURE: {
265958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        int capture = part.data;
266958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        int from = match[capture * 2];
267958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        int to = match[capture * 2 + 1];
268958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (from >= 0 && to > from) {
269958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          builder->AddSubjectSlice(from, to);
270958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
273958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case REPLACEMENT_SUBSTRING:
274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      case REPLACEMENT_STRING:
275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        builder->AddString(replacement_substrings_[part.data]);
276958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        break;
277958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      default:
278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        UNREACHABLE();
279958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
282958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FindOneByteStringIndices(Vector<const uint8_t> subject, uint8_t pattern,
284c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                              List<int>* indices, unsigned int limit) {
285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(limit > 0);
286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Collect indices of pattern in subject using memchr.
287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stop after finding at most limit values.
288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const uint8_t* subject_start = subject.start();
289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const uint8_t* subject_end = subject_start + subject.length();
290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const uint8_t* pos = subject_start;
291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (limit > 0) {
292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pos = reinterpret_cast<const uint8_t*>(
293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        memchr(pos, pattern, subject_end - pos));
294958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (pos == NULL) return;
295c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    indices->Add(static_cast<int>(pos - subject_start));
296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    pos++;
297958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    limit--;
298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
301958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FindTwoByteStringIndices(const Vector<const uc16> subject, uc16 pattern,
302c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                              List<int>* indices, unsigned int limit) {
303958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(limit > 0);
304958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const uc16* subject_start = subject.start();
305958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const uc16* subject_end = subject_start + subject.length();
306958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (const uc16* pos = subject_start; pos < subject_end && limit > 0; pos++) {
307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (*pos == pattern) {
308c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      indices->Add(static_cast<int>(pos - subject_start));
309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      limit--;
310958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
311958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
312958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
313958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
314958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename SubjectChar, typename PatternChar>
315958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FindStringIndices(Isolate* isolate, Vector<const SubjectChar> subject,
316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                       Vector<const PatternChar> pattern, List<int>* indices,
317c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                       unsigned int limit) {
318958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(limit > 0);
319958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Collect indices of pattern in subject.
320958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Stop after finding at most limit values.
321958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int pattern_length = pattern.length();
322958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int index = 0;
323958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  StringSearch<PatternChar, SubjectChar> search(isolate, pattern);
324958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (limit > 0) {
325958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    index = search.Search(subject, index);
326958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (index < 0) return;
327c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    indices->Add(index);
328958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    index += pattern_length;
329958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    limit--;
330958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
331958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
332958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
333958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid FindStringIndicesDispatch(Isolate* isolate, String* subject,
334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               String* pattern, List<int>* indices,
335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               unsigned int limit) {
336958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  {
337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DisallowHeapAllocation no_gc;
338958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    String::FlatContent subject_content = subject->GetFlatContent();
339958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    String::FlatContent pattern_content = pattern->GetFlatContent();
340958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(subject_content.IsFlat());
341958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    DCHECK(pattern_content.IsFlat());
342958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (subject_content.IsOneByte()) {
343958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Vector<const uint8_t> subject_vector = subject_content.ToOneByteVector();
344958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (pattern_content.IsOneByte()) {
345958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Vector<const uint8_t> pattern_vector =
346958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            pattern_content.ToOneByteVector();
347958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (pattern_vector.length() == 1) {
348958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindOneByteStringIndices(subject_vector, pattern_vector[0], indices,
349c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   limit);
350958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
351958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindStringIndices(isolate, subject_vector, pattern_vector, indices,
352c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                            limit);
353958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
354958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
355958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        FindStringIndices(isolate, subject_vector,
356c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                          pattern_content.ToUC16Vector(), indices, limit);
357958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
358958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
359958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Vector<const uc16> subject_vector = subject_content.ToUC16Vector();
360958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (pattern_content.IsOneByte()) {
361958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Vector<const uint8_t> pattern_vector =
362958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            pattern_content.ToOneByteVector();
363958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (pattern_vector.length() == 1) {
364958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices,
365c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   limit);
366958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
367958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindStringIndices(isolate, subject_vector, pattern_vector, indices,
368c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                            limit);
369958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
370958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
371958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Vector<const uc16> pattern_vector = pattern_content.ToUC16Vector();
372958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        if (pattern_vector.length() == 1) {
373958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindTwoByteStringIndices(subject_vector, pattern_vector[0], indices,
374c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                   limit);
375958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        } else {
376958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          FindStringIndices(isolate, subject_vector, pattern_vector, indices,
377c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                            limit);
378958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
379958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
380958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
381958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
382958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
383958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
384c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace {
385c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochList<int>* GetRewoundRegexpIndicesList(Isolate* isolate) {
386c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  List<int>* list = isolate->regexp_indices();
387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  list->Rewind(0);
388c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return list;
389c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
391c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochvoid TruncateRegexpIndicesList(Isolate* isolate) {
392c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Same size as smallest zone segment, preserving behavior from the
393c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // runtime zone.
394c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  static const int kMaxRegexpIndicesListCapacity = 8 * KB;
395c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (isolate->regexp_indices()->capacity() > kMaxRegexpIndicesListCapacity) {
396c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    isolate->regexp_indices()->Clear();  //  Throw away backing storage
397c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
398c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace
400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
401958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename ResultSeqString>
402958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
403958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp,
404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
405958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(subject->IsFlat());
406958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(replacement->IsFlat());
407958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
408c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  List<int>* indices = GetRewoundRegexpIndicesList(isolate);
409c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
410958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
411958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  String* pattern =
412958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
413958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_len = subject->length();
414958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int pattern_len = pattern->length();
415958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int replacement_len = replacement->length();
416958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FindStringIndicesDispatch(isolate, *subject, pattern, indices, 0xffffffff);
418958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
419c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int matches = indices->length();
420958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (matches == 0) return *subject;
421958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
422958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Detect integer overflow.
423958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int64_t result_len_64 = (static_cast<int64_t>(replacement_len) -
424958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                           static_cast<int64_t>(pattern_len)) *
425958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                              static_cast<int64_t>(matches) +
426958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          static_cast<int64_t>(subject_len);
427958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int result_len;
428958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (result_len_64 > static_cast<int64_t>(String::kMaxLength)) {
429958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    STATIC_ASSERT(String::kMaxLength < kMaxInt);
430958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    result_len = kMaxInt;  // Provoke exception.
431958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
432958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    result_len = static_cast<int>(result_len_64);
433958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
43462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (result_len == 0) {
43562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return isolate->heap()->empty_string();
43662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
437958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
438958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_pos = 0;
439958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int result_pos = 0;
440958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
441958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  MaybeHandle<SeqString> maybe_res;
442958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (ResultSeqString::kHasOneByteEncoding) {
443958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    maybe_res = isolate->factory()->NewRawOneByteString(result_len);
444958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
445958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    maybe_res = isolate->factory()->NewRawTwoByteString(result_len);
446958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
447958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<SeqString> untyped_res;
448958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, untyped_res, maybe_res);
449958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<ResultSeqString> result = Handle<ResultSeqString>::cast(untyped_res);
450958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
451958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  for (int i = 0; i < matches; i++) {
452958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Copy non-matched subject content.
453c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (subject_pos < indices->at(i)) {
454958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::WriteToFlat(*subject, result->GetChars() + result_pos,
455c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                          subject_pos, indices->at(i));
456c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      result_pos += indices->at(i) - subject_pos;
457958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
458958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
459958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Replace match.
460958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (replacement_len > 0) {
461958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::WriteToFlat(*replacement, result->GetChars() + result_pos, 0,
462958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                          replacement_len);
463958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      result_pos += replacement_len;
464958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
465958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
466c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    subject_pos = indices->at(i) + pattern_len;
467958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
468958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Add remaining subject content at the end.
469958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (subject_pos < subject_len) {
470958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    String::WriteToFlat(*subject, result->GetChars() + result_pos, subject_pos,
471958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        subject_len);
472958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
473958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
474c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int32_t match_indices[] = {indices->at(matches - 1),
475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             indices->at(matches - 1) + pattern_len};
476958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
477958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  TruncateRegexpIndicesList(isolate);
479c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
480958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return *result;
481958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
482958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
483958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
484958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
485c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
486958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(subject->IsFlat());
487958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(replacement->IsFlat());
488958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
489958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int capture_count = regexp->CaptureCount();
490958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_length = subject->length();
491958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
492958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // CompiledReplacement uses zone allocation.
493c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate->allocator(), ZONE_NAME);
494c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CompiledReplacement compiled_replacement(&zone);
495958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool simple_replace =
496958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      compiled_replacement.Compile(replacement, capture_count, subject_length);
497958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
498958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Shortcut for simple non-regexp global replacements
499958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (regexp->TypeTag() == JSRegExp::ATOM && simple_replace) {
500958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (subject->HasOnlyOneByteChars() && replacement->HasOnlyOneByteChars()) {
501958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
502958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, replacement, last_match_info);
503958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
504958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
505958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, replacement, last_match_info);
506958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
507958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
508958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
509109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  RegExpImpl::GlobalCache global_cache(regexp, subject, isolate);
510958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
511958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
512958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t* current_match = global_cache.FetchNext();
513958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (current_match == NULL) {
514958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (global_cache.HasException()) return isolate->heap()->exception();
515958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return *subject;
516958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
517958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
518958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Guessing the number of parts that the final result string is built
519958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // from. Global regexps can match any number of times, so we guess
520958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // conservatively.
521958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int expected_parts = (compiled_replacement.parts() + 1) * 4 + 1;
522958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  ReplacementStringBuilder builder(isolate->heap(), subject, expected_parts);
523958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
524958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Number of parts added by compiled replacement plus preceeding
525958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // string and possibly suffix after last match.  It is possible for
526958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // all components to use two elements when encoded as two smis.
527958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  const int parts_added_per_loop = 2 * (compiled_replacement.parts() + 2);
528958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
529958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int prev = 0;
530958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
531958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  do {
532958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    builder.EnsureCapacity(parts_added_per_loop);
533958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
534958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int start = current_match[0];
535958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int end = current_match[1];
536958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
537958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (prev < start) {
538958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder.AddSubjectSlice(prev, start);
539958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
540958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
541958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (simple_replace) {
542958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      builder.AddString(replacement);
543958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
544958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      compiled_replacement.Apply(&builder, start, end, current_match);
545958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
546958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    prev = end;
547958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
548958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    current_match = global_cache.FetchNext();
549958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } while (current_match != NULL);
550958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
551958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
552958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
553958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (prev < subject_length) {
554958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    builder.EnsureCapacity(2);
555958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    builder.AddSubjectSlice(prev, subject_length);
556958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
557958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
558958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RegExpImpl::SetLastMatchInfo(last_match_info, subject, capture_count,
559958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               global_cache.LastSuccessfulMatch());
560958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
56113e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RETURN_RESULT_OR_FAILURE(isolate, builder.ToString());
562958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
563958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
564958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <typename ResultSeqString>
565958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierMUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
566958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<RegExpMatchInfo> last_match_info) {
568958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(subject->IsFlat());
569958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
570958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Shortcut for simple non-regexp global replacements
571958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (regexp->TypeTag() == JSRegExp::ATOM) {
572958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<String> empty_string = isolate->factory()->empty_string();
573958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (subject->IsOneByteRepresentation()) {
574958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
575958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, empty_string, last_match_info);
576958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
577958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
578958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, empty_string, last_match_info);
579958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
580958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
581958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
582109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  RegExpImpl::GlobalCache global_cache(regexp, subject, isolate);
583958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
584958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
585958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int32_t* current_match = global_cache.FetchNext();
586958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (current_match == NULL) {
587958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (global_cache.HasException()) return isolate->heap()->exception();
588958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return *subject;
589958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
590958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
591958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int start = current_match[0];
592958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int end = current_match[1];
593958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int capture_count = regexp->CaptureCount();
594958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_length = subject->length();
595958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
596958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int new_length = subject_length - (end - start);
597958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (new_length == 0) return isolate->heap()->empty_string();
598958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
599958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<ResultSeqString> answer;
600958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (ResultSeqString::kHasOneByteEncoding) {
601958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    answer = Handle<ResultSeqString>::cast(
602958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate->factory()->NewRawOneByteString(new_length).ToHandleChecked());
603958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
604958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    answer = Handle<ResultSeqString>::cast(
605958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate->factory()->NewRawTwoByteString(new_length).ToHandleChecked());
606958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
607958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
608958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int prev = 0;
609958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int position = 0;
610958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
611958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  do {
612958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    start = current_match[0];
613958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    end = current_match[1];
614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (prev < start) {
615958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Add substring subject[prev;start] to answer string.
616958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      String::WriteToFlat(*subject, answer->GetChars() + position, prev, start);
617958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      position += start - prev;
618958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
619958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    prev = end;
620958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
621958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    current_match = global_cache.FetchNext();
622958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } while (current_match != NULL);
623958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
625958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
626958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  RegExpImpl::SetLastMatchInfo(last_match_info, subject, capture_count,
627958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                               global_cache.LastSuccessfulMatch());
628958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
629958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (prev < subject_length) {
630958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Add substring subject[prev;length] to answer string.
631958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    String::WriteToFlat(*subject, answer->GetChars() + position, prev,
632958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                        subject_length);
633958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    position += subject_length - prev;
634958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
635958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
636958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (position == 0) return isolate->heap()->empty_string();
637958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
638958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Shorten string and fill
639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int string_size = ResultSeqString::SizeFor(position);
640958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int allocated_string_size = ResultSeqString::SizeFor(new_length);
641958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int delta = allocated_string_size - string_size;
642958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
643958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  answer->set_length(position);
644958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (delta == 0) return *answer;
645958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
646958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Address end_of_string = answer->address() + string_size;
647958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Heap* heap = isolate->heap();
648958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
649958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The trimming is performed on a newly allocated object, which is on a
650958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // fresly allocated page or on an already swept page. Hence, the sweeper
651958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // thread can not get confused with the filler creation. No synchronization
652958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // needed.
653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // TODO(hpayer): We should shrink the large object page if the size
654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // of the object changed significantly.
655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (!heap->lo_space()->Contains(*answer)) {
6563b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    heap->CreateFillerObjectAt(end_of_string, delta, ClearRecordedSlots::kNo);
657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  heap->AdjustLiveBytes(*answer, -delta);
659958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return *answer;
660958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
661958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace {
663958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochObject* StringReplaceGlobalRegExpWithStringHelper(
665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Isolate* isolate, Handle<JSRegExp> regexp, Handle<String> subject,
666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
66713e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
668958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
669958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  subject = String::Flatten(subject);
670958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
671958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (replacement->length() == 0) {
672958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (subject->HasOnlyOneByteChars()) {
673958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, last_match_info);
675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    } else {
676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          isolate, subject, regexp, last_match_info);
678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
680958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
681958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  replacement = String::Flatten(replacement);
682958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
683958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return StringReplaceGlobalRegExpWithString(isolate, subject, regexp,
684958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                             replacement, last_match_info);
685958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
686958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace
688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  HandleScope scope(isolate);
69162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(4, args.length());
692c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
695c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
696c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3);
697c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
698c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return StringReplaceGlobalRegExpWithStringHelper(
699c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, regexp, subject, replacement, last_match_info);
700c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_StringSplit) {
703958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope handle_scope(isolate);
70462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
706958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
707958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_NUMBER_CHECKED(uint32_t, limit, Uint32, args[2]);
70813e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(limit > 0);
709958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
710958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_length = subject->length();
711958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int pattern_length = pattern->length();
71213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(pattern_length > 0);
713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
714958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (limit == 0xffffffffu) {
715014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FixedArray* last_match_cache_unused;
716958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    Handle<Object> cached_answer(
717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        RegExpResultsCache::Lookup(isolate->heap(), *subject, *pattern,
718014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   &last_match_cache_unused,
719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                   RegExpResultsCache::STRING_SPLIT_SUBSTRINGS),
720958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        isolate);
721c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (*cached_answer != Smi::kZero) {
722958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // The cache FixedArray is a COW-array and can therefore be reused.
723958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
724958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          Handle<FixedArray>::cast(cached_answer));
725958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return *result;
726958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
727958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
728958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
729958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The limit can be very large (0xffffffffu), but since the pattern
730958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // isn't empty, we can never create more parts than ~half the length
731958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // of the subject.
732958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
733958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  subject = String::Flatten(subject);
734958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  pattern = String::Flatten(pattern);
735958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
736c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  List<int>* indices = GetRewoundRegexpIndicesList(isolate);
737958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
738c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  FindStringIndicesDispatch(isolate, *subject, *pattern, indices, limit);
739958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (static_cast<uint32_t>(indices->length()) < limit) {
741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    indices->Add(subject_length);
742958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // The list indices now contains the end of each part to create.
745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Create JSArray of substrings separated by separator.
747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int part_count = indices->length();
748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
7493b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch  Handle<JSArray> result =
7503b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch      isolate->factory()->NewJSArray(FAST_ELEMENTS, part_count, part_count,
7513b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch                                     INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
752958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
753958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(result->HasFastObjectElements());
754958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
755958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<FixedArray> elements(FixedArray::cast(result->elements()));
756014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
757c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (part_count == 1 && indices->at(0) == subject_length) {
758014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    elements->set(0, *subject);
759014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  } else {
760014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int part_start = 0;
7613b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    FOR_WITH_HANDLE_SCOPE(isolate, int, i = 0, i, i < part_count, i++, {
762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      int part_end = indices->at(i);
763014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<String> substring =
764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          isolate->factory()->NewProperSubString(subject, part_start, part_end);
765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      elements->set(i, *substring);
766014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      part_start = part_end + pattern_length;
7673b9bc31999c9787eb726ecdbfd5796bfdec32a18Ben Murdoch    });
768958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
769958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
770958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (limit == 0xffffffffu) {
771958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (result->HasFastObjectElements()) {
772958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      RegExpResultsCache::Enter(isolate, subject, pattern, elements,
773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                isolate->factory()->empty_fixed_array(),
774958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                RegExpResultsCache::STRING_SPLIT_SUBSTRINGS);
775958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
776958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
777958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
778c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  TruncateRegexpIndicesList(isolate);
779c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
780958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return *result;
781958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
782958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
783c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES##sec-regexpcreate
784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// RegExpCreate ( P, F )
785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_RegExpCreate) {
786c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  HandleScope scope(isolate);
78762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(1, args.length());
788c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(Object, source_object, 0);
789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> source;
791c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (source_object->IsUndefined(isolate)) {
792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    source = isolate->factory()->empty_string();
793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
794c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
795c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, source, Object::ToString(isolate, source_object));
796c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
797c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Map> map(isolate->regexp_function()->initial_map());
799c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<JSRegExp> regexp =
800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<JSRegExp>::cast(isolate->factory()->NewJSObjectFromMap(map));
801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
802c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  JSRegExp::Flags flags = JSRegExp::kNone;
803c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
804c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  RETURN_FAILURE_ON_EXCEPTION(isolate,
805c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                              JSRegExp::Initialize(regexp, source, flags));
806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return *regexp;
808c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
809958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
810014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_RegExpExec) {
811958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope scope(isolate);
81262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(4, args.length());
813958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
814958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
815958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_INT32_ARG_CHECKED(index, 2);
816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3);
817958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Due to the way the JS calls are constructed this must be less than the
818958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // length of a string, i.e. it is always a Smi.  We check anyway for security.
81913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(index >= 0);
82013e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(index <= subject->length());
821958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  isolate->counters()->regexp_entry_runtime()->Increment();
82213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  RETURN_RESULT_OR_FAILURE(
82313e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch      isolate, RegExpImpl::Exec(regexp, subject, index, last_match_info));
824958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
825958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
826c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_RegExpInternalReplace) {
827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  HandleScope scope(isolate);
82862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
830c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
831c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
832958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<RegExpMatchInfo> internal_match_info =
834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate->regexp_internal_match_info();
835c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return StringReplaceGlobalRegExpWithStringHelper(
837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, regexp, subject, replacement, internal_match_info);
838014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}
839014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
840c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochnamespace {
841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochclass MatchInfoBackedMatch : public String::Match {
843c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch public:
844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  MatchInfoBackedMatch(Isolate* isolate, Handle<String> subject,
845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                       Handle<RegExpMatchInfo> match_info)
846c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : isolate_(isolate), match_info_(match_info) {
847c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    subject_ = String::Flatten(subject);
848c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
849014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetMatch() override {
851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return RegExpUtils::GenericCaptureGetter(isolate_, match_info_, 0, nullptr);
852c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
853958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
855c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> capture_obj = RegExpUtils::GenericCaptureGetter(
856c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate_, match_info_, i, capture_exists);
857c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return (*capture_exists) ? Object::ToString(isolate_, capture_obj)
858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             : isolate_->factory()->empty_string();
859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
860958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetPrefix() override {
862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int match_start = match_info_->Capture(0);
863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return isolate_->factory()->NewSubString(subject_, 0, match_start);
864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
865958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
866c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetSuffix() override {
867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int match_end = match_info_->Capture(1);
868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return isolate_->factory()->NewSubString(subject_, match_end,
869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                             subject_->length());
870c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
871958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
872c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int CaptureCount() override {
873c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return match_info_->NumberOfCaptureRegisters() / 2;
874c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual ~MatchInfoBackedMatch() {}
877c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch private:
879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Isolate* isolate_;
880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> subject_;
881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<RegExpMatchInfo> match_info_;
882c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch};
883c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
884c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdochclass VectorBackedMatch : public String::Match {
885c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch public:
886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  VectorBackedMatch(Isolate* isolate, Handle<String> subject,
887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                    Handle<String> match, int match_position,
888c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                    ZoneVector<Handle<Object>>* captures)
889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      : isolate_(isolate),
890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        match_(match),
891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        match_position_(match_position),
892c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        captures_(captures) {
893c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    subject_ = String::Flatten(subject);
894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
895c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
896c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetMatch() override { return match_; }
897c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
898c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> capture_obj = captures_->at(i);
900c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (capture_obj->IsUndefined(isolate_)) {
901c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      *capture_exists = false;
902c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return isolate_->factory()->empty_string();
903c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
904c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    *capture_exists = true;
905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return Object::ToString(isolate_, capture_obj);
906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
907958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
908c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetPrefix() override {
909c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return isolate_->factory()->NewSubString(subject_, 0, match_position_);
910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> GetSuffix() override {
913c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int match_end_position = match_position_ + match_->length();
914c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return isolate_->factory()->NewSubString(subject_, match_end_position,
915c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                             subject_->length());
916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
917c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  int CaptureCount() override { return static_cast<int>(captures_->size()); }
919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
920c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  virtual ~VectorBackedMatch() {}
921c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch private:
923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Isolate* isolate_;
924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> subject_;
925c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> match_;
926c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int match_position_;
927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ZoneVector<Handle<Object>>* captures_;
928c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch};
929958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
930958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Only called from Runtime_RegExpExecMultiple so it doesn't need to maintain
931958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// separate last match info.  See comment on that function.
932958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniertemplate <bool has_capture>
933958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
934958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Handle<JSRegExp> regexp,
935c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                    Handle<RegExpMatchInfo> last_match_array,
936958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                    Handle<JSArray> result_array) {
937958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(subject->IsFlat());
938958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK_NE(has_capture, regexp->CaptureCount() == 0);
939958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
940958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int capture_count = regexp->CaptureCount();
941958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int subject_length = subject->length();
942958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
943958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMinLengthToCache = 0x1000;
944958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
945958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (subject_length > kMinLengthToCache) {
946014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    FixedArray* last_match_cache;
947014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    Object* cached_answer = RegExpResultsCache::Lookup(
948014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        isolate->heap(), *subject, regexp->data(), &last_match_cache,
949014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
950014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    if (cached_answer->IsFixedArray()) {
951014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int capture_registers = (capture_count + 1) * 2;
952014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int32_t* last_match = NewArray<int32_t>(capture_registers);
953014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int i = 0; i < capture_registers; i++) {
954014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        last_match[i] = Smi::cast(last_match_cache->get(i))->value();
955014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
956958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<FixedArray> cached_fixed_array =
957014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          Handle<FixedArray>(FixedArray::cast(cached_answer));
958c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // The cache FixedArray is a COW-array and we need to return a copy.
959c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<FixedArray> copied_fixed_array =
960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate->factory()->CopyFixedArrayWithMap(
961c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              cached_fixed_array, isolate->factory()->fixed_array_map());
962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      JSArray::SetContent(result_array, copied_fixed_array);
963958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count,
964014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                   last_match);
965014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      DeleteArray(last_match);
966958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      return *result_array;
967958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
968958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
969958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
970109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch  RegExpImpl::GlobalCache global_cache(regexp, subject, isolate);
971958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
972958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
973958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Ensured in Runtime_RegExpExecMultiple.
974958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  DCHECK(result_array->HasFastObjectElements());
975958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  Handle<FixedArray> result_elements(
976958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      FixedArray::cast(result_array->elements()));
977958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (result_elements->length() < 16) {
978958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    result_elements = isolate->factory()->NewFixedArrayWithHoles(16);
979958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
980958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
981958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  FixedArrayBuilder builder(result_elements);
982958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
983958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Position to search from.
984958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int match_start = -1;
985958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  int match_end = 0;
986958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  bool first = true;
987958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
988958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // Two smis before and after the match, for very long strings.
989958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  static const int kMaxBuilderEntriesPerRegExpMatch = 5;
990958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
991958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  while (true) {
992958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    int32_t* current_match = global_cache.FetchNext();
993958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (current_match == NULL) break;
994958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    match_start = current_match[0];
995958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    builder.EnsureCapacity(kMaxBuilderEntriesPerRegExpMatch);
996958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (match_end < match_start) {
997958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ReplacementStringBuilder::AddSubjectSlice(&builder, match_end,
998958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                match_start);
999958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1000958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    match_end = current_match[1];
1001958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    {
1002958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      // Avoid accumulating new handles inside loop.
1003958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      HandleScope temp_scope(isolate);
1004958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      Handle<String> match;
1005958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (!first) {
1006958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        match = isolate->factory()->NewProperSubString(subject, match_start,
1007958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                       match_end);
1008958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
1009958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        match =
1010958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            isolate->factory()->NewSubString(subject, match_start, match_end);
1011958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        first = false;
1012958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1013958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1014958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      if (has_capture) {
1015958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // Arguments array to replace function is match, captures, index and
1016958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        // subject, i.e., 3 + capture count in total.
1017958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        Handle<FixedArray> elements =
1018958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            isolate->factory()->NewFixedArray(3 + capture_count);
1019958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1020958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        elements->set(0, *match);
1021958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        for (int i = 1; i <= capture_count; i++) {
1022958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          int start = current_match[i * 2];
1023958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          if (start >= 0) {
1024958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            int end = current_match[i * 2 + 1];
1025958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            DCHECK(start <= end);
1026958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            Handle<String> substring =
1027958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                isolate->factory()->NewSubString(subject, start, end);
1028958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            elements->set(i, *substring);
1029958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          } else {
1030958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            DCHECK(current_match[i * 2 + 1] < 0);
1031958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier            elements->set(i, isolate->heap()->undefined_value());
1032958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier          }
1033958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        }
1034958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        elements->set(capture_count + 1, Smi::FromInt(match_start));
1035958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        elements->set(capture_count + 2, *subject);
1036958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        builder.Add(*isolate->factory()->NewJSArrayWithElements(elements));
1037958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      } else {
1038958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier        builder.Add(*match);
1039958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      }
1040958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1041958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1042958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1043958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (global_cache.HasException()) return isolate->heap()->exception();
1044958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1045958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (match_start >= 0) {
1046958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    // Finished matching, with at least one match.
1047958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (match_end < subject_length) {
1048958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier      ReplacementStringBuilder::AddSubjectSlice(&builder, match_end,
1049958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                                subject_length);
1050958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1051958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1052958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    RegExpImpl::SetLastMatchInfo(last_match_array, subject, capture_count,
1053014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                                 global_cache.LastSuccessfulMatch());
1054958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1055958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    if (subject_length > kMinLengthToCache) {
1056014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // Store the last successful match into the array for caching.
1057014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      // TODO(yangguo): do not expose last match to JS and simplify caching.
1058014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int capture_registers = (capture_count + 1) * 2;
1059014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<FixedArray> last_match_cache =
1060014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          isolate->factory()->NewFixedArray(capture_registers);
1061014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      int32_t* last_match = global_cache.LastSuccessfulMatch();
1062014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      for (int i = 0; i < capture_registers; i++) {
1063014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        last_match_cache->set(i, Smi::FromInt(last_match[i]));
1064014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      }
1065014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      Handle<FixedArray> result_fixed_array = builder.array();
1066014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      result_fixed_array->Shrink(builder.length());
1067c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Cache the result and copy the FixedArray into a COW array.
1068c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<FixedArray> copied_fixed_array =
1069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate->factory()->CopyFixedArrayWithMap(
1070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              result_fixed_array, isolate->factory()->fixed_array_map());
1071014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RegExpResultsCache::Enter(
1072c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate, subject, handle(regexp->data(), isolate), copied_fixed_array,
1073014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch          last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
1074958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    }
1075958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return *builder.ToJSArray(result_array);
1076958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1077958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return isolate->heap()->null_value();  // No matches at all.
1078958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1079958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1080958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1081c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochMUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction(
1082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
1083c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> replace_obj) {
1084c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Factory* factory = isolate->factory();
1085c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
108762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const int flags = regexp->GetFlags();
108862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
108962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
109062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
109162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
109262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  // TODO(jgruber): This should be an easy port to CSA with massive payback.
109362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
109462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const bool sticky = (flags & JSRegExp::kSticky) != 0;
109562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t last_index = 0;
109662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (sticky) {
109762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
109862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
109962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               Object::ToLength(isolate, last_index_obj),
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                               String);
110162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    last_index = PositiveNumberToUint32(*last_index_obj);
110262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
110362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (static_cast<int>(last_index) > subject->length()) last_index = 0;
110462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
110562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1106c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Object> match_indices_obj;
1107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(
1108c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, match_indices_obj,
110962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      RegExpImpl::Exec(regexp, subject, last_index, last_match_info), String);
1110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1111c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (match_indices_obj->IsNull(isolate)) {
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (sticky) regexp->SetLastIndex(0);
1113c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return subject;
1114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1116c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<RegExpMatchInfo> match_indices =
1117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<RegExpMatchInfo>::cast(match_indices_obj);
1118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int index = match_indices->Capture(0);
1120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int end_of_match = match_indices->Capture(1);
1121c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
112262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (sticky) regexp->SetLastIndex(end_of_match);
112362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  IncrementalStringBuilder builder(isolate);
1125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  builder.AppendString(factory->NewSubString(subject, 0, index));
1126c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Compute the parameter list consisting of the match, captures, index,
1128c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // and subject for the replace function invocation.
1129c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // The number of captures plus one for the match.
1130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int m = match_indices->NumberOfCaptureRegisters() / 2;
1131c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1132c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int argc = m + 2;
1133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ScopedVector<Handle<Object>> argv(argc);
1134c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (int j = 0; j < m; j++) {
1136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    bool ok;
1137c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> capture =
1138c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
1139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (ok) {
1140c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      argv[j] = capture;
1141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    } else {
1142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      argv[j] = factory->undefined_value();
1143c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1144c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1145c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  argv[argc - 2] = handle(Smi::FromInt(index), isolate);
1147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  argv[argc - 1] = subject;
1148c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Object> replacement_obj;
1150c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(
1151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, replacement_obj,
1152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
1153c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                      argv.start()),
1154c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      String);
1155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1156c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> replacement;
1157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(
1158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, replacement, Object::ToString(isolate, replacement_obj), String);
1159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1160c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  builder.AppendString(replacement);
1161c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  builder.AppendString(
1162c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      factory->NewSubString(subject, end_of_match, subject->length()));
1163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return builder.Finish();
1165c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Legacy implementation of RegExp.prototype[Symbol.replace] which
1168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// doesn't properly call the underlying exec method.
1169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochMUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
1170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                  Handle<JSRegExp> regexp,
1171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                  Handle<String> string,
1172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                  Handle<Object> replace_obj) {
1173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Factory* factory = isolate->factory();
1174c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1175c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const int flags = regexp->GetFlags();
1176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const bool global = (flags & JSRegExp::kGlobal) != 0;
117762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const bool sticky = (flags & JSRegExp::kSticky) != 0;
1178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Functional fast-paths are dispatched directly by replace builtin.
1180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  DCHECK(!replace_obj->IsCallable());
1181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1182c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> replace;
1183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(isolate, replace,
1184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                             Object::ToString(isolate, replace_obj), String);
1185c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  replace = String::Flatten(replace);
1186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1188c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (!global) {
1190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Non-global regexp search, string replace.
1191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
119262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    uint32_t last_index = 0;
119362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (sticky) {
119462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
119562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
119662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 Object::ToLength(isolate, last_index_obj),
119762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 String);
119862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      last_index = PositiveNumberToUint32(*last_index_obj);
119962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
120062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (static_cast<int>(last_index) > string->length()) last_index = 0;
120162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
120262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> match_indices_obj;
1204c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_ON_EXCEPTION(
1205c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, match_indices_obj,
120662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        RegExpImpl::Exec(regexp, string, last_index, last_match_info), String);
1207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1208c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (match_indices_obj->IsNull(isolate)) {
120962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (sticky) regexp->SetLastIndex(0);
1210c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return string;
1211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
1214958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1215c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int start_index = match_indices->Capture(0);
1216c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int end_index = match_indices->Capture(1);
1217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
121862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (sticky) regexp->SetLastIndex(end_index);
121962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    IncrementalStringBuilder builder(isolate);
1221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    builder.AppendString(factory->NewSubString(string, 0, start_index));
1222c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (replace->length() > 0) {
1224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      MatchInfoBackedMatch m(isolate, string, match_indices);
1225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<String> replacement;
1226c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement,
1227c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 String::GetSubstitution(isolate, &m, replace),
1228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                 String);
1229c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      builder.AppendString(replacement);
1230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1231c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    builder.AppendString(
1233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        factory->NewSubString(string, end_index, string->length()));
1234c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    return builder.Finish();
1235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  } else {
1236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Global regexp search, string replace.
1237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    DCHECK(global);
1238c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0),
1239c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                        String);
1240c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (replace->length() == 0) {
1242c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (string->HasOnlyOneByteChars()) {
1243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Object* result =
1244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
1245c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                isolate, string, regexp, last_match_info);
1246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        return handle(String::cast(result), isolate);
1247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      } else {
1248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Object* result =
1249c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
1250c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                isolate, string, regexp, last_match_info);
1251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        return handle(String::cast(result), isolate);
1252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1254c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1255c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Object* result = StringReplaceGlobalRegExpWithString(
1256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, string, regexp, replace, last_match_info);
1257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (result->IsString()) {
1258c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return handle(String::cast(result), isolate);
1259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    } else {
1260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      return MaybeHandle<String>();
1261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1263c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  UNREACHABLE();
1265c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  return MaybeHandle<String>();
1266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1267c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}  // namespace
1269c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1270c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// This is only called for StringReplaceGlobalRegExpWithFunction.
1271958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily BernierRUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
1272958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  HandleScope handles(isolate);
127362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(4, args.length());
1274958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1275958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
1276014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
1277c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 2);
1278958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
127913e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(result_array->HasFastObjectElements());
1280958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1281958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  subject = String::Flatten(subject);
128213e2dadd00298019ed862f2b2fc5068bba730bcfBen Murdoch  CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
1283958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1284958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  if (regexp->CaptureCount() == 0) {
1285958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return SearchRegExpMultiple<false>(isolate, subject, regexp,
1286958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                       last_match_info, result_array);
1287958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  } else {
1288958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier    return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info,
1289958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier                                      result_array);
1290958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  }
1291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1293c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
1294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  HandleScope scope(isolate);
129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
1296c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
1298c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
1299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2);
1300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
130162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1303c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction(
1304c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                        isolate, subject, regexp, replace));
1305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochnamespace {
130862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
130962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// ES##sec-speciesconstructor
131062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// SpeciesConstructor ( O, defaultConstructor )
131162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor(
131262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Isolate* isolate, Handle<JSReceiver> recv,
131362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSFunction> default_ctor) {
131462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> ctor_obj;
131562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(
131662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, ctor_obj,
131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      JSObject::GetProperty(recv, isolate->factory()->constructor_string()),
131862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Object);
131962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
132062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (ctor_obj->IsUndefined(isolate)) return default_ctor;
132162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
132262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!ctor_obj->IsJSReceiver()) {
132362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    THROW_NEW_ERROR(isolate,
132462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    NewTypeError(MessageTemplate::kConstructorNotReceiver),
132562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    Object);
132662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
132762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
132862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSReceiver> ctor = Handle<JSReceiver>::cast(ctor_obj);
132962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
133062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> species;
133162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(
133262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, species,
133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      JSObject::GetProperty(ctor, isolate->factory()->species_symbol()),
133462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Object);
133562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
133662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (species->IsNullOrUndefined(isolate)) {
133762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return default_ctor;
133862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
133962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
134062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (species->IsConstructor()) return species;
134162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  THROW_NEW_ERROR(
134362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, NewTypeError(MessageTemplate::kSpeciesNotConstructor), Object);
134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
134562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
134662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochMUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
134762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                             Handle<Object> object,
134862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                             uint32_t* out) {
134962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (object->IsUndefined(isolate)) {
135062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    *out = kMaxUInt32;
135162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return object;
135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
135362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
135462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> number;
135562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_ON_EXCEPTION(isolate, number, Object::ToNumber(object), Object);
135662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  *out = NumberToUint32(*number);
135762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return object;
135862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
135962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
136062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochHandle<JSArray> NewJSArrayWithElements(Isolate* isolate,
136162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       Handle<FixedArray> elems,
136262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       int num_elems) {
136362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  elems->Shrink(num_elems);
136462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return isolate->factory()->NewJSArrayWithElements(elems);
136562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
136662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
136762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}  // namespace
136862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
136962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// Slow path for:
137062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// ES#sec-regexp.prototype-@@replace
137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch// RegExp.prototype [ @@split ] ( string, limit )
137262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochRUNTIME_FUNCTION(Runtime_RegExpSplit) {
137362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
137462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
137562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK(args[1]->IsString());
137762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
137862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0);
137962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, string, 1);
138062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(Object, limit_obj, 2);
138162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
138262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Factory* factory = isolate->factory();
138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
138462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSFunction> regexp_fun = isolate->regexp_function();
138562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> ctor;
138662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
138762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, ctor, SpeciesConstructor(isolate, recv, regexp_fun));
138862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
138962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> flags_obj;
139062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
139162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      isolate, flags_obj, JSObject::GetProperty(recv, factory->flags_string()));
139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<String> flags;
139462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, flags,
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                     Object::ToString(isolate, flags_obj));
139662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
139762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<String> u_str = factory->LookupSingleCharacterStringFromCode('u');
139862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const bool unicode = (String::IndexOf(isolate, flags, u_str, 0) >= 0);
139962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
140062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<String> y_str = factory->LookupSingleCharacterStringFromCode('y');
140162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const bool sticky = (String::IndexOf(isolate, flags, y_str, 0) >= 0);
140262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
140362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<String> new_flags = flags;
140462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (!sticky) {
140562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, new_flags,
140662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                       factory->NewConsString(flags, y_str));
140762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
140862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
140962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<JSReceiver> splitter;
141062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
141162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const int argc = 2;
141262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ScopedVector<Handle<Object>> argv(argc);
141462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    argv[0] = recv;
141562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    argv[1] = new_flags;
141662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
141762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<JSFunction> ctor_fun = Handle<JSFunction>::cast(ctor);
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> splitter_obj;
141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
142062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, splitter_obj, Execution::New(ctor_fun, argc, argv.start()));
142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
142262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    splitter = Handle<JSReceiver>::cast(splitter_obj);
142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
142462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
142562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t limit;
142662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RETURN_FAILURE_ON_EXCEPTION(isolate, ToUint32(isolate, limit_obj, &limit));
142762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
142862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const uint32_t length = string->length();
142962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (limit == 0) return *factory->NewJSArray(0);
143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
143262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if (length == 0) {
143362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> result;
143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
143562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
143662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                 factory->undefined_value()));
143762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
143862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (!result->IsNull(isolate)) return *factory->NewJSArray(0);
143962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<FixedArray> elems = factory->NewUninitializedFixedArray(1);
144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    elems->set(0, *string);
144262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return *factory->NewJSArrayWithElements(elems);
144362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
144462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
144562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  static const int kInitialArraySize = 8;
144662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<FixedArray> elems = factory->NewFixedArrayWithHoles(kInitialArraySize);
144762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  int num_elems = 0;
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
144962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t string_index = 0;
145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t prev_string_index = 0;
145162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  while (string_index < length) {
145262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    RETURN_FAILURE_ON_EXCEPTION(
145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, RegExpUtils::SetLastIndex(isolate, splitter, string_index));
145462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
145562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> result;
145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, result, RegExpUtils::RegExpExec(isolate, splitter, string,
145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                 factory->undefined_value()));
145962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
146062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (result->IsNull(isolate)) {
146162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
146262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     string_index, unicode);
146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      continue;
146462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
146562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
146662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> last_index_obj;
146762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
146862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, last_index_obj, RegExpUtils::GetLastIndex(isolate, splitter));
146962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
147262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const uint32_t end =
147462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        std::min(PositiveNumberToUint32(*last_index_obj), length);
147562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    if (end == prev_string_index) {
147662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      string_index = RegExpUtils::AdvanceStringIndex(isolate, string,
147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                     string_index, unicode);
147862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      continue;
147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
148062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
148162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    {
148262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<String> substr =
148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          factory->NewSubString(string, prev_string_index, string_index);
148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
148562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (static_cast<uint32_t>(num_elems) == limit) {
148662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return *NewJSArrayWithElements(isolate, elems, num_elems);
148762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
148962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    prev_string_index = end;
149162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
149262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<Object> num_captures_obj;
149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
149462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, num_captures_obj,
149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Object::GetProperty(result, isolate->factory()->length_string()));
149662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
149762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
149862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate, num_captures_obj, Object::ToLength(isolate, num_captures_obj));
149962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const int num_captures = PositiveNumberToUint32(*num_captures_obj);
150062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
150162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    for (int i = 1; i < num_captures; i++) {
150262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Handle<Object> capture;
150362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
150462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          isolate, capture, Object::GetElement(isolate, result, i));
150562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      elems = FixedArray::SetAndGrow(elems, num_elems++, capture);
150662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      if (static_cast<uint32_t>(num_elems) == limit) {
150762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        return *NewJSArrayWithElements(isolate, elems, num_elems);
150862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      }
150962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    }
151062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
151162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    string_index = prev_string_index;
151262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
151362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
151462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  {
151562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Handle<String> substr =
151662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        factory->NewSubString(string, prev_string_index, length);
151762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    elems = FixedArray::SetAndGrow(elems, num_elems++, substr);
151862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
151962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
152062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return *NewJSArrayWithElements(isolate, elems, num_elems);
152162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
152262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
1523c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// Slow path for:
1524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES#sec-regexp.prototype-@@replace
1525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// RegExp.prototype [ @@replace ] ( string, replaceValue )
1526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen MurdochRUNTIME_FUNCTION(Runtime_RegExpReplace) {
1527c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  HandleScope scope(isolate);
152862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
1529c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1530c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSReceiver, recv, 0);
1531c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, string, 1);
153262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> replace_obj = args.at(2);
1533c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1534c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Factory* factory = isolate->factory();
1535c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1536c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  string = String::Flatten(string);
1537c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Fast-path for unmodified JSRegExps.
1539c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) {
1540c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    RETURN_RESULT_OR_FAILURE(
1541c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string,
1542c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                               replace_obj));
1543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
154562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  const uint32_t length = string->length();
1546c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const bool functional_replace = replace_obj->IsCallable();
1547c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1548c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<String> replace;
1549c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (!functional_replace) {
1550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, replace,
1551c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Object::ToString(isolate, replace_obj));
1552c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1553c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1554c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Handle<Object> global_obj;
1555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      isolate, global_obj,
1557c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      JSReceiver::GetProperty(recv, factory->global_string()));
1558c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  const bool global = global_obj->BooleanValue();
1559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  bool unicode = false;
1561c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (global) {
1562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> unicode_obj;
1563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, unicode_obj,
1565c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        JSReceiver::GetProperty(recv, factory->unicode_string()));
1566c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    unicode = unicode_obj->BooleanValue();
1567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    RETURN_FAILURE_ON_EXCEPTION(isolate,
1569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                RegExpUtils::SetLastIndex(isolate, recv, 0));
1570c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1571c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1572c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Zone zone(isolate->allocator(), ZONE_NAME);
1573c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  ZoneVector<Handle<Object>> results(&zone);
1574c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1575c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  while (true) {
1576c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> result;
1577c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1578c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, result, RegExpUtils::RegExpExec(isolate, recv, string,
1579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                                 factory->undefined_value()));
1580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1581c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (result->IsNull(isolate)) break;
1582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    results.push_back(result);
1584c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (!global) break;
1585c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1586c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> match_obj;
1587c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj,
1588c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Object::GetElement(isolate, result, 0));
1589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1590c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> match;
1591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match,
1592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Object::ToString(isolate, match_obj));
1593c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1594c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (match->length() == 0) {
1595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      RETURN_FAILURE_ON_EXCEPTION(isolate, RegExpUtils::SetAdvancedStringIndex(
1596c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                               isolate, recv, string, unicode));
1597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1598c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // TODO(jgruber): Look into ReplacementStringBuilder instead.
1601c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  IncrementalStringBuilder builder(isolate);
160262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  uint32_t next_source_position = 0;
1603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1604c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  for (const auto& result : results) {
1605c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> captures_length_obj;
1606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, captures_length_obj,
1608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Object::GetProperty(result, factory->length_string()));
1609c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1610c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1611c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, captures_length_obj,
1612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Object::ToLength(isolate, captures_length_obj));
161362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const int captures_length = PositiveNumberToUint32(*captures_length_obj);
1614c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> match_obj;
1616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match_obj,
1617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Object::GetElement(isolate, result, 0));
1618c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1619c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> match;
1620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, match,
1621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                       Object::ToString(isolate, match_obj));
1622c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    const int match_length = match->length();
1624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1625c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<Object> position_obj;
1626c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, position_obj,
1628c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        Object::GetProperty(result, factory->index_string()));
1629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1630c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // TODO(jgruber): Extract and correct error handling. Since we can go up to
1631c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // 2^53 - 1 (at least for ToLength), we might actually need uint64_t here?
1632c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        isolate, position_obj, Object::ToInteger(isolate, position_obj));
163462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    const uint32_t position =
163562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        std::min(PositiveNumberToUint32(*position_obj), length);
1636c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    ZoneVector<Handle<Object>> captures(&zone);
1638c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    for (int n = 0; n < captures_length; n++) {
1639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<Object> capture;
1640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1641c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate, capture, Object::GetElement(isolate, result, n));
1642c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1643c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      if (!capture->IsUndefined(isolate)) {
1644c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, capture,
1645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                                           Object::ToString(isolate, capture));
1646c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      captures.push_back(capture);
1648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1650c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Handle<String> replacement;
1651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (functional_replace) {
1652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      const int argc = captures_length + 2;
1653c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ScopedVector<Handle<Object>> argv(argc);
1654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      for (int j = 0; j < captures_length; j++) {
1656c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        argv[j] = captures[j];
1657c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1658c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1659c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      argv[captures_length] = handle(Smi::FromInt(position), isolate);
1660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      argv[captures_length + 1] = string;
1661c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Handle<Object> replacement_obj;
1663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate, replacement_obj,
1665c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Execution::Call(isolate, replace_obj, factory->undefined_value(),
1666c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                          argc, argv.start()));
1667c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate, replacement, Object::ToString(isolate, replacement_obj));
1670c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    } else {
1671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      VectorBackedMatch m(isolate, string, match, position, &captures);
1672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1673c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          isolate, replacement, String::GetSubstitution(isolate, &m, replace));
1674c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1675c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    if (position >= next_source_position) {
1677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      builder.AppendString(
1678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          factory->NewSubString(string, next_source_position, position));
1679c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      builder.AppendString(replacement);
1680c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1681c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      next_source_position = position + match_length;
1682c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1685c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  if (next_source_position < length) {
1686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    builder.AppendString(
1687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        factory->NewSubString(string, next_source_position, length));
1688c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1689c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1690c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
1691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1692958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_RegExpExecReThrow) {
1694958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  SealHandleScope shs(isolate);
169562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(4, args.length());
1696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  Object* exception = isolate->pending_exception();
1697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  isolate->clear_pending_exception();
1698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  return isolate->ReThrow(exception);
1699958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
170162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochRUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) {
170262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  HandleScope scope(isolate);
170362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(3, args.length());
170462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
170562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
170662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  CONVERT_ARG_HANDLE_CHECKED(String, flags, 2);
170762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
170862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RETURN_FAILURE_ON_EXCEPTION(isolate,
170962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                              JSRegExp::Initialize(regexp, source, flags));
171062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
171162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  return *regexp;
171262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch}
1713958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier
1714014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochRUNTIME_FUNCTION(Runtime_IsRegExp) {
1715958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  SealHandleScope shs(isolate);
171662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  DCHECK_EQ(1, args.length());
1717958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  CONVERT_ARG_CHECKED(Object, obj, 0);
1718958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1719958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier}
1720c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1721014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
1722014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
1723