// Copyright 2018 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 "src/objects/ordered-hash-table.h"

#include "src/execution/isolate.h"
#include "src/heap/heap-inl.h"
#include "src/objects/internal-index.h"
#include "src/objects/js-collection-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/ordered-hash-table-inl.h"
#include "src/roots/roots.h"

namespace v8 {
namespace internal {

template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  // Capacity must be a power of two, since we depend on being able
  // to divide and multiple by 2 (kLoadFactor) to derive capacity
  // from number of buckets. If we decide to change kLoadFactor
  // to something other than 2, capacity should be stored as another
  // field of this object.
  capacity =
      base::bits::RoundUpToPowerOfTwo32(std::max({kInitialCapacity, capacity}));
  if (capacity > MaxCapacity()) {
    return MaybeHandle<Derived>();
  }
  int num_buckets = capacity / kLoadFactor;
  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArrayWithMap(
      Derived::GetMap(ReadOnlyRoots(isolate)),
      HashTableStartIndex() + num_buckets + (capacity * kEntrySize),
      allocation);
  Handle<Derived> table = Handle<Derived>::cast(backing_store);
  for (int i = 0; i < num_buckets; ++i) {
    table->set(HashTableStartIndex() + i, Smi::FromInt(kNotFound));
  }
  table->SetNumberOfBuckets(num_buckets);
  table->SetNumberOfElements(0);
  table->SetNumberOfDeletedElements(0);
  return table;
}

template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::AllocateEmpty(
    Isolate* isolate, AllocationType allocation, RootIndex root_index) {
  // This is only supposed to be used to create the canonical empty versions
  // of each ordered structure, and should not be used afterwards.
  // Requires that the map has already been set up in the roots table.
  DCHECK(ReadOnlyRoots(isolate).at(root_index) == kNullAddress);

  Handle<FixedArray> backing_store = isolate->factory()->NewFixedArrayWithMap(
      Derived::GetMap(ReadOnlyRoots(isolate)), HashTableStartIndex(),
      allocation);
  Handle<Derived> table = Handle<Derived>::cast(backing_store);
  table->SetNumberOfBuckets(0);
  table->SetNumberOfElements(0);
  table->SetNumberOfDeletedElements(0);
  return table;
}

template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::EnsureGrowable(
    Isolate* isolate, Handle<Derived> table) {
  DCHECK(!table->IsObsolete());

  int nof = table->NumberOfElements();
  int nod = table->NumberOfDeletedElements();
  int capacity = table->Capacity();
  if ((nof + nod) < capacity) return table;

  int new_capacity;
  if (capacity == 0) {
    // step from empty to minimum proper size
    new_capacity = kInitialCapacity;
  } else if (nod >= (capacity >> 1)) {
    // Don't need to grow if we can simply clear out deleted entries instead.
    // Note that we can't compact in place, though, so we always allocate
    // a new table.
    new_capacity = capacity;
  } else {
    new_capacity = capacity << 1;
  }

  return Derived::Rehash(isolate, table, new_capacity);
}

template <class Derived, int entrysize>
Handle<Derived> OrderedHashTable<Derived, entrysize>::Shrink(
    Isolate* isolate, Handle<Derived> table) {
  DCHECK(!table->IsObsolete());

  int nof = table->NumberOfElements();
  int capacity = table->Capacity();
  if (nof >= (capacity >> 2)) return table;
  return Derived::Rehash(isolate, table, capacity / 2).ToHandleChecked();
}

template <class Derived, int entrysize>
Handle<Derived> OrderedHashTable<Derived, entrysize>::Clear(
    Isolate* isolate, Handle<Derived> table) {
  DCHECK(!table->IsObsolete());

  AllocationType allocation_type = Heap::InYoungGeneration(*table)
                                       ? AllocationType::kYoung
                                       : AllocationType::kOld;

  Handle<Derived> new_table =
      Allocate(isolate, kInitialCapacity, allocation_type).ToHandleChecked();

  if (table->NumberOfBuckets() > 0) {
    // Don't try to modify the empty canonical table which lives in RO space.
    table->SetNextTable(*new_table);
    table->SetNumberOfDeletedElements(kClearedTableSentinel);
  }

  return new_table;
}

template <class Derived, int entrysize>
bool OrderedHashTable<Derived, entrysize>::HasKey(Isolate* isolate,
                                                  Derived table, Object key) {
  DCHECK_IMPLIES(entrysize == 1, table.IsOrderedHashSet());
  DCHECK_IMPLIES(entrysize == 2, table.IsOrderedHashMap());
  DisallowHeapAllocation no_gc;
  InternalIndex entry = table.FindEntry(isolate, key);
  return entry.is_found();
}

template <class Derived, int entrysize>
InternalIndex OrderedHashTable<Derived, entrysize>::FindEntry(Isolate* isolate,
                                                              Object key) {
  if (NumberOfElements() == 0) {
    // This is not just an optimization but also ensures that we do the right
    // thing if Capacity() == 0
    return InternalIndex::NotFound();
  }

  int raw_entry;
  // This special cases for Smi, so that we avoid the HandleScope
  // creation below.
  if (key.IsSmi()) {
    uint32_t hash = ComputeUnseededHash(Smi::ToInt(key));
    raw_entry = HashToEntryRaw(hash & Smi::kMaxValue);
  } else {
    HandleScope scope(isolate);
    Object hash = key.GetHash();
    // If the object does not have an identity hash, it was never used as a key
    if (hash.IsUndefined(isolate)) return InternalIndex::NotFound();
    raw_entry = HashToEntryRaw(Smi::ToInt(hash));
  }

  // Walk the chain in the bucket to find the key.
  while (raw_entry != kNotFound) {
    Object candidate_key = KeyAt(InternalIndex(raw_entry));
    if (candidate_key.SameValueZero(key)) return InternalIndex(raw_entry);
    raw_entry = NextChainEntryRaw(raw_entry);
  }

  return InternalIndex::NotFound();
}

MaybeHandle<OrderedHashSet> OrderedHashSet::Add(Isolate* isolate,
                                                Handle<OrderedHashSet> table,
                                                Handle<Object> key) {
  int hash = key->GetOrCreateHash(isolate).value();
  if (table->NumberOfElements() > 0) {
    int raw_entry = table->HashToEntryRaw(hash);
    // Walk the chain of the bucket and try finding the key.
    while (raw_entry != kNotFound) {
      Object candidate_key = table->KeyAt(InternalIndex(raw_entry));
      // Do not add if we have the key already
      if (candidate_key.SameValueZero(*key)) return table;
      raw_entry = table->NextChainEntryRaw(raw_entry);
    }
  }

  MaybeHandle<OrderedHashSet> table_candidate =
      OrderedHashSet::EnsureGrowable(isolate, table);
  if (!table_candidate.ToHandle(&table)) {
    return table_candidate;
  }
  // Read the existing bucket values.
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToEntryRaw(hash);
  int nof = table->NumberOfElements();
  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();
  int new_index = table->EntryToIndexRaw(new_entry);
  table->set(new_index, *key);
  table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
  // and point the bucket to the new entry.
  table->set(HashTableStartIndex() + bucket, Smi::FromInt(new_entry));
  table->SetNumberOfElements(nof + 1);
  return table;
}

Handle<FixedArray> OrderedHashSet::ConvertToKeysArray(
    Isolate* isolate, Handle<OrderedHashSet> table, GetKeysConversion convert) {
  int length = table->NumberOfElements();
  int nof_buckets = table->NumberOfBuckets();
  // Convert the dictionary to a linear list.
  Handle<FixedArray> result = Handle<FixedArray>::cast(table);
  // From this point on table is no longer a valid OrderedHashSet.
  result->set_map(ReadOnlyRoots(isolate).fixed_array_map());
  int const kMaxStringTableEntries =
      isolate->heap()->MaxNumberToStringCacheSize();
  for (int i = 0; i < length; i++) {
    int index = HashTableStartIndex() + nof_buckets + (i * kEntrySize);
    Object key = table->get(index);
    uint32_t index_value;
    if (convert == GetKeysConversion::kConvertToString) {
      if (key.ToArrayIndex(&index_value)) {
        // Avoid trashing the Number2String cache if indices get very large.
        bool use_cache = i < kMaxStringTableEntries;
        key = *isolate->factory()->Uint32ToString(index_value, use_cache);
      } else {
        CHECK(key.IsName());
      }
    } else if (convert == GetKeysConversion::kNoNumbers) {
      DCHECK(!key.ToArrayIndex(&index_value));
    }
    result->set(i, key);
  }
  return FixedArray::ShrinkOrEmpty(isolate, result, length);
}

HeapObject OrderedHashSet::GetEmpty(ReadOnlyRoots ro_roots) {
  return ro_roots.empty_ordered_hash_set();
}

HeapObject OrderedHashMap::GetEmpty(ReadOnlyRoots ro_roots) {
  return ro_roots.empty_ordered_hash_map();
}

template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
    Isolate* isolate, Handle<Derived> table) {
  return OrderedHashTable<Derived, entrysize>::Rehash(isolate, table,
                                                      table->Capacity());
}

