Commit 70318619 authored by ishell's avatar ishell Committed by Commit bot

[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}
parent 61c137c8
...@@ -2342,6 +2342,7 @@ bool Heap::CreateInitialMaps() { ...@@ -2342,6 +2342,7 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table) ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, hash_table)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, ordered_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, function_context)
ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context) ALLOCATE_VARSIZE_MAP(FIXED_ARRAY_TYPE, catch_context)
......
...@@ -46,6 +46,7 @@ using v8::MemoryPressureLevel; ...@@ -46,6 +46,7 @@ using v8::MemoryPressureLevel;
V(Map, fixed_array_map, FixedArrayMap) \ V(Map, fixed_array_map, FixedArrayMap) \
V(Map, fixed_cow_array_map, FixedCOWArrayMap) \ V(Map, fixed_cow_array_map, FixedCOWArrayMap) \
V(Map, hash_table_map, HashTableMap) \ V(Map, hash_table_map, HashTableMap) \
V(Map, unseeded_number_dictionary_map, UnseededNumberDictionaryMap) \
V(Map, symbol_map, SymbolMap) \ V(Map, symbol_map, SymbolMap) \
V(Map, one_byte_string_map, OneByteStringMap) \ V(Map, one_byte_string_map, OneByteStringMap) \
V(Map, one_byte_internalized_string_map, OneByteInternalizedStringMap) \ V(Map, one_byte_internalized_string_map, OneByteInternalizedStringMap) \
......
...@@ -850,9 +850,8 @@ bool Object::IsSeededNumberDictionary() const { ...@@ -850,9 +850,8 @@ bool Object::IsSeededNumberDictionary() const {
return IsDictionary(); return IsDictionary();
} }
bool HeapObject::IsUnseededNumberDictionary() const {
bool Object::IsUnseededNumberDictionary() const { return map() == GetHeap()->unseeded_number_dictionary_map();
return IsDictionary();
} }
bool HeapObject::IsStringTable() const { return IsHashTable(); } bool HeapObject::IsStringTable() const { return IsHashTable(); }
...@@ -3063,6 +3062,10 @@ void HashTableBase::SetNumberOfDeletedElements(int nod) { ...@@ -3063,6 +3062,10 @@ void HashTableBase::SetNumberOfDeletedElements(int nod) {
set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod)); set(kNumberOfDeletedElementsIndex, Smi::FromInt(nod));
} }
template <typename Key>
Map* BaseShape<Key>::GetMap(Isolate* isolate) {
return isolate->heap()->hash_table_map();
}
template <typename Derived, typename Shape, typename Key> template <typename Derived, typename Shape, typename Key>
int HashTable<Derived, Shape, Key>::FindEntry(Key key) { int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
...@@ -7473,14 +7476,16 @@ void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry, ...@@ -7473,14 +7476,16 @@ void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry,
Handle<Object> key, Handle<Object> key,
Handle<Object> value, Handle<Object> value,
PropertyDetails details) { PropertyDetails details) {
STATIC_ASSERT(Dictionary::kEntrySize == 3); STATIC_ASSERT(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
DCHECK(!key->IsName() || details.dictionary_index() > 0); DCHECK(!key->IsName() || details.dictionary_index() > 0);
int index = dict->EntryToIndex(entry); int index = dict->EntryToIndex(entry);
DisallowHeapAllocation no_gc; DisallowHeapAllocation no_gc;
WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc); WriteBarrierMode mode = dict->GetWriteBarrierMode(no_gc);
dict->set(index + Dictionary::kEntryKeyIndex, *key, mode); dict->set(index + Dictionary::kEntryKeyIndex, *key, mode);
dict->set(index + Dictionary::kEntryValueIndex, *value, 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, ...@@ -7517,6 +7522,9 @@ uint32_t UnseededNumberDictionaryShape::HashForObject(uint32_t key,
return ComputeIntegerHash(static_cast<uint32_t>(other->Number()), 0); return ComputeIntegerHash(static_cast<uint32_t>(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) { uint32_t SeededNumberDictionaryShape::SeededHash(uint32_t key, uint32_t seed) {
return ComputeIntegerHash(key, seed); return ComputeIntegerHash(key, seed);
......
...@@ -16189,7 +16189,7 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New( ...@@ -16189,7 +16189,7 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New(
Factory* factory = isolate->factory(); Factory* factory = isolate->factory();
int length = EntryToIndex(capacity); int length = EntryToIndex(capacity);
Handle<FixedArray> array = factory->NewFixedArray(length, pretenure); Handle<FixedArray> 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<Derived> table = Handle<Derived>::cast(array); Handle<Derived> table = Handle<Derived>::cast(array);
table->SetNumberOfElements(0); table->SetNumberOfElements(0);
......
...@@ -980,6 +980,7 @@ template <class C> inline bool Is(Object* obj); ...@@ -980,6 +980,7 @@ template <class C> inline bool Is(Object* obj);
V(JSRegExp) \ V(JSRegExp) \
V(HashTable) \ V(HashTable) \
V(Dictionary) \ V(Dictionary) \
V(UnseededNumberDictionary) \
V(StringTable) \ V(StringTable) \
V(StringSet) \ V(StringSet) \
V(NormalizedMapCache) \ V(NormalizedMapCache) \
...@@ -1078,7 +1079,6 @@ class Object { ...@@ -1078,7 +1079,6 @@ class Object {
INLINE(bool IsNameDictionary() const); INLINE(bool IsNameDictionary() const);
INLINE(bool IsGlobalDictionary() const); INLINE(bool IsGlobalDictionary() const);
INLINE(bool IsSeededNumberDictionary() const); INLINE(bool IsSeededNumberDictionary() const);
INLINE(bool IsUnseededNumberDictionary() const);
INLINE(bool IsOrderedHashSet() const); INLINE(bool IsOrderedHashSet() const);
INLINE(bool IsOrderedHashMap() const); INLINE(bool IsOrderedHashMap() const);
...@@ -3124,6 +3124,7 @@ class BaseShape { ...@@ -3124,6 +3124,7 @@ class BaseShape {
DCHECK(UsesSeed); DCHECK(UsesSeed);
return HashForObject(key, object); return HashForObject(key, object);
} }
static inline Map* GetMap(Isolate* isolate);
}; };
...@@ -3646,7 +3647,6 @@ class NumberDictionaryShape : public BaseDictionaryShape<uint32_t> { ...@@ -3646,7 +3647,6 @@ class NumberDictionaryShape : public BaseDictionaryShape<uint32_t> {
public: public:
static inline bool IsMatch(uint32_t key, Object* other); static inline bool IsMatch(uint32_t key, Object* other);
static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key); static inline Handle<Object> AsHandle(Isolate* isolate, uint32_t key);
static const int kEntrySize = 3;
static const bool kIsEnumerable = false; static const bool kIsEnumerable = false;
}; };
...@@ -3655,6 +3655,7 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape { ...@@ -3655,6 +3655,7 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape {
public: public:
static const bool UsesSeed = true; static const bool UsesSeed = true;
static const int kPrefixSize = 2; 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 SeededHash(uint32_t key, uint32_t seed);
static inline uint32_t SeededHashForObject(uint32_t key, static inline uint32_t SeededHashForObject(uint32_t key,
...@@ -3666,9 +3667,24 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape { ...@@ -3666,9 +3667,24 @@ class SeededNumberDictionaryShape : public NumberDictionaryShape {
class UnseededNumberDictionaryShape : public NumberDictionaryShape { class UnseededNumberDictionaryShape : public NumberDictionaryShape {
public: public:
static const int kPrefixSize = 0; static const int kPrefixSize = 0;
static const int kEntrySize = 2;
static inline uint32_t Hash(uint32_t key); static inline uint32_t Hash(uint32_t key);
static inline uint32_t HashForObject(uint32_t key, Object* object); static inline uint32_t HashForObject(uint32_t key, Object* object);
template <typename Dictionary>
static inline PropertyDetails DetailsAt(Dictionary* dict, int entry) {
UNREACHABLE();
return PropertyDetails::Empty();
}
template <typename Dictionary>
static inline void DetailsAtPut(Dictionary* dict, int entry,
PropertyDetails value) {
UNREACHABLE();
}
static inline Map* GetMap(Isolate* isolate);
}; };
......
...@@ -39,20 +39,13 @@ FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind( ...@@ -39,20 +39,13 @@ FeedbackVectorSlotKind TypeFeedbackMetadata::GetKind(
String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const { String* TypeFeedbackMetadata::GetName(FeedbackVectorSlot slot) const {
DCHECK(SlotRequiresName(GetKind(slot))); DCHECK(SlotRequiresName(GetKind(slot)));
FixedArray* names = FixedArray::cast(get(kNamesTableIndex)); UnseededNumberDictionary* names =
// TODO(ishell): consider using binary search here or even Dictionary when we UnseededNumberDictionary::cast(get(kNamesTableIndex));
// have more ICs with names. int entry = names->FindEntry(GetIsolate(), slot.ToInt());
Smi* key = Smi::FromInt(slot.ToInt()); CHECK_NE(UnseededNumberDictionary::kNotFound, entry);
for (int entry = 0; entry < names->length(); entry += kNameTableEntrySize) { Object* name = names->ValueAt(entry);
Object* current_key = names->get(entry + kNameTableSlotIndex); DCHECK(name->IsString());
if (current_key == key) { return String::cast(name);
Object* name = names->get(entry + kNameTableNameIndex);
DCHECK(name->IsString());
return String::cast(name);
}
}
UNREACHABLE();
return nullptr;
} }
void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot, void TypeFeedbackMetadata::SetKind(FeedbackVectorSlot slot,
...@@ -107,10 +100,9 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate, ...@@ -107,10 +100,9 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
// Add names to NamesTable. // Add names to NamesTable.
const int name_count = spec->name_count(); const int name_count = spec->name_count();
Handle<FixedArray> names = Handle<UnseededNumberDictionary> names =
name_count == 0 UnseededNumberDictionary::New(isolate, name_count);
? factory->empty_fixed_array()
: factory->NewFixedArray(name_count * kNameTableEntrySize);
int name_index = 0; int name_index = 0;
for (int i = 0; i < slot_count; i++) { for (int i = 0; i < slot_count; i++) {
FeedbackVectorSlotKind kind = spec->GetKind(i); FeedbackVectorSlotKind kind = spec->GetKind(i);
...@@ -118,9 +110,7 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate, ...@@ -118,9 +110,7 @@ Handle<TypeFeedbackMetadata> TypeFeedbackMetadata::New(Isolate* isolate,
if (SlotRequiresName(kind)) { if (SlotRequiresName(kind)) {
Handle<String> name = spec->GetName(name_index); Handle<String> name = spec->GetName(name_index);
DCHECK(!name.is_null()); DCHECK(!name.is_null());
int entry = name_index * kNameTableEntrySize; names = UnseededNumberDictionary::AtNumberPut(names, i, name);
names->set(entry + kNameTableSlotIndex, Smi::FromInt(i));
names->set(entry + kNameTableNameIndex, *name);
name_index++; name_index++;
} }
} }
......
...@@ -20,7 +20,7 @@ TypeFeedbackOracle::TypeFeedbackOracle( ...@@ -20,7 +20,7 @@ TypeFeedbackOracle::TypeFeedbackOracle(
Handle<TypeFeedbackVector> feedback_vector, Handle<Context> native_context) Handle<TypeFeedbackVector> feedback_vector, Handle<Context> native_context)
: native_context_(native_context), isolate_(isolate), zone_(zone) { : native_context_(native_context), isolate_(isolate), zone_(zone) {
BuildDictionary(code); BuildDictionary(code);
DCHECK(dictionary_->IsDictionary()); DCHECK(dictionary_->IsUnseededNumberDictionary());
// We make a copy of the feedback vector because a GC could clear // We make a copy of the feedback vector because a GC could clear
// the type feedback info contained therein. // the type feedback info contained therein.
// TODO(mvstanton): revisit the decision to copy when we weakly // TODO(mvstanton): revisit the decision to copy when we weakly
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment