diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc index 803072e8b7..902e350b45 100644 --- a/src/objects/js-objects.cc +++ b/src/objects/js-objects.cc @@ -3690,12 +3690,12 @@ Maybe JSObject::GetPropertyAttributesWithInterceptor( void JSObject::NormalizeProperties(Isolate* isolate, Handle object, PropertyNormalizationMode mode, int expected_additional_properties, - const char* reason) { + bool use_cache, const char* reason) { if (!object->HasFastProperties()) return; Handle map(object->map(), isolate); - Handle new_map = - Map::Normalize(isolate, map, map->elements_kind(), mode, reason); + Handle new_map = Map::Normalize(isolate, map, map->elements_kind(), mode, + use_cache, reason); JSObject::MigrateToMap(isolate, object, new_map, expected_additional_properties); @@ -4756,20 +4756,41 @@ void JSObject::OptimizeAsPrototype(Handle object, bool enable_setup_mode) { Isolate* isolate = object->GetIsolate(); if (object->IsJSGlobalObject()) return; - if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) { - // First normalize to ensure all JSFunctions are DATA_CONSTANT. - JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES, 0, - "NormalizeAsPrototype"); - } - if (object->map().is_prototype_map()) { + if (object->map(isolate).is_prototype_map()) { + if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) { + // This is the only way PrototypeBenefitsFromNormalization can be true: + DCHECK(!object->map(isolate).should_be_fast_prototype_map()); + // First normalize to ensure all JSFunctions are DATA_CONSTANT. + constexpr bool kUseCache = true; + JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES, + 0, kUseCache, "NormalizeAsPrototype"); + } if (!V8_DICT_PROPERTY_CONST_TRACKING_BOOL && - object->map().should_be_fast_prototype_map() && + object->map(isolate).should_be_fast_prototype_map() && !object->HasFastProperties()) { JSObject::MigrateSlowToFast(object, 0, "OptimizeAsPrototype"); } } else { - Handle new_map = - Map::Copy(isolate, handle(object->map(), isolate), "CopyAsPrototype"); + Handle new_map; + if (enable_setup_mode && PrototypeBenefitsFromNormalization(object)) { +#if DEBUG + Handle old_map = handle(object->map(isolate), isolate); +#endif // DEBUG + // First normalize to ensure all JSFunctions are DATA_CONSTANT. Don't use + // the cache, since we're going to use the normalized version directly, + // without making a copy. + constexpr bool kUseCache = false; + JSObject::NormalizeProperties(isolate, object, KEEP_INOBJECT_PROPERTIES, + 0, kUseCache, + "NormalizeAndCopyAsPrototype"); + // A new map was created. + DCHECK_NE(*old_map, object->map(isolate)); + + new_map = handle(object->map(isolate), isolate); + } else { + new_map = + Map::Copy(isolate, handle(object->map(), isolate), "CopyAsPrototype"); + } new_map->set_is_prototype_map(true); // Replace the pointer to the exact constructor with the Object function @@ -4810,8 +4831,9 @@ void JSObject::OptimizeAsPrototype(Handle object, #ifdef DEBUG bool should_be_dictionary = V8_DICT_PROPERTY_CONST_TRACKING_BOOL && enable_setup_mode && !object->IsJSGlobalProxy() && - !object->GetIsolate()->bootstrapper()->IsActive(); - DCHECK_IMPLIES(should_be_dictionary, object->map().is_dictionary_map()); + !isolate->bootstrapper()->IsActive(); + DCHECK_IMPLIES(should_be_dictionary, + object->map(isolate).is_dictionary_map()); #endif } diff --git a/src/objects/js-objects.h b/src/objects/js-objects.h index 002c9d0500..608e84acbf 100644 --- a/src/objects/js-objects.h +++ b/src/objects/js-objects.h @@ -651,7 +651,15 @@ class JSObject : public TorqueGeneratedJSObject { // an initial capacity for holding these properties. V8_EXPORT_PRIVATE static void NormalizeProperties( Isolate* isolate, Handle object, PropertyNormalizationMode mode, - int expected_additional_properties, const char* reason); + int expected_additional_properties, bool use_cache, const char* reason); + + V8_EXPORT_PRIVATE static void NormalizeProperties( + Isolate* isolate, Handle object, PropertyNormalizationMode mode, + int expected_additional_properties, const char* reason) { + const bool kUseCache = true; + NormalizeProperties(isolate, object, mode, expected_additional_properties, + kUseCache, reason); + } // Convert and update the elements backing store to be a // NumberDictionary dictionary. Returns the backing after conversion. diff --git a/src/objects/map-inl.h b/src/objects/map-inl.h index 7355e70533..7105676b31 100644 --- a/src/objects/map-inl.h +++ b/src/objects/map-inl.h @@ -171,7 +171,9 @@ void Map::GeneralizeIfCanHaveTransitionableFastElementsKind( Handle Map::Normalize(Isolate* isolate, Handle fast_map, PropertyNormalizationMode mode, const char* reason) { - return Normalize(isolate, fast_map, fast_map->elements_kind(), mode, reason); + const bool kUseCache = true; + return Normalize(isolate, fast_map, fast_map->elements_kind(), mode, + kUseCache, reason); } bool Map::EquivalentToForNormalization(const Map other, diff --git a/src/objects/map.cc b/src/objects/map.cc index 0db0b71104..f487f02ac8 100644 --- a/src/objects/map.cc +++ b/src/objects/map.cc @@ -1182,13 +1182,15 @@ Handle Map::RawCopy(Isolate* isolate, Handle src_handle, Handle Map::Normalize(Isolate* isolate, Handle fast_map, ElementsKind new_elements_kind, - PropertyNormalizationMode mode, const char* reason) { + PropertyNormalizationMode mode, bool use_cache, + const char* reason) { DCHECK(!fast_map->is_dictionary_map()); Handle maybe_cache(isolate->native_context()->normalized_map_cache(), isolate); - bool use_cache = - !fast_map->is_prototype_map() && !maybe_cache->IsUndefined(isolate); + if (fast_map->is_prototype_map() || maybe_cache->IsUndefined(isolate)) { + use_cache = false; + } Handle cache; if (use_cache) cache = Handle::cast(maybe_cache); diff --git a/src/objects/map.h b/src/objects/map.h index 0fe14ffcec..5f934a1237 100644 --- a/src/objects/map.h +++ b/src/objects/map.h @@ -534,11 +534,17 @@ class Map : public TorqueGeneratedMap { Isolate* isolate, Handle old_map, InternalIndex descriptor_number, PropertyConstness constness, Handle value); + V8_EXPORT_PRIVATE static Handle Normalize( + Isolate* isolate, Handle map, ElementsKind new_elements_kind, + PropertyNormalizationMode mode, bool use_cache, const char* reason); V8_EXPORT_PRIVATE static Handle Normalize(Isolate* isolate, Handle map, ElementsKind new_elements_kind, PropertyNormalizationMode mode, - const char* reason); + const char* reason) { + const bool kUseCache = true; + return Normalize(isolate, map, new_elements_kind, mode, kUseCache, reason); + } inline static Handle Normalize(Isolate* isolate, Handle fast_map, PropertyNormalizationMode mode,