template <class Derived, int entrysize>
MaybeHandle<Derived> OrderedHashTable<Derived, entrysize>::Rehash(
    Isolate* isolate, Handle<Derived> table, int new_capacity) {
  DCHECK(!table->IsObsolete());

  MaybeHandle<Derived> new_table_candidate =
      Derived::Allocate(isolate, new_capacity,
                        Heap::InYoungGeneration(*table) ? AllocationType::kYoung
                                                        : AllocationType::kOld);
  Handle<Derived> new_table;
  if (!new_table_candidate.ToHandle(&new_table)) {
    return new_table_candidate;
  }
  int new_buckets = new_table->NumberOfBuckets();
  int new_entry = 0;
  int removed_holes_index = 0;

  DisallowHeapAllocation no_gc;

  for (InternalIndex old_entry : table->IterateEntries()) {
    int old_entry_raw = old_entry.as_int();
    Object key = table->KeyAt(old_entry);
    if (key.IsTheHole(isolate)) {
      table->SetRemovedIndexAt(removed_holes_index++, old_entry_raw);
      continue;
    }

    Object hash = key.GetHash();
    int bucket = Smi::ToInt(hash) & (new_buckets - 1);
    Object chain_entry = new_table->get(HashTableStartIndex() + bucket);
    new_table->set(HashTableStartIndex() + bucket, Smi::FromInt(new_entry));
    int new_index = new_table->EntryToIndexRaw(new_entry);
    int old_index = table->EntryToIndexRaw(old_entry_raw);
    for (int i = 0; i < entrysize; ++i) {
      Object value = table->get(old_index + i);
      new_table->set(new_index + i, value);
    }
    new_table->set(new_index + kChainOffset, chain_entry);
    ++new_entry;
  }

  DCHECK_EQ(table->NumberOfDeletedElements(), removed_holes_index);

  new_table->SetNumberOfElements(table->NumberOfElements());
  if (table->NumberOfBuckets() > 0) {
    // Don't try to modify the empty canonical table which lives in RO space.
    table->SetNextTable(*new_table);
  }

  return new_table_candidate;
}

MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(Isolate* isolate,
                                                   Handle<OrderedHashSet> table,
                                                   int new_capacity) {
  return Base::Rehash(isolate, table, new_capacity);
}

MaybeHandle<OrderedHashSet> OrderedHashSet::Rehash(
    Isolate* isolate, Handle<OrderedHashSet> table) {
  return Base::Rehash(isolate, table);
}

MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(
    Isolate* isolate, Handle<OrderedHashMap> table) {
  return Base::Rehash(isolate, table);
}

MaybeHandle<OrderedHashMap> OrderedHashMap::Rehash(Isolate* isolate,
                                                   Handle<OrderedHashMap> table,
                                                   int new_capacity) {
  return Base::Rehash(isolate, table, new_capacity);
}

MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Rehash(
    Isolate* isolate, Handle<OrderedNameDictionary> table, int new_capacity) {
  MaybeHandle<OrderedNameDictionary> new_table_candidate =
      Base::Rehash(isolate, table, new_capacity);
  Handle<OrderedNameDictionary> new_table;
  if (new_table_candidate.ToHandle(&new_table)) {
    new_table->SetHash(table->Hash());
  }
  return new_table_candidate;
}

template <class Derived, int entrysize>
bool OrderedHashTable<Derived, entrysize>::Delete(Isolate* isolate,
                                                  Derived table, Object key) {
  DisallowHeapAllocation no_gc;
  InternalIndex entry = table.FindEntry(isolate, key);
  if (entry.is_not_found()) return false;

  int nof = table.NumberOfElements();
  int nod = table.NumberOfDeletedElements();
  int index = table.EntryToIndex(entry);

  Object hole = ReadOnlyRoots(isolate).the_hole_value();
  for (int i = 0; i < entrysize; ++i) {
    table.set(index + i, hole);
  }

  table.SetNumberOfElements(nof - 1);
  table.SetNumberOfDeletedElements(nod + 1);

  return true;
}

// Parameter |roots| only here for compatibility with HashTable<...>::ToKey.
template <class Derived, int entrysize>
bool OrderedHashTable<Derived, entrysize>::ToKey(ReadOnlyRoots roots,
                                                 InternalIndex entry,
                                                 Object* out_key) {
  Object k = KeyAt(entry);
  if (!IsKey(roots, k)) return false;
  *out_key = k;
  return true;
}

Address OrderedHashMap::GetHash(Isolate* isolate, Address raw_key) {
  DisallowHeapAllocation no_gc;
  Object key(raw_key);
  Object hash = key.GetHash();
  // If the object does not have an identity hash, it was never used as a key
  if (hash.IsUndefined(isolate)) return Smi::FromInt(-1).ptr();
  DCHECK(hash.IsSmi());
  DCHECK_GE(Smi::cast(hash).value(), 0);
  return hash.ptr();
}

