v8/test/cctest/test-orderedhashtable.cc
Frank Emrich eeb74f09c1 [dict-proto] make small ordered hash tables use InternalIndex, too
This CL changes the "small" versions of ordered hash tables, like
SmallOrderedNameDictionary and the corresponding handlers, like
OrderedNameDictionaryHandler, to use InternalIndex rather than int
as the type used for indices.

This is part of an effort to make the interfaces of the
ordered and unordered name dictionaries more similar.

Bug: v8:7569
Change-Id: I3b6fe79dfd3c6743f58a04cfe82798fe2ef09e19
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2505720
Commit-Queue: Frank Emrich <emrich@google.com>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70876}
2020-10-29 13:00:53 +00:00

2447 lines
85 KiB
C++

// Copyright 2017 the V8 project authors. All rights reserved.
// 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/objects/objects-inl.h"
#include "src/objects/ordered-hash-table-inl.h"
#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
namespace test_orderedhashtable {
static Isolate* GetIsolateFrom(LocalContext* context) {
return reinterpret_cast<Isolate*>((*context)->GetIsolate());
}
void CopyHashCode(Handle<JSReceiver> from, Handle<JSReceiver> to) {
int hash = Smi::ToInt(from->GetHash());
to->SetIdentityHash(hash);
}
void Verify(Isolate* isolate, Handle<HeapObject> obj) {
#if VERIFY_HEAP
obj->ObjectVerify(isolate);
#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).is_found();
}
// 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
InternalIndex entry = table->FindEntry(isolate, key);
if (entry.is_not_found()) return table;
return OrderedNameDictionary::DeleteEntry(isolate, table, entry);
}
TEST(SmallOrderedHashSetInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!set->HasKey(isolate, key1));
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
// Add existing key.
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
CHECK(!set->HasKey(isolate, key2));
set = SmallOrderedHashSet::Add(isolate, set, key2).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
set = SmallOrderedHashSet::Add(isolate, set, key2).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!set->HasKey(isolate, key3));
set = SmallOrderedHashSet::Add(isolate, set, key3).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(3, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
set = SmallOrderedHashSet::Add(isolate, set, key3).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(3, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
Handle<Object> key4 = factory->NewHeapNumber(42.0);
CHECK(!set->HasKey(isolate, key4));
set = SmallOrderedHashSet::Add(isolate, set, key4).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(4, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
CHECK(set->HasKey(isolate, key4));
set = SmallOrderedHashSet::Add(isolate, set, key4).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(4, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
CHECK(set->HasKey(isolate, key4));
}
TEST(SmallOrderedHashMapInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashMap> map = factory->NewSmallOrderedHashMap();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
CHECK(!map->HasKey(isolate, key1));
map = SmallOrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
// Add existing key.
map = SmallOrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
Handle<String> value = factory->NewStringFromAsciiChecked("foo");
CHECK(!map->HasKey(isolate, key2));
map = SmallOrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
map = SmallOrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!map->HasKey(isolate, key3));
map = SmallOrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
map = SmallOrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
Handle<Object> key4 = factory->NewHeapNumber(42.0);
CHECK(!map->HasKey(isolate, key4));
map = SmallOrderedHashMap::Add(isolate, map, key4, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(4, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
CHECK(map->HasKey(isolate, key4));
map = SmallOrderedHashMap::Add(isolate, map, key4, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(4, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
CHECK(map->HasKey(isolate, key4));
}
TEST(SmallOrderedHashSetDuplicateHashCode) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
set = SmallOrderedHashSet::Add(isolate, set, key2).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
}
TEST(SmallOrderedHashMapDuplicateHashCode) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashMap> map = factory->NewSmallOrderedHashMap();
Handle<JSObject> value = factory->NewJSObjectWithNullProto();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
map = SmallOrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
CHECK(!key1->SameValue(*key2));
Object hash1 = key1->GetHash();
Object hash2 = key2->GetHash();
CHECK_EQ(hash1, hash2);
map = SmallOrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
}
TEST(SmallOrderedHashSetGrow) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
std::vector<Handle<Object>> keys;
for (int i = 0; i < 254; i++) {
Handle<Smi> key(Smi::FromInt(i), isolate);
keys.push_back(key);
}
for (size_t i = 0; i < 4; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 4; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(4, set->NumberOfElements());
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 4; i < 8; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 8; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(8, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 8; i < 16; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 16; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(16, set->NumberOfElements());
CHECK_EQ(8, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 16; i < 32; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 32; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(32, set->NumberOfElements());
CHECK_EQ(16, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 32; i < 64; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 64; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(64, set->NumberOfElements());
CHECK_EQ(32, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 64; i < 128; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 128; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(128, set->NumberOfElements());
CHECK_EQ(64, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
for (size_t i = 128; i < 254; i++) {
set = SmallOrderedHashSet::Add(isolate, set, keys[i]).ToHandleChecked();
Verify(isolate, set);
}
for (size_t i = 0; i < 254; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(isolate, set);
}
CHECK_EQ(254, set->NumberOfElements());
CHECK_EQ(127, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(isolate, set);
}
TEST(SmallOrderedHashMapGrow) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashMap> map = factory->NewSmallOrderedHashMap();
std::vector<Handle<Object>> keys;
for (int i = 0; i < 254; i++) {
Handle<Smi> key(Smi::FromInt(i), isolate);
keys.push_back(key);
}
for (size_t i = 0; i < 4; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 4; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(4, map->NumberOfElements());
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 4; i < 8; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 8; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(8, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 8; i < 16; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 16; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(16, map->NumberOfElements());
CHECK_EQ(8, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 16; i < 32; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 32; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(32, map->NumberOfElements());
CHECK_EQ(16, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 32; i < 64; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 64; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(64, map->NumberOfElements());
CHECK_EQ(32, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 64; i < 128; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 128; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(128, map->NumberOfElements());
CHECK_EQ(64, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
for (size_t i = 128; i < 254; i++) {
map = SmallOrderedHashMap::Add(isolate, map, keys[i], keys[i])
.ToHandleChecked();
Verify(isolate, map);
}
for (size_t i = 0; i < 254; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(isolate, map);
}
CHECK_EQ(254, map->NumberOfElements());
CHECK_EQ(127, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(isolate, map);
}
TEST(OrderedHashTableInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashMap> map = factory->NewOrderedHashMap();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
map = OrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
// Add existing key.
map = OrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
Handle<String> value = factory->NewStringFromAsciiChecked("bar");
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
map = OrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
map = OrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
map = OrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
map = OrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
Handle<Object> key4 = factory->NewHeapNumber(42.0);
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key4));
map = OrderedHashMap::Add(isolate, map, key4, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(4, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key4));
map = OrderedHashMap::Add(isolate, map, key4, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(4, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key4));
}
TEST(OrderedHashMapDuplicateHashCode) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashMap> map = factory->NewOrderedHashMap();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
Handle<JSObject> value = factory->NewJSObjectWithNullProto();
map = OrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
map = OrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
}
TEST(OrderedHashMapDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
Handle<String> value = factory->NewStringFromAsciiChecked("bar");
Handle<OrderedHashMap> map = factory->NewOrderedHashMap();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
// Delete from an empty hash table
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
map = OrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
// Delete single existing key
CHECK(OrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
map = OrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
map = OrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
map = OrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
// Delete multiple existing keys
CHECK(OrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK_EQ(2, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
CHECK(OrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(3, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(OrderedHashMap::HasKey(isolate, *map, *key3));
CHECK(OrderedHashMap::Delete(isolate, *map, *key3));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
// Delete non existent key from non new hash table
CHECK(!OrderedHashMap::Delete(isolate, *map, *key3));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfDeletedElements());
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
// Delete non existent key from non empty hash table
map = OrderedHashMap::Shrink(isolate, map);
map = OrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
CHECK(!OrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key3));
}
TEST(SmallOrderedHashMapDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
Handle<String> value = factory->NewStringFromAsciiChecked("bar");
Handle<SmallOrderedHashMap> map = factory->NewSmallOrderedHashMap();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
// Delete from an empty hash table
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!SmallOrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
map = SmallOrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
// Delete single existing key
CHECK(SmallOrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
map = SmallOrderedHashMap::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
CHECK(!map->HasKey(isolate, key2));
map = SmallOrderedHashMap::Add(isolate, map, key2, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!map->HasKey(isolate, key3));
map = SmallOrderedHashMap::Add(isolate, map, key3, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(3, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
// Delete multiple existing keys
CHECK(SmallOrderedHashMap::Delete(isolate, *map, *key1));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK_EQ(2, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
CHECK(SmallOrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(3, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
CHECK(map->HasKey(isolate, key3));
CHECK(SmallOrderedHashMap::Delete(isolate, *map, *key3));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
CHECK(!map->HasKey(isolate, key3));
// Delete non existent key from non new hash table
CHECK(!SmallOrderedHashMap::Delete(isolate, *map, *key3));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
CHECK(!map->HasKey(isolate, key3));
// Delete non existent key from non empty hash table
map = SmallOrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
CHECK(!map->HasKey(isolate, key3));
CHECK(!SmallOrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
CHECK(!map->HasKey(isolate, key3));
}
TEST(OrderedHashMapDuplicateHashCodeDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashMap> map = factory->NewOrderedHashMap();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
Handle<JSObject> value = factory->NewJSObjectWithNullProto();
map = OrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
// We shouldn't be able to delete the key!
CHECK(!OrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
CHECK(!OrderedHashMap::HasKey(isolate, *map, *key2));
}
TEST(SmallOrderedHashMapDuplicateHashCodeDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashMap> map = factory->NewSmallOrderedHashMap();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
Handle<JSObject> value = factory->NewJSObjectWithNullProto();
map = SmallOrderedHashMap::Add(isolate, map, key1, value).ToHandleChecked();
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
// We shouldn't be able to delete the key!
CHECK(!SmallOrderedHashMap::Delete(isolate, *map, *key2));
Verify(isolate, map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(map->HasKey(isolate, key1));
CHECK(!map->HasKey(isolate, key2));
}
TEST(OrderedHashSetDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashSet> set = factory->NewOrderedHashSet();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
// Delete from an empty hash table
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
set = OrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
// Delete single existing key
CHECK(OrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
set = OrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
set = OrderedHashSet::Add(isolate, set, key2).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key3));
set = OrderedHashSet::Add(isolate, set, key3).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(3, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(OrderedHashSet::HasKey(isolate, *set, *key3));
// Delete multiple existing keys
CHECK(OrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK_EQ(2, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(OrderedHashSet::HasKey(isolate, *set, *key3));
CHECK(OrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(3, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(OrderedHashSet::HasKey(isolate, *set, *key3));
CHECK(OrderedHashSet::Delete(isolate, *set, *key3));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key3));
// Delete non existent key from non new hash table
CHECK(!OrderedHashSet::Delete(isolate, *set, *key3));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfDeletedElements());
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key3));
// Delete non existent key from non empty hash table
set = OrderedHashSet::Shrink(isolate, set);
set = OrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key3));
CHECK(!OrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key3));
}
TEST(SmallOrderedHashSetDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
// Delete from an empty hash table
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!SmallOrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
// Delete single existing key
CHECK(SmallOrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
Handle<String> key2 = factory->NewStringFromAsciiChecked("foo");
CHECK(!set->HasKey(isolate, key2));
set = SmallOrderedHashSet::Add(isolate, set, key2).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key2));
Handle<Symbol> key3 = factory->NewSymbol();
CHECK(!set->HasKey(isolate, key3));
set = SmallOrderedHashSet::Add(isolate, set, key3).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(3, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
// Delete multiple existing keys
CHECK(SmallOrderedHashSet::Delete(isolate, *set, *key1));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK_EQ(2, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
CHECK(SmallOrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(3, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
CHECK(set->HasKey(isolate, key3));
CHECK(SmallOrderedHashSet::Delete(isolate, *set, *key3));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
CHECK(!set->HasKey(isolate, key3));
// Delete non existent key from non new hash table
CHECK(!SmallOrderedHashSet::Delete(isolate, *set, *key3));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
CHECK(!set->HasKey(isolate, key3));
// Delete non existent key from non empty hash table
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
CHECK(!set->HasKey(isolate, key3));
CHECK(!SmallOrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
CHECK(!set->HasKey(isolate, key3));
}
TEST(OrderedHashSetDuplicateHashCodeDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashSet> set = factory->NewOrderedHashSet();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
set = OrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
// We shouldn't be able to delete the key!
CHECK(!OrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(OrderedHashSet::HasKey(isolate, *set, *key1));
CHECK(!OrderedHashSet::HasKey(isolate, *set, *key2));
}
TEST(SmallOrderedHashSetDuplicateHashCodeDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
Handle<JSObject> key1 = factory->NewJSObjectWithNullProto();
set = SmallOrderedHashSet::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
Handle<JSObject> key2 = factory->NewJSObjectWithNullProto();
CopyHashCode(key1, key2);
// We shouldn't be able to delete the key!
CHECK(!SmallOrderedHashSet::Delete(isolate, *set, *key2));
Verify(isolate, set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(set->HasKey(isolate, key1));
CHECK(!set->HasKey(isolate, key2));
}
TEST(OrderedHashSetHandlerInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> set =
OrderedHashSetHandler::Allocate(isolate, 4).ToHandleChecked();
Verify(isolate, set);
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashSetHandler::HasKey(isolate, set, key1));
set = OrderedHashSetHandler::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
// Add existing key.
set = OrderedHashSetHandler::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
CHECK(SmallOrderedHashSet::Is(set));
for (int i = 0; i < 1024; i++) {
Handle<Smi> key_i(Smi::FromInt(i), isolate);
set = OrderedHashSetHandler::Add(isolate, set, key_i).ToHandleChecked();
Verify(isolate, set);
for (int j = 0; j <= i; j++) {
Handle<Smi> key_j(Smi::FromInt(j), isolate);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key_j));
}
}
CHECK(OrderedHashSet::Is(set));
}
TEST(OrderedHashMapHandlerInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> map =
OrderedHashMapHandler::Allocate(isolate, 4).ToHandleChecked();
Verify(isolate, map);
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashMapHandler::HasKey(isolate, map, key1));
map =
OrderedHashMapHandler::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
// Add existing key.
map =
OrderedHashMapHandler::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
CHECK(SmallOrderedHashMap::Is(map));
for (int i = 0; i < 1024; i++) {
Handle<Smi> key_i(Smi::FromInt(i), isolate);
Handle<Smi> value_i(Smi::FromInt(i), isolate);
map = OrderedHashMapHandler::Add(isolate, map, key_i, value_i)
.ToHandleChecked();
Verify(isolate, map);
for (int j = 0; j <= i; j++) {
Handle<Smi> key_j(Smi::FromInt(j), isolate);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key_j));
}
}
CHECK(OrderedHashMap::Is(map));
}
TEST(OrderedHashSetHandlerDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> set =
OrderedHashSetHandler::Allocate(isolate, 4).ToHandleChecked();
Verify(isolate, set);
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashSetHandler::HasKey(isolate, set, key1));
set = OrderedHashSetHandler::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
// Add existing key.
set = OrderedHashSetHandler::Add(isolate, set, key1).ToHandleChecked();
Verify(isolate, set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
CHECK(SmallOrderedHashSet::Is(set));
// Remove a non-existing key.
Handle<Smi> key2(Smi::FromInt(2), isolate);
OrderedHashSetHandler::Delete(isolate, set, key2);
Verify(isolate, set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
CHECK(!OrderedHashSetHandler::HasKey(isolate, set, key2));
CHECK(SmallOrderedHashSet::Is(set));
// Remove an existing key.
OrderedHashSetHandler::Delete(isolate, set, key1);
Verify(isolate, set);
CHECK(!OrderedHashSetHandler::HasKey(isolate, set, key1));
CHECK(SmallOrderedHashSet::Is(set));
}
TEST(OrderedHashMapHandlerDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> map =
OrderedHashMapHandler::Allocate(isolate, 4).ToHandleChecked();
Verify(isolate, map);
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
Handle<Smi> value1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashMapHandler::HasKey(isolate, map, key1));
map =
OrderedHashMapHandler::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
// Add existing key.
map =
OrderedHashMapHandler::Add(isolate, map, key1, value1).ToHandleChecked();
Verify(isolate, map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
CHECK(SmallOrderedHashMap::Is(map));
// Remove a non-existing key.
Handle<Smi> key2(Smi::FromInt(2), isolate);
OrderedHashMapHandler::Delete(isolate, map, key2);
Verify(isolate, map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
CHECK(!OrderedHashMapHandler::HasKey(isolate, map, key2));
CHECK(SmallOrderedHashMap::Is(map));
// Remove an existing key.
OrderedHashMapHandler::Delete(isolate, map, key1);
Verify(isolate, map);
CHECK(!OrderedHashMapHandler::HasKey(isolate, map, key1));
CHECK(SmallOrderedHashMap::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 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = OrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
}
TEST(OrderedNameDictionaryFindEntry) {
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 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
InternalIndex entry = dict->FindEntry(isolate, *key1);
CHECK_EQ(entry, InternalIndex(0));
CHECK(entry.is_found());
Handle<Symbol> key2 = factory->NewSymbol();
dict = OrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
entry = dict->FindEntry(isolate, *key1);
CHECK(entry.is_found());
CHECK_EQ(entry, InternalIndex(0));
entry = dict->FindEntry(isolate, *key2);
CHECK(entry.is_found());
CHECK_EQ(entry, InternalIndex(1));
}
TEST(OrderedNameDictionaryValueAtAndValueAtPut) {
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 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
InternalIndex entry = dict->FindEntry(isolate, *key1);
Handle<Object> found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
Handle<String> other_value = isolate->factory()->InternalizeUtf8String("baz");
dict->ValueAtPut(entry, *other_value);
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = OrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
entry = dict->FindEntry(isolate, *key2);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
dict->ValueAtPut(entry, *other_value);
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
}
TEST(OrderedNameDictionaryDetailsAtAndDetailsAtPut) {
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 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
InternalIndex entry = dict->FindEntry(isolate, *key1);
PropertyDetails found = dict->DetailsAt(entry);
CHECK_EQ(PropertyDetails::Empty().AsSmi(), found.AsSmi());
PropertyDetails other =
PropertyDetails(kAccessor, READ_ONLY, PropertyCellType::kNoCell);
dict->DetailsAtPut(entry, other);
found = dict->DetailsAt(entry);
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
CHECK_EQ(other.AsSmi(), found.AsSmi());
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = OrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
entry = dict->FindEntry(isolate, *key1);
found = dict->DetailsAt(entry);
CHECK_EQ(other.AsSmi(), found.AsSmi());
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
entry = dict->FindEntry(isolate, *key2);
dict->DetailsAtPut(entry, other);
found = dict->DetailsAt(entry);
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
CHECK_EQ(other.AsSmi(), found.AsSmi());
}
TEST(SmallOrderedNameDictionaryInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = SmallOrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
}
TEST(SmallOrderedNameDictionaryInsertionMax) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
char buf[10];
for (int i = 0; i < SmallOrderedNameDictionary::kMaxCapacity; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
Handle<String> key = isolate->factory()->InternalizeUtf8String(buf);
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
}
CHECK_EQ(SmallOrderedNameDictionary::kMaxCapacity /
SmallOrderedNameDictionary::kLoadFactor,
dict->NumberOfBuckets());
CHECK_EQ(SmallOrderedNameDictionary::kMaxCapacity, dict->NumberOfElements());
// This should overflow and fail.
CHECK(SmallOrderedNameDictionary::Add(isolate, dict, value, value, details)
.is_null());
}
TEST(SmallOrderedNameDictionaryFindEntry) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
InternalIndex entry = dict->FindEntry(isolate, *key1);
CHECK(entry.is_found());
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = SmallOrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
}
TEST(SmallOrderedNameDictionaryValueAtAndValueAtPut) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
InternalIndex entry = dict->FindEntry(isolate, *key1);
Handle<Object> found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
Handle<String> other_value = isolate->factory()->InternalizeUtf8String("baz");
dict->ValueAtPut(entry, *other_value);
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = SmallOrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
entry = dict->FindEntry(isolate, *key2);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
dict->ValueAtPut(entry, *other_value);
entry = dict->FindEntry(isolate, *key1);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
}
TEST(SmallOrderedNameDictionaryDetailsAtAndDetailsAtPut) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key1 = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key1).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key1, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
InternalIndex entry = dict->FindEntry(isolate, *key1);
PropertyDetails found = dict->DetailsAt(entry);
CHECK_EQ(PropertyDetails::Empty().AsSmi(), found.AsSmi());
PropertyDetails other =
PropertyDetails(kAccessor, READ_ONLY, PropertyCellType::kNoCell);
dict->DetailsAtPut(entry, other);
found = dict->DetailsAt(entry);
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
CHECK_EQ(other.AsSmi(), found.AsSmi());
Handle<Symbol> key2 = factory->NewSymbol();
CHECK(dict->FindEntry(isolate, *key2).is_not_found());
dict = SmallOrderedNameDictionary::Add(isolate, dict, key2, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(2, dict->NumberOfElements());
CHECK_EQ(InternalIndex(0), dict->FindEntry(isolate, *key1));
CHECK_EQ(InternalIndex(1), dict->FindEntry(isolate, *key2));
entry = dict->FindEntry(isolate, *key1);
found = dict->DetailsAt(entry);
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
CHECK_EQ(other.AsSmi(), found.AsSmi());
entry = dict->FindEntry(isolate, *key2);
dict->DetailsAtPut(entry, other);
found = dict->DetailsAt(entry);
CHECK_NE(PropertyDetails::Empty().AsSmi(), found.AsSmi());
CHECK_EQ(other.AsSmi(), found.AsSmi());
}
TEST(SmallOrderedNameDictionarySetAndMigrateHash) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
CHECK_EQ(PropertyArray::kNoHashSentinel, dict->Hash());
dict->SetHash(100);
CHECK_EQ(100, dict->Hash());
char buf[10];
for (int i = 0; i < SmallOrderedNameDictionary::kMaxCapacity; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
Handle<String> key = isolate->factory()->InternalizeUtf8String(buf);
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(100, dict->Hash());
}
}
TEST(OrderedNameDictionarySetAndMigrateHash) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedNameDictionary> dict = factory->NewOrderedNameDictionary();
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
PropertyDetails details = PropertyDetails::Empty();
CHECK_EQ(PropertyArray::kNoHashSentinel, dict->Hash());
dict->SetHash(100);
CHECK_EQ(100, dict->Hash());
char buf[10];
for (int i = 0; i <= 1024; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
Handle<String> key = isolate->factory()->InternalizeUtf8String(buf);
dict = OrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(100, dict->Hash());
}
}
TEST(OrderedNameDictionaryHandlerInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> table =
OrderedNameDictionaryHandler::Allocate(isolate, 4).ToHandleChecked();
CHECK(table->IsSmallOrderedNameDictionary());
Verify(isolate, table);
// Add a new key.
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
Handle<String> key = isolate->factory()->InternalizeUtf8String("foo");
PropertyDetails details = PropertyDetails::Empty();
table = OrderedNameDictionaryHandler::Add(isolate, table, key, value, details)
.ToHandleChecked();
DCHECK(key->IsUniqueName());
Verify(isolate, table);
CHECK(table->IsSmallOrderedNameDictionary());
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key)
.is_found());
char buf[10];
for (int i = 0; i < 1024; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
key = isolate->factory()->InternalizeUtf8String(buf);
table =
OrderedNameDictionaryHandler::Add(isolate, table, key, value, details)
.ToHandleChecked();
DCHECK(key->IsUniqueName());
Verify(isolate, table);
for (int j = 0; j <= i; j++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", j));
Handle<Name> key_j = isolate->factory()->InternalizeUtf8String(buf);
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key_j)
.is_found());
}
for (int j = i + 1; j < 1024; j++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", j));
Handle<Name> key_j = isolate->factory()->InternalizeUtf8String(buf);
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key_j)
.is_not_found());
}
}
CHECK(table->IsOrderedNameDictionary());
}
TEST(OrderedNameDictionaryHandlerDeletion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
HandleScope scope(isolate);
Handle<HeapObject> table =
OrderedNameDictionaryHandler::Allocate(isolate, 4).ToHandleChecked();
CHECK(table->IsSmallOrderedNameDictionary());
Verify(isolate, table);
// Add a new key.
Handle<String> value = isolate->factory()->InternalizeUtf8String("bar");
Handle<String> key = isolate->factory()->InternalizeUtf8String("foo");
Handle<String> key2 = isolate->factory()->InternalizeUtf8String("foo2");
PropertyDetails details = PropertyDetails::Empty();
table = OrderedNameDictionaryHandler::Add(isolate, table, key, value, details)
.ToHandleChecked();
DCHECK(key->IsUniqueName());
Verify(isolate, table);
CHECK(table->IsSmallOrderedNameDictionary());
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key)
.is_found());
// Remove a non-existing key.
OrderedNameDictionaryHandler::Delete(isolate, table, key2);
Verify(isolate, table);
CHECK(table->IsSmallOrderedNameDictionary());
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key2)
.is_not_found());
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key)
.is_found());
// Remove an existing key.
OrderedNameDictionaryHandler::Delete(isolate, table, key);
Verify(isolate, table);
CHECK(table->IsSmallOrderedNameDictionary());
CHECK(OrderedNameDictionaryHandler::FindEntry(isolate, *table, *key)
.is_not_found());
CHECK(table->IsSmallOrderedNameDictionary());
}
TEST(OrderedNameDictionarySetEntry) {
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());
CHECK_EQ(0, dict->NumberOfDeletedElements());
Handle<String> key = factory->InternalizeUtf8String("foo");
Handle<String> value = factory->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
InternalIndex entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
Handle<Object> found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
Handle<String> other_value = isolate->factory()->InternalizeUtf8String("baz");
PropertyDetails other_details =
PropertyDetails(kAccessor, READ_ONLY, PropertyCellType::kNoCell);
dict->SetEntry(entry, *key, *other_value, other_details);
entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
found = handle(dict->KeyAt(entry), isolate);
CHECK_EQ(*found, *key);
PropertyDetails found_details = dict->DetailsAt(entry);
CHECK_EQ(found_details.AsSmi(), other_details.AsSmi());
}
TEST(SmallOrderedNameDictionarySetEntry) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key = factory->InternalizeUtf8String("foo");
Handle<String> value = factory->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(0, dict->NumberOfDeletedElements());
InternalIndex entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
Handle<Object> found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *value);
// Change the value
Handle<String> other_value = factory->InternalizeUtf8String("baz");
PropertyDetails other_details =
PropertyDetails(kAccessor, READ_ONLY, PropertyCellType::kNoCell);
dict->SetEntry(entry, *key, *other_value, other_details);
entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
found = handle(dict->ValueAt(entry), isolate);
CHECK_EQ(*found, *other_value);
found = handle(dict->KeyAt(entry), isolate);
CHECK_EQ(*found, *key);
PropertyDetails found_details = dict->DetailsAt(entry);
CHECK_EQ(found_details.AsSmi(), other_details.AsSmi());
}
TEST(OrderedNameDictionaryDeleteEntry) {
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> key = factory->InternalizeUtf8String("foo");
Handle<String> value = factory->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = OrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(0, dict->NumberOfDeletedElements());
InternalIndex entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
dict = OrderedNameDictionary::DeleteEntry(isolate, dict, entry);
entry = dict->FindEntry(isolate, *key);
CHECK(entry.is_not_found());
CHECK_EQ(0, dict->NumberOfElements());
char buf[10];
// Make sure we grow at least once.
CHECK_LT(OrderedNameDictionaryHandler::Capacity(*dict), 100);
for (int i = 0; i < 100; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
key = factory->InternalizeUtf8String(buf);
dict = OrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
DCHECK(key->IsUniqueName());
Verify(isolate, dict);
}
CHECK_EQ(100, dict->NumberOfElements());
// Initial dictionary has grown.
CHECK_EQ(0, dict->NumberOfDeletedElements());
for (int i = 0; i < 100; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
key = factory->InternalizeUtf8String(buf);
entry = dict->FindEntry(isolate, *key);
dict = OrderedNameDictionary::DeleteEntry(isolate, dict, entry);
Verify(isolate, dict);
entry = dict->FindEntry(isolate, *key);
CHECK(entry.is_not_found());
}
CHECK_EQ(0, dict->NumberOfElements());
// Dictionary shrunk again.
CHECK_EQ(0, dict->NumberOfDeletedElements());
}
TEST(SmallOrderedNameDictionaryDeleteEntry) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedNameDictionary> dict =
factory->NewSmallOrderedNameDictionary();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(0, dict->NumberOfElements());
Handle<String> key = factory->InternalizeUtf8String("foo");
Handle<String> value = factory->InternalizeUtf8String("bar");
CHECK(dict->FindEntry(isolate, *key).is_not_found());
PropertyDetails details = PropertyDetails::Empty();
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
Verify(isolate, dict);
CHECK_EQ(2, dict->NumberOfBuckets());
CHECK_EQ(1, dict->NumberOfElements());
CHECK_EQ(0, dict->NumberOfDeletedElements());
InternalIndex entry = dict->FindEntry(isolate, *key);
CHECK_EQ(InternalIndex(0), entry);
dict = SmallOrderedNameDictionary::DeleteEntry(isolate, dict, entry);
entry = dict->FindEntry(isolate, *key);
CHECK(entry.is_not_found());
char buf[10];
// Make sure we grow at least once.
CHECK_LT(dict->Capacity(), SmallOrderedNameDictionary::kMaxCapacity);
for (int i = 0; i < SmallOrderedNameDictionary::kMaxCapacity; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
key = factory->InternalizeUtf8String(buf);
dict = SmallOrderedNameDictionary::Add(isolate, dict, key, value, details)
.ToHandleChecked();
DCHECK(key->IsUniqueName());
Verify(isolate, dict);
}
CHECK_EQ(SmallOrderedNameDictionary::kMaxCapacity, dict->NumberOfElements());
// Dictionary has grown.
CHECK_EQ(0, dict->NumberOfDeletedElements());
for (int i = 0; i < SmallOrderedNameDictionary::kMaxCapacity; i++) {
CHECK_LT(0, snprintf(buf, sizeof(buf), "foo%d", i));
key = factory->InternalizeUtf8String(buf);
entry = dict->FindEntry(isolate, *key);
dict = SmallOrderedNameDictionary::DeleteEntry(isolate, dict, entry);
Verify(isolate, dict);
entry = dict->FindEntry(isolate, *key);
CHECK(entry.is_not_found());
}
CHECK_EQ(0, dict->NumberOfElements());
// Dictionary shrunk.
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).is_not_found());
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).is_not_found());
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).is_not_found());
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