Commit 48a99add authored by Frank Emrich's avatar Frank Emrich Committed by Commit Bot

[dict-proto] allow and fix empty versions of ordered hash tables

This changes OrderedHashMap, OrderedHashSet, and OrderedNameDictionary
as follows:
- Create a dedicated allocation function AllocateEmpty to create zero-
  element instances of these classes
- Fix bugs resulting from using these zero-element versions

Further, this CL
- provides a canonical empty versions of OrderedNameDictionary
- changes the types of the canonical ordered hash table and hash set
  from FixedArray to the actual subclasses

Bug: v8:7569
Change-Id: I0fe1215e7d164617afa777c8b3208a0857ab6edd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2476315
Commit-Queue: Frank Emrich <emrich@google.com>
Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarUlan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70604}
parent 7506e063
......@@ -3371,7 +3371,7 @@ TNode<NameDictionary> CodeStubAssembler::CopyNameDictionary(
template <typename CollectionType>
TNode<CollectionType> CodeStubAssembler::AllocateOrderedHashTable() {
static const int kCapacity = CollectionType::kMinCapacity;
static const int kCapacity = CollectionType::kMinNonZeroCapacity;
static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
static const int kDataTableLength = kCapacity * CollectionType::kEntrySize;
static const int kFixedArrayLength =
......
......@@ -536,18 +536,20 @@ Handle<SmallOrderedNameDictionary> Factory::NewSmallOrderedNameDictionary(
}
Handle<OrderedHashSet> Factory::NewOrderedHashSet() {
return OrderedHashSet::Allocate(isolate(), OrderedHashSet::kMinCapacity)
return OrderedHashSet::Allocate(isolate(),
OrderedHashSet::kMinNonZeroCapacity)
.ToHandleChecked();
}
Handle<OrderedHashMap> Factory::NewOrderedHashMap() {
return OrderedHashMap::Allocate(isolate(), OrderedHashMap::kMinCapacity)
return OrderedHashMap::Allocate(isolate(),
OrderedHashMap::kMinNonZeroCapacity)
.ToHandleChecked();
}
Handle<OrderedNameDictionary> Factory::NewOrderedNameDictionary() {
return OrderedNameDictionary::Allocate(isolate(),
OrderedNameDictionary::kMinCapacity)
return OrderedNameDictionary::Allocate(
isolate(), OrderedNameDictionary::kMinNonZeroCapacity)
.ToHandleChecked();
}
......
......@@ -845,25 +845,23 @@ void Heap::CreateInitialObjects() {
set_next_template_serial_number(Smi::zero());
// Allocate the empty OrderedHashMap.
Handle<FixedArray> empty_ordered_hash_map = factory->NewFixedArray(
OrderedHashMap::HashTableStartIndex(), AllocationType::kReadOnly);
empty_ordered_hash_map->set_map_no_write_barrier(
*factory->ordered_hash_map_map());
for (int i = 0; i < empty_ordered_hash_map->length(); ++i) {
empty_ordered_hash_map->set(i, Smi::zero());
}
Handle<OrderedHashMap> empty_ordered_hash_map =
OrderedHashMap::AllocateEmpty(isolate(), AllocationType::kReadOnly)
.ToHandleChecked();
set_empty_ordered_hash_map(*empty_ordered_hash_map);
// Allocate the empty OrderedHashSet.
Handle<FixedArray> empty_ordered_hash_set = factory->NewFixedArray(
OrderedHashSet::HashTableStartIndex(), AllocationType::kReadOnly);
empty_ordered_hash_set->set_map_no_write_barrier(
*factory->ordered_hash_set_map());
for (int i = 0; i < empty_ordered_hash_set->length(); ++i) {
empty_ordered_hash_set->set(i, Smi::zero());
}
Handle<OrderedHashSet> empty_ordered_hash_set =
OrderedHashSet::AllocateEmpty(isolate(), AllocationType::kReadOnly)
.ToHandleChecked();
set_empty_ordered_hash_set(*empty_ordered_hash_set);
// Allocate the empty OrderedNameDictionary
Handle<OrderedNameDictionary> empty_ordered_property_dictionary =
OrderedNameDictionary::AllocateEmpty(isolate(), AllocationType::kReadOnly)
.ToHandleChecked();
set_empty_ordered_property_dictionary(*empty_ordered_property_dictionary);
// Allocate the empty FeedbackMetadata.
Handle<FeedbackMetadata> empty_feedback_metadata =
factory->NewFeedbackMetadata(0, 0, AllocationType::kReadOnly);
......
......@@ -22,7 +22,8 @@ MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Allocate(
// from number of buckets. If we decide to change kLoadFactor
// to something other than 2, capacity should be stored as another
// field of this object.
capacity = base::bits::RoundUpToPowerOfTwo32(Max(kMinCapacity, capacity));
capacity =
base::bits::RoundUpToPowerOfTwo32(Max(kMinNonZeroCapacity, capacity));
if (capacity > MaxCapacity()) {
return MaybeHandle<Derived>();
}
......@@ -41,6 +42,24 @@ MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Allocate(
return table;
}
template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::AllocateEmpty(
Isolate* isolate, AllocationType allocation, RootIndex root_index) {
// This is only supposed to be used to create the canonical empty versions
// of each ordered structure, and should not be used afterwards.
// Requires that the map has already been set up in the roots table.
DCHECK(ReadOnlyRoots(isolate).at(root_index) == kNullAddress);
Handle<FixedArray> backing_store = isolate->factory()->NewFixedArrayWithMap(
Derived::GetMap(ReadOnlyRoots(isolate)), HashTableStartIndex(),
allocation);
Handle<Derived> table = Handle<Derived>::cast(backing_store);
table->SetNumberOfBuckets(0);
table->SetNumberOfElements(0);
table->SetNumberOfDeletedElements(0);
return table;
}
template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
Isolate* isolate, Handle<Derived> table) {
......@@ -50,11 +69,21 @@ MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
int nod = table->NumberOfDeletedElements();
int capacity = table->Capacity();
if ((nof + nod) < capacity) return table;
int new_capacity;
if (capacity == 0) {
// step from empty to minimum proper size
new_capacity = kMinNonZeroCapacity;
} else if (nod >= (capacity >> 1)) {
// Don't need to grow if we can simply clear out deleted entries instead.
// Note that we can't compact in place, though, so we always allocate
// a new table.
return Derived::Rehash(isolate, table,
(nod < (capacity >> 1)) ? capacity << 1 : capacity);
new_capacity = capacity;
} else {
new_capacity = capacity << 1;
}
return Derived::Rehash(isolate, table, new_capacity);
}
template <class Derived, int entrysize>
......@@ -78,10 +107,13 @@ Handle<Derived> OrderedHashTable<Derived, entrysize>::Clear(
: AllocationType::kOld;
Handle<Derived> new_table =
Allocate(isolate, kMinCapacity, allocation_type).ToHandleChecked();
Allocate(isolate, kMinNonZeroCapacity, allocation_type).ToHandleChecked();
if (table->NumberOfBuckets() > 0) {
// Don't try to modify the empty canonical table which lives in RO space.
table->SetNextTable(*new_table);
table->SetNumberOfDeletedElements(kClearedTableSentinel);
}
return new_table;
}
......@@ -99,6 +131,12 @@ bool OrderedHashTable<Derived, entrysize>::HasKey(Isolate* isolate,
template <class Derived, int entrysize>
int OrderedHashTable<Derived, entrysize>::FindEntry(Isolate* isolate,
Object key) {
if (NumberOfElements() == 0) {
// This is not just an optimization but also ensures that we do the right
// thing if Capacity() == 0
return kNotFound;
}
int entry;
// This special cases for Smi, so that we avoid the HandleScope
// creation below.
......@@ -127,6 +165,7 @@ MaybeHandle<OrderedHashSet> OrderedHashSet::Add(Isolate* isolate,
Handle<OrderedHashSet> table,
Handle<Object> key) {
int hash = key->GetOrCreateHash(isolate).value();
if (table->NumberOfElements() > 0) {
int entry = table->HashToEntry(hash);
// Walk the chain of the bucket and try finding the key.
while (entry != kNotFound) {
......@@ -135,6 +174,7 @@ MaybeHandle<OrderedHashSet> OrderedHashSet::Add(Isolate* isolate,
if (candidate_key.SameValueZero(*key)) return table;
entry = table->NextChainEntry(entry);
}
}
MaybeHandle<OrderedHashSet> table_candidate =
OrderedHashSet::EnsureGrowable(isolate, table);
......@@ -245,7 +285,10 @@ MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
DCHECK_EQ(nod, removed_holes_index);
new_table->SetNumberOfElements(nof);
if (table->NumberOfBuckets() > 0) {
// Don't try to modify the empty canonical table which lives in RO space.
table->SetNextTable(*new_table);
}
return new_table_candidate;
}
......@@ -253,36 +296,29 @@ MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(Isolate* isolate,
Handle<OrderedHashSet> table,
int new_capacity) {
return OrderedHashTable<OrderedHashSet, 1>::Rehash(isolate, table,
new_capacity);
return Base::Rehash(isolate, table, new_capacity);
}
MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(
Isolate* isolate, Handle<OrderedHashSet> table) {
return OrderedHashTable<
OrderedHashSet, OrderedHashSet::kEntrySizeWithoutChain>::Rehash(isolate,
table);
return Base::Rehash(isolate, table);
}
MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(
Isolate* isolate, Handle<OrderedHashMap> table) {
return OrderedHashTable<
OrderedHashMap, OrderedHashMap::kEntrySizeWithoutChain>::Rehash(isolate,
table);
return Base::Rehash(isolate, table);
}
MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(Isolate* isolate,
Handle<OrderedHashMap> table,
int new_capacity) {
return OrderedHashTable<OrderedHashMap, 2>::Rehash(isolate, table,
new_capacity);
return Base::Rehash(isolate, table, new_capacity);
}
MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Rehash(
Isolate* isolate, Handle<OrderedNameDictionary> table, int new_capacity) {
MaybeHandle<OrderedNameDictionary> new_table_candidate =
OrderedHashTable<OrderedNameDictionary, 3>::Rehash(isolate, table,
new_capacity);
Base::Rehash(isolate, table, new_capacity);
Handle<OrderedNameDictionary> new_table;
if (new_table_candidate.ToHandle(&new_table)) {
new_table->SetHash(table->Hash());
......@@ -328,6 +364,7 @@ MaybeHandle<OrderedHashMap> OrderedHashMap::Add(Isolate* isolate,
Handle<Object> key,
Handle<Object> value) {
int hash = key->GetOrCreateHash(isolate).value();
if (table->NumberOfElements() > 0) {
int entry = table->HashToEntry(hash);
// Walk the chain of the bucket and try finding the key.
{
......@@ -340,6 +377,7 @@ MaybeHandle<OrderedHashMap> OrderedHashMap::Add(Isolate* isolate,
entry = table->NextChainEntry(entry);
}
}
}
MaybeHandle<OrderedHashMap> table_candidate =
OrderedHashMap::EnsureGrowable(isolate, table);
......@@ -362,14 +400,18 @@ MaybeHandle<OrderedHashMap> OrderedHashMap::Add(Isolate* isolate,
return table;
}
template <>
V8_EXPORT_PRIVATE int OrderedHashTable<OrderedNameDictionary, 3>::FindEntry(
Isolate* isolate, Object key) {
int OrderedNameDictionary::FindEntry(Isolate* isolate, Object key) {
DisallowHeapAllocation no_gc;
DCHECK(key.IsUniqueName());
Name raw_key = Name::cast(key);
if (NumberOfElements() == 0) {
// This is not just an optimization but also ensures that we do the right
// thing if Capacity() == 0
return kNotFound;
}
int entry = HashToEntry(raw_key.Hash());
while (entry != kNotFound) {
Object candidate_key = KeyAt(entry);
......@@ -452,21 +494,18 @@ Handle<OrderedNameDictionary> OrderedNameDictionary::DeleteEntry(
MaybeHandle<OrderedHashSet> OrderedHashSet::Allocate(
Isolate* isolate, int capacity, AllocationType allocation) {
return OrderedHashTable<OrderedHashSet, 1>::Allocate(isolate, capacity,
allocation);
return Base::Allocate(isolate, capacity, allocation);
}
MaybeHandle<OrderedHashMap> OrderedHashMap::Allocate(
Isolate* isolate, int capacity, AllocationType allocation) {
return OrderedHashTable<OrderedHashMap, 2>::Allocate(isolate, capacity,
allocation);
return Base::Allocate(isolate, capacity, allocation);
}
MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Allocate(
Isolate* isolate, int capacity, AllocationType allocation) {
MaybeHandle<OrderedNameDictionary> table_candidate =
OrderedHashTable<OrderedNameDictionary, 3>::Allocate(isolate, capacity,
allocation);
Base::Allocate(isolate, capacity, allocation);
Handle<OrderedNameDictionary> table;
if (table_candidate.ToHandle(&table)) {
table->SetHash(PropertyArray::kNoHashSentinel);
......@@ -474,6 +513,31 @@ MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Allocate(
return table_candidate;
}
MaybeHandle<OrderedHashSet> OrderedHashSet::AllocateEmpty(
Isolate* isolate, AllocationType allocation) {
RootIndex ri = RootIndex::kEmptyOrderedHashSet;
return Base::AllocateEmpty(isolate, allocation, ri);
}
MaybeHandle<OrderedHashMap> OrderedHashMap::AllocateEmpty(
Isolate* isolate, AllocationType allocation) {
RootIndex ri = RootIndex::kEmptyOrderedHashMap;
return Base::AllocateEmpty(isolate, allocation, ri);
}
MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::AllocateEmpty(
Isolate* isolate, AllocationType allocation) {
RootIndex ri = RootIndex::kEmptyOrderedPropertyDictionary;
MaybeHandle<OrderedNameDictionary> table_candidate =
Base::AllocateEmpty(isolate, allocation, ri);
Handle<OrderedNameDictionary> table;
if (table_candidate.ToHandle(&table)) {
table->SetHash(PropertyArray::kNoHashSentinel);
}
return table_candidate;
}
template V8_EXPORT_PRIVATE MaybeHandle<OrderedHashSet>
OrderedHashTable<OrderedHashSet, 1>::EnsureGrowable(
Isolate* isolate, Handle<OrderedHashSet> table);
......@@ -516,7 +580,7 @@ template V8_EXPORT_PRIVATE bool OrderedHashTable<OrderedHashMap, 2>::Delete(
template V8_EXPORT_PRIVATE int OrderedHashTable<OrderedHashMap, 2>::FindEntry(
Isolate* isolate, Object key);
template Handle<OrderedNameDictionary>
template V8_EXPORT_PRIVATE Handle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::Shrink(
Isolate* isolate, Handle<OrderedNameDictionary> table);
......
......@@ -142,7 +142,9 @@ class OrderedHashTable : public FixedArray {
static const int kChainOffset = entrysize;
static const int kNotFound = -1;
static const int kMinCapacity = 4;
// The minimum capacity. Note that despite this value, 0 is also a permitted
// capacity, indicating a table without any storage for elements.
static const int kMinNonZeroCapacity = 4;
static constexpr int PrefixIndex() { return 0; }
......@@ -202,6 +204,10 @@ class OrderedHashTable : public FixedArray {
Isolate* isolate, int capacity,
AllocationType allocation = AllocationType::kYoung);
static MaybeHandle<Derived> AllocateEmpty(Isolate* isolate,
AllocationType allocation,
RootIndex root_ndex);
static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table);
static MaybeHandle<Derived> Rehash(Isolate* isolate, Handle<Derived> table,
int new_capacity);
......@@ -235,6 +241,8 @@ class OrderedHashTable : public FixedArray {
class V8_EXPORT_PRIVATE OrderedHashSet
: public OrderedHashTable<OrderedHashSet, 1> {
using Base = OrderedHashTable<OrderedHashSet, 1>;
public:
DECL_CAST(OrderedHashSet)
......@@ -252,6 +260,10 @@ class V8_EXPORT_PRIVATE OrderedHashSet
static MaybeHandle<OrderedHashSet> Allocate(
Isolate* isolate, int capacity,
AllocationType allocation = AllocationType::kYoung);
static MaybeHandle<OrderedHashSet> AllocateEmpty(
Isolate* isolate, AllocationType allocation = AllocationType::kReadOnly);
static HeapObject GetEmpty(ReadOnlyRoots ro_roots);
static inline Handle<Map> GetMap(ReadOnlyRoots roots);
static inline bool Is(Handle<HeapObject> table);
......@@ -262,6 +274,8 @@ class V8_EXPORT_PRIVATE OrderedHashSet
class V8_EXPORT_PRIVATE OrderedHashMap
: public OrderedHashTable<OrderedHashMap, 2> {
using Base = OrderedHashTable<OrderedHashMap, 2>;
public:
DECL_CAST(OrderedHashMap)
......@@ -275,6 +289,10 @@ class V8_EXPORT_PRIVATE OrderedHashMap
static MaybeHandle<OrderedHashMap> Allocate(
Isolate* isolate, int capacity,
AllocationType allocation = AllocationType::kYoung);
static MaybeHandle<OrderedHashMap> AllocateEmpty(
Isolate* isolate, AllocationType allocation = AllocationType::kReadOnly);
static MaybeHandle<OrderedHashMap> Rehash(Isolate* isolate,
Handle<OrderedHashMap> table,
int new_capacity);
......@@ -699,25 +717,31 @@ class V8_EXPORT_PRIVATE OrderedHashSetHandler
Isolate* isolate, Handle<SmallOrderedHashSet> table);
};
class OrderedNameDictionary
class V8_EXPORT_PRIVATE OrderedNameDictionary
: public OrderedHashTable<OrderedNameDictionary, 3> {
using Base = OrderedHashTable<OrderedNameDictionary, 3>;
public:
DECL_CAST(OrderedNameDictionary)
V8_EXPORT_PRIVATE static MaybeHandle<OrderedNameDictionary> Add(
static MaybeHandle<OrderedNameDictionary> Add(
Isolate* isolate, Handle<OrderedNameDictionary> table, Handle<Name> key,
Handle<Object> value, PropertyDetails details);
V8_EXPORT_PRIVATE void SetEntry(int entry, Object key, Object value,
PropertyDetails details);
void SetEntry(int entry, Object key, Object value, PropertyDetails details);
V8_EXPORT_PRIVATE static Handle<OrderedNameDictionary> DeleteEntry(
int FindEntry(Isolate* isolate, Object key);
static Handle<OrderedNameDictionary> DeleteEntry(
Isolate* isolate, Handle<OrderedNameDictionary> table, int entry);
static MaybeHandle<OrderedNameDictionary> Allocate(
Isolate* isolate, int capacity,
AllocationType allocation = AllocationType::kYoung);
static MaybeHandle<OrderedNameDictionary> AllocateEmpty(
Isolate* isolate, AllocationType allocation = AllocationType::kReadOnly);
static MaybeHandle<OrderedNameDictionary> Rehash(
Isolate* isolate, Handle<OrderedNameDictionary> table, int new_capacity);
......
......@@ -166,11 +166,13 @@ class Symbol;
EmptyClosureFeedbackCellArray) \
V(NumberDictionary, empty_slow_element_dictionary, \
EmptySlowElementDictionary) \
V(FixedArray, empty_ordered_hash_map, EmptyOrderedHashMap) \
V(FixedArray, empty_ordered_hash_set, EmptyOrderedHashSet) \
V(OrderedHashMap, empty_ordered_hash_map, EmptyOrderedHashMap) \
V(OrderedHashSet, empty_ordered_hash_set, EmptyOrderedHashSet) \
V(FeedbackMetadata, empty_feedback_metadata, EmptyFeedbackMetadata) \
V(PropertyCell, empty_property_cell, EmptyPropertyCell) \
V(NameDictionary, empty_property_dictionary, EmptyPropertyDictionary) \
V(OrderedNameDictionary, empty_ordered_property_dictionary, \
EmptyOrderedPropertyDictionary) \
V(InterceptorInfo, noop_interceptor_info, NoOpInterceptorInfo) \
V(WeakFixedArray, empty_weak_fixed_array, EmptyWeakFixedArray) \
V(WeakArrayList, empty_weak_array_list, EmptyWeakArrayList) \
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "src/init/v8.h"
#include "src/init/v8.h"
#include "src/objects/objects-inl.h"
#include "src/objects/ordered-hash-table-inl.h"
#include "test/cctest/cctest.h"
......@@ -27,6 +27,69 @@ void Verify(Isolate* isolate, Handle<HeapObject> obj) {
#endif
}
// Helpers to abstract over differences in interfaces of the different ordered
// datastructures
template <typename T>
Handle<T> Add(Isolate* isolate, Handle<T> table, Handle<String> key1,
Handle<String> value1, PropertyDetails details);
template <>
Handle<OrderedHashMap> Add(Isolate* isolate, Handle<OrderedHashMap> table,
Handle<String> key, Handle<String> value,
PropertyDetails details) {
return OrderedHashMap::Add(isolate, table, key, value).ToHandleChecked();
}
template <>
Handle<OrderedHashSet> Add(Isolate* isolate, Handle<OrderedHashSet> table,
Handle<String> key, Handle<String> value,
PropertyDetails details) {
return OrderedHashSet::Add(isolate, table, key).ToHandleChecked();
}
template <>
Handle<OrderedNameDictionary> Add(Isolate* isolate,
Handle<OrderedNameDictionary> table,
Handle<String> key, Handle<String> value,
PropertyDetails details) {
return OrderedNameDictionary::Add(isolate, table, key, value, details)
.ToHandleChecked();
}
// version for
// OrderedHashMap, OrderedHashSet
template <typename T>
bool HasKey(Isolate* isolate, Handle<T> table, Object key) {
return T::HasKey(isolate, *table, key);
}
template <>
bool HasKey(Isolate* isolate, Handle<OrderedNameDictionary> table, Object key) {
return table->FindEntry(isolate, key) != OrderedNameDictionary::kNotFound;
}
// version for
// OrderedHashTable, OrderedHashSet
template <typename T>
Handle<T> Delete(Isolate* isolate, Handle<T> table, Object key) {
T::Delete(isolate, *table, key);
return table;
}
template <>
Handle<OrderedNameDictionary> Delete(Isolate* isolate,
Handle<OrderedNameDictionary> table,
Object key) {
// OrderedNameDictionary doesn't have Delete, but only DeleteEntry, which
// requires the key to be deleted to be present
int entry = table->FindEntry(isolate, key);
if (entry == OrderedNameDictionary::kNotFound)
return table;
else
return OrderedNameDictionary::DeleteEntry(isolate, table, entry);
}
TEST(SmallOrderedHashSetInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
......@@ -2132,6 +2195,265 @@ TEST(SmallOrderedNameDictionaryDeleteEntry) {
CHECK_EQ(0, dict->NumberOfDeletedElements());
}
template <typename T>
void TestEmptyOrderedHashTable(Isolate* isolate, Factory* factory,
Handle<T> table) {
CHECK_EQ(0, table->NumberOfElements());
PropertyDetails details = PropertyDetails::Empty();
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("key1");
Handle<String> value1 = isolate->factory()->InternalizeUtf8String("value1");
table = Add(isolate, table, key1, value1, details);
Verify(isolate, table);
CHECK_EQ(1, table->NumberOfElements());
CHECK(HasKey(isolate, table, *key1));
Handle<String> key2 = factory->InternalizeUtf8String("key2");
Handle<String> value2 = factory->InternalizeUtf8String("value2");
CHECK(!HasKey(isolate, table, *key2));
table = Add(isolate, table, key2, value2, details);
Verify(isolate, table);
CHECK_EQ(2, table->NumberOfElements());
CHECK(HasKey(isolate, table, *key1));
CHECK(HasKey(isolate, table, *key2));
Handle<String> key3 = factory->InternalizeUtf8String("key3");
Handle<String> value3 = factory->InternalizeUtf8String("value3");
CHECK(!HasKey(isolate, table, *key3));
table = Add(isolate, table, key3, value3, details);
Verify(isolate, table);
CHECK_EQ(3, table->NumberOfElements());
CHECK(HasKey(isolate, table, *key1));
CHECK(HasKey(isolate, table, *key2));
CHECK(HasKey(isolate, table, *key3));
Handle<String> key4 = factory->InternalizeUtf8String("key4");
Handle<String> value4 = factory->InternalizeUtf8String("value4");
CHECK(!HasKey(isolate, table, *key4));
table = Delete(isolate, table, *key4);
Verify(isolate, table);
CHECK_EQ(3, table->NumberOfElements());
CHECK_EQ(0, table->NumberOfDeletedElements());
CHECK(!HasKey(isolate, table, *key4));
table = Add(isolate, table, key4, value4, details);
Verify(isolate, table);
CHECK_EQ(4, table->NumberOfElements());
CHECK_EQ(0, table->NumberOfDeletedElements());
CHECK(HasKey(isolate, table, *key4));
CHECK(HasKey(isolate, table, *key4));
table = Delete(isolate, table, *key4);
Verify(isolate, table);
CHECK_EQ(3, table->NumberOfElements());
CHECK_EQ(1, table->NumberOfDeletedElements());
CHECK(!HasKey(isolate, table, *key4));
}
TEST(ZeroSizeOrderedHashMap) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
ReadOnlyRoots ro_roots(isolate);
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
Handle<OrderedHashMap> empty =
Handle<OrderedHashMap>(ro_roots.empty_ordered_hash_map(), isolate);
{
Handle<OrderedHashMap> map = empty;
CHECK_EQ(0, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
TestEmptyOrderedHashTable(isolate, factory, map);
}
{
Handle<OrderedHashMap> map = empty;
map = OrderedHashMap::EnsureGrowable(isolate, map).ToHandleChecked();
CHECK_LT(0, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
}
{
Handle<OrderedHashMap> map = empty;
CHECK(map->FindEntry(isolate, *key1) == OrderedHashMap::kNotFound);
TestEmptyOrderedHashTable(isolate, factory, map);
}
{
Handle<OrderedHashMap> map = empty;
map = OrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
CHECK_EQ(1, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
}
{
Handle<OrderedHashMap> map = empty;
map = OrderedHashMap::Clear(isolate, map);
TestEmptyOrderedHashTable(isolate, factory, map);
}
{
Handle<OrderedHashMap> map = empty;
map = OrderedHashMap::Rehash(isolate, map).ToHandleChecked();
TestEmptyOrderedHashTable(isolate, factory, map);
}
{
Handle<OrderedHashMap> map = empty;
map = OrderedHashMap::Shrink(isolate, map);
TestEmptyOrderedHashTable(isolate, factory, map);
}
{
Handle<OrderedHashMap> map = empty;
OrderedHashMap::Delete(isolate, *map, *key1);
TestEmptyOrderedHashTable(isolate, factory, map);
}
}
TEST(ZeroSizeOrderedHashSet) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
ReadOnlyRoots ro_roots(isolate);
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
Handle<OrderedHashSet> empty =
Handle<OrderedHashSet>(ro_roots.empty_ordered_hash_set(), isolate);
{
Handle<OrderedHashSet> set = empty;
CHECK_EQ(0, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
TestEmptyOrderedHashTable(isolate, factory, set);
}
{
Handle<OrderedHashSet> set = empty;
set = OrderedHashSet::EnsureGrowable(isolate, set).ToHandleChecked();
CHECK_LT(0, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
}
{
Handle<OrderedHashSet> set = empty;
CHECK(set->FindEntry(isolate, *key1) == OrderedHashSet::kNotFound);
TestEmptyOrderedHashTable(isolate, factory, set);
}
{
Handle<OrderedHashSet> set = empty;
set = OrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
CHECK_EQ(1, set->NumberOfElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
}
{
Handle<OrderedHashSet> set = empty;
set = OrderedHashSet::Clear(isolate, set);
TestEmptyOrderedHashTable(isolate, factory, set);
}
{
Handle<OrderedHashSet> set = empty;
set = OrderedHashSet::Rehash(isolate, set).ToHandleChecked();
TestEmptyOrderedHashTable(isolate, factory, set);
}
{
Handle<OrderedHashSet> set = empty;
set = OrderedHashSet::Shrink(isolate, set);
TestEmptyOrderedHashTable(isolate, factory, set);
}
{
Handle<OrderedHashSet> set = empty;
OrderedHashSet::Delete(isolate, *set, *key1);
TestEmptyOrderedHashTable(isolate, factory, set);
}
}
TEST(ZeroSizeOrderedNameDictionary) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
ReadOnlyRoots ro_roots(isolate);
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("key1");
Handle<String> value1 = isolate->factory()->InternalizeUtf8String("value1");
PropertyDetails details = PropertyDetails::Empty();
Handle<OrderedNameDictionary> empty = Handle<OrderedNameDictionary>(
ro_roots.empty_ordered_property_dictionary(), isolate);
{
Handle<OrderedNameDictionary> dict = empty;
CHECK_EQ(0, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
CHECK(!HasKey(isolate, dict, *key1));
TestEmptyOrderedHashTable(isolate, factory, dict);
}
{
Handle<OrderedNameDictionary> dict = empty;
CHECK(dict->FindEntry(isolate, *key1) == OrderedNameDictionary::kNotFound);
TestEmptyOrderedHashTable(isolate, factory, dict);
}
{
Handle<OrderedNameDictionary> dict = empty;
dict = OrderedNameDictionary::Add(isolate, dict, key1, value1, details)
.ToHandleChecked();
CHECK_EQ(1, dict->NumberOfElements());
CHECK(HasKey(isolate, dict, *key1));
}
{
Handle<OrderedNameDictionary> dict = empty;
dict = OrderedNameDictionary::Rehash(isolate, dict, 0).ToHandleChecked();
TestEmptyOrderedHashTable(isolate, factory, dict);
}
{
Handle<OrderedNameDictionary> dict = empty;
dict = OrderedNameDictionary::Shrink(isolate, dict);
TestEmptyOrderedHashTable(isolate, factory, dict);
}
}
} // namespace test_orderedhashtable
} // namespace internal
} // namespace v8
......@@ -297,66 +297,66 @@ KNOWN_MAPS = {
("read_only_space", 0x03191): (67, "SelfReferenceMarkerMap"),
("read_only_space", 0x031b9): (67, "BasicBlockCountersMarkerMap"),
("read_only_space", 0x031fd): (87, "ArrayBoilerplateDescriptionMap"),
("read_only_space", 0x032cd): (99, "InterceptorInfoMap"),
("read_only_space", 0x053d5): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x053fd): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x05425): (74, "CallableTaskMap"),
("read_only_space", 0x0544d): (75, "CallbackTaskMap"),
("read_only_space", 0x05475): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x0549d): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x054c5): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x054ed): (81, "AccessCheckInfoMap"),
("read_only_space", 0x05515): (82, "AccessorInfoMap"),
("read_only_space", 0x0553d): (83, "AccessorPairMap"),
("read_only_space", 0x05565): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x0558d): (85, "AllocationMementoMap"),
("read_only_space", 0x055b5): (88, "AsmWasmDataMap"),
("read_only_space", 0x055dd): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x05605): (90, "BreakPointMap"),
("read_only_space", 0x0562d): (91, "BreakPointInfoMap"),
("read_only_space", 0x05655): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x0567d): (94, "ClassPositionsMap"),
("read_only_space", 0x056a5): (95, "DebugInfoMap"),
("read_only_space", 0x056cd): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x056f5): (100, "InterpreterDataMap"),
("read_only_space", 0x0571d): (101, "PromiseCapabilityMap"),
("read_only_space", 0x05745): (102, "PromiseReactionMap"),
("read_only_space", 0x0576d): (103, "PropertyDescriptorObjectMap"),
("read_only_space", 0x05795): (104, "PrototypeInfoMap"),
("read_only_space", 0x057bd): (105, "ScriptMap"),
("read_only_space", 0x057e5): (106, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x0580d): (107, "StackFrameInfoMap"),
("read_only_space", 0x05835): (108, "StackTraceFrameMap"),
("read_only_space", 0x0585d): (109, "TemplateObjectDescriptionMap"),
("read_only_space", 0x05885): (110, "Tuple2Map"),
("read_only_space", 0x058ad): (111, "WasmCapiFunctionDataMap"),
("read_only_space", 0x058d5): (112, "WasmExceptionTagMap"),
("read_only_space", 0x058fd): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x05925): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x0594d): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x05975): (116, "WasmValueMap"),
("read_only_space", 0x0599d): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x059c5): (172, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x059ed): (169, "InternalClassMap"),
("read_only_space", 0x05a15): (178, "SmiPairMap"),
("read_only_space", 0x05a3d): (177, "SmiBoxMap"),
("read_only_space", 0x05a65): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05a8d): (147, "ExportedSubClassMap"),
("read_only_space", 0x05ab5): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05add): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b05): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b2d): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05b55): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05b7d): (179, "SortStateMap"),
("read_only_space", 0x05ba5): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05bcd): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05bf5): (77, "LoadHandler1Map"),
("read_only_space", 0x05c1d): (77, "LoadHandler2Map"),
("read_only_space", 0x05c45): (77, "LoadHandler3Map"),
("read_only_space", 0x05c6d): (78, "StoreHandler0Map"),
("read_only_space", 0x05c95): (78, "StoreHandler1Map"),
("read_only_space", 0x05cbd): (78, "StoreHandler2Map"),
("read_only_space", 0x05ce5): (78, "StoreHandler3Map"),
("read_only_space", 0x032e5): (99, "InterceptorInfoMap"),
("read_only_space", 0x053ed): (72, "PromiseFulfillReactionJobTaskMap"),
("read_only_space", 0x05415): (73, "PromiseRejectReactionJobTaskMap"),
("read_only_space", 0x0543d): (74, "CallableTaskMap"),
("read_only_space", 0x05465): (75, "CallbackTaskMap"),
("read_only_space", 0x0548d): (76, "PromiseResolveThenableJobTaskMap"),
("read_only_space", 0x054b5): (79, "FunctionTemplateInfoMap"),
("read_only_space", 0x054dd): (80, "ObjectTemplateInfoMap"),
("read_only_space", 0x05505): (81, "AccessCheckInfoMap"),
("read_only_space", 0x0552d): (82, "AccessorInfoMap"),
("read_only_space", 0x05555): (83, "AccessorPairMap"),
("read_only_space", 0x0557d): (84, "AliasedArgumentsEntryMap"),
("read_only_space", 0x055a5): (85, "AllocationMementoMap"),
("read_only_space", 0x055cd): (88, "AsmWasmDataMap"),
("read_only_space", 0x055f5): (89, "AsyncGeneratorRequestMap"),
("read_only_space", 0x0561d): (90, "BreakPointMap"),
("read_only_space", 0x05645): (91, "BreakPointInfoMap"),
("read_only_space", 0x0566d): (92, "CachedTemplateObjectMap"),
("read_only_space", 0x05695): (94, "ClassPositionsMap"),
("read_only_space", 0x056bd): (95, "DebugInfoMap"),
("read_only_space", 0x056e5): (98, "FunctionTemplateRareDataMap"),
("read_only_space", 0x0570d): (100, "InterpreterDataMap"),
("read_only_space", 0x05735): (101, "PromiseCapabilityMap"),
("read_only_space", 0x0575d): (102, "PromiseReactionMap"),
("read_only_space", 0x05785): (103, "PropertyDescriptorObjectMap"),
("read_only_space", 0x057ad): (104, "PrototypeInfoMap"),
("read_only_space", 0x057d5): (105, "ScriptMap"),
("read_only_space", 0x057fd): (106, "SourceTextModuleInfoEntryMap"),
("read_only_space", 0x05825): (107, "StackFrameInfoMap"),
("read_only_space", 0x0584d): (108, "StackTraceFrameMap"),
("read_only_space", 0x05875): (109, "TemplateObjectDescriptionMap"),
("read_only_space", 0x0589d): (110, "Tuple2Map"),
("read_only_space", 0x058c5): (111, "WasmCapiFunctionDataMap"),
("read_only_space", 0x058ed): (112, "WasmExceptionTagMap"),
("read_only_space", 0x05915): (113, "WasmExportedFunctionDataMap"),
("read_only_space", 0x0593d): (114, "WasmIndirectFunctionTableMap"),
("read_only_space", 0x05965): (115, "WasmJSFunctionDataMap"),
("read_only_space", 0x0598d): (116, "WasmValueMap"),
("read_only_space", 0x059b5): (135, "SloppyArgumentsElementsMap"),
("read_only_space", 0x059dd): (172, "OnHeapBasicBlockProfilerDataMap"),
("read_only_space", 0x05a05): (169, "InternalClassMap"),
("read_only_space", 0x05a2d): (178, "SmiPairMap"),
("read_only_space", 0x05a55): (177, "SmiBoxMap"),
("read_only_space", 0x05a7d): (146, "ExportedSubClassBaseMap"),
("read_only_space", 0x05aa5): (147, "ExportedSubClassMap"),
("read_only_space", 0x05acd): (68, "AbstractInternalClassSubclass1Map"),
("read_only_space", 0x05af5): (69, "AbstractInternalClassSubclass2Map"),
("read_only_space", 0x05b1d): (134, "InternalClassWithSmiElementsMap"),
("read_only_space", 0x05b45): (170, "InternalClassWithStructElementsMap"),
("read_only_space", 0x05b6d): (148, "ExportedSubClass2Map"),
("read_only_space", 0x05b95): (179, "SortStateMap"),
("read_only_space", 0x05bbd): (86, "AllocationSiteWithWeakNextMap"),
("read_only_space", 0x05be5): (86, "AllocationSiteWithoutWeakNextMap"),
("read_only_space", 0x05c0d): (77, "LoadHandler1Map"),
("read_only_space", 0x05c35): (77, "LoadHandler2Map"),
("read_only_space", 0x05c5d): (77, "LoadHandler3Map"),
("read_only_space", 0x05c85): (78, "StoreHandler0Map"),
("read_only_space", 0x05cad): (78, "StoreHandler1Map"),
("read_only_space", 0x05cd5): (78, "StoreHandler2Map"),
("read_only_space", 0x05cfd): (78, "StoreHandler3Map"),
("map_space", 0x02115): (1057, "ExternalMap"),
("map_space", 0x0213d): (1072, "JSMessageObjectMap"),
("map_space", 0x02165): (181, "WasmRttEqrefMap"),
......@@ -397,20 +397,21 @@ KNOWN_OBJECTS = {
("read_only_space", 0x03285): "EmptyFeedbackMetadata",
("read_only_space", 0x03291): "EmptyPropertyCell",
("read_only_space", 0x032a5): "EmptyPropertyDictionary",
("read_only_space", 0x032f5): "NoOpInterceptorInfo",
("read_only_space", 0x0331d): "EmptyWeakArrayList",
("read_only_space", 0x03329): "InfinityValue",
("read_only_space", 0x03335): "MinusZeroValue",
("read_only_space", 0x03341): "MinusInfinityValue",
("read_only_space", 0x0334d): "SelfReferenceMarker",
("read_only_space", 0x0338d): "BasicBlockCountersMarker",
("read_only_space", 0x033d1): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x033dd): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x033e9): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x033f5): "GlobalThisBindingScopeInfo",
("read_only_space", 0x0342d): "EmptyFunctionScopeInfo",
("read_only_space", 0x03455): "NativeScopeInfo",
("read_only_space", 0x03471): "HashSeed",
("read_only_space", 0x032cd): "EmptyOrderedPropertyDictionary",
("read_only_space", 0x0330d): "NoOpInterceptorInfo",
("read_only_space", 0x03335): "EmptyWeakArrayList",
("read_only_space", 0x03341): "InfinityValue",
("read_only_space", 0x0334d): "MinusZeroValue",
("read_only_space", 0x03359): "MinusInfinityValue",
("read_only_space", 0x03365): "SelfReferenceMarker",
("read_only_space", 0x033a5): "BasicBlockCountersMarker",
("read_only_space", 0x033e9): "OffHeapTrampolineRelocationInfo",
("read_only_space", 0x033f5): "TrampolineTrivialCodeDataContainer",
("read_only_space", 0x03401): "TrampolinePromiseRejectionCodeDataContainer",
("read_only_space", 0x0340d): "GlobalThisBindingScopeInfo",
("read_only_space", 0x03445): "EmptyFunctionScopeInfo",
("read_only_space", 0x0346d): "NativeScopeInfo",
("read_only_space", 0x03489): "HashSeed",
("old_space", 0x02115): "ArgumentsIteratorAccessor",
("old_space", 0x02159): "ArrayLengthAccessor",
("old_space", 0x0219d): "BoundFunctionLengthAccessor",
......
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