MaybeHandle<OrderedHashMap> OrderedHashMap::Add(Isolate* isolate,
                                                Handle<OrderedHashMap> table,
                                                Handle<Object> key,
                                                Handle<Object> value) {
  int hash = key->GetOrCreateHash(isolate).value();
  if (table->NumberOfElements() > 0) {
    int raw_entry = table->HashToEntryRaw(hash);
    // Walk the chain of the bucket and try finding the key.
    {
      DisallowHeapAllocation no_gc;
      Object raw_key = *key;
      while (raw_entry != kNotFound) {
        Object candidate_key = table->KeyAt(InternalIndex(raw_entry));
        // Do not add if we have the key already
        if (candidate_key.SameValueZero(raw_key)) return table;
        raw_entry = table->NextChainEntryRaw(raw_entry);
      }
    }
  }

  MaybeHandle<OrderedHashMap> table_candidate =
      OrderedHashMap::EnsureGrowable(isolate, table);
  if (!table_candidate.ToHandle(&table)) {
    return table_candidate;
  }
  // Read the existing bucket values.
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToEntryRaw(hash);
  int nof = table->NumberOfElements();
  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();
  int new_index = table->EntryToIndexRaw(new_entry);
  table->set(new_index, *key);
  table->set(new_index + kValueOffset, *value);
  table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
  // and point the bucket to the new entry.
  table->set(HashTableStartIndex() + bucket, Smi::FromInt(new_entry));
  table->SetNumberOfElements(nof + 1);
  return table;
}

InternalIndex OrderedNameDictionary::FindEntry(Isolate* isolate, Object key) {
  DisallowHeapAllocation no_gc;

  DCHECK(key.IsUniqueName());
  Name raw_key = Name::cast(key);

  if (NumberOfElements() == 0) {
    // This is not just an optimization but also ensures that we do the right
    // thing if Capacity() == 0
    return InternalIndex::NotFound();
  }

  int raw_entry = HashToEntryRaw(raw_key.Hash());
  while (raw_entry != kNotFound) {
    InternalIndex entry(raw_entry);
    Object candidate_key = KeyAt(entry);
    DCHECK(candidate_key.IsTheHole() ||
           Name::cast(candidate_key).IsUniqueName());
    if (candidate_key == raw_key) return entry;

    // TODO(gsathya): This is loading the bucket count from the hash
    // table for every iteration. This should be peeled out of the
    // loop.
    raw_entry = NextChainEntryRaw(raw_entry);
  }

  return InternalIndex::NotFound();
}

// TODO(emrich): This is almost an identical copy of
// Dictionary<..>::SlowReverseLookup.
// Consolidate both versions elsewhere (e.g., hash-table-utils)?
Object OrderedNameDictionary::SlowReverseLookup(Isolate* isolate,
                                                Object value) {
  ReadOnlyRoots roots(isolate);
  for (InternalIndex i : IterateEntries()) {
    Object k;
    if (!ToKey(roots, i, &k)) continue;
    Object e = this->ValueAt(i);
    if (e == value) return k;
  }
  return roots.undefined_value();
}

// TODO(emrich): This is almost an identical copy of
// HashTable<..>::NumberOfEnumerableProperties.
// Consolidate both versions elsewhere (e.g., hash-table-utils)?
int OrderedNameDictionary::NumberOfEnumerableProperties() {
  ReadOnlyRoots roots = this->GetReadOnlyRoots();
  int result = 0;
  for (InternalIndex i : this->IterateEntries()) {
    Object k;
    if (!this->ToKey(roots, i, &k)) continue;
    if (k.FilterKey(ENUMERABLE_STRINGS)) continue;
    PropertyDetails details = this->DetailsAt(i);
    PropertyAttributes attr = details.attributes();
    if ((attr & ONLY_ENUMERABLE) == 0) result++;
  }
  return result;
}

MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Add(
    Isolate* isolate, Handle<OrderedNameDictionary> table, Handle<Name> key,
    Handle<Object> value, PropertyDetails details) {
  DCHECK(table->FindEntry(isolate, *key).is_not_found());

  MaybeHandle<OrderedNameDictionary> table_candidate =
      OrderedNameDictionary::EnsureGrowable(isolate, table);
  if (!table_candidate.ToHandle(&table)) {
    return table_candidate;
  }
  // Read the existing bucket values.
  int hash = key->Hash();
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToEntryRaw(hash);
  int nof = table->NumberOfElements();
  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();
  int new_index = table->EntryToIndexRaw(new_entry);
  table->set(new_index, *key);
  table->set(new_index + kValueOffset, *value);

  // TODO(gsathya): Optimize how PropertyDetails are stored in this
  // dictionary to save memory (by reusing padding?) and performance
  // (by not doing the Smi conversion).
  table->set(new_index + kPropertyDetailsOffset, details.AsSmi());

  table->set(new_index + kChainOffset, Smi::FromInt(previous_entry));
  // and point the bucket to the new entry.
  table->set(HashTableStartIndex() + bucket, Smi::FromInt(new_entry));
  table->SetNumberOfElements(nof + 1);
  return table;
}

void OrderedNameDictionary::SetEntry(InternalIndex entry, Object key,
                                     Object value, PropertyDetails details) {
  DisallowHeapAllocation gc;
  DCHECK_IMPLIES(!key.IsName(), key.IsTheHole());
  DisallowHeapAllocation no_gc;
  int index = EntryToIndex(entry);
  this->set(index, key);
  this->set(index + kValueOffset, value);

  // TODO(gsathya): Optimize how PropertyDetails are stored in this
  // dictionary to save memory (by reusing padding?) and performance
  // (by not doing the Smi conversion).
  this->set(index + kPropertyDetailsOffset, details.AsSmi());
}

Handle<OrderedNameDictionary> OrderedNameDictionary::DeleteEntry(
    Isolate* isolate, Handle<OrderedNameDictionary> table,
    InternalIndex entry) {
  DCHECK(entry.is_found());

  Object hole = ReadOnlyRoots(isolate).the_hole_value();
  PropertyDetails details = PropertyDetails::Empty();
  table->SetEntry(entry, hole, hole, details);

  int nof = table->NumberOfElements();
  table->SetNumberOfElements(nof - 1);
  int nod = table->NumberOfDeletedElements();
  table->SetNumberOfDeletedElements(nod + 1);

  return Shrink(isolate, table);
}

MaybeHandle<OrderedHashSet> OrderedHashSet::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  return Base::Allocate(isolate, capacity, allocation);
}

MaybeHandle<OrderedHashMap> OrderedHashMap::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  return Base::Allocate(isolate, capacity, allocation);
}

MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  MaybeHandle<OrderedNameDictionary> table_candidate =
      Base::Allocate(isolate, capacity, allocation);
  Handle<OrderedNameDictionary> table;
  if (table_candidate.ToHandle(&table)) {
    table->SetHash(PropertyArray::kNoHashSentinel);
  }
  return table_candidate;
}

MaybeHandle<OrderedHashSet> OrderedHashSet::AllocateEmpty(
    Isolate* isolate, AllocationType allocation) {
  RootIndex ri = RootIndex::kEmptyOrderedHashSet;
  return Base::AllocateEmpty(isolate, allocation, ri);
}

MaybeHandle<OrderedHashMap> OrderedHashMap::AllocateEmpty(
    Isolate* isolate, AllocationType allocation) {
  RootIndex ri = RootIndex::kEmptyOrderedHashMap;
  return Base::AllocateEmpty(isolate, allocation, ri);
}

