// 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.

#ifndef V8_OBJECTS_DICTIONARY_INL_H_
#define V8_OBJECTS_DICTIONARY_INL_H_

#include "src/execution/isolate-utils-inl.h"
#include "src/numbers/hash-seed-inl.h"
#include "src/objects/dictionary.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/oddball.h"
#include "src/objects/property-cell-inl.h"

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {

CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(NameDictionary)
CAST_ACCESSOR(NumberDictionary)
CAST_ACCESSOR(SimpleNumberDictionary)

template <typename Derived, typename Shape>
Dictionary<Derived, Shape>::Dictionary(Address ptr)
    : HashTable<Derived, Shape>(ptr) {}

template <typename Derived, typename Shape>
Object Dictionary<Derived, Shape>::ValueAt(InternalIndex entry) {
  IsolateRoot isolate = GetIsolateForPtrCompr(*this);
  return ValueAt(isolate, entry);
}

template <typename Derived, typename Shape>
Object Dictionary<Derived, Shape>::ValueAt(IsolateRoot isolate,
                                           InternalIndex entry) {
  return this->get(isolate, DerivedHashTable::EntryToIndex(entry) +
                                Derived::kEntryValueIndex);
}

template <typename Derived, typename Shape>
void Dictionary<Derived, Shape>::ValueAtPut(InternalIndex entry, Object value) {
  this->set(DerivedHashTable::EntryToIndex(entry) + Derived::kEntryValueIndex,
            value);
}

template <typename Derived, typename Shape>
PropertyDetails Dictionary<Derived, Shape>::DetailsAt(InternalIndex entry) {
  return Shape::DetailsAt(Derived::cast(*this), entry);
}

template <typename Derived, typename Shape>
void Dictionary<Derived, Shape>::DetailsAtPut(InternalIndex entry,
                                              PropertyDetails value) {
  Shape::DetailsAtPut(Derived::cast(*this), entry, value);
}

template <typename Derived, typename Shape>
BaseNameDictionary<Derived, Shape>::BaseNameDictionary(Address ptr)
    : Dictionary<Derived, Shape>(ptr) {}

template <typename Derived, typename Shape>
void BaseNameDictionary<Derived, Shape>::set_next_enumeration_index(int index) {
  DCHECK_LT(0, index);
  this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
}

template <typename Derived, typename Shape>
int BaseNameDictionary<Derived, Shape>::next_enumeration_index() {
  return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
}

template <typename Derived, typename Shape>
void BaseNameDictionary<Derived, Shape>::SetHash(int hash) {
  DCHECK(PropertyArray::HashField::is_valid(hash));
  this->set(kObjectHashIndex, Smi::FromInt(hash));
}

template <typename Derived, typename Shape>
int BaseNameDictionary<Derived, Shape>::Hash() const {
  Object hash_obj = this->get(kObjectHashIndex);
  int hash = Smi::ToInt(hash_obj);
  DCHECK(PropertyArray::HashField::is_valid(hash));
  return hash;
}

GlobalDictionary::GlobalDictionary(Address ptr)
    : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>(ptr) {
  SLOW_DCHECK(IsGlobalDictionary());
}

NameDictionary::NameDictionary(Address ptr)
    : BaseNameDictionary<NameDictionary, NameDictionaryShape>(ptr) {
  SLOW_DCHECK(IsNameDictionary());
}

NumberDictionary::NumberDictionary(Address ptr)
    : Dictionary<NumberDictionary, NumberDictionaryShape>(ptr) {
  SLOW_DCHECK(IsNumberDictionary());
}

SimpleNumberDictionary::SimpleNumberDictionary(Address ptr)
    : Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>(ptr) {
  SLOW_DCHECK(IsSimpleNumberDictionary());
}

bool NumberDictionary::requires_slow_elements() {
  Object max_index_object = get(kMaxNumberKeyIndex);
  if (!max_index_object.IsSmi()) return false;
  return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask);
}

