32void Builtins::Generate_RegExpInterpreterTrampoline(MacroAssembler* masm) {
33 ExternalReference interpreter_code_entry =
34 ExternalReference::re_match_for_call_from_js();
35 masm->Jump(interpreter_code_entry);
40void Builtins::Generate_RegExpExperimentalTrampoline(MacroAssembler* masm) {
41 ExternalReference interpreter_code_entry =
42 ExternalReference::re_experimental_match_for_call_from_js();
43 masm->Jump(interpreter_code_entry);
65 Label result_has_indices(
this), allocated(
this);
67 std::optional<TNode<AllocationSite>> no_gc_site = std::nullopt;
78 Context::REGEXP_RESULT_MAP_INDEX));
79 std::tie(var_array, var_elements) =
81 elements_kind, map, length, no_gc_site, length_intptr,
86 BIND(&result_has_indices);
90 Context::REGEXP_RESULT_WITH_INDICES_MAP_INDEX));
91 std::tie(var_array, var_elements) =
93 elements_kind, map, length, no_gc_site, length_intptr,
107 CodeAssembler::LoadRoot(RootIndex::kUndefinedValue));
124 [=,
this] {
return SmiZero(); });
129 Label finish_initialization(
this);
132 static_assert(std::is_base_of_v<JSRegExpResult, JSRegExpResultWithIndices>,
133 "JSRegExpResultWithIndices is a subclass of JSRegExpResult");
135 result, JSRegExpResultWithIndices::kIndicesOffset, undefined_value);
136 Goto(&finish_initialization);
139 BIND(&finish_initialization);
144 length_intptr, RootIndex::kUndefinedValue);
146 if (elements_out) *elements_out =
CAST(var_elements.value());
153 static const int field_offset =
168 static const int field_offset =
202 Label named_captures(
this), maybe_build_indices(
this), out(
this);
205 match_info, offsetof(
RegExpMatchInfo, number_of_capture_registers_))));
223 last_index, has_indices, &result_elements);
236 Label loop(
this, {&var_from_cursor, &var_to_cursor});
245 Label next_iter(
this);
253 string, start_cursor, end_cursor));
260 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop,
264 BIND(&named_captures);
272 regexp, JSRegExp::kDataOffset, kRegExpDataIndirectPointerTag));
313 Label inner_loop(
this, &var_i);
341 Label add_name_entry(
this, &var_name_index),
342 duplicate_name(
this, &var_name_index), next(
this);
344 CAST(properties), name, &duplicate_name, &var_name_index,
346 BIND(&duplicate_name);
347 GotoIf(IsUndefined(capture), &next);
350 CAST(properties), var_name_index.value()),
351 UndefinedConstant()));
353 var_name_index.value(), capture);
356 BIND(&add_name_entry);
358 &add_dictionary_property_slow,
359 var_name_index.value());
365 &maybe_build_indices, &inner_loop);
367 BIND(&add_dictionary_property_slow);
377 BIND(&maybe_build_indices);
384 CallRuntime(Runtime::kRegExpBuildIndices, context, regexp,
385 match_info, maybe_names));
420 Label if_dynamic(
this), out(
this);
425 GotoIf(SmiAbove(register_count,
430 ExternalReference::address_of_regexp_static_result_offsets_vector(
442 address_of_regexp_static_result_offsets_vector,
457 return {var_vector.value(), var_is_dynamic.value()};
462 Label if_dynamic(
this), out(
this);
471 ExternalReference::address_of_regexp_static_result_offsets_vector(
476 address_of_regexp_static_result_offsets_vector)),
479 address_of_regexp_static_result_offsets_vector,
497static constexpr int kInt32SizeLog2 = 2;
498static_assert(
kInt32Size == 1 << kInt32SizeLog2);
502TNode<RegExpMatchInfo>
519 var_match_info.value(), register_count));
552 vars, loop_start, loop_end,
558 var_match_info.value(), var_to_offset.value(),
565 return var_match_info.value();
571 Label out(
this), not_matched(
this);
574 regexp, JSRegExp::kDataOffset, kRegExpDataIndirectPointerTag));
578 TNode<Smi> result_offsets_vector_length = register_count_per_match;
581 std::tie(result_offsets_vector, result_offsets_vector_is_dynamic) =
593 context, regexp, data,
string, last_index, result_offsets_vector,
601 LoadContextElement(context, Context::REGEXP_LAST_MATCH_INFO_INDEX));
603 context, last_match_info, register_count_per_match,
string,
604 result_offsets_vector);
610 result_offsets_vector_is_dynamic);
611 CallRuntime(Runtime::kReThrow, context, var_exception.value());
616 result_offsets_vector_is_dynamic);
617 Goto(if_not_matched);
621 result_offsets_vector_is_dynamic);
622 return var_result.value();
631 regexp, JSRegExp::kDataOffset,
632 kRegExpDataIndirectPointerTag)));
652 GotoIf(UintPtrGreaterThan(int_last_index, int_string_length), &out,
679 Label* labels[] = {&next, &atom, &next};
700#ifdef V8_ENABLE_SANDBOX
718 &var_string_start, &var_string_end);
721 var_bytecode =
LoadObjectField(data, IrRegExpData::kLatin1BytecodeOffset);
729 &var_string_start, &var_string_end);
732 var_bytecode =
LoadObjectField(data, IrRegExpData::kUc16BytecodeOffset);
742#ifdef V8_ENABLE_SANDBOX
805#ifdef V8_ENABLE_SANDBOX
806 TNode<RawPtrT> code_entry = LoadCodeEntryFromIndirectPointerHandle(
820 code_entry, retval_type, std::make_pair(arg0_type, arg0),
821 std::make_pair(arg1_type, arg1), std::make_pair(arg2_type, arg2),
822 std::make_pair(arg3_type, arg3), std::make_pair(arg4_type, arg4),
823 std::make_pair(arg5_type, arg5), std::make_pair(arg6_type, arg6),
824 std::make_pair(arg7_type, arg7), std::make_pair(arg8_type, arg8)));
847 Goto(&retry_experimental);
856 IsolateAddressId::kExceptionAddress,
isolate()));
860 CallRuntime(Runtime::kThrowStackOverflow, context);
864 BIND(&retry_experimental);
870 result_offsets_vector);
874 Runtime::kRegExpExperimentalOneshotExec, context, regexp,
string,
875 last_index,
SmiFromInt32(result_offsets_vector_length)));
890 result_offsets_vector);
894 CallRuntime(Runtime::kRegExpExec, context, regexp,
string, last_index,
908 result_offsets_vector, result_offsets_vector_length);
913 return var_result.value();
931 var_result = has_initialmap;
941 return var_result.value();
953 std::optional<DescriptorIndexNameValue> additional_property_to_check,
954 Label* if_isunmodified,
Label* if_ismodified) {
968 LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset));
982 LoadContextElement(
native_context, Context::REGEXP_PROTOTYPE_MAP_INDEX));
985 int property_count = 0;
988 Context::REGEXP_EXEC_FUNCTION_INDEX};
989 if (additional_property_to_check) {
990 properties_to_check[property_count++] = *additional_property_to_check;
999 prototype_check_assembler.
CheckAndBranch(prototype, if_isunmodified,
1004 Label* if_ismodified) {
1006 context,
object,
LoadMap(
object),
1009 RootIndex::ksearch_symbol,
1010 Context::REGEXP_SEARCH_FUNCTION_INDEX},
1011 if_isunmodified, if_ismodified);
1016 Label* if_ismodified) {
1018 context,
object,
LoadMap(
object),
1021 RootIndex::kmatch_symbol,
1022 Context::REGEXP_MATCH_FUNCTION_INDEX},
1023 if_isunmodified, if_ismodified);
1028 Label* if_ismodified) {
1031 std::nullopt, if_isunmodified, if_ismodified);
1036 Label* if_ismodified) {
1039 if_isunmodified, if_ismodified);
1044 Label* if_isunmodified,
1045 Label* if_ismodified) {
1051 LoadContextElement(
native_context, Context::REGEXP_RESULT_MAP_INDEX);
1053 Label maybe_result_with_indices(
this);
1056 BIND(&maybe_result_with_indices);
1058 static_assert(std::is_base_of_v<JSRegExpResult, JSRegExpResultWithIndices>,
1059 "JSRegExpResultWithIndices is a subclass of JSRegExpResult");
1060 const TNode<Object> initial_regexp_result_with_indices_map =
1062 Context::REGEXP_RESULT_WITH_INDICES_MAP_INDEX);
1064 if_isunmodified, if_ismodified);
1090 auto regexp = Parameter<JSRegExp>(Descriptor::kRegExp);
1091 auto subject_string = Parameter<String>(Descriptor::kString);
1092 auto last_index = Parameter<Smi>(Descriptor::kLastIndex);
1093 auto match_info = Parameter<RegExpMatchInfo>(Descriptor::kMatchInfo);
1094 auto context = Parameter<Context>(Descriptor::kContext);
1096 CSA_DCHECK(
this, TaggedIsPositiveSmi(last_index));
1099 regexp, JSRegExp::kDataOffset, kRegExpDataIndirectPointerTag));
1100 CSA_SBXCHECK(
this, HasInstanceType(data, ATOM_REG_EXP_DATA_TYPE));
1104 UintPtrLessThanOrEqual(SmiUntag(last_index),
1105 LoadStringLengthAsWord(subject_string)));
1108 LoadObjectField<String>(data, AtomRegExpData::kPatternOffset);
1115 CSA_DCHECK(
this, IntPtrGreaterThan(LoadStringLengthAsWord(needle_string),
1116 IntPtrConstant(0)));
1119 CAST(CallBuiltin(Builtin::kStringIndexOf, context, subject_string,
1120 needle_string, last_index));
1122 Label if_failure(
this), if_success(
this);
1123 Branch(SmiEqual(match_from, SmiConstant(-1)), &if_failure, &if_success);
1127 CSA_DCHECK(
this, TaggedIsPositiveSmi(match_from));
1128 CSA_DCHECK(
this, UintPtrLessThan(SmiUntag(match_from),
1129 LoadStringLengthAsWord(subject_string)));
1135 SmiAdd(match_from, LoadStringLengthAsSmi(needle_string));
1137 StoreObjectField(match_info,
1140 StoreObjectField(match_info, offsetof(
RegExpMatchInfo, last_subject_),
1144 UnsafeStoreArrayElement(match_info, 0, match_from,
1152 Return(NullConstant());
1180#define CASE_FOR_FLAG(Lower, Camel, ...) \
1183 GotoIfNot(IsSetWord(var_flags.value(), JSRegExp::k##Camel), &next); \
1184 var_length = Uint32Add(var_length.value(), Uint32Constant(1)); \
1197#define CASE_FOR_FLAG(NAME, FLAG) \
1200 const TNode<Object> flag = GetProperty( \
1201 context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \
1202 Label if_isflagset(this); \
1203 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \
1204 BIND(&if_isflagset); \
1205 var_length = Uint32Add(var_length.value(), Uint32Constant(1)); \
1206 var_flags = Signed(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \
1221#define CASE_FOR_FLAG(NAME, V8_FLAG_EXTERN_REF, FLAG) \
1224 TNode<Word32T> flag_value = UncheckedCast<Word32T>( \
1225 Load(MachineType::Uint8(), ExternalConstant(V8_FLAG_EXTERN_REF))); \
1226 GotoIf(Word32Equal(Word32And(flag_value, Int32Constant(0xFF)), \
1227 Int32Constant(0)), \
1229 const TNode<Object> flag = GetProperty( \
1230 context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \
1231 Label if_isflagset(this); \
1232 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \
1233 BIND(&if_isflagset); \
1234 var_length = Uint32Add(var_length.value(), Uint32Constant(1)); \
1235 var_flags = Signed(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \
1242 ExternalReference::address_of_enable_experimental_regexp_engine(),
1258#define CASE_FOR_FLAG(Lower, Camel, LowerCamel, Char, ...) \
1261 GotoIfNot(IsSetWord(var_flags.value(), JSRegExp::k##Camel), &next); \
1262 const TNode<Int32T> value = Int32Constant(Char); \
1263 StoreNoWriteBarrier(MachineRepresentation::kWord8, string, \
1264 var_offset.value(), value); \
1265 var_offset = IntPtrAdd(var_offset.value(), int_one); \
1299 IsUndefined(maybe_pattern), [=,
this] {
return EmptyStringConstant(); },
1304 IsUndefined(maybe_flags), [=,
this] {
return EmptyStringConstant(); },
1309 return CallRuntime(Runtime::kRegExpInitializeAndCompile, context, regexp,
1316 auto pattern = Parameter<JSAny>(Descriptor::kPattern);
1317 auto flags = Parameter<JSAny>(Descriptor::kFlags);
1318 auto new_target = Parameter<JSAny>(Descriptor::kJSNewTarget);
1319 auto context = Parameter<Context>(Descriptor::kContext);
1337 var_new_target = regexp_function;
1339 GotoIfNot(pattern_is_regexp, &next);
1340 GotoIfNot(IsUndefined(flags), &next);
1343 GetProperty(context,
pattern, isolate->factory()->constructor_string());
1345 GotoIfNot(TaggedEqual(value, regexp_function), &next);
1352 Label next(
this), if_patternisfastregexp(
this),
1353 if_patternisslowregexp(
this);
1354 GotoIf(TaggedIsSmi(
pattern), &next);
1356 GotoIf(IsJSRegExp(
CAST(
pattern)), &if_patternisfastregexp);
1358 Branch(pattern_is_regexp, &if_patternisslowregexp, &next);
1360 BIND(&if_patternisfastregexp);
1367 Label inner_next(
this);
1368 GotoIfNot(IsUndefined(flags), &inner_next);
1370 var_flags = FlagsGetter(context,
pattern,
true);
1379 BIND(&if_patternisslowregexp);
1382 GetProperty(context,
pattern, isolate->factory()->source_string());
1385 Label inner_next(
this);
1386 GotoIfNot(IsUndefined(flags), &inner_next);
1389 GetProperty(context,
pattern, isolate->factory()->flags_string());
1405 Label allocate_jsregexp(
this), allocate_generic(
this, Label::kDeferred),
1407 Branch(TaggedEqual(var_new_target.value(), regexp_function),
1408 &allocate_jsregexp, &allocate_generic);
1410 BIND(&allocate_jsregexp);
1413 regexp_function, JSFunction::kPrototypeOrInitialMapOffset));
1414 var_regexp =
CAST(AllocateJSObjectFromMap(initial_map));
1418 BIND(&allocate_generic);
1422 context, regexp_function,
CAST(var_new_target.value())));
1431 ClearTrustedPointerField(var_regexp.value(), JSRegExp::kDataOffset);
1434 context, var_regexp.value(), var_pattern.value(), var_flags.value());
1441 auto maybe_receiver = Parameter<Object>(Descriptor::kReceiver);
1442 auto maybe_pattern = Parameter<Object>(Descriptor::kPattern);
1443 auto maybe_flags = Parameter<Object>(Descriptor::kFlags);
1444 auto context = Parameter<Context>(Descriptor::kContext);
1446 ThrowIfNotInstanceType(context, maybe_receiver, JS_REG_EXP_TYPE,
1447 "RegExp.prototype.compile");
1457 GotoIf(TaggedIsSmi(maybe_pattern), &next);
1458 GotoIfNot(IsJSRegExp(
CAST(maybe_pattern)), &next);
1462 Label maybe_flags_is_undefined(
this);
1463 GotoIf(IsUndefined(maybe_flags), &maybe_flags_is_undefined);
1465 ThrowTypeError(context, MessageTemplate::kRegExpFlags);
1467 BIND(&maybe_flags_is_undefined);
1473 LoadObjectField(
pattern, JSRegExp::kSourceOffset);
1475 var_flags = new_flags;
1476 var_pattern = new_pattern;
1483 context,
receiver, var_pattern.value(), var_flags.value());
1489 JSRegExp::Flag flag) {
1528 Label if_isunicode(
this), out(
this);
1535 BIND(&if_isunicode);
1540 GotoIfNot(UintPtrLessThan(untagged_plus_one, string_length), &out,
1556 var_result = index_plus_two;
1562 return var_result.value();
1572 Context::INITIAL_REGEXP_STRING_ITERATOR_PROTOTYPE_MAP_INDEX));
1580 JSRegExpStringIterator::kPropertiesOrHashOffset,
1581 RootIndex::kEmptyFixedArray);
1583 RootIndex::kEmptyFixedArray);
1587 iterator, JSRegExpStringIterator::kIteratingRegExpOffset, regexp);
1591 iterator, JSRegExpStringIterator::kIteratedStringOffset,
string);
1606 return CAST(iterator);
1614 CSA_DCHECK(
this, IsFastRegExpPermissive(context, regexp));
1633 regexp, JSRegExp::kDataOffset, kRegExpDataIndirectPointerTag));
1638 std::tie(result_offsets_vector, result_offsets_vector_is_dynamic) =
1656 Branch(SmiEqual(string_length,
SmiZero()), &if_stringisempty, &next,
1659 BIND(&if_stringisempty);
1662 context, regexp, data,
string,
SmiZero(), result_offsets_vector,
1663 result_offsets_vector_length));
1665 Label if_matched(
this), if_not_matched(
this);
1674 context, Context::REGEXP_LAST_MATCH_INFO_INDEX));
1677 register_count_per_match,
string,
1678 result_offsets_vector);
1679 Goto(&return_empty_array);
1682 BIND(&if_not_matched);
1686 std::optional<TNode<AllocationSite>> allocation_site = std::nullopt;
1691 length, allocation_site);
1712 {array.var_array(), array.var_length(), array.var_capacity(),
1713 &var_last_matched_until, &var_next_search_from}),
1714 push_suffix_and_out(
this), out(
this);
1719 TNode<Smi> next_search_from = var_next_search_from.value();
1720 TNode<Smi> last_matched_until = var_last_matched_until.value();
1723 GotoIf(SmiEqual(next_search_from, string_length), &push_suffix_and_out);
1728 context, regexp, data,
string, next_search_from,
1729 result_offsets_vector, result_offsets_vector_length));
1739 GotoIf(SmiEqual(match_from, string_length), &push_suffix_and_out);
1748 LoadContextElement(context, Context::REGEXP_LAST_MATCH_INFO_INDEX));
1750 context, match_info, register_count_per_match,
string,
1751 result_offsets_vector);
1759 GotoIfNot(SmiEqual(match_to, next_search_from), &next);
1760 GotoIfNot(SmiEqual(match_to, last_matched_until), &next);
1767 var_next_search_from =
CAST(new_next_search_from);
1777 array.Push(
CallBuiltin(Builtin::kSubString, context,
string, from, to));
1788 Label nested_loop(
this, {array.var_array(), array.var_length(),
1789 array.var_capacity(), &var_reg}),
1790 nested_loop_out(
this);
1791 Branch(IntPtrLessThan(var_reg.value(), int_num_registers), &nested_loop,
1800 Label select_capture(
this), select_undefined(
this), store_value(
this);
1805 BIND(&select_capture);
1808 CallBuiltin(Builtin::kSubString, context,
string, from, to);
1812 BIND(&select_undefined);
1814 var_value = UndefinedConstant();
1820 array.Push(var_value.value());
1826 Branch(IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
1831 BIND(&nested_loop_out);
1834 var_last_matched_until = match_to;
1835 var_next_search_from = match_to;
1839 BIND(&push_suffix_and_out);
1841 TNode<Smi> from = var_last_matched_until.value();
1843 array.Push(
CallBuiltin(Builtin::kSubString, context,
string, from, to));
1849 var_result = array.ToJSArray(context);
1853 BIND(&return_empty_array);
1857 std::optional<TNode<AllocationSite>> allocation_site = std::nullopt;
1861 var_result =
AllocateJSArray(elements_kind, array_map, capacity, length,
1867 BIND(&if_exception);
1869 result_offsets_vector_is_dynamic);
1870 CallRuntime(Runtime::kReThrow, context, var_exception.value());
1875 result_offsets_vector_is_dynamic);
1876 return var_result.value();
1883 CSA_DCHECK(
this, IsFastRegExpPermissive(context, regexp));
1913 SmiMax(register_count_per_match,
1917 std::tie(result_offsets_vector, result_offsets_vector_is_dynamic) =
1930 IntPtrDiv(
SmiUntag(result_offsets_vector_length),
1931 SmiUntag(register_count_per_match));
1938 {&var_num_matches_in_batch, &var_num_matches, &var_last_index,
1939 &var_start_of_last_match, &var_last_match_offsets_vector},
1941 outer_loop_merge_vars.
insert(outer_loop_merge_vars.end(), merge_vars.
begin(),
1943 Label outer_loop(
this, outer_loop_merge_vars);
1944 Label outer_loop_exit(
this);
1950 IntPtrLessThan(var_num_matches_in_batch.value(), max_matches_in_batch),
1957 context, regexp, data, subject,
SmiFromInt32(var_last_index.value()),
1958 result_offsets_vector,
SmiToInt32(result_offsets_vector_length)));
1964 IntPtrAdd(var_num_matches.value(), var_num_matches_in_batch.value());
1970 once_per_batch(var_num_matches_in_batch.value());
1973 SmiUntag(register_count_per_match);
1975 {&var_last_index, &var_start_of_last_match,
1976 &var_last_match_offsets_vector},
1978 inner_loop_merge_vars.
insert(inner_loop_merge_vars.end(),
1979 merge_vars.
begin(), merge_vars.
end());
1984 register_count_per_match_intptr,
IntPtrConstant(kInt32SizeLog2));
1987 IntPtrMul(inner_loop_increment, var_num_matches_in_batch.value()));
1991 inner_loop_merge_vars, var_inner_loop_index, inner_loop_start,
2004 var_last_match_offsets_vector = current_match_offsets_vector;
2005 var_start_of_last_match =
start;
2006 var_last_index =
end;
2013 Word32NotEqual(var_start_of_last_match.value(), var_last_index.value()),
2018 subject,
SmiFromInt32(var_last_index.value()), is_unicode,
true)));
2022 BIND(&outer_loop_exit);
2030 CAST(LoadContextElement(context, Context::REGEXP_LAST_MATCH_INFO_INDEX));
2033 register_count_per_match, subject,
2034 var_last_match_offsets_vector.value());
2038 BIND(&if_exception);
2040 result_offsets_vector_is_dynamic);
2041 CallRuntime(Runtime::kReThrow, context, var_exception.value());
2046 result_offsets_vector_is_dynamic);
2047 return var_num_matches.value();
2053 CSA_DCHECK(
this, IsFastRegExpPermissive(context, regexp));
2061 {array.var_array(), array.var_length(), array.var_capacity()},
zone());
2063 context, regexp, subject, data, merge_vars,
2066 IntPtrAdd(array.length(), num_matches_in_batch)));
2077 array.Push(matched_string);
2086 var_result = array.ToJSArray(context);
2090 return var_result.value();
2099 from_string, slice_start, slice_end));
2101 CallBuiltin(Builtin::kStringAdd_CheckNone, context, to_string, slice));
2107 CSA_DCHECK(
this, IsFastRegExpPermissive(context, regexp));
2113 context, replace_string),
2123 context, regexp, subject, data, merge_vars,
2132 var_last_match_end.value(),
start);
2140 var_result.value(), replace_string));
2146 var_last_match_end =
end;
2150 var_last_match_end.value(),
2152 return var_result.value();
#define CSA_SLOW_DCHECK(csa,...)
#define CSA_SBXCHECK(csa,...)
#define CSA_DCHECK(csa,...)
#define CSA_CHECK(csa, x)
#define CASE_FOR_FLAG(Lower, Camel,...)
#define TF_BUILTIN(Name, AssemblerBase)
TNode< String > AllocateSeqOneByteString(uint32_t length, AllocationFlags flags=AllocationFlag::kNone)
TNode< JSArray > AllocateJSArray(ElementsKind kind, TNode< Map > array_map, TNode< IntPtrT > capacity, TNode< Smi > length, std::optional< TNode< AllocationSite > > allocation_site, AllocationFlags allocation_flags=AllocationFlag::kNone)
TNode< IntPtrT > LoadAndUntagFixedArrayBaseLength(TNode< FixedArrayBase > array)
TNode< Smi > SmiFromInt32(TNode< Int32T > value)
TNode< BoolT > IsRegExpSpeciesProtectorCellInvalid()
TNode< Smi > SmiShl(TNode< Smi > a, int shift)
void NameDictionaryLookup(TNode< Dictionary > dictionary, TNode< Name > unique_name, Label *if_found, TVariable< IntPtrT > *var_name_index, Label *if_not_found, LookupMode mode=kFindExisting)
TNode< Int32T > TruncateIntPtrToInt32(TNode< IntPtrT > value)
TNode< Map > LoadSlowObjectWithNullPrototypeMap(TNode< NativeContext > native_context)
TNode< TrustedObject > LoadTrustedPointerFromObject(TNode< HeapObject > object, int offset, IndirectPointerTag tag)
TNode< SwissNameDictionary > AllocateSwissNameDictionary(TNode< IntPtrT > at_least_space_for)
TNode< IntPtrT > OffsetOfElementAt(TNode< TIndex > index)
void GotoIfForceSlowPath(Label *if_true)
TNode< JSAny > GetProperty(TNode< Context > context, TNode< JSAny > receiver, Handle< Name > name)
TNode< Smi > SmiTag(TNode< IntPtrT > value)
void Increment(TVariable< TIndex > *variable, int value=1)
TNode< Smi > LoadSmiArrayLength(TNode< Array > array)
TNode< BoolT > IsNumberPositive(TNode< Number > number)
TNode< BoolT > TaggedEqual(TNode< AnyTaggedT > a, TNode< AnyTaggedT > b)
TNode< HeapObject > Allocate(TNode< IntPtrT > size, AllocationFlags flags=AllocationFlag::kNone)
void StoreObjectFieldRoot(TNode< HeapObject > object, int offset, RootIndex root)
TNode< FixedArrayBase > LoadElements(TNode< JSObject > object)
TNode< T > LoadObjectField(TNode< HeapObject > object, int offset)
TNode< NameDictionary > AllocateNameDictionary(int at_least_space_for)
TNode< BoolT > TaggedIsNotSmi(TNode< MaybeObject > a)
TNode< String > ToString_Inline(TNode< Context > context, TNode< Object > input)
TNode< BoolT > TaggedIsPositiveSmi(TNode< Object > a)
TNode< Smi > LoadStringLengthAsSmi(TNode< String > string)
std::pair< TNode< JSArray >, TNode< FixedArrayBase > > AllocateUninitializedJSArrayWithElements(ElementsKind kind, TNode< Map > array_map, TNode< Smi > length, std::optional< TNode< AllocationSite > > allocation_site, TNode< IntPtrT > capacity, AllocationFlags allocation_flags=AllocationFlag::kNone, int array_header_size=JSArray::kHeaderSize)
void StoreValueByKeyIndex(TNode< ContainerType > container, TNode< IntPtrT > key_index, TNode< Object > value, WriteBarrierMode write_barrier=UPDATE_WRITE_BARRIER)
TNode< Uint16T > StringCharCodeAt(TNode< String > string, TNode< UintPtrT > index)
TNode< JSPrototype > LoadMapPrototype(TNode< Map > map)
TNode< IntPtrT > SmiUntag(TNode< Smi > value)
TNode< Map > LoadJSArrayElementsMap(ElementsKind kind, TNode< NativeContext > native_context)
TNode< BoolT > IsSetSmi(TNode< Smi > smi, int untagged_mask)
TNode< BoolT > IsNumberNormalized(TNode< Number > number)
TNode< Object > LoadValueByKeyIndex(TNode< ContainerType > container, TNode< IntPtrT > key_index)
void BuildFastLoop(const VariableList &vars, TVariable< TIndex > &var_index, TNode< TIndex > start_index, TNode< TIndex > end_index, const FastLoopBody< TIndex > &body, TNode< TIndex > increment, LoopUnrollingMode unrolling_mode, IndexAdvanceMode advance_mode, IndexAdvanceDirection advance_direction)
TNode< Map > LoadReceiverMap(TNode< Object > receiver)
void StoreObjectFieldNoWriteBarrier(TNode< HeapObject > object, TNode< IntPtrT > offset, TNode< T > value)
TNode< Object > LoadFixedArrayElement(TNode< FixedArray > object, TNode< TIndex > index, int additional_offset=0, CheckBounds check_bounds=CheckBounds::kAlways)
void IncrementCounter(StatsCounter *counter, int delta)
TNode< BoolT > HasInstanceType(TNode< HeapObject > object, InstanceType type)
TNode< IntPtrT > ElementOffsetFromIndex(TNode< TIndex > index, ElementsKind kind, int base_size=0)
void UnsafeStoreFixedArrayElement(TNode< FixedArray > object, int index, TNode< Object > value, WriteBarrierMode barrier_mode=UPDATE_WRITE_BARRIER)
TNode< IntPtrT > LoadStringLengthAsWord(TNode< String > string)
TNode< Smi > SmiShr(TNode< Smi > a, int shift)
@ kFindExistingOrInsertionIndex
TNode< NativeContext > LoadNativeContext(TNode< Context > context)
TNode< T > Select(TNode< BoolT > condition, const NodeGenerator< T > &true_body, const NodeGenerator< T > &false_body, BranchHint branch_hint=BranchHint::kNone)
TNode< BoolT > TaggedIsSmi(TNode< MaybeObject > a)
TNode< BoolT > IsJSRegExp(TNode< HeapObject > object)
TNode< Object > SetPropertyStrict(TNode< Context > context, TNode< JSAny > receiver, TNode< Object > key, TNode< Object > value)
TNode< Map > LoadMap(TNode< HeapObject > object)
TNode< Int32T > SmiToInt32(TNode< Smi > value)
TNode< JSObject > AllocateJSObjectFromMap(TNode< Map > map, std::optional< TNode< HeapObject > > properties=std::nullopt, std::optional< TNode< FixedArray > > elements=std::nullopt, AllocationFlags flags=AllocationFlag::kNone, SlackTrackingMode slack_tracking_mode=kNoSlackTracking)
Uint32LessThanOrEqual IntPtrGreaterThanOrEqual
TNode< IntPtrT > PositiveSmiUntag(TNode< Smi > value)
void StoreObjectField(TNode< HeapObject > object, int offset, TNode< Smi > value)
void FillFixedArrayWithValue(ElementsKind kind, TNode< FixedArrayBase > array, TNode< TIndex > from_index, TNode< TIndex > to_index, RootIndex value_root_index)
TNode< TValue > LoadArrayElement(TNode< Array > array, int array_header_size, TNode< TIndex > index, int additional_offset=0)
Uint32LessThanOrEqual Int32GreaterThanOrEqual TNode< Smi > SmiMax(TNode< Smi > a, TNode< Smi > b)
void StoreMapNoWriteBarrier(TNode< HeapObject > object, RootIndex map_root_index)
void AddToDictionary(TNode< Dictionary > dictionary, TNode< Name > key, TNode< Object > value, Label *bailout, std::optional< TNode< IntPtrT > > insertion_index=std::nullopt)
TNode< RawPtrT > LoadCodeInstructionStart(TNode< Code > code, CodeEntrypointTag tag)
TNode< JSObject > FastNewObject(TNode< Context > context, TNode< JSFunction > target, TNode< JSReceiver > new_target)
static V8_EXPORT_PRIVATE ExternalReference isolate_address()
static ExternalReference Create(const SCTableReference &table_ref)
static V8_INLINE constexpr bool IsValidSmi(T value)
static const int kJSRegexpStaticOffsetsVectorSize
static constexpr uint32_t kMaxFastArrayLength
static constexpr int kLastIndexFieldIndex
static constexpr int kMaxCaptures
static constexpr int kExecFunctionDescriptorIndex
static constexpr int kSymbolSearchFunctionDescriptorIndex
static constexpr int kAtomCaptureCount
static constexpr int kSymbolMatchFunctionDescriptorIndex
static constexpr MachineType Pointer()
static constexpr MachineType Int32()
static constexpr MachineType AnyTagged()
static constexpr MachineType Uint32()
static constexpr MachineType TaggedPointer()
static constexpr MachineRepresentation PointerRepresentation()
static constexpr MachineType IntPtr()
@ kCheckPrototypePropertyConstness
void CheckAndBranch(TNode< HeapObject > prototype, Label *if_unmodified, Label *if_modified)
TNode< String > RegExpReplaceGlobalSimpleString(TNode< Context > context, TNode< JSRegExp > regexp, TNode< String > subject, TNode< RegExpData > data, TNode< String > replace_string)
TNode< Object > FastLoadLastIndexBeforeSmiCheck(TNode< JSRegExp > regexp)
TNode< UintPtrT > RegExpExecAtom(TNode< Context > context, TNode< AtomRegExpData > data, TNode< String > string, TNode< Smi > last_index, TNode< RawPtrT > result_offsets_vector, TNode< Int32T > result_offsets_vector_length)
std::pair< TNode< RawPtrT >, TNode< BoolT > > LoadOrAllocateRegExpResultVector(TNode< Smi > register_count)
void BranchIfRegExpResult(const TNode< Context > context, const TNode< Object > object, Label *if_isunmodified, Label *if_ismodified)
TNode< Union< Null, JSArray > > RegExpMatchGlobal(TNode< Context > context, TNode< JSRegExp > regexp, TNode< String > subject, TNode< RegExpData > data)
TNode< UintPtrT > RegExpExecInternal(TNode< Context > context, TNode< JSRegExp > regexp, TNode< RegExpData > data, TNode< String > string, TNode< Number > last_index, TNode< RawPtrT > result_offsets_vector, TNode< Int32T > result_offsets_vector_length)
void BranchIfFastRegExpForMatch(TNode< Context > context, TNode< HeapObject > object, Label *if_isunmodified, Label *if_ismodified)
TNode< JSRegExpResult > ConstructNewResultFromMatchInfo(TNode< Context > context, TNode< JSRegExp > regexp, TNode< RegExpMatchInfo > match_info, TNode< String > string, TNode< Number > last_index)
void FastStoreLastIndex(TNode< JSRegExp > regexp, TNode< Smi > value)
TNode< Object > RegExpInitialize(const TNode< Context > context, const TNode< JSRegExp > regexp, const TNode< Object > maybe_pattern, const TNode< Object > maybe_flags)
std::function< void(TNode< IntPtrT >)> OncePerBatchFunction
TNode< JSAny > SlowLoadLastIndex(TNode< Context > context, TNode< JSAny > regexp)
TNode< RegExpMatchInfo > RegExpExecInternal_Single(TNode< Context > context, TNode< JSRegExp > regexp, TNode< String > string, TNode< Number > last_index, Label *if_not_matched)
void FreeRegExpResultVector(TNode< RawPtrT > result_vector, TNode< BoolT > is_dynamic)
TNode< Smi > LoadCaptureCount(TNode< RegExpData > data)
TNode< String > FlagsGetter(TNode< Context > context, TNode< JSAny > regexp, const bool is_fastpath)
void BranchIfFastRegExp_Strict(TNode< Context > context, TNode< HeapObject > object, Label *if_isunmodified, Label *if_ismodified)
TNode< BoolT > IsFastRegExpNoPrototype(TNode< Context > context, TNode< Object > object)
void BranchIfFastRegExp(TNode< Context > context, TNode< HeapObject > object, TNode< Map > map, PrototypeCheckAssembler::Flags prototype_check_flags, std::optional< DescriptorIndexNameValue > additional_property_to_check, Label *if_isunmodified, Label *if_ismodified)
TNode< JSRegExpResult > AllocateRegExpResult(TNode< Context > context, TNode< Smi > length, TNode< Smi > index, TNode< String > input, TNode< JSRegExp > regexp, TNode< Number > last_index, TNode< BoolT > has_indices, TNode< FixedArray > *elements_out=nullptr)
std::function< void(TNode< RawPtrT >, TNode< Int32T >, TNode< Int32T >)> OncePerMatchFunction
TNode< RegExpMatchInfo > InitializeMatchInfoFromRegisters(TNode< Context > context, TNode< RegExpMatchInfo > match_info, TNode< Smi > register_count, TNode< String > subject, TNode< RawPtrT > result_offsets_vector)
TNode< BoolT > FastFlagGetter(TNode< JSRegExp > regexp, JSRegExp::Flag flag)
TNode< Smi > RegistersForCaptureCount(TNode< Smi > capture_count)
void BranchIfFastRegExp_Permissive(TNode< Context > context, TNode< HeapObject > object, Label *if_isunmodified, Label *if_ismodified)
TNode< String > AppendStringSlice(TNode< Context > context, TNode< String > to_string, TNode< String > from_string, TNode< Smi > slice_start, TNode< Smi > slice_end)
TNode< IntPtrT > IntPtrZero()
void SlowStoreLastIndex(TNode< Context > context, TNode< JSAny > regexp, TNode< Object > value)
TNode< Number > AdvanceStringIndex(TNode< String > string, TNode< Number > index, TNode< BoolT > is_unicode, bool is_fastpath)
TNode< IntPtrT > RegExpExecInternal_Batched(TNode< Context > context, TNode< JSRegExp > regexp, TNode< String > subject, TNode< RegExpData > data, const VariableList &merge_vars, OncePerBatchFunction once_per_batch, OncePerMatchFunction once_per_match)
TNode< JSArray > RegExpPrototypeSplitBody(TNode< Context > context, TNode< JSRegExp > regexp, TNode< String > string, TNode< Smi > limit)
void BranchIfFastRegExpForSearch(TNode< Context > context, TNode< HeapObject > object, Label *if_isunmodified, Label *if_ismodified)
void GetStringPointers(TNode< RawPtrT > string_data, TNode< IntPtrT > offset, TNode< IntPtrT > last_index, TNode< IntPtrT > string_length, String::Encoding encoding, TVariable< RawPtrT > *var_string_start, TVariable< RawPtrT > *var_string_end)
TNode< JSAny > CreateRegExpStringIterator(TNode< NativeContext > native_context, TNode< JSAny > regexp, TNode< String > string, TNode< BoolT > global, TNode< BoolT > full_unicode)
static constexpr int kMinCapacity
static constexpr int kInternalRegExpException
static constexpr int kInternalRegExpSuccess
static constexpr int kInternalRegExpRetry
static constexpr int kInternalRegExpFallbackToExperimental
static constexpr int kInternalRegExpFailure
static constexpr int kMaxValue
TNode< Smi > IndexOfDollarChar(const TNode< Context > context, const TNode< String > string)
static const uint32_t kMaxLength
TNode< IntPtrT > offset()
TNode< RawPtrT > PointerToData(Label *if_bailout)
TNode< String > ToDirect()
TNode< BoolT > IsOneByte()
T * insert(const T *pos, It first, It last)
MachineRepresentation rep() const
CodeAssemblerState * state()
TNode< BoolT > Word32NotEqual(TNode< Word32T > left, TNode< Word32T > right)
Node * CallCFunctionWithoutFunctionDescriptor(Node *function, MachineType return_type, CArgs... cargs)
TNode< IntPtrT > IntPtrMul(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > IntPtrAdd(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< IntPtrT > IntPtrConstant(intptr_t value)
TNode< T > UncheckedCast(Node *value)
TNode< IntPtrT > WordShl(TNode< IntPtrT > left, TNode< IntegralT > right)
TNode< BoolT > WordEqual(TNode< WordT > left, TNode< WordT > right)
void GotoIfNot(TNode< IntegralT > condition, Label *false_label, GotoHint goto_hint=GotoHint::kNone)
TNode< IntPtrT > WordSar(TNode< IntPtrT > left, TNode< IntegralT > right)
Isolate * isolate() const
TNode< Object > LoadFullTagged(Node *base)
TNode< Uint32T > Unsigned(TNode< Word32T > x)
TNode< Int32T > Word32And(TNode< Int32T > left, TNode< Int32T > right)
TNode< T > ReinterpretCast(Node *value)
TNode< BoolT > Int32FalseConstant()
Factory * factory() const
TNode< Smi > SmiConstant(Tagged< Smi > value)
void GotoIf(TNode< IntegralT > condition, Label *true_label, GotoHint goto_hint=GotoHint::kNone)
Node * Load(MachineType type, Node *base)
TNode< IntPtrT > ChangeInt32ToIntPtr(TNode< Word32T > value)
TNode< Int32T > Word32Or(TNode< Int32T > left, TNode< Int32T > right)
TNode< Int32T > Word32Shl(TNode< Int32T > left, TNode< Int32T > right)
TNode< BoolT > IntPtrEqual(TNode< WordT > left, TNode< WordT > right)
void Switch(Node *index, Label *default_label, const int32_t *case_values, Label **case_labels, size_t case_count)
TNode< IntPtrT > IntPtrSub(TNode< IntPtrT > left, TNode< IntPtrT > right)
TNode< BoolT > Int32TrueConstant()
TNode< ExternalReference > ExternalConstant(ExternalReference address)
TNode< Int32T > Int32Constant(int32_t value)
TNode< BoolT > WordNotEqual(TNode< WordT > left, TNode< WordT > right)
Node * CallCFunction(Node *function, std::optional< MachineType > return_type, CArgs... cargs)
TNode< Uint32T > Uint32Constant(uint32_t value)
TNode< Type > HeapConstantNoHole(Handle< Type > object)
TNode< BoolT > Word32Equal(TNode< Word32T > left, TNode< Word32T > right)
TNode< T > CallRuntime(Runtime::FunctionId function, TNode< Object > context, TArgs... args)
TNode< UintPtrT > UintPtrConstant(uintptr_t value)
TNode< UintPtrT > WordShr(TNode< UintPtrT > left, TNode< IntegralT > right)
TNode< T > CallBuiltin(Builtin id, TNode< Object > context, TArgs... args)
void Branch(TNode< IntegralT > condition, Label *true_label, Label *false_label, BranchHint branch_hint=BranchHint::kNone)
void StoreNoWriteBarrier(MachineRepresentation rep, Node *base, Node *value)
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
DirectHandle< Object > new_target
ZoneVector< RpoNumber > & result
LiftoffAssembler::CacheState state
InstructionOperand source
constexpr unsigned CountTrailingZeros(T value)
constexpr int kTaggedSize
@ UNSAFE_SKIP_WRITE_BARRIER
constexpr IndirectPointerHandle kNullIndirectPointerHandle
template const char * string
constexpr int kNumRegisters
!IsContextMap !IsContextMap native_context
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)