MaybeHandle<OrderedNameDictionary> OrderedNameDictionary::AllocateEmpty(
    Isolate* isolate, AllocationType allocation) {
  RootIndex ri = RootIndex::kEmptyOrderedPropertyDictionary;
  MaybeHandle<OrderedNameDictionary> table_candidate =
      Base::AllocateEmpty(isolate, allocation, ri);
  Handle<OrderedNameDictionary> table;
  if (table_candidate.ToHandle(&table)) {
    table->SetHash(PropertyArray::kNoHashSentinel);
  }

  return table_candidate;
}

template V8_EXPORT_PRIVATE MaybeHandle<OrderedHashSet>
OrderedHashTable<OrderedHashSet, 1>::EnsureGrowable(
    Isolate* isolate, Handle<OrderedHashSet> table);

template V8_EXPORT_PRIVATE Handle<OrderedHashSet>
OrderedHashTable<OrderedHashSet, 1>::Shrink(Isolate* isolate,
                                            Handle<OrderedHashSet> table);

template V8_EXPORT_PRIVATE Handle<OrderedHashSet>
OrderedHashTable<OrderedHashSet, 1>::Clear(Isolate* isolate,
                                           Handle<OrderedHashSet> table);

template V8_EXPORT_PRIVATE bool OrderedHashTable<OrderedHashSet, 1>::HasKey(
    Isolate* isolate, OrderedHashSet table, Object key);

template V8_EXPORT_PRIVATE bool OrderedHashTable<OrderedHashSet, 1>::Delete(
    Isolate* isolate, OrderedHashSet table, Object key);

template V8_EXPORT_PRIVATE InternalIndex
OrderedHashTable<OrderedHashSet, 1>::FindEntry(Isolate* isolate, Object key);

template V8_EXPORT_PRIVATE MaybeHandle<OrderedHashMap>
OrderedHashTable<OrderedHashMap, 2>::EnsureGrowable(
    Isolate* isolate, Handle<OrderedHashMap> table);

template V8_EXPORT_PRIVATE Handle<OrderedHashMap>
OrderedHashTable<OrderedHashMap, 2>::Shrink(Isolate* isolate,
                                            Handle<OrderedHashMap> table);

template V8_EXPORT_PRIVATE Handle<OrderedHashMap>
OrderedHashTable<OrderedHashMap, 2>::Clear(Isolate* isolate,
                                           Handle<OrderedHashMap> table);

template V8_EXPORT_PRIVATE bool OrderedHashTable<OrderedHashMap, 2>::HasKey(
    Isolate* isolate, OrderedHashMap table, Object key);

template V8_EXPORT_PRIVATE bool OrderedHashTable<OrderedHashMap, 2>::Delete(
    Isolate* isolate, OrderedHashMap table, Object key);

template V8_EXPORT_PRIVATE InternalIndex
OrderedHashTable<OrderedHashMap, 2>::FindEntry(Isolate* isolate, Object key);

template V8_EXPORT_PRIVATE Handle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::Shrink(
    Isolate* isolate, Handle<OrderedNameDictionary> table);

template MaybeHandle<OrderedNameDictionary>
OrderedHashTable<OrderedNameDictionary, 3>::EnsureGrowable(
    Isolate* isolate, Handle<OrderedNameDictionary> table);

template <>
Handle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  return isolate->factory()->NewSmallOrderedHashSet(capacity, allocation);
}

template <>
Handle<SmallOrderedHashMap>
SmallOrderedHashTable<SmallOrderedHashMap>::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  return isolate->factory()->NewSmallOrderedHashMap(capacity, allocation);
}

template <>
Handle<SmallOrderedNameDictionary>
SmallOrderedHashTable<SmallOrderedNameDictionary>::Allocate(
    Isolate* isolate, int capacity, AllocationType allocation) {
  return isolate->factory()->NewSmallOrderedNameDictionary(capacity,
                                                           allocation);
}

template <class Derived>
void SmallOrderedHashTable<Derived>::Initialize(Isolate* isolate,
                                                int capacity) {
  DisallowHeapAllocation no_gc;
  int num_buckets = capacity / kLoadFactor;
  int num_chains = capacity;

  SetNumberOfBuckets(num_buckets);
  SetNumberOfElements(0);
  SetNumberOfDeletedElements(0);
  memset(reinterpret_cast<void*>(field_address(PaddingOffset())), 0,
         PaddingSize());

  Address hashtable_start = GetHashTableStartAddress(capacity);
  memset(reinterpret_cast<byte*>(hashtable_start), kNotFound,
         num_buckets + num_chains);

  if (Heap::InYoungGeneration(*this)) {
    MemsetTagged(RawField(DataTableStartOffset()),
                 ReadOnlyRoots(isolate).the_hole_value(),
                 capacity * Derived::kEntrySize);
  } else {
    for (int i = 0; i < capacity; i++) {
      for (int j = 0; j < Derived::kEntrySize; j++) {
        SetDataEntry(i, j, ReadOnlyRoots(isolate).the_hole_value());
      }
    }
  }

#ifdef DEBUG
  for (int i = 0; i < num_buckets; ++i) {
    DCHECK_EQ(kNotFound, GetFirstEntry(i));
  }

  for (int i = 0; i < num_chains; ++i) {
    DCHECK_EQ(kNotFound, GetNextEntry(i));
  }

  for (int i = 0; i < capacity; ++i) {
    for (int j = 0; j < Derived::kEntrySize; j++) {
      DCHECK_EQ(ReadOnlyRoots(isolate).the_hole_value(), GetDataEntry(i, j));
    }
  }
#endif  // DEBUG
}

MaybeHandle<SmallOrderedHashSet> SmallOrderedHashSet::Add(
    Isolate* isolate, Handle<SmallOrderedHashSet> table, Handle<Object> key) {
  if (table->HasKey(isolate, key)) return table;

  if (table->UsedCapacity() >= table->Capacity()) {
    MaybeHandle<SmallOrderedHashSet> new_table =
        SmallOrderedHashSet::Grow(isolate, table);
    if (!new_table.ToHandle(&table)) {
      return MaybeHandle<SmallOrderedHashSet>();
    }
  }

  int hash = key->GetOrCreateHash(isolate).value();
  int nof = table->NumberOfElements();

  // Read the existing bucket values.
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToFirstEntry(hash);

  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();

  table->SetDataEntry(new_entry, SmallOrderedHashSet::kKeyIndex, *key);
  table->SetFirstEntry(bucket, new_entry);
  table->SetNextEntry(new_entry, previous_entry);

  // and update book keeping.
  table->SetNumberOfElements(nof + 1);

  return table;
}

bool SmallOrderedHashSet::Delete(Isolate* isolate, SmallOrderedHashSet table,
                                 Object key) {
  return SmallOrderedHashTable<SmallOrderedHashSet>::Delete(isolate, table,
                                                            key);
}

bool SmallOrderedHashSet::HasKey(Isolate* isolate, Handle<Object> key) {
  return SmallOrderedHashTable<SmallOrderedHashSet>::HasKey(isolate, key);
}