uint32_t NumberDictionary::max_number_key() {
  DCHECK(!requires_slow_elements());
  Object max_index_object = get(kMaxNumberKeyIndex);
  if (!max_index_object.IsSmi()) return 0;
  uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object));
  return value >> kRequiresSlowElementsTagSize;
}

void NumberDictionary::set_requires_slow_elements() {
  set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
}

template <typename Derived, typename Shape>
void Dictionary<Derived, Shape>::ClearEntry(InternalIndex entry) {
  Object the_hole = this->GetReadOnlyRoots().the_hole_value();
  PropertyDetails details = PropertyDetails::Empty();
  Derived::cast(*this).SetEntry(entry, the_hole, the_hole, details);
}

template <typename Derived, typename Shape>
void Dictionary<Derived, Shape>::SetEntry(InternalIndex entry, Object key,
                                          Object value,
                                          PropertyDetails details) {
  DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
  DCHECK(!key.IsName() || details.dictionary_index() > 0);
  int index = DerivedHashTable::EntryToIndex(entry);
  DisallowHeapAllocation no_gc;
  WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc);
  this->set(index + Derived::kEntryKeyIndex, key, mode);
  this->set(index + Derived::kEntryValueIndex, value, mode);
  if (Shape::kHasDetails) DetailsAtPut(entry, details);
}

template <typename Derived, typename Shape>
ObjectSlot Dictionary<Derived, Shape>::RawFieldOfValueAt(InternalIndex entry) {
  return this->RawFieldOfElementAt(DerivedHashTable::EntryToIndex(entry) +
                                   Derived::kEntryValueIndex);
}

template <typename Key>
template <typename Dictionary>
PropertyDetails BaseDictionaryShape<Key>::DetailsAt(Dictionary dict,
                                                    InternalIndex entry) {
  STATIC_ASSERT(Dictionary::kEntrySize == 3);
  DCHECK(entry.is_found());
  return PropertyDetails(Smi::cast(dict.get(Dictionary::EntryToIndex(entry) +
                                            Dictionary::kEntryDetailsIndex)));
}

template <typename Key>
template <typename Dictionary>
void BaseDictionaryShape<Key>::DetailsAtPut(Dictionary dict,
                                            InternalIndex entry,
                                            PropertyDetails value) {
  STATIC_ASSERT(Dictionary::kEntrySize == 3);
  dict.set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
           value.AsSmi());
}

Object GlobalDictionaryShape::Unwrap(Object object) {
  return PropertyCell::cast(object).name();
}

Handle<Map> GlobalDictionary::GetMap(ReadOnlyRoots roots) {
  return roots.global_dictionary_map_handle();
}

Name NameDictionary::NameAt(InternalIndex entry) {
  IsolateRoot isolate = GetIsolateForPtrCompr(*this);
  return NameAt(isolate, entry);
}

Name NameDictionary::NameAt(IsolateRoot isolate, InternalIndex entry) {
  return Name::cast(KeyAt(isolate, entry));
}

Handle<Map> NameDictionary::GetMap(ReadOnlyRoots roots) {
  return roots.name_dictionary_map_handle();
}

PropertyCell GlobalDictionary::CellAt(InternalIndex entry) {
  IsolateRoot isolate = GetIsolateForPtrCompr(*this);
  return CellAt(isolate, entry);
}

PropertyCell GlobalDictionary::CellAt(IsolateRoot isolate,
                                      InternalIndex entry) {
  DCHECK(KeyAt(isolate, entry).IsPropertyCell(isolate));
  return PropertyCell::cast(KeyAt(isolate, entry));
}

Name GlobalDictionary::NameAt(InternalIndex entry) {
  IsolateRoot isolate = GetIsolateForPtrCompr(*this);
  return NameAt(isolate, entry);
}

Name GlobalDictionary::NameAt(IsolateRoot isolate, InternalIndex entry) {
  return CellAt(isolate, entry).name(isolate);
}

Object GlobalDictionary::ValueAt(InternalIndex entry) {
  IsolateRoot isolate = GetIsolateForPtrCompr(*this);
  return ValueAt(isolate, entry);
}

