23 isolate->regexp_result_indices_map())));
30 int num_indices = match_info->number_of_capture_registers();
31 int num_results = num_indices >> 1;
33 isolate->factory()->NewFixedArray(num_results);
36 for (
int i = 0;
i < num_results;
i++) {
37 const int start_offset =
39 const int end_offset =
44 if (start_offset == -1) {
48 isolate->factory()->NewFixedArray(2));
52 isolate->factory()->NewJSArrayWithElements(indices_sub_array,
54 indices_array->set(
i, *indices_sub_jsarray);
61 if (IsUndefined(*maybe_names, isolate)) {
62 indices->FastPropertyAtPut(groups_index,
70 int num_names = names->length() >> 1;
73 group_names = isolate->factory()->NewSwissNameDictionary(num_names);
75 group_names = isolate->factory()->NewNameDictionary(num_names);
79 for (
int i = 0;
i < num_names;
i++) {
80 int base_offset =
i * 2;
81 int name_offset = base_offset;
82 int index_offset = base_offset + 1;
87 if (!IsUndefined(*capture_indices, isolate)) {
90 InternalIndex group_entry = group_names_dict->FindEntry(isolate, name);
99 if (!IsUndefined(*capture_indices, isolate)) {
100 DCHECK(IsUndefined(group_names_dict->ValueAt(group_entry), isolate));
101 group_names_dict->ValueAtPut(group_entry, *capture_indices);
105 PropertyDictionary::Add(isolate, group_names_dict, name,
113 isolate->factory()->empty_fixed_array();
116 isolate->factory()->NewSlowJSObjectWithPropertiesAndElements(
117 null, group_names, elements);
118 indices->FastPropertyAtPut(groups_index, *js_group_names);
125 const int length = flags->length();
128 if (length > JSRegExp::kFlagCount)
return {};
135 if (!flag.has_value())
return {};
136 if (value & flag.value())
return {};
137 value |= flag.value();
145 JSRegExp::Flags flags) {
147 return isolate->factory()->NewStringFromAsciiChecked(
155 uint32_t backtrack_limit) {
162 regexp->clear_data();
171 Isolate* isolate = regexp->GetIsolate();
173 if (!flags.has_value() ||
177 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string));
179 return Initialize(regexp, source, flags.value());
184bool IsLineTerminator(
int c) {
192template <
typename Char>
193int CountAdditionalEscapeChars(DirectHandle<String> source,
194 bool* needs_escapes_out) {
197 bool needs_escapes =
false;
198 bool in_character_class =
false;
201 const Char c = src[
i];
203 if (
i + 1 < src.
length() && IsLineTerminator(src[
i + 1])) {
210 }
else if (c ==
'/' && !in_character_class) {
212 needs_escapes =
true;
214 }
else if (c ==
'[') {
215 in_character_class =
true;
216 }
else if (c ==
']') {
217 in_character_class =
false;
218 }
else if (c ==
'\n') {
219 needs_escapes =
true;
221 }
else if (c ==
'\r') {
222 needs_escapes =
true;
224 }
else if (
static_cast<int>(c) == 0x2028) {
225 needs_escapes =
true;
226 escapes += std::strlen(
"\\u2028") - 1;
227 }
else if (
static_cast<int>(c) == 0x2029) {
228 needs_escapes =
true;
229 escapes += std::strlen(
"\\u2029") - 1;
234 DCHECK(!in_character_class);
237 *needs_escapes_out = needs_escapes;
241template <
typename Char>
242void WriteStringToCharVector(base::Vector<Char> v,
int* d,
const char*
string) {
244 while (
string[s] !=
'\0') v[(*d)++] =
string[s++];
247template <
typename Char,
typename StringType>
248DirectHandle<StringType> WriteEscapedRegExpSource(
249 DirectHandle<String> source, DirectHandle<StringType>
result) {
251 base::Vector<const Char> src = source->GetCharVector<Char>(no_gc);
252 base::Vector<Char> dst(
result->GetChars(no_gc),
result->length());
255 bool in_character_class =
false;
256 while (s < src.length()) {
257 const Char c = src[
s];
267 if (s == src.length())
break;
268 }
else if (c ==
'/' && !in_character_class) {
271 }
else if (c ==
'[') {
272 in_character_class =
true;
273 }
else if (c ==
']') {
274 in_character_class =
false;
275 }
else if (c ==
'\n') {
276 WriteStringToCharVector(dst, &d,
"\\n");
279 }
else if (c ==
'\r') {
280 WriteStringToCharVector(dst, &d,
"\\r");
283 }
else if (
static_cast<int>(c) == 0x2028) {
284 WriteStringToCharVector(dst, &d,
"\\u2028");
287 }
else if (
static_cast<int>(c) == 0x2029) {
288 WriteStringToCharVector(dst, &d,
"\\u2029");
297 DCHECK(!in_character_class);
301MaybeDirectHandle<String> EscapeRegExpSource(Isolate* isolate,
302 DirectHandle<String> source) {
304 if (source->length() == 0)
return isolate->factory()->query_colon_string();
306 bool needs_escapes =
false;
307 int additional_escape_chars =
308 one_byte ? CountAdditionalEscapeChars<uint8_t>(source, &needs_escapes)
309 : CountAdditionalEscapeChars<
base::
uc16>(source, &needs_escapes);
310 if (!needs_escapes)
return source;
311 int length = source->length() + additional_escape_chars;
313 DirectHandle<SeqOneByteString>
result;
315 isolate->factory()->NewRawOneByteString(length));
316 return WriteEscapedRegExpSource<uint8_t>(source,
result);
318 DirectHandle<SeqTwoByteString>
result;
320 isolate->factory()->NewRawTwoByteString(length));
321 return WriteEscapedRegExpSource<base::uc16>(source,
result);
331 uint32_t backtrack_limit) {
332 Isolate* isolate = regexp->GetIsolate();
333 Factory* factory = isolate->factory();
336 if (source->length() == 0) source = factory->query_colon_string();
346 EscapeRegExpSource(isolate, source));
348 regexp->set_source(*escaped_source);
353 if (IsJSFunction(constructor) &&
364 isolate, regexp, factory->lastIndex_string(),
374 return re_data->has_latin1_code() || re_data->has_uc16_code();
389 return ticks_until_tier_up() == 0;
394 int tier_up_ticks = ticks_until_tier_up();
395 set_ticks_until_tier_up(tier_up_ticks + 1);
399 int tier_up_ticks = ticks_until_tier_up();
400 if (tier_up_ticks == 0) {
404 set_ticks_until_tier_up(tier_up_ticks - 1);
409 set_ticks_until_tier_up(0);
413 return v8_flags.regexp_interpret_all ||
421 clear_latin1_bytecode();
422 clear_uc16_bytecode();
427 set_latin1_bytecode(bytecode);
428 set_uc16_bytecode(bytecode);
432 set_latin1_code(trampoline);
433 set_uc16_code(trampoline);
#define BUILTIN_CODE(isolate, name)
static FieldIndex ForDescriptor(Tagged< Map > map, InternalIndex descriptor_index)
base::uc32 Get(uint32_t index) const
void ResetLastTierUpTick()
void SetBytecodeForExperimental(Isolate *isolate, Tagged< TrustedByteArray > bytecode)
bool ShouldProduceBytecode()
void MarkTierUpForNextExec()
void DiscardCompiledCodeForSerialization()
static void SetContent(DirectHandle< JSArray > array, DirectHandle< FixedArrayBase > storage)
static DirectHandle< JSRegExpResultIndices > BuildIndices(Isolate *isolate, DirectHandle< RegExpMatchInfo > match_info, DirectHandle< Object > maybe_names)
static constexpr int kGroupsDescriptorIndex
static const char * FlagsToString(Flags flags, FlagsBuffer *out_buffer)
static constexpr int kLastIndexFieldIndex
static MaybeDirectHandle< JSRegExp > Initialize(DirectHandle< JSRegExp > regexp, DirectHandle< String > source, Flags flags, uint32_t backtrack_limit=kNoBacktrackLimit)
static constexpr RegExpFlags AsRegExpFlags(Flags f)
static V8_EXPORT_PRIVATE DirectHandle< String > StringFromFlags(Isolate *isolate, Flags flags)
static V8_EXPORT_PRIVATE MaybeDirectHandle< JSRegExp > New(Isolate *isolate, DirectHandle< String > source, Flags flags, uint32_t backtrack_limit=kNoBacktrackLimit)
static constexpr Flags AsJSRegExpFlags(RegExpFlags f)
static std::optional< RegExpFlag > FlagFromChar(char c)
static std::optional< Flags > FlagsFromString(Isolate *isolate, DirectHandle< String > flags)
static constexpr int kInitialLastIndexValue
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > SetProperty(LookupIterator *it, DirectHandle< Object > value, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
V8_EXPORT_PRIVATE bool HasCompiledCode() const
static constexpr int capture_start_index(int capture_index)
static constexpr int capture_end_index(int capture_index)
static V8_EXPORT_PRIVATE bool VerifyFlags(RegExpFlags flags)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > Compile(Isolate *isolate, DirectHandle< JSRegExp > re, DirectHandle< String > pattern, RegExpFlags flags, uint32_t backtrack_limit)
static constexpr Tagged< Smi > FromInt(int value)
static constexpr Tagged< Smi > zero()
static V8_INLINE HandleType< String > Flatten(Isolate *isolate, HandleType< T > string, AllocationType allocation=AllocationType::kYoung)
static bool IsOneByteRepresentationUnderneath(Tagged< String > string)
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
#define RETURN_ON_EXCEPTION(isolate, call)
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
#define THROW_NEW_ERROR(isolate, call)
ZoneVector< RpoNumber > & result
V8_INLINE bool IsLineTerminator(uchar c)
V8_EXPORT_PRIVATE base::Vector< Flag > Flags()
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in name
V8_EXPORT_PRIVATE FlagValues v8_flags
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)