MaybeHandle<SmallOrderedHashMap> SmallOrderedHashMap::Add(
    Isolate* isolate, Handle<SmallOrderedHashMap> table, Handle<Object> key,
    Handle<Object> value) {
  if (table->HasKey(isolate, key)) return table;

  if (table->UsedCapacity() >= table->Capacity()) {
    MaybeHandle<SmallOrderedHashMap> new_table =
        SmallOrderedHashMap::Grow(isolate, table);
    if (!new_table.ToHandle(&table)) {
      return MaybeHandle<SmallOrderedHashMap>();
    }
  }

  int hash = key->GetOrCreateHash(isolate).value();
  int nof = table->NumberOfElements();

  // Read the existing bucket values.
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToFirstEntry(hash);

  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();

  table->SetDataEntry(new_entry, SmallOrderedHashMap::kValueIndex, *value);
  table->SetDataEntry(new_entry, SmallOrderedHashMap::kKeyIndex, *key);
  table->SetFirstEntry(bucket, new_entry);
  table->SetNextEntry(new_entry, previous_entry);

  // and update book keeping.
  table->SetNumberOfElements(nof + 1);

  return table;
}

bool SmallOrderedHashMap::Delete(Isolate* isolate, SmallOrderedHashMap table,
                                 Object key) {
  return SmallOrderedHashTable<SmallOrderedHashMap>::Delete(isolate, table,
                                                            key);
}

bool SmallOrderedHashMap::HasKey(Isolate* isolate, Handle<Object> key) {
  return SmallOrderedHashTable<SmallOrderedHashMap>::HasKey(isolate, key);
}

template <>
InternalIndex V8_EXPORT_PRIVATE
SmallOrderedHashTable<SmallOrderedNameDictionary>::FindEntry(Isolate* isolate,
                                                             Object key) {
  DisallowHeapAllocation no_gc;
  DCHECK(key.IsUniqueName());
  Name raw_key = Name::cast(key);

  int raw_entry = HashToFirstEntry(raw_key.Hash());

  // Walk the chain in the bucket to find the key.
  while (raw_entry != kNotFound) {
    InternalIndex entry(raw_entry);
    Object candidate_key = KeyAt(entry);
    if (candidate_key == key) return entry;
    raw_entry = GetNextEntry(raw_entry);
  }

  return InternalIndex::NotFound();
}

MaybeHandle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Add(
    Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
    Handle<Name> key, Handle<Object> value, PropertyDetails details) {
  DCHECK(table->FindEntry(isolate, *key).is_not_found());

  if (table->UsedCapacity() >= table->Capacity()) {
    MaybeHandle<SmallOrderedNameDictionary> new_table =
        SmallOrderedNameDictionary::Grow(isolate, table);
    if (!new_table.ToHandle(&table)) {
      return MaybeHandle<SmallOrderedNameDictionary>();
    }
  }

  int nof = table->NumberOfElements();

  // Read the existing bucket values.
  int hash = key->Hash();
  int bucket = table->HashToBucket(hash);
  int previous_entry = table->HashToFirstEntry(hash);

  // Insert a new entry at the end,
  int new_entry = nof + table->NumberOfDeletedElements();

  table->SetDataEntry(new_entry, SmallOrderedNameDictionary::kValueIndex,
                      *value);
  table->SetDataEntry(new_entry, SmallOrderedNameDictionary::kKeyIndex, *key);

  // TODO(gsathya): PropertyDetails should be stored as part of the
  // data table to save more memory.
  table->SetDataEntry(new_entry,
                      SmallOrderedNameDictionary::kPropertyDetailsIndex,
                      details.AsSmi());
  table->SetFirstEntry(bucket, new_entry);
  table->SetNextEntry(new_entry, previous_entry);

  // and update book keeping.
  table->SetNumberOfElements(nof + 1);

  return table;
}

void SmallOrderedNameDictionary::SetEntry(InternalIndex entry, Object key,
                                          Object value,
                                          PropertyDetails details) {
  int raw_entry = entry.as_int();
  DCHECK_IMPLIES(!key.IsName(), key.IsTheHole());
  SetDataEntry(raw_entry, SmallOrderedNameDictionary::kValueIndex, value);
  SetDataEntry(raw_entry, SmallOrderedNameDictionary::kKeyIndex, key);

  // TODO(gsathya): PropertyDetails should be stored as part of the
  // data table to save more memory.
  SetDataEntry(raw_entry, SmallOrderedNameDictionary::kPropertyDetailsIndex,
               details.AsSmi());
}

template <class Derived>
bool SmallOrderedHashTable<Derived>::HasKey(Isolate* isolate,
                                            Handle<Object> key) {
  DisallowHeapAllocation no_gc;
  return FindEntry(isolate, *key).is_found();
}

template <class Derived>
bool SmallOrderedHashTable<Derived>::Delete(Isolate* isolate, Derived table,
                                            Object key) {
  DisallowHeapAllocation no_gc;
  InternalIndex entry = table.FindEntry(isolate, key);
  if (entry.is_not_found()) return false;

  int nof = table.NumberOfElements();
  int nod = table.NumberOfDeletedElements();

  Object hole = ReadOnlyRoots(isolate).the_hole_value();
  for (int j = 0; j < Derived::kEntrySize; j++) {
    table.SetDataEntry(entry.as_int(), j, hole);
  }

  table.SetNumberOfElements(nof - 1);
  table.SetNumberOfDeletedElements(nod + 1);

  return true;
}

Handle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::DeleteEntry(
    Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
    InternalIndex entry) {
  DCHECK(entry.is_found());
  {
    DisallowHeapAllocation no_gc;
    Object hole = ReadOnlyRoots(isolate).the_hole_value();
    PropertyDetails details = PropertyDetails::Empty();
    table->SetEntry(entry, hole, hole, details);

    int nof = table->NumberOfElements();
    table->SetNumberOfElements(nof - 1);
    int nod = table->NumberOfDeletedElements();
    table->SetNumberOfDeletedElements(nod + 1);
  }
  return Shrink(isolate, table);
}

template <class Derived>
Handle<Derived> SmallOrderedHashTable<Derived>::Rehash(Isolate* isolate,
                                                       Handle<Derived> table,
                                                       int new_capacity) {
  DCHECK_GE(kMaxCapacity, new_capacity);

  Handle<Derived> new_table = SmallOrderedHashTable<Derived>::Allocate(
      isolate, new_capacity,
      Heap::InYoungGeneration(*table) ? AllocationType::kYoung
                                      : AllocationType::kOld);
  int new_entry = 0;

  {
    DisallowHeapAllocation no_gc;
    for (InternalIndex old_entry : table->IterateEntries()) {
      Object key = table->KeyAt(old_entry);
      if (key.IsTheHole(isolate)) continue;

      int hash = Smi::ToInt(key.GetHash());
      int bucket = new_table->HashToBucket(hash);
      int chain = new_table->GetFirstEntry(bucket);

      new_table->SetFirstEntry(bucket, new_entry);
      new_table->SetNextEntry(new_entry, chain);

      for (int i = 0; i < Derived::kEntrySize; ++i) {
        Object value = table->GetDataEntry(old_entry.as_int(), i);
        new_table->SetDataEntry(new_entry, i, value);
      }

      ++new_entry;
    }

    new_table->SetNumberOfElements(table->NumberOfElements());
  }
  return new_table;
}

