v8/test/cctest/test-orderedhashtable.cc
Sathya Gunasekaran da02f095d3 [hash-table] Introduce OrderedHashTableHandler
OrderedHashTableHandler (to be renamed to OrderedHashTable) is the
interface that abstracts away the two different ordered hash tables.

All operations on the two ordered hash tables must be performed
through this new interface so that we can seamlessly migrate from one
table to another behind the scenes.

Bug: v8:6443, v8:7569
Change-Id: Ifc0a38974605b63e0a2a36b4aafb8dc68a081f4a
Reviewed-on: https://chromium-review.googlesource.com/1059865
Commit-Queue: Sathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53622}
2018-06-11 00:22:12 +00:00

1270 lines
42 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/v8.h"
#include "src/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(Handle<HeapObject> obj) {
#if VERIFY_HEAP
obj->ObjectVerify();
#endif
}
TEST(SmallOrderedHashSetInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<SmallOrderedHashSet> set = factory->NewSmallOrderedHashSet();
Verify(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(set, key1).ToHandleChecked();
Verify(set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(1, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
// Add existing key.
set = SmallOrderedHashSet::Add(set, key1).ToHandleChecked();
Verify(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(set, key2).ToHandleChecked();
Verify(set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(2, set->NumberOfElements());
CHECK(set->HasKey(isolate, key1));
CHECK(set->HasKey(isolate, key2));
set = SmallOrderedHashSet::Add(set, key2).ToHandleChecked();
Verify(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(set, key3).ToHandleChecked();
Verify(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(set, key3).ToHandleChecked();
Verify(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(set, key4).ToHandleChecked();
Verify(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(set, key4).ToHandleChecked();
Verify(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(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(map, key1, value1).ToHandleChecked();
Verify(map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
// Add existing key.
map = SmallOrderedHashMap::Add(map, key1, value1).ToHandleChecked();
Verify(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(map, key2, value).ToHandleChecked();
Verify(map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(2, map->NumberOfElements());
CHECK(map->HasKey(isolate, key1));
CHECK(map->HasKey(isolate, key2));
map = SmallOrderedHashMap::Add(map, key2, value).ToHandleChecked();
Verify(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(map, key3, value).ToHandleChecked();
Verify(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(map, key3, value).ToHandleChecked();
Verify(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(map, key4, value).ToHandleChecked();
Verify(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(map, key4, value).ToHandleChecked();
Verify(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(set, key1).ToHandleChecked();
Verify(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(set, key2).ToHandleChecked();
Verify(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(map, key1, value).ToHandleChecked();
Verify(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(map, key2, value).ToHandleChecked();
Verify(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(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 4; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(4, set->NumberOfElements());
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 4; i < 8; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 8; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(8, set->NumberOfElements());
CHECK_EQ(4, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 8; i < 16; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 16; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(16, set->NumberOfElements());
CHECK_EQ(8, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 16; i < 32; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 32; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(32, set->NumberOfElements());
CHECK_EQ(16, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 32; i < 64; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 64; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(64, set->NumberOfElements());
CHECK_EQ(32, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 64; i < 128; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 128; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(128, set->NumberOfElements());
CHECK_EQ(64, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(set);
for (size_t i = 128; i < 254; i++) {
set = SmallOrderedHashSet::Add(set, keys[i]).ToHandleChecked();
Verify(set);
}
for (size_t i = 0; i < 254; i++) {
CHECK(set->HasKey(isolate, keys[i]));
Verify(set);
}
CHECK_EQ(254, set->NumberOfElements());
CHECK_EQ(127, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfDeletedElements());
Verify(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(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 4; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(4, map->NumberOfElements());
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 4; i < 8; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 8; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(8, map->NumberOfElements());
CHECK_EQ(4, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 8; i < 16; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 16; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(16, map->NumberOfElements());
CHECK_EQ(8, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 16; i < 32; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 32; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(32, map->NumberOfElements());
CHECK_EQ(16, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 32; i < 64; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 64; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(64, map->NumberOfElements());
CHECK_EQ(32, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 64; i < 128; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 128; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(128, map->NumberOfElements());
CHECK_EQ(64, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
for (size_t i = 128; i < 254; i++) {
map = SmallOrderedHashMap::Add(map, keys[i], keys[i]).ToHandleChecked();
Verify(map);
}
for (size_t i = 0; i < 254; i++) {
CHECK(map->HasKey(isolate, keys[i]));
Verify(map);
}
CHECK_EQ(254, map->NumberOfElements());
CHECK_EQ(127, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfDeletedElements());
Verify(map);
}
TEST(OrderedHashTableInsertion) {
LocalContext context;
Isolate* isolate = GetIsolateFrom(&context);
Factory* factory = isolate->factory();
HandleScope scope(isolate);
Handle<OrderedHashMap> map = factory->NewOrderedHashMap();
Verify(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(map, key1, value1);
Verify(map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(1, map->NumberOfElements());
CHECK(OrderedHashMap::HasKey(isolate, *map, *key1));
// Add existing key.
map = OrderedHashMap::Add(map, key1, value1);
Verify(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(map, key2, value);
Verify(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(map, key2, value);
Verify(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(map, key3, value);
Verify(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(map, key3, value);
Verify(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(map, key4, value);
Verify(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(map, key4, value);
Verify(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(map, key1, value);
Verify(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(map, key2, value);
Verify(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(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(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(map, key1, value1);
Verify(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(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(map, key1, value1);
Verify(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(map, key2, value);
Verify(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(map, key3, value);
Verify(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(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(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(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(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(map);
map = OrderedHashMap::Add(map, key1, value);
Verify(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(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(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(map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(0, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
map = SmallOrderedHashMap::Add(map, key1, value1).ToHandleChecked();
Verify(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(map);
CHECK_EQ(2, map->NumberOfBuckets());
CHECK_EQ(0, map->NumberOfElements());
CHECK_EQ(1, map->NumberOfDeletedElements());
CHECK(!map->HasKey(isolate, key1));
map = SmallOrderedHashMap::Add(map, key1, value1).ToHandleChecked();
Verify(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(map, key2, value).ToHandleChecked();
Verify(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(map, key3, value).ToHandleChecked();
Verify(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(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(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(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(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(map, key1, value).ToHandleChecked();
Verify(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(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(map, key1, value);
Verify(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(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(map, key1, value).ToHandleChecked();
Verify(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(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(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(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(set, key1);
Verify(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(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(set, key1);
Verify(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(set, key2);
Verify(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(set, key3);
Verify(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(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(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(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(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(set);
set = OrderedHashSet::Add(set, key1);
Verify(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(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(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(set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(0, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
set = SmallOrderedHashSet::Add(set, key1).ToHandleChecked();
Verify(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(set);
CHECK_EQ(2, set->NumberOfBuckets());
CHECK_EQ(0, set->NumberOfElements());
CHECK_EQ(1, set->NumberOfDeletedElements());
CHECK(!set->HasKey(isolate, key1));
set = SmallOrderedHashSet::Add(set, key1).ToHandleChecked();
Verify(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(set, key2).ToHandleChecked();
Verify(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(set, key3).ToHandleChecked();
Verify(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(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(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(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(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(set, key1).ToHandleChecked();
Verify(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(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(set, key1);
Verify(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(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(set, key1).ToHandleChecked();
Verify(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(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);
Verify(set);
// Add a new key.
Handle<Smi> key1(Smi::FromInt(1), isolate);
CHECK(!OrderedHashSetHandler::HasKey(isolate, set, key1));
set = OrderedHashSetHandler::Add(isolate, set, key1);
Verify(set);
CHECK(OrderedHashSetHandler::HasKey(isolate, set, key1));
// Add existing key.
set = OrderedHashSetHandler::Add(isolate, set, key1);
Verify(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);
Verify(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);
Verify(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);
Verify(map);
CHECK(OrderedHashMapHandler::HasKey(isolate, map, key1));
// Add existing key.
map = OrderedHashMapHandler::Add(isolate, map, key1, value1);
Verify(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);
Verify(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));
}
} // namespace test_orderedhashtable
} // namespace internal
} // namespace v8