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