Handle<SmallOrderedHashSet> SmallOrderedHashSet::Rehash(
    Isolate* isolate, Handle<SmallOrderedHashSet> table, int new_capacity) {
  return SmallOrderedHashTable<SmallOrderedHashSet>::Rehash(isolate, table,
                                                            new_capacity);
}

Handle<SmallOrderedHashMap> SmallOrderedHashMap::Rehash(
    Isolate* isolate, Handle<SmallOrderedHashMap> table, int new_capacity) {
  return SmallOrderedHashTable<SmallOrderedHashMap>::Rehash(isolate, table,
                                                            new_capacity);
}

Handle<SmallOrderedNameDictionary> SmallOrderedNameDictionary::Rehash(
    Isolate* isolate, Handle<SmallOrderedNameDictionary> table,
    int new_capacity) {
  Handle<SmallOrderedNameDictionary> new_table =
      SmallOrderedHashTable<SmallOrderedNameDictionary>::Rehash(isolate, table,
                                                                new_capacity);
  new_table->SetHash(table->Hash());
  return new_table;
}

template <class Derived>
Handle<Derived> SmallOrderedHashTable<Derived>::Shrink(Isolate* isolate,
                                                       Handle<Derived> table) {
  int nof = table->NumberOfElements();
  int capacity = table->Capacity();
  if (nof >= (capacity >> 2)) return table;
  return Derived::Rehash(isolate, table, capacity / 2);
}

template <class Derived>
MaybeHandle<Derived> SmallOrderedHashTable<Derived>::Grow(
    Isolate* isolate, Handle<Derived> table) {
  int capacity = table->Capacity();
  int new_capacity = capacity;

  // Don't need to grow if we can simply clear out deleted entries instead.
  // TODO(gsathya): Compact in place, instead of allocating a new table.
  if (table->NumberOfDeletedElements() < (capacity >> 1)) {
    new_capacity = capacity << 1;

    // The max capacity of our table is 254. We special case for 256 to
    // account for our growth strategy, otherwise we would only fill up
    // to 128 entries in our table.
    if (new_capacity == kGrowthHack) {
      new_capacity = kMaxCapacity;
    }

    // We need to migrate to a bigger hash table.
    if (new_capacity > kMaxCapacity) {
      return MaybeHandle<Derived>();
    }
  }

  return Derived::Rehash(isolate, table, new_capacity);
}

template <class Derived>
InternalIndex SmallOrderedHashTable<Derived>::FindEntry(Isolate* isolate,
                                                        Object key) {
  DisallowHeapAllocation no_gc;
  Object hash = key.GetHash();

  if (hash.IsUndefined(isolate)) return InternalIndex::NotFound();
  int raw_entry = HashToFirstEntry(Smi::ToInt(hash));

  // Walk the chain in the bucket to find the key.
  while (raw_entry != kNotFound) {
    InternalIndex entry(raw_entry);
    Object candidate_key = KeyAt(entry);
    if (candidate_key.SameValueZero(key)) return entry;
    raw_entry = GetNextEntry(raw_entry);
  }
  return InternalIndex::NotFound();
}

template bool EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
    SmallOrderedHashTable<SmallOrderedHashSet>::HasKey(Isolate* isolate,
                                                       Handle<Object> key);
template V8_EXPORT_PRIVATE Handle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Rehash(
    Isolate* isolate, Handle<SmallOrderedHashSet> table, int new_capacity);
template V8_EXPORT_PRIVATE Handle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Shrink(
    Isolate* isolate, Handle<SmallOrderedHashSet> table);
template V8_EXPORT_PRIVATE MaybeHandle<SmallOrderedHashSet>
SmallOrderedHashTable<SmallOrderedHashSet>::Grow(
    Isolate* isolate, Handle<SmallOrderedHashSet> table);
template V8_EXPORT_PRIVATE void
SmallOrderedHashTable<SmallOrderedHashSet>::Initialize(Isolate* isolate,
                                                       int capacity);
template V8_EXPORT_PRIVATE bool
SmallOrderedHashTable<SmallOrderedHashSet>::Delete(Isolate* isolate,
                                                   SmallOrderedHashSet table,
                                                   Object key);

template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) bool SmallOrderedHashTable<
    SmallOrderedHashMap>::HasKey(Isolate* isolate, Handle<Object> key);
template V8_EXPORT_PRIVATE Handle<SmallOrderedHashMap>
SmallOrderedHashTable<SmallOrderedHashMap>::Rehash(
    Isolate* isolate, Handle<SmallOrderedHashMap> table, int new_capacity);
template V8_EXPORT_PRIVATE Handle<SmallOrderedHashMap>
SmallOrderedHashTable<SmallOrderedHashMap>::Shrink(
    Isolate* isolate, Handle<SmallOrderedHashMap> table);
template V8_EXPORT_PRIVATE MaybeHandle<SmallOrderedHashMap>
SmallOrderedHashTable<SmallOrderedHashMap>::Grow(
    Isolate* isolate, Handle<SmallOrderedHashMap> table);
template V8_EXPORT_PRIVATE void
SmallOrderedHashTable<SmallOrderedHashMap>::Initialize(Isolate* isolate,
                                                       int capacity);

template V8_EXPORT_PRIVATE bool
SmallOrderedHashTable<SmallOrderedHashMap>::Delete(Isolate* isolate,
                                                   SmallOrderedHashMap table,
                                                   Object key);

template V8_EXPORT_PRIVATE void
SmallOrderedHashTable<SmallOrderedNameDictionary>::Initialize(Isolate* isolate,
                                                              int capacity);
template V8_EXPORT_PRIVATE Handle<SmallOrderedNameDictionary>
SmallOrderedHashTable<SmallOrderedNameDictionary>::Shrink(
    Isolate* isolate, Handle<SmallOrderedNameDictionary> table);

template <class SmallTable, class LargeTable>
MaybeHandle<HeapObject>
OrderedHashTableHandler<SmallTable, LargeTable>::Allocate(Isolate* isolate,
                                                          int capacity) {
  if (capacity < SmallTable::kMaxCapacity) {
    return SmallTable::Allocate(isolate, capacity);
  }

  return LargeTable::Allocate(isolate, capacity);
}

template V8_EXPORT_PRIVATE MaybeHandle<HeapObject>
OrderedHashTableHandler<SmallOrderedHashSet, OrderedHashSet>::Allocate(
    Isolate* isolate, int capacity);
template V8_EXPORT_PRIVATE MaybeHandle<HeapObject>
OrderedHashTableHandler<SmallOrderedHashMap, OrderedHashMap>::Allocate(
    Isolate* isolate, int capacity);
template V8_EXPORT_PRIVATE MaybeHandle<HeapObject>
OrderedHashTableHandler<SmallOrderedNameDictionary,
                        OrderedNameDictionary>::Allocate(Isolate* isolate,
                                                         int capacity);

template <class SmallTable, class LargeTable>
bool OrderedHashTableHandler<SmallTable, LargeTable>::Delete(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key) {
  if (SmallTable::Is(table)) {
    return SmallTable::Delete(isolate, *Handle<SmallTable>::cast(table), *key);
  }

  DCHECK(LargeTable::Is(table));
  // Note: Once we migrate to the a big hash table, we never migrate
  // down to a smaller hash table.
  return LargeTable::Delete(isolate, *Handle<LargeTable>::cast(table), *key);
}

