diff --git a/src/ast.h b/src/ast.h index 10ae7de458..b36d967708 100644 --- a/src/ast.h +++ b/src/ast.h @@ -277,6 +277,14 @@ class SmallMapList { bool is_empty() const { return list_.is_empty(); } int length() const { return list_.length(); } + void AddMapIfMissing(Handle map, Zone* zone) { + map = Map::CurrentMapForDeprecated(map); + for (int i = 0; i < length(); ++i) { + if (at(i).is_identical_to(map)) return; + } + Add(map, zone); + } + void Add(Handle handle, Zone* zone) { list_.Add(handle.location(), zone); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 29474b99fd..b988d3bf2b 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -3610,6 +3610,12 @@ bool Map::CanBeDeprecated() { } +Handle Map::CurrentMapForDeprecated(Handle map) { + if (!map->is_deprecated()) return map; + return GeneralizeRepresentation(map, 0, Representation::Smi()); +} + + void Map::NotifyLeafMapLayoutChange() { dependent_code()->DeoptimizeDependentCodeGroup( GetIsolate(), diff --git a/src/objects.cc b/src/objects.cc index 94fd487aa3..d094b87c93 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -7280,7 +7280,7 @@ MaybeObject* DescriptorArray::Merge(int verbatim, // Allocate a new descriptor array large enough to hold the required // descriptors, with minimally the exact same size as this descriptor array. MaybeObject* maybe_descriptors = DescriptorArray::Allocate( - new_size, Max(new_size, number_of_descriptors()) - new_size); + new_size, Max(new_size, other->number_of_descriptors()) - new_size); if (!maybe_descriptors->To(&result)) return maybe_descriptors; ASSERT(result->length() > length() || result->NumberOfSlackDescriptors() > 0 || diff --git a/src/objects.h b/src/objects.h index 4b5b51d9d9..6748951247 100644 --- a/src/objects.h +++ b/src/objects.h @@ -5344,6 +5344,12 @@ class Map: public HeapObject { inline void deprecate(); inline bool is_deprecated(); inline bool CanBeDeprecated(); + // Returns a non-deprecated version of the input. If the input was not + // deprecated, it is directly returned. Otherwise, the non-deprecated version + // is found by re-transitioning from the root of the transition tree using the + // descriptor array of the map. New maps (and transitions) may be created if + // no new (more general) version exists. + static inline Handle CurrentMapForDeprecated(Handle map); MUST_USE_RESULT MaybeObject* RawCopy(int instance_size); MUST_USE_RESULT MaybeObject* CopyWithPreallocatedFieldDescriptors(); diff --git a/src/stub-cache.cc b/src/stub-cache.cc index 63748779b1..e1e145100c 100644 --- a/src/stub-cache.cc +++ b/src/stub-cache.cc @@ -1059,45 +1059,40 @@ void StubCache::Clear() { void StubCache::CollectMatchingMaps(SmallMapList* types, - Name* name, + Handle name, Code::Flags flags, Handle native_context, Zone* zone) { for (int i = 0; i < kPrimaryTableSize; i++) { - if (primary_[i].key == name) { + if (primary_[i].key == *name) { Map* map = primary_[i].map; // Map can be NULL, if the stub is constant function call // with a primitive receiver. if (map == NULL) continue; - int offset = PrimaryOffset(name, flags, map); + int offset = PrimaryOffset(*name, flags, map); if (entry(primary_, offset) == &primary_[i] && !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { - types->Add(Handle(map), zone); + types->AddMapIfMissing(Handle(map), zone); } } } for (int i = 0; i < kSecondaryTableSize; i++) { - if (secondary_[i].key == name) { + if (secondary_[i].key == *name) { Map* map = secondary_[i].map; // Map can be NULL, if the stub is constant function call // with a primitive receiver. if (map == NULL) continue; // Lookup in primary table and skip duplicates. - int primary_offset = PrimaryOffset(name, flags, map); - Entry* primary_entry = entry(primary_, primary_offset); - if (primary_entry->key == name) { - Map* primary_map = primary_entry->map; - if (map == primary_map) continue; - } + int primary_offset = PrimaryOffset(*name, flags, map); // Lookup in secondary table and add matches. - int offset = SecondaryOffset(name, flags, primary_offset); + int offset = SecondaryOffset(*name, flags, primary_offset); if (entry(secondary_, offset) == &secondary_[i] && !TypeFeedbackOracle::CanRetainOtherContext(map, *native_context)) { - types->Add(Handle(map), zone); + types->AddMapIfMissing(Handle(map), zone); } } } diff --git a/src/stub-cache.h b/src/stub-cache.h index 6a08d95694..84f7f932b4 100644 --- a/src/stub-cache.h +++ b/src/stub-cache.h @@ -311,7 +311,7 @@ class StubCache { // Collect all maps that match the name and flags. void CollectMatchingMaps(SmallMapList* types, - Name* name, + Handle name, Code::Flags flags, Handle native_context, Zone* zone); diff --git a/src/type-info.cc b/src/type-info.cc index 3bc509a618..d29fd12ba0 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -539,15 +539,6 @@ TypeInfo TypeFeedbackOracle::IncrementType(CountOperation* expr) { } -static void AddMapIfMissing(Handle map, SmallMapList* list, - Zone* zone) { - for (int i = 0; i < list->length(); ++i) { - if (list->at(i).is_identical_to(map)) return; - } - list->Add(map, zone); -} - - void TypeFeedbackOracle::CollectPolymorphicMaps(Handle code, SmallMapList* types) { MapHandleList maps; @@ -556,7 +547,7 @@ void TypeFeedbackOracle::CollectPolymorphicMaps(Handle code, for (int i = 0; i < maps.length(); i++) { Handle map(maps.at(i)); if (!CanRetainOtherContext(*map, *native_context_)) { - AddMapIfMissing(map, types, zone()); + types->AddMapIfMissing(map, zone()); } } } @@ -574,7 +565,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, // we need a generic store (or load) here. ASSERT(Handle::cast(object)->ic_state() == GENERIC); } else if (object->IsMap()) { - types->Add(Handle::cast(object), zone()); + types->AddMapIfMissing(Handle::cast(object), zone()); } else if (Handle::cast(object)->ic_state() == POLYMORPHIC) { CollectPolymorphicMaps(Handle::cast(object), types); } else if (FLAG_collect_megamorphic_maps_from_stub_cache && @@ -582,7 +573,7 @@ void TypeFeedbackOracle::CollectReceiverTypes(TypeFeedbackId ast_id, types->Reserve(4, zone()); ASSERT(object->IsCode()); isolate_->stub_cache()->CollectMatchingMaps(types, - *name, + name, flags, native_context_, zone());