27 if (obj1 == obj2)
return true;
33 Representation rep1, DirectHandle<FieldType> type1, Representation rep2,
34 DirectHandle<FieldType> type2, Isolate* isolate) {
40void PrintGeneralization(Isolate* isolate, DirectHandle<Map> map, FILE* file,
41 const char* reason, InternalIndex modify_index,
42 int split,
int descriptors,
bool descriptor_to_field,
43 Representation old_representation,
44 Representation new_representation,
47 MaybeDirectHandle<FieldType> old_field_type,
48 MaybeDirectHandle<Object> old_value,
49 MaybeDirectHandle<FieldType> new_field_type,
50 MaybeDirectHandle<Object> new_value) {
52 os <<
"[generalizing]";
53 Tagged<Name> name = map->instance_descriptors(isolate)->GetKey(modify_index);
57 os <<
"{symbol " <<
reinterpret_cast<void*
>(name.ptr()) <<
"}";
60 if (descriptor_to_field) {
63 os << old_representation.Mnemonic() <<
"{";
64 if (old_field_type.is_null()) {
65 os << Brief(*(old_value.ToHandleChecked()));
69 os <<
";" << old_constness <<
"}";
71 os <<
"->" << new_representation.Mnemonic() <<
"{";
72 if (new_field_type.is_null()) {
73 os << Brief(*(new_value.ToHandleChecked()));
77 os <<
";" << new_constness <<
"} (";
78 if (strlen(reason) > 0) {
81 os <<
"+" << (descriptors -
split) <<
" maps";
94 old_nof_(old_map_->NumberOfOwnDescriptors()),
95 new_elements_kind_(old_map_->elements_kind()),
96 is_transitionable_fast_elements_kind_(
100 !IsFunctionTemplateInfo(old_map->FindRootMap(isolate)->GetConstructor()));
165 DCHECK_EQ(descriptors->GetDetails(descriptor).location(), location);
206 GeneralizeFieldType(old_representation, old_field_type,
266 if (!map->is_deprecated())
return map;
271 return mu.UpdateImpl();
298struct IntegrityLevelTransitionInfo {
299 explicit IntegrityLevelTransitionInfo(
Tagged<Map> map)
308IntegrityLevelTransitionInfo DetectIntegrityLevelTransitions(
311 IntegrityLevelTransitionInfo
info(map);
315 DCHECK(!map->is_extensible());
318 if (!last_transitions.HasIntegrityLevelTransitionTo(
319 map, &info.integrity_level_symbol, &info.integrity_level)) {
333 while (!source_map->is_extensible()) {
336 if (!transitions.HasIntegrityLevelTransitionTo(source_map)) {
343 CHECK_EQ(map->NumberOfOwnDescriptors(), source_map->NumberOfOwnDescriptors());
345 info.has_integrity_level_transition =
true;
346 info.integrity_level_source_map = source_map;
359 Tagged<Map> root_map = old_map->FindRootMap(isolate);
360 if (root_map->is_deprecated()) {
363 DCHECK(constructor->has_initial_map());
364 DCHECK(constructor->initial_map()->is_dictionary_map());
365 if (constructor->initial_map()->elements_kind() !=
366 old_map->elements_kind()) {
369 return constructor->initial_map();
372 if (
v8_flags.move_prototype_transitions_first &&
373 root_map->prototype() != old_map->prototype()) {
375 isolate, root_map, old_map->prototype());
376 if (!maybe_transition) {
379 root_map = *maybe_transition;
382 if (!old_map->EquivalentToForTransition(root_map, cmode))
return {};
387 IntegrityLevelTransitionInfo
info(old_map);
388 if (root_map->is_extensible() != old_map->is_extensible()) {
389 DCHECK(!old_map->is_extensible());
390 DCHECK(root_map->is_extensible());
391 info = DetectIntegrityLevelTransitions(old_map, isolate, &no_gc, cmode);
394 if (!info.has_integrity_level_transition)
return {};
401 to_kind = info.integrity_level_source_map->elements_kind();
403 if (from_kind != to_kind) {
405 root_map = root_map->LookupElementsTransitionMap(isolate, to_kind, cmode);
406 if (root_map.
is_null())
return {};
412 isolate, info.integrity_level_source_map, cmode);
413 if (
result.is_null())
return {};
415 if (info.has_integrity_level_transition) {
420 if (
result.is_null())
return {};
424 if (old_map->elements_kind() != (*result)->elements_kind()) {
425 isolate->PushStackTraceAndDie(
reinterpret_cast<void*
>(old_map.
address()),
426 reinterpret_cast<void*
>((*result).address()),
427 reinterpret_cast<void*
>(root_map.
address()));
429 CHECK_EQ(old_map->instance_type(), (*result)->instance_type());
439 new_representation, new_field_type);
458 CHECK(IsUndefined(initial_map->GetBackPointer(), isolate));
460 const int slack = initial_map->ComputeMinObjectSlack(isolate);
470 int new_unused = map->UnusedPropertyFields() - slack;
472 map->set_instance_size(map->InstanceSizeFromSlack(slack));
475 DCHECK_EQ(new_unused, map->UnusedPropertyFields());
495 transitions.TraverseTransitionTree(
callback);
523 if (
v8_flags.trace_generalization) {
611 if (!
old_map_->EquivalentToForTransition(
613 v8_flags.move_prototype_transitions_first
616 return Normalize(
"Normalize_NotEquivalent");
623 return Normalize(
"Normalize_PrivateSymbolsOnNonExtensible");
641 return Normalize(
"Normalize_InvalidElementsTransition");
644 int root_nof =
root_map_->NumberOfOwnDescriptors();
651 return Normalize(
"Normalize_RootModification1");
654 return Normalize(
"Normalize_RootModification2");
657 return Normalize(
"Normalize_RootModification4");
680 if (!
old_map_->EquivalentToForTransition(
682 return Normalize(
"Normalize_NotEquivalent");
697 int root_nof =
root_map_->NumberOfOwnDescriptors();
704 if (!maybe_tmp_map.
ToHandle(&tmp_map))
break;
714 tmp_descriptors->GetStrongValue(
i))) {
716 return Normalize(
"Normalize_Incompatible");
729 tmp_representation = generalized;
740 tmp_descriptors->GetStrongValue(
i))) {
744 DCHECK(!tmp_map->is_deprecated());
749 int target_nof =
target_map_->NumberOfOwnDescriptors();
770 EqualImmutableValues({}, target_descriptors->GetStrongValue(
800 if (!maybe_tmp_map.
ToHandle(&tmp_map))
break;
811 tmp_descriptors->GetStrongValue(
i))) {
812 return Normalize(
"Normalize_Incompatible");
814 DCHECK(!tmp_map->is_deprecated());
824 int target_nof =
target_map_->NumberOfOwnDescriptors();
836 DCHECK(new_descriptors->number_of_all_descriptors() >
837 target_descriptors->number_of_all_descriptors() ||
838 new_descriptors->number_of_slack_descriptors() > 0 ||
839 new_descriptors->number_of_descriptors() ==
843 int root_nof =
root_map_->NumberOfOwnDescriptors();
849 int current_offset = 0;
861 root_map_->instance_descriptors()->GetDetails(
i);
896 !EqualImmutableValues(target_descriptors->GetStrongValue(
i),
915 target_details.
location(), next_representation);
919 next_representation, target_field_type,
isolate_);
922 isolate_, instance_type, &next_representation, &next_field_type);
928 next_constness, next_representation,
935 new_descriptors->Set(
i, &d);
943 new_descriptors->Set(
i, &d);
974 next_constness, next_representation,
981 new_descriptors->Set(
i, &d);
994 new_descriptors->Set(
i, &d);
998 new_descriptors->Sort();
999 return new_descriptors;
1004 int root_nof =
root_map_->NumberOfOwnDescriptors();
1014 next->instance_descriptors(
isolate_);
1029 if (!EqualImmutableValues(descriptors->GetStrongValue(
i),
1030 next_descriptors->GetStrongValue(
i))) {
1047 int split_nof = split_map->NumberOfOwnDescriptors();
1061 if (!maybe_transition.
is_null()) {
1068 if (maybe_transition.
is_null() &&
1070 return Normalize(
"Normalize_CantHaveMoreTransitions");
1099 PrintGeneralization(
1106 old_value, new_field_type, new_value);
1112 bool had_any_enum_cache =
1113 split_map->instance_descriptors(
isolate_)
1122 split_map->ReplaceDescriptors(
isolate_, *new_descriptors);
1126 if (had_any_enum_cache && new_map->NumberOfEnumerableProperties() > 0) {
1128 isolate_, new_map, new_map->NumberOfEnumerableProperties());
1151 return Normalize(
"Normalize_CantHaveMoreTransitions");
1156 "CopyForPreventExtensions",
1171 os <<
"[reconfiguring]";
1172 Tagged<Name> name = map->instance_descriptors(isolate)->GetKey(modify_index);
1173 if (IsString(name)) {
1176 os <<
"{symbol " <<
reinterpret_cast<void*
>(name.ptr()) <<
"}";
1180 os << attributes <<
" [";
1193 DCHECK(!map->is_dictionary_map());
1196 if (!IsMap(map->GetBackPointer())) {
1200 "Normalize_AttributesMismatchProtoMap");
1203 if (
v8_flags.trace_generalization) {
1204 PrintReconfiguration(isolate, map, stdout, descriptor,
kind, attributes);
1222 map->instance_descriptors(isolate)->GetDetails(descriptor);
1226 if (new_constness != details.
constness() && map->is_prototype_map()) {
1230 std::queue<Tagged<Map>> backlog;
1232 std::vector<Tagged<Map>> sidestep_transition;
1235 while (!backlog.empty()) {
1240 transitions.ForEachTransition(
1241 &no_gc, [&](
Tagged<Map> target) { backlog.push(target); },
1243 if (
v8_flags.move_prototype_transitions_first) {
1244 backlog.push(target);
1248 if (!target.IsSmi() && !
Cast<Map>(target)->is_deprecated()) {
1249 sidestep_transition.push_back(
Cast<Map>(target));
1254 current->instance_descriptors(isolate);
1255 details = descriptors->GetDetails(descriptor);
1264 if (new_constness == details.
constness() &&
1273 name, descriptors->GetFieldIndex(descriptor), details.
attributes(),
1274 new_constness, new_representation, wrapped_type);
1275 DCHECK_EQ(descriptors->GetKey(descriptor), *d.key_);
1276 descriptors->Replace(descriptor, &d);
1281 current->instance_descriptors(isolate);
1282 details = descriptors->GetDetails(descriptor);
1291 direct_handle(descriptors->GetFieldType(descriptor), isolate),
1292 cur_new_representation, new_type, isolate);
1296 if (cur_new_constness != details.
constness() ||
1301 cur_new_constness, cur_new_representation, cur_new_type);
1313 CHECK(!map->is_deprecated());
1317 map->instance_descriptors(isolate), isolate);
1318 PropertyDetails old_details = old_descriptors->GetDetails(modify_index);
1322 old_descriptors->GetFieldType(modify_index), isolate);
1328 old_representation.
Equals(new_representation) &&
1331 *GeneralizeFieldType(old_representation, old_field_type,
1332 new_representation, new_field_type, isolate),
1341 field_owner->instance_descriptors(isolate), isolate);
1342 DCHECK_EQ(*old_field_type, descriptors->GetFieldType(modify_index));
1345 GeneralizeFieldType(old_representation, old_field_type,
1346 new_representation, new_field_type, isolate);
1353 UpdateFieldType(isolate, field_owner, modify_index, name, new_constness,
1354 new_representation, new_field_type);
1359 if (new_constness != old_constness) {
1365 if (!new_representation.
Equals(old_representation)) {
1371 if (
v8_flags.trace_generalization) {
1372 PrintGeneralization(
1373 isolate, map, stdout,
"field type generalization", modify_index,
1374 map->NumberOfOwnDescriptors(), map->NumberOfOwnDescriptors(),
false,
1376 descriptors->GetDetails(modify_index).representation(), old_constness,
@ kFieldRepresentationGroup
static void DeoptimizeDependencyGroups(Isolate *isolate, ObjectT object, DependencyGroups groups)
static V8_EXPORT_PRIVATE Handle< DescriptorArray > Allocate(IsolateT *isolate, int nof_descriptors, int slack, AllocationType allocation=AllocationType::kYoung)
static Descriptor DataField(Isolate *isolate, DirectHandle< Name > key, int field_index, PropertyAttributes attributes, Representation representation)
static Descriptor AccessorConstant(DirectHandle< Name > key, DirectHandle< Object > foreign, PropertyAttributes attributes)
static Descriptor DataConstant(DirectHandle< Name > key, DirectHandle< Object > value, PropertyAttributes attributes)
PropertyDetails GetDetails() const
static Handle< FixedArray > InitializeFastPropertyEnumCache(Isolate *isolate, DirectHandle< Map > map, int enum_length, AllocationType allocation=AllocationType::kOld)
static V8_EXPORT_PRIVATE void PrintTo(Tagged< FieldType > type, std::ostream &os)
static V8_EXPORT_PRIVATE bool Equals(Tagged< FieldType > type, Tagged< FieldType > other)
static V8_EXPORT_PRIVATE Tagged< FieldType > Any()
static V8_EXPORT_PRIVATE Tagged< FieldType > None()
static bool NowIs(Tagged< FieldType > type, Tagged< FieldType > other)
constexpr int as_int() const
LocalIsolate * main_thread_local_isolate()
base::Mutex * map_updater_access()
static Tagged< Map > InvalidatePrototypeChains(Tagged< Map > map)
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
State ConstructNewMapWithIntegrityLevelTransition()
PropertyLocation new_location_
static void GeneralizeField(Isolate *isolate, DirectHandle< Map > map, InternalIndex modify_index, PropertyConstness new_constness, Representation new_representation, DirectHandle< FieldType > new_field_type)
static void UpdateFieldType(Isolate *isolate, DirectHandle< Map > map, InternalIndex descriptor_number, DirectHandle< Name > name, PropertyConstness new_constness, Representation new_representation, DirectHandle< FieldType > new_type)
Tagged< FieldType > GetFieldType(InternalIndex descriptor) const
DirectHandle< FieldType > new_field_type_
Representation new_representation_
static void CompleteInobjectSlackTracking(Isolate *isolate, Tagged< Map > initial_map)
bool has_integrity_level_transition_
DirectHandle< FieldType > GetOrComputeFieldType(InternalIndex descriptor, PropertyLocation location, Representation representation) const
Handle< Map > ReconfigureToDataField(InternalIndex descriptor, PropertyAttributes attributes, PropertyConstness constness, Representation representation, DirectHandle< FieldType > field_type)
Handle< Map > UpdateImpl()
Handle< Map > target_map_
State Normalize(const char *reason)
bool is_transitionable_fast_elements_kind_
DirectHandle< Map > ReconfigureElementsKind(ElementsKind elements_kind)
Tagged< Name > GetKey(InternalIndex descriptor) const
Handle< Map > ApplyPrototypeTransition(DirectHandle< JSPrototype > prototype)
bool TrySaveIntegrityLevelTransitions()
PropertyConstness new_constness_
PropertyDetails GetDetails(InternalIndex descriptor) const
PropertyAttributes new_attributes_
DirectHandle< Map > old_map_
State TryReconfigureToDataFieldInplace()
Handle< Map > result_map_
Tagged< Object > GetValue(InternalIndex descriptor) const
@ kAtIntegrityLevelSource
static std::optional< Tagged< Map > > TryUpdateNoLock(Isolate *isolate, Tagged< Map > old_map, ConcurrencyMode cmode) V8_WARN_UNUSED_RESULT
ElementsKind new_elements_kind_
DirectHandle< Symbol > integrity_level_symbol_
InternalIndex modified_descriptor_
static Handle< Map > ReconfigureExistingProperty(Isolate *isolate, DirectHandle< Map > map, InternalIndex descriptor, PropertyKind kind, PropertyAttributes attributes, PropertyConstness constness)
DirectHandle< Map > FindSplitMap(DirectHandle< DescriptorArray > descriptors)
static DirectHandle< Map > UpdateMapNoLock(Isolate *isolate, DirectHandle< Map > old_map)
DirectHandle< Map > integrity_source_map_
DirectHandle< DescriptorArray > old_descriptors_
MapUpdater(Isolate *isolate, DirectHandle< Map > old_map)
DirectHandle< JSPrototype > new_prototype_
PropertyAttributes integrity_level_
DirectHandle< DescriptorArray > BuildDescriptorArray()
static V8_EXPORT_PRIVATE Handle< Map > TransitionToUpdatePrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
static Handle< Map > CopyForPrototypeTransition(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype)
static const int kNoSlackTracking
static MaybeObjectDirectHandle WrapFieldType(DirectHandle< FieldType > type)
static bool IsMostGeneralFieldType(Representation representation, Tagged< FieldType > field_type)
static V8_EXPORT_PRIVATE Handle< Map > Normalize(Isolate *isolate, DirectHandle< Map > map, ElementsKind new_elements_kind, DirectHandle< JSPrototype > new_prototype, PropertyNormalizationMode mode, bool use_cache, const char *reason)
static V8_EXPORT_PRIVATE Handle< Map > CopyForPreventExtensions(Isolate *isolate, DirectHandle< Map > map, PropertyAttributes attrs_to_add, DirectHandle< Symbol > transition_marker, const char *reason, bool old_map_is_dictionary_elements_kind=false)
static void GeneralizeIfCanHaveTransitionableFastElementsKind(Isolate *isolate, InstanceType instance_type, Representation *representation, DirectHandle< FieldType > *field_type)
static V8_EXPORT_PRIVATE VisitorId GetVisitorId(Tagged< Map > map)
static V8_EXPORT_PRIVATE Handle< Map > AsElementsKind(Isolate *isolate, DirectHandle< Map > map, ElementsKind kind)
static V8_EXPORT_PRIVATE Handle< Map > AddMissingTransitions(Isolate *isolate, DirectHandle< Map > map, DirectHandle< DescriptorArray > descriptors)
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_INLINE bool is_null() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(Handle< S > *out) const
static DirectHandle< FieldType > OptimalType(Tagged< Object > obj, Isolate *isolate, Representation representation)
PropertyAttributes attributes() const
PropertyLocation location() const
int field_width_in_words() const
Representation representation() const
PropertyKind kind() const
PropertyConstness constness() const
constexpr bool IsHeapObject() const
bool fits_into(const Representation &other) const
constexpr bool IsNone() const
bool IsCompatibleForLoad(const Representation &other) const
Representation generalize(Representation other)
bool Equals(const Representation &other) const
static constexpr Representation None()
bool CanBeInPlaceChangedTo(const Representation &other) const
V8_INLINE constexpr bool is_null() const
static bool CanHaveMoreTransitions(Isolate *isolate, DirectHandle< Map > map)
static std::optional< Tagged< Map > > GetPrototypeTransition(Isolate *isolate, Tagged< Map > map, Tagged< Object > prototype)
Tagged< Map > SearchTransition(Tagged< Name > name, PropertyKind kind, PropertyAttributes attributes)
static void SetMigrationTarget(Isolate *isolate, DirectHandle< Map > map, Tagged< Map > migration_target)
std::function< void(Tagged< Map >)> TraverseCallback
Tagged< Map > SearchSpecial(Tagged< Symbol > name)
bool HasIntegrityLevelTransitionTo(Tagged< Map > to, Tagged< Symbol > *out_symbol=nullptr, PropertyAttributes *out_integrity_level=nullptr)
Handle< SharedFunctionInfo > info
ZoneVector< RpoNumber > & result
Tagged< Symbol > integrity_level_symbol
bool has_integrity_level_transition
PropertyAttributes integrity_level
Tagged< Map > integrity_level_source_map
void split(const std::string &str, char delimiter, std::vector< std::string > *vparams)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
bool IsAnyHoleyNonextensibleElementsKind(ElementsKind kind)
bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, ElementsKind to_kind)
Tagged(T object) -> Tagged< T >
V8_INLINE IndirectHandle< T > indirect_handle(DirectHandle< T > handle)
bool IsAnyNonextensibleElementsKind(ElementsKind kind)
@ SLOW_STRING_WRAPPER_ELEMENTS
@ SLOW_SLOPPY_ARGUMENTS_ELEMENTS
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
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
PropertyConstness GeneralizeConstness(PropertyConstness a, PropertyConstness b)
bool IsClass(Tagged< FieldType > obj)
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsGeneralizableTo(PropertyLocation a, PropertyLocation b)
bool IsTypedArrayOrRabGsabTypedArrayElementsKind(ElementsKind kind)
bool IsTransitionableFastElementsKind(ElementsKind from_kind)
constexpr bool IsConcurrent(ConcurrencyMode mode)
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
@ CLEAR_INOBJECT_PROPERTIES
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
#define DCHECK_LE(v1, v2)
#define CHECK_IMPLIES(lhs, rhs)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define CHECK_EQ(lhs, rhs)
#define DCHECK(condition)
#define DCHECK_EQ(v1, v2)
#define V8_WARN_UNUSED_RESULT
#define V8_UNLIKELY(condition)