Commit 64a3d657 authored by Sathya Gunasekaran's avatar Sathya Gunasekaran

[dict] Add ordered name dictionary type

This is the larger dictionary specialized for Name. To be used as a
property backing store.

More methods and tests will be added in the future as it reaches
parity with NameDictionary.


Bug: v8:6443, v8:7569
Change-Id: I8f5d88b2f6f4e14d4851548566ffa9f59535358b
Reviewed-on: https://chromium-review.googlesource.com/c/1329204Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57430}
parent 126d1d7b
......@@ -277,6 +277,7 @@ Type::bitset BitsetType::Lub(const MapRefLike& map) {
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
......
......@@ -555,6 +555,11 @@ Handle<OrderedHashMap> Factory::NewOrderedHashMap() {
return OrderedHashMap::Allocate(isolate(), OrderedHashMap::kMinCapacity);
}
Handle<OrderedNameDictionary> Factory::NewOrderedNameDictionary() {
return OrderedNameDictionary::Allocate(isolate(),
OrderedNameDictionary::kMinCapacity);
}
Handle<AccessorPair> Factory::NewAccessorPair() {
Handle<AccessorPair> accessors =
Handle<AccessorPair>::cast(NewStruct(ACCESSOR_PAIR_TYPE, TENURED));
......
......@@ -177,6 +177,7 @@ class V8_EXPORT_PRIVATE Factory {
Handle<OrderedHashSet> NewOrderedHashSet();
Handle<OrderedHashMap> NewOrderedHashMap();
Handle<OrderedNameDictionary> NewOrderedNameDictionary();
Handle<SmallOrderedHashSet> NewSmallOrderedHashSet(
int capacity = SmallOrderedHashSet::kMinCapacity,
......
......@@ -452,6 +452,7 @@ bool Heap::CreateInitialMaps() {
ALLOCATE_VARSIZE_MAP(HASH_TABLE_TYPE, hash_table)
ALLOCATE_VARSIZE_MAP(ORDERED_HASH_MAP_TYPE, ordered_hash_map)
ALLOCATE_VARSIZE_MAP(ORDERED_HASH_SET_TYPE, ordered_hash_set)
ALLOCATE_VARSIZE_MAP(ORDERED_NAME_DICTIONARY_TYPE, ordered_name_dictionary)
ALLOCATE_VARSIZE_MAP(NAME_DICTIONARY_TYPE, name_dictionary)
ALLOCATE_VARSIZE_MAP(GLOBAL_DICTIONARY_TYPE, global_dictionary)
ALLOCATE_VARSIZE_MAP(NUMBER_DICTIONARY_TYPE, number_dictionary)
......
......@@ -754,6 +754,7 @@ ReturnType BodyDescriptorApply(InstanceType type, T1 p1, T2 p2, T3 p3, T4 p4) {
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
......
......@@ -156,6 +156,7 @@ void HeapObject::HeapObjectVerify(Isolate* isolate) {
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
......
......@@ -131,6 +131,7 @@ namespace internal {
V(HASH_TABLE_TYPE) \
V(ORDERED_HASH_MAP_TYPE) \
V(ORDERED_HASH_SET_TYPE) \
V(ORDERED_NAME_DICTIONARY_TYPE) \
V(NAME_DICTIONARY_TYPE) \
V(GLOBAL_DICTIONARY_TYPE) \
V(NUMBER_DICTIONARY_TYPE) \
......
......@@ -483,6 +483,7 @@ CAST_ACCESSOR(HeapObject)
CAST_ACCESSOR(HeapNumber)
CAST_ACCESSOR(LayoutDescriptor)
CAST_ACCESSOR(MutableHeapNumber)
CAST_ACCESSOR(OrderedNameDictionary)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NormalizedMapCache)
CAST_ACCESSOR(NumberDictionary)
......
......@@ -151,6 +151,7 @@ void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case SIMPLE_NUMBER_DICTIONARY_TYPE:
......
......@@ -3108,6 +3108,7 @@ VisitorId Map::GetVisitorId(Map* map) {
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
......@@ -3483,6 +3484,10 @@ void HeapObject::HeapObjectShortPrint(std::ostream& os) { // NOLINT
case ORDERED_HASH_SET_TYPE:
os << "<OrderedHashSet[" << FixedArray::cast(this)->length() << "]>";
break;
case ORDERED_NAME_DICTIONARY_TYPE:
os << "<OrderedNameDictionary[" << FixedArray::cast(this)->length()
<< "]>";
break;
case NAME_DICTIONARY_TYPE:
os << "<NameDictionary[" << FixedArray::cast(this)->length() << "]>";
break;
......@@ -3826,6 +3831,7 @@ bool HeapObject::CanBeRehashed() const {
switch (map()->instance_type()) {
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
// TODO(yangguo): actually support rehashing OrderedHash{Map,Set}.
return false;
case NAME_DICTIONARY_TYPE:
......@@ -13185,6 +13191,7 @@ bool CanSubclassHaveInobjectProperties(InstanceType instance_type) {
case HASH_TABLE_TYPE:
case ORDERED_HASH_MAP_TYPE:
case ORDERED_HASH_SET_TYPE:
case ORDERED_NAME_DICTIONARY_TYPE:
case NAME_DICTIONARY_TYPE:
case GLOBAL_DICTIONARY_TYPE:
case NUMBER_DICTIONARY_TYPE:
......
......@@ -427,6 +427,7 @@ enum InstanceType : uint16_t {
HASH_TABLE_TYPE, // FIRST_HASH_TABLE_TYPE
ORDERED_HASH_MAP_TYPE, // FIRST_DICTIONARY_TYPE
ORDERED_HASH_SET_TYPE,
ORDERED_NAME_DICTIONARY_TYPE,
NAME_DICTIONARY_TYPE,
GLOBAL_DICTIONARY_TYPE,
NUMBER_DICTIONARY_TYPE,
......@@ -815,6 +816,7 @@ class ZoneForwardList;
V(Oddball) \
V(OrderedHashMap) \
V(OrderedHashSet) \
V(OrderedNameDictionary) \
V(PreParsedScopeData) \
V(PromiseReactionJobTask) \
V(PropertyArray) \
......@@ -964,6 +966,7 @@ class ZoneForwardList;
V(Oddball, ODDBALL_TYPE) \
V(OrderedHashMap, ORDERED_HASH_MAP_TYPE) \
V(OrderedHashSet, ORDERED_HASH_SET_TYPE) \
V(OrderedNameDictionary, ORDERED_NAME_DICTIONARY_TYPE) \
V(PreParsedScopeData, PRE_PARSED_SCOPE_DATA_TYPE) \
V(PropertyArray, PROPERTY_ARRAY_TYPE) \
V(PropertyCell, PROPERTY_CELL_TYPE) \
......
......@@ -21,6 +21,10 @@ RootIndex OrderedHashMap::GetMapRootIndex() {
return RootIndex::kOrderedHashMapMap;
}
RootIndex OrderedNameDictionary::GetMapRootIndex() {
return RootIndex::kOrderedNameDictionaryMap;
}
RootIndex SmallOrderedHashMap::GetMapRootIndex() {
return RootIndex::kSmallOrderedHashMapMap;
}
......
......@@ -83,7 +83,8 @@ template <class Derived, int entrysize>
bool OrderedHashTable<Derived, entrysize>::HasKey(Isolate* isolate,
Derived* table, Object* key) {
DCHECK((entrysize == 1 && table->IsOrderedHashSet()) ||
(entrysize == 2 && table->IsOrderedHashMap()));
(entrysize == 2 && table->IsOrderedHashMap()) ||
(entrysize == 3 && table->IsOrderedNameDictionary()));
DisallowHeapAllocation no_gc;
int entry = table->FindEntry(isolate, key);
return entry != kNotFound;
......@@ -265,6 +266,51 @@ Handle<OrderedHashMap> OrderedHashMap::Add(Isolate* isolate,
return table;
}
Handle<OrderedNameDictionary> OrderedNameDictionary::Add(
Isolate* isolate, Handle<OrderedNameDictionary> table, Handle<Name> key,
Handle<Object> value, PropertyDetails details) {
int hash = key->Hash();
#ifdef DEBUG
// Walk the chain of the bucket and try finding the key.
{
DisallowHeapAllocation no_gc;
int entry = table->HashToEntry(hash);
Object* raw_key = *key;
while (entry != kNotFound) {
Object* candidate_key = table->KeyAt(entry);
// Key should not exist already!
CHECK(!candidate_key->SameValueZero(raw_key));
entry = table->NextChainEntry(entry);
}
}
#endif
table = OrderedNameDictionary::EnsureGrowable(isolate, table);
// Read the existing bucket values.
int bucket = table->HashToBucket(hash);
int previous_entry = table->HashToEntry(hash);
int nof = table->NumberOfElements();
// Insert a new entry at the end,
int new_entry = nof + table->NumberOfDeletedElements();
int new_index = table->EntryToIndex(new_entry);
table->set(new_index, *key);
table->set(new_index + kValueOffset, *value);
// TODO(gsathya): Optimize how PropertyDetails are stored in this
// dictionary to save memory (by reusing padding?) and performance
// (by not doing the Smi conversion).
table->set(new_index + kPropertyDetailsOffset, details.AsSmi());
table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
// and point the bucket to the new entry.
table->set(kHashTableStartIndex + bucket, Smi::FromInt(new_entry));
table->SetNumberOfElements(nof + 1);
return table;
}
template Handle<OrderedHashSet> OrderedHashTable<OrderedHashSet, 1>::Allocate(
Isolate* isolate, int capacity, PretenureFlag pretenure);
......@@ -307,6 +353,18 @@ template bool OrderedHashTable<OrderedHashMap, 2>::Delete(Isolate* isolate,
OrderedHashMap* table,
Object* key);
template Handle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::Allocate(Isolate* isolate,
int capacity,
PretenureFlag pretenure);
template bool OrderedHashTable<OrderedNameDictionary, 3>::HasKey(
Isolate* isolate, OrderedNameDictionary* table, Object* key);
template Handle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::EnsureGrowable(
Isolate* isolate, Handle<OrderedNameDictionary> table);
template <>
Handle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Allocate(Isolate* isolate,
......
......@@ -614,6 +614,24 @@ class OrderedHashSetHandler
Isolate* isolate, Handle<SmallOrderedHashSet> table);
};
class OrderedNameDictionary
: public OrderedHashTable<OrderedNameDictionary, 3> {
public:
DECL_CAST(OrderedNameDictionary)
static Handle<OrderedNameDictionary> Add(Isolate* isolate,
Handle<OrderedNameDictionary> table,
Handle<Name> key,
Handle<Object> value,
PropertyDetails details);
static HeapObject* GetEmpty(ReadOnlyRoots ro_roots);
static inline RootIndex GetMapRootIndex();
static const int kValueOffset = 1;
static const int kPropertyDetailsOffset = 2;
};
class JSCollectionIterator : public JSObject {
public:
// [table]: the backing hash table mapping keys to values.
......
......@@ -99,6 +99,7 @@ class RootVisitor;
V(Map*, one_closure_cell_map, OneClosureCellMap) \
V(Map*, ordered_hash_map_map, OrderedHashMapMap) \
V(Map*, ordered_hash_set_map, OrderedHashSetMap) \
V(Map*, ordered_name_dictionary_map, OrderedNameDictionaryMap) \
V(Map*, pre_parsed_scope_data_map, PreParsedScopeDataMap) \
V(Map*, property_array_map, PropertyArrayMap) \
V(Map*, side_effect_call_handler_info_map, SideEffectCallHandlerInfoMap) \
......
......@@ -1271,6 +1271,37 @@ TEST(OrderedHashMapHandlerInsertion) {
CHECK(OrderedHashMap::Is(map));
}
TEST(OrderedNameDictionaryInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedNameDictionary> dict = factory->NewOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key1 = factory->NewStringFromAsciiChecked("foo");
Handle<String> value = factory->NewStringFromAsciiChecked("foo");
CHECK(!OrderedNameDictionary::HasKey(isolate, *dict, *key1));
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key1, value, details);
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK(OrderedNameDictionary::HasKey(isolate, *dict, *key1));
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(!OrderedNameDictionary::HasKey(isolate, *dict, *key2));
dict = OrderedNameDictionary::Add(isolate, dict, key2, value, details);
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK(OrderedNameDictionary::HasKey(isolate, *dict, *key1));
CHECK(OrderedNameDictionary::HasKey(isolate, *dict, *key2));
}
} // namespace test_orderedhashtable
} // namespace internal
} // namespace v8
This diff is collapsed.
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