From 70318619905dd1a10ac0f063da19cebf6d385ba0 Mon Sep 17 00:00:00 2001 From: ishell Date: Tue, 28 Jun 2016 09:15:18 -0700 Subject: [PATCH] [ic] Use UnseededNumberDictionary as a storage for names in TypeFeedbackMetadata. The serializer does not support serialization of HashTables in general because after deserialization it might be necessary to rehash the table. However the UnseededNumberDictionary does not require rehashing and this CL allows them to be serialized. This CL also changes the shape of UnseededNumberDictionary: the details field is no longer part of the entry since no one needs it. BUG=chromium:576312, chromium:623516 Review-Url: https://codereview.chromium.org/2102073002 Cr-Commit-Position: refs/heads/master@{#37336} --- src/heap/heap.cc | 1 + src/heap/heap.h | 1 + src/objects-inl.h | 18 +++++++++++++----- src/objects.cc | 2 +- src/objects.h | 20 ++++++++++++++++++-- src/type-feedback-vector.cc | 32 +++++++++++--------------------- src/type-info.cc | 2 +- 7 files changed, 46 insertions(+), 30 deletions(-) diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 8161056681a..1a768fbc920 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -2342,6 +2342,7 @@ bool Heap::CreateInitialMaps() { ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table) ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, ordered_hash_table) + ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, unseeded_number_dictionary) ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, function_context) ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context) diff --git a/src/heap/heap.h b/src/heap/heap.h index 7f03d89abe4..1badd964393 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -46,6 +46,7 @@ using v8::MemoryPressureLevel; V(Map, fixed_array_map, FixedArrayMap) \ V(Map, fixed_cow_array_map, FixedCOWArrayMap) \ V(Map, hash_table_map, HashTableMap) \ + V(Map, unseeded_number_dictionary_map, UnseededNumberDictionaryMap) \ V(Map, symbol_map, SymbolMap) \ V(Map, one_byte_string_map, OneByteStringMap) \ V(Map, one_byte_internalized_string_map, OneByteInternalizedStringMap) \ diff --git a/src/objects-inl.h b/src/objects-inl.h index 5d59cd3e19e..b30e9626c5e 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -850,9 +850,8 @@ bool Object::IsSeededNumberDictionary() const { return IsDictionary(); } - -bool Object::IsUnseededNumberDictionary() const { - return IsDictionary(); +bool HeapObject::IsUnseededNumberDictionary() const { + return map() == GetHeap()->unseeded_number_dictionary_map(); } bool HeapObject::IsStringTable() const { return IsHashTable(); } @@ -3063,6 +3062,10 @@ void HashTableBase::SetNumberOfDeletedElements(int nod) { set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); } +template +Map* BaseShape::GetMap(Isolate* isolate) { + return isolate->heap()->hash_table_map(); +} template int HashTable::FindEntry(Key key) { @@ -7473,14 +7476,16 @@ void BaseDictionaryShape::SetEntry(Dictionary* dict, int entry, Handle key, Handle value, PropertyDetails details) { - STATIC_ASSERT(Dictionary::kEntrySize == 3); + STATIC_ASSERT(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3); DCHECK(!key->IsName() || details.dictionary_index() > 0); int index = dict->EntryToIndex(entry); DisallowHeapAllocation no_gc; WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); dict->set(index + Dictionary::kEntryKeyIndex, *key, mode); dict->set(index + Dictionary::kEntryValueIndex, *value, mode); - dict->set(index + Dictionary::kEntryDetailsIndex, details.AsSmi()); + if (Dictionary::kEntrySize == 3) { + dict->set(index + Dictionary::kEntryDetailsIndex, details.AsSmi()); + } } @@ -7517,6 +7522,9 @@ uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key, return ComputeIntegerHash(static_cast(other->Number()), 0); } +Map* UnseededNumberDictionaryShape::GetMap(Isolate* isolate) { + return *isolate->factory()->unseeded_number_dictionary_map(); +} uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) { return ComputeIntegerHash(key, seed); diff --git a/src/objects.cc b/src/objects.cc index 64655281009..8a97b2d7852 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -16189,7 +16189,7 @@ Handle HashTable::New( Factory* factory = isolate->factory(); int length = EntryToIndex(capacity); Handle array = factory->NewFixedArray(length, pretenure); - array->set_map_no_write_barrier(*factory->hash_table_map()); + array->set_map_no_write_barrier(Shape::GetMap(isolate)); Handle table = Handle::cast(array); table->SetNumberOfElements(0); diff --git a/src/objects.h b/src/objects.h index c52a17bef61..eb5fc790900 100644 --- a/src/objects.h +++ b/src/objects.h @@ -980,6 +980,7 @@ template inline bool Is(Object* obj); V(JSRegExp) \ V(HashTable) \ V(Dictionary) \ + V(UnseededNumberDictionary) \ V(StringTable) \ V(StringSet) \ V(NormalizedMapCache) \ @@ -1078,7 +1079,6 @@ class Object { INLINE(bool IsNameDictionary() const); INLINE(bool IsGlobalDictionary() const); INLINE(bool IsSeededNumberDictionary() const); - INLINE(bool IsUnseededNumberDictionary() const); INLINE(bool IsOrderedHashSet() const); INLINE(bool IsOrderedHashMap() const); @@ -3124,6 +3124,7 @@ class BaseShape { DCHECK(UsesSeed); return HashForObject(key, object); } + static inline Map* GetMap(Isolate* isolate); }; @@ -3646,7 +3647,6 @@ class NumberDictionaryShape : public BaseDictionaryShape { public: static inline bool IsMatch(uint32_t key, Object* other); static inline Handle AsHandle(Isolate* isolate, uint32_t key); - static const int kEntrySize = 3; static const bool kIsEnumerable = false; }; @@ -3655,6 +3655,7 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape { public: static const bool UsesSeed = true; static const int kPrefixSize = 2; + static const int kEntrySize = 3; static inline uint32_t SeededHash(uint32_t key, uint32_t seed); static inline uint32_t SeededHashForObject(uint32_t key, @@ -3666,9 +3667,24 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape { class UnseededNumberDictionaryShape : public NumberDictionaryShape { public: static const int kPrefixSize = 0; + static const int kEntrySize = 2; static inline uint32_t Hash(uint32_t key); static inline uint32_t HashForObject(uint32_t key, Object* object); + + template + static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) { + UNREACHABLE(); + return PropertyDetails::Empty(); + } + + template + static inline void DetailsAtPut(Dictionary* dict, int entry, + PropertyDetails value) { + UNREACHABLE(); + } + + static inline Map* GetMap(Isolate* isolate); }; diff --git a/src/type-feedback-vector.cc b/src/type-feedback-vector.cc index bc2f1c288bc..661aa2feac4 100644 --- a/src/type-feedback-vector.cc +++ b/src/type-feedback-vector.cc @@ -39,20 +39,13 @@ FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const { DCHECK(SlotRequiresName(GetKind(slot))); - FixedArray* names = FixedArray::cast(get(kNamesTableIndex)); - // TODO(ishell): consider using binary search here or even Dictionary when we - // have more ICs with names. - Smi* key = Smi::FromInt(slot.ToInt()); - for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) { - Object* current_key = names->get(entry + kNameTableSlotIndex); - if (current_key == key) { - Object* name = names->get(entry + kNameTableNameIndex); - DCHECK(name->IsString()); - return String::cast(name); - } - } - UNREACHABLE(); - return nullptr; + UnseededNumberDictionary* names = + UnseededNumberDictionary::cast(get(kNamesTableIndex)); + int entry = names->FindEntry(GetIsolate(), slot.ToInt()); + CHECK_NE(UnseededNumberDictionary::kNotFound, entry); + Object* name = names->ValueAt(entry); + DCHECK(name->IsString()); + return String::cast(name); } void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, @@ -107,10 +100,9 @@ Handle TypeFeedbackMetadata::New(Isolate* isolate, // Add names to NamesTable. const int name_count = spec->name_count(); - Handle names = - name_count == 0 - ? factory->empty_fixed_array() - : factory->NewFixedArray(name_count * kNameTableEntrySize); + Handle names = + UnseededNumberDictionary::New(isolate, name_count); + int name_index = 0; for (int i = 0; i < slot_count; i++) { FeedbackVectorSlotKind kind = spec->GetKind(i); @@ -118,9 +110,7 @@ Handle TypeFeedbackMetadata::New(Isolate* isolate, if (SlotRequiresName(kind)) { Handle name = spec->GetName(name_index); DCHECK(!name.is_null()); - int entry = name_index * kNameTableEntrySize; - names->set(entry + kNameTableSlotIndex, Smi::FromInt(i)); - names->set(entry + kNameTableNameIndex, *name); + names = UnseededNumberDictionary::AtNumberPut(names, i, name); name_index++; } } diff --git a/src/type-info.cc b/src/type-info.cc index 5f5c1e87311..61af125c47c 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -20,7 +20,7 @@ TypeFeedbackOracle::TypeFeedbackOracle( Handle feedback_vector, Handle native_context) : native_context_(native_context), isolate_(isolate), zone_(zone) { BuildDictionary(code); - DCHECK(dictionary_->IsDictionary()); + DCHECK(dictionary_->IsUnseededNumberDictionary()); // We make a copy of the feedback vector because a GC could clear // the type feedback info contained therein. // TODO(mvstanton): revisit the decision to copy when we weakly