Object GlobalDictionary::ValueAt(IsolateRoot isolate, InternalIndex entry) {
  return CellAt(isolate, entry).value(isolate);
}

void GlobalDictionary::SetEntry(InternalIndex entry, Object key, Object value,
                                PropertyDetails details) {
  DCHECK_EQ(key, PropertyCell::cast(value).name());
  set(EntryToIndex(entry) + kEntryKeyIndex, value);
  DetailsAtPut(entry, details);
}

void GlobalDictionary::ClearEntry(InternalIndex entry) {
  Object the_hole = this->GetReadOnlyRoots().the_hole_value();
  set(EntryToIndex(entry) + kEntryKeyIndex, the_hole);
}

void GlobalDictionary::ValueAtPut(InternalIndex entry, Object value) {
  set(EntryToIndex(entry), value);
}

bool NumberDictionaryBaseShape::IsMatch(uint32_t key, Object other) {
  DCHECK(other.IsNumber());
  return key == static_cast<uint32_t>(other.Number());
}

uint32_t NumberDictionaryBaseShape::Hash(ReadOnlyRoots roots, uint32_t key) {
  return ComputeSeededHash(key, HashSeed(roots));
}

uint32_t NumberDictionaryBaseShape::HashForObject(ReadOnlyRoots roots,
                                                  Object other) {
  DCHECK(other.IsNumber());
  return ComputeSeededHash(static_cast<uint32_t>(other.Number()),
                           HashSeed(roots));
}

Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate,
                                                   uint32_t key) {
  return isolate->factory()->NewNumberFromUint(key);
}

Handle<Object> NumberDictionaryBaseShape::AsHandle(LocalIsolate* isolate,
                                                   uint32_t key) {
  return isolate->factory()->NewNumberFromUint<AllocationType::kOld>(key);
}

Handle<Map> NumberDictionary::GetMap(ReadOnlyRoots roots) {
  return roots.number_dictionary_map_handle();
}

Handle<Map> SimpleNumberDictionary::GetMap(ReadOnlyRoots roots) {
  return roots.simple_number_dictionary_map_handle();
}

bool NameDictionaryShape::IsMatch(Handle<Name> key, Object other) {
  DCHECK(other.IsTheHole() || Name::cast(other).IsUniqueName());
  DCHECK(key->IsUniqueName());
  return *key == other;
}

uint32_t NameDictionaryShape::Hash(ReadOnlyRoots roots, Handle<Name> key) {
  return key->Hash();
}

uint32_t NameDictionaryShape::HashForObject(ReadOnlyRoots roots, Object other) {
  return Name::cast(other).Hash();
}

bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object other) {
  DCHECK(PropertyCell::cast(other).name().IsUniqueName());
  return *key == PropertyCell::cast(other).name();
}

uint32_t GlobalDictionaryShape::HashForObject(ReadOnlyRoots roots,
                                              Object other) {
  return PropertyCell::cast(other).name().Hash();
}

Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
                                             Handle<Name> key) {
  DCHECK(key->IsUniqueName());
  return key;
}

Handle<Object> NameDictionaryShape::AsHandle(LocalIsolate* isolate,
                                             Handle<Name> key) {
  DCHECK(key->IsUniqueName());
  return key;
}

template <typename Dictionary>
PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict,
                                                 InternalIndex entry) {
  DCHECK(entry.is_found());
  return dict.CellAt(entry).property_details();
}

template <typename Dictionary>
void GlobalDictionaryShape::DetailsAtPut(Dictionary dict, InternalIndex entry,
                                         PropertyDetails value) {
  DCHECK(entry.is_found());
  PropertyCell cell = dict.CellAt(entry);
  if (cell.property_details().IsReadOnly() != value.IsReadOnly()) {
    cell.dependent_code().DeoptimizeDependentCodeGroup(
        DependentCode::kPropertyCellChangedGroup);
  }
  cell.set_property_details(value);
}

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_DICTIONARY_INL_H_
