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() {
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)
......
......@@ -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) \
......
......@@ -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 <typename Key>
Map* BaseShape<Key>::GetMap(Isolate* isolate) {
return isolate->heap()->hash_table_map();
}
template <typename Derived, typename Shape, typename Key>
int HashTable<Derived, Shape, Key>::FindEntry(Key key) {
......@@ -7473,14 +7476,16 @@ void BaseDictionaryShape<Key>::SetEntry(Dictionary* dict, int entry,
Handle<Object> key,
Handle<Object> 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<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) {
return ComputeIntegerHash(key, seed);
......
......@@ -16189,7 +16189,7 @@ Handle<Derived> HashTable<Derived, Shape, Key>::New(
Factory* factory = isolate->factory();
int length = EntryToIndex(capacity);
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);
table->SetNumberOfElements(0);
......
......@@ -980,6 +980,7 @@ template <class C> 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<uint32_t> {
public:
static inline bool IsMatch(uint32_t key, Object* other);
static inline Handle<Object> 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 <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(
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> TypeFeedbackMetadata::New(Isolate* isolate,
// Add names to NamesTable.
const int name_count = spec->name_count();
Handle<FixedArray> names =
name_count == 0
? factory->empty_fixed_array()
: factory->NewFixedArray(name_count * kNameTableEntrySize);
Handle<UnseededNumberDictionary> 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> TypeFeedbackMetadata::New(Isolate* isolate,
if (SlotRequiresName(kind)) {
Handle<String> 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++;
}
}
......
......@@ -20,7 +20,7 @@ TypeFeedbackOracle::TypeFeedbackOracle(
Handle<TypeFeedbackVector> feedback_vector, Handle<Context> 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
......
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