template <class SmallTable, class LargeTable>
bool OrderedHashTableHandler<SmallTable, LargeTable>::HasKey(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key) {
  if (SmallTable::Is(table)) {
    return Handle<SmallTable>::cast(table)->HasKey(isolate, key);
  }

  DCHECK(LargeTable::Is(table));
  return LargeTable::HasKey(isolate, LargeTable::cast(*table), *key);
}

template bool
OrderedHashTableHandler<SmallOrderedHashSet, OrderedHashSet>::HasKey(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key);
template bool
OrderedHashTableHandler<SmallOrderedHashMap, OrderedHashMap>::HasKey(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key);

template bool
OrderedHashTableHandler<SmallOrderedHashSet, OrderedHashSet>::Delete(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key);
template bool
OrderedHashTableHandler<SmallOrderedHashMap, OrderedHashMap>::Delete(
    Isolate* isolate, Handle<HeapObject> table, Handle<Object> key);
template bool
OrderedHashTableHandler<SmallOrderedNameDictionary,
                        OrderedNameDictionary>::Delete(Isolate* isolate,
                                                       Handle<HeapObject> table,
                                                       Handle<Object> key);

MaybeHandle<OrderedHashMap> OrderedHashMapHandler::AdjustRepresentation(
    Isolate* isolate, Handle<SmallOrderedHashMap> table) {
  MaybeHandle<OrderedHashMap> new_table_candidate =
      OrderedHashMap::Allocate(isolate, OrderedHashTableMinSize);
  Handle<OrderedHashMap> new_table;
  if (!new_table_candidate.ToHandle(&new_table)) {
    return new_table_candidate;
  }

  // TODO(gsathya): Optimize the lookup to not re calc offsets. Also,
  // unhandlify this code as we preallocate the new backing store with
  // the proper capacity.
  for (InternalIndex entry : table->IterateEntries()) {
    Handle<Object> key = handle(table->KeyAt(entry), isolate);
    if (key->IsTheHole(isolate)) continue;
    Handle<Object> value = handle(
        table->GetDataEntry(entry.as_int(), SmallOrderedHashMap::kValueIndex),
        isolate);
    new_table_candidate = OrderedHashMap::Add(isolate, new_table, key, value);
    if (!new_table_candidate.ToHandle(&new_table)) {
      return new_table_candidate;
    }
  }

  return new_table_candidate;
}

MaybeHandle<OrderedHashSet> OrderedHashSetHandler::AdjustRepresentation(
    Isolate* isolate, Handle<SmallOrderedHashSet> table) {
  MaybeHandle<OrderedHashSet> new_table_candidate =
      OrderedHashSet::Allocate(isolate, OrderedHashTableMinSize);
  Handle<OrderedHashSet> new_table;
  if (!new_table_candidate.ToHandle(&new_table)) {
    return new_table_candidate;
  }

  // TODO(gsathya): Optimize the lookup to not re calc offsets. Also,
  // unhandlify this code as we preallocate the new backing store with
  // the proper capacity.
  for (InternalIndex entry : table->IterateEntries()) {
    Handle<Object> key = handle(table->KeyAt(entry), isolate);
    if (key->IsTheHole(isolate)) continue;
    new_table_candidate = OrderedHashSet::Add(isolate, new_table, key);
    if (!new_table_candidate.ToHandle(&new_table)) {
      return new_table_candidate;
    }
  }

  return new_table_candidate;
}

MaybeHandle<OrderedNameDictionary>
OrderedNameDictionaryHandler::AdjustRepresentation(
    Isolate* isolate, Handle<SmallOrderedNameDictionary> table) {
  MaybeHandle<OrderedNameDictionary> new_table_candidate =
      OrderedNameDictionary::Allocate(isolate, OrderedHashTableMinSize);
  Handle<OrderedNameDictionary> new_table;
  if (!new_table_candidate.ToHandle(&new_table)) {
    return new_table_candidate;
  }

  // TODO(gsathya): Optimize the lookup to not re calc offsets. Also,
  // unhandlify this code as we preallocate the new backing store with
  // the proper capacity.
  for (InternalIndex entry : table->IterateEntries()) {
    Handle<Name> key(Name::cast(table->KeyAt(entry)), isolate);
    if (key->IsTheHole(isolate)) continue;
    Handle<Object> value(table->ValueAt(entry), isolate);
    PropertyDetails details = table->DetailsAt(entry);
    new_table_candidate =
        OrderedNameDictionary::Add(isolate, new_table, key, value, details);
    if (!new_table_candidate.ToHandle(&new_table)) {
      return new_table_candidate;
    }
  }

  return new_table_candidate;
}

MaybeHandle<HeapObject> OrderedHashMapHandler::Add(Isolate* isolate,
                                                   Handle<HeapObject> table,
                                                   Handle<Object> key,
                                                   Handle<Object> value) {
  if (table->IsSmallOrderedHashMap()) {
    Handle<SmallOrderedHashMap> small_map =
        Handle<SmallOrderedHashMap>::cast(table);
    MaybeHandle<SmallOrderedHashMap> new_map =
        SmallOrderedHashMap::Add(isolate, small_map, key, value);
    if (!new_map.is_null()) return new_map.ToHandleChecked();

    // We couldn't add to the small table, let's migrate to the
    // big table.
    MaybeHandle<OrderedHashMap> table_candidate =
        OrderedHashMapHandler::AdjustRepresentation(isolate, small_map);
    if (!table_candidate.ToHandle(&table)) {
      return table_candidate;
    }
  }

  DCHECK(table->IsOrderedHashMap());
  return OrderedHashMap::Add(isolate, Handle<OrderedHashMap>::cast(table), key,
                             value);
}

MaybeHandle<HeapObject> OrderedHashSetHandler::Add(Isolate* isolate,
                                                   Handle<HeapObject> table,
                                                   Handle<Object> key) {
  if (table->IsSmallOrderedHashSet()) {
    Handle<SmallOrderedHashSet> small_set =
        Handle<SmallOrderedHashSet>::cast(table);
    MaybeHandle<SmallOrderedHashSet> new_set =
        SmallOrderedHashSet::Add(isolate, small_set, key);
    if (!new_set.is_null()) return new_set.ToHandleChecked();

    // We couldn't add to the small table, let's migrate to the
    // big table.
    MaybeHandle<OrderedHashSet> table_candidate =
        OrderedHashSetHandler::AdjustRepresentation(isolate, small_set);
    if (!table_candidate.ToHandle(&table)) {
      return table_candidate;
    }
  }

  DCHECK(table->IsOrderedHashSet());
  return OrderedHashSet::Add(isolate, Handle<OrderedHashSet>::cast(table), key);
}

MaybeHandle<HeapObject> OrderedNameDictionaryHandler::Add(
    Isolate* isolate, Handle<HeapObject> table, Handle<Name> key,
    Handle<Object> value, PropertyDetails details) {
  if (table->IsSmallOrderedNameDictionary()) {
    Handle<SmallOrderedNameDictionary> small_dict =
        Handle<SmallOrderedNameDictionary>::cast(table);
    MaybeHandle<SmallOrderedNameDictionary> new_dict =
        SmallOrderedNameDictionary::Add(isolate, small_dict, key, value,
                                        details);
    if (!new_dict.is_null()) return new_dict.ToHandleChecked();

    // We couldn't add to the small table, let's migrate to the
    // big table.
    MaybeHandle<OrderedNameDictionary> table_candidate =
        OrderedNameDictionaryHandler::AdjustRepresentation(isolate, small_dict);
    if (!table_candidate.ToHandle(&table)) {
      return table_candidate;
    }
  }

  DCHECK(table->IsOrderedNameDictionary());
  return OrderedNameDictionary::Add(
      isolate, Handle<OrderedNameDictionary>::cast(table), key, value, details);
}

void OrderedNameDictionaryHandler::SetEntry(HeapObject table,
                                            InternalIndex entry, Object key,
                                            Object value,
                                            PropertyDetails details) {
  DisallowHeapAllocation no_gc;
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).SetEntry(entry, key, value,
                                                            details);
  }

  DCHECK(table.IsOrderedNameDictionary());
  return OrderedNameDictionary::cast(table).SetEntry(InternalIndex(entry), key,
                                                     value, details);
}

InternalIndex OrderedNameDictionaryHandler::FindEntry(Isolate* isolate,
                                                      HeapObject table,
                                                      Name key) {
  DisallowHeapAllocation no_gc;
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).FindEntry(isolate, key);
  }

  DCHECK(table.IsOrderedNameDictionary());
  return OrderedNameDictionary::cast(table).FindEntry(isolate, key);
}

Object OrderedNameDictionaryHandler::ValueAt(HeapObject table,
                                             InternalIndex entry) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).ValueAt(entry);
  }

  DCHECK(table.IsOrderedNameDictionary());
  return OrderedNameDictionary::cast(table).ValueAt(entry);
}

void OrderedNameDictionaryHandler::ValueAtPut(HeapObject table,
                                              InternalIndex entry,
                                              Object value) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).ValueAtPut(entry, value);
  }

  DCHECK(table.IsOrderedNameDictionary());
  OrderedNameDictionary::cast(table).ValueAtPut(entry, value);
}

PropertyDetails OrderedNameDictionaryHandler::DetailsAt(HeapObject table,
                                                        InternalIndex entry) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).DetailsAt(entry);
  }

  DCHECK(table.IsOrderedNameDictionary());
  return OrderedNameDictionary::cast(table).DetailsAt(entry);
}

void OrderedNameDictionaryHandler::DetailsAtPut(HeapObject table,
                                                InternalIndex entry,
                                                PropertyDetails details) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).DetailsAtPut(entry, details);
  }

  DCHECK(table.IsOrderedNameDictionary());
  OrderedNameDictionary::cast(table).DetailsAtPut(entry, details);
}

int OrderedNameDictionaryHandler::Hash(HeapObject table) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).Hash();
  }

  DCHECK(table.IsOrderedNameDictionary());
  return OrderedNameDictionary::cast(table).Hash();
}

void OrderedNameDictionaryHandler::SetHash(HeapObject table, int hash) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).SetHash(hash);
  }

  DCHECK(table.IsOrderedNameDictionary());
  OrderedNameDictionary::cast(table).SetHash(hash);
}

Name OrderedNameDictionaryHandler::KeyAt(HeapObject table,
                                         InternalIndex entry) {
  if (table.IsSmallOrderedNameDictionary()) {
    return Name::cast(SmallOrderedNameDictionary::cast(table).KeyAt(entry));
  }

  return Name::cast(
      OrderedNameDictionary::cast(table).KeyAt(InternalIndex(entry)));
}

int OrderedNameDictionaryHandler::NumberOfElements(HeapObject table) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).NumberOfElements();
  }

  return OrderedNameDictionary::cast(table).NumberOfElements();
}

int OrderedNameDictionaryHandler::Capacity(HeapObject table) {
  if (table.IsSmallOrderedNameDictionary()) {
    return SmallOrderedNameDictionary::cast(table).Capacity();
  }

  return OrderedNameDictionary::cast(table).Capacity();
}

Handle<HeapObject> OrderedNameDictionaryHandler::Shrink(
    Isolate* isolate, Handle<HeapObject> table) {
  if (table->IsSmallOrderedNameDictionary()) {
    Handle<SmallOrderedNameDictionary> small_dict =
        Handle<SmallOrderedNameDictionary>::cast(table);
    return SmallOrderedNameDictionary::Shrink(isolate, small_dict);
  }

  Handle<OrderedNameDictionary> large_dict =
      Handle<OrderedNameDictionary>::cast(table);
  return OrderedNameDictionary::Shrink(isolate, large_dict);
}

Handle<HeapObject> OrderedNameDictionaryHandler::DeleteEntry(
    Isolate* isolate, Handle<HeapObject> table, InternalIndex entry) {
  DisallowHeapAllocation no_gc;
  if (table->IsSmallOrderedNameDictionary()) {
    Handle<SmallOrderedNameDictionary> small_dict =
        Handle<SmallOrderedNameDictionary>::cast(table);
    return SmallOrderedNameDictionary::DeleteEntry(isolate, small_dict, entry);
  }

  Handle<OrderedNameDictionary> large_dict =
      Handle<OrderedNameDictionary>::cast(table);
  return OrderedNameDictionary::DeleteEntry(isolate, large_dict,
                                            InternalIndex(entry));
}

template <class Derived, class TableType>
void OrderedHashTableIterator<Derived, TableType>::Transition() {
  DisallowHeapAllocation no_allocation;
  TableType table = TableType::cast(this->table());
  if (!table.IsObsolete()) return;

  int index = Smi::ToInt(this->index());
  DCHECK_LE(0, index);
  while (table.IsObsolete()) {
    TableType next_table = table.NextTable();

    if (index > 0) {
      int nod = table.NumberOfDeletedElements();

      if (nod == TableType::kClearedTableSentinel) {
        index = 0;
      } else {
        int old_index = index;
        for (int i = 0; i < nod; ++i) {
          int removed_index = table.RemovedIndexAt(i);
          if (removed_index >= old_index) break;
          --index;
        }
      }
    }

    table = next_table;
  }

  set_table(table);
  set_index(Smi::FromInt(index));
}

template <class Derived, class TableType>
bool OrderedHashTableIterator<Derived, TableType>::HasMore() {
  DisallowHeapAllocation no_allocation;
  ReadOnlyRoots ro_roots = GetReadOnlyRoots();

  Transition();

  TableType table = TableType::cast(this->table());
  int index = Smi::ToInt(this->index());
  int used_capacity = table.UsedCapacity();

  while (index < used_capacity &&
         table.KeyAt(InternalIndex(index)).IsTheHole(ro_roots)) {
    index++;
  }

  set_index(Smi::FromInt(index));

  if (index < used_capacity) return true;

  set_table(TableType::GetEmpty(ro_roots));
  return false;
}

template bool
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::HasMore();

template void
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::MoveNext();

template Object
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::CurrentKey();

template void
OrderedHashTableIterator<JSSetIterator, OrderedHashSet>::Transition();

template bool
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::HasMore();

template void
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::MoveNext();

template Object
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::CurrentKey();

template void
OrderedHashTableIterator<JSMapIterator, OrderedHashMap>::Transition();

}  // namespace internal
}  // namespace v8
