1// Copyright 2018 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_OBJECTS_ORDERED_HASH_TABLE_INL_H_
6#define V8_OBJECTS_ORDERED_HASH_TABLE_INL_H_
7
8#include "src/objects/ordered-hash-table.h"
9
10#include "src/heap/heap.h"
11#include "src/objects/compressed-slots.h"
12#include "src/objects/fixed-array-inl.h"
13#include "src/objects/js-collection-iterator.h"
14#include "src/objects/objects-inl.h"
15#include "src/objects/slots.h"
16
17// Has to be the last include (doesn't have include guards):
18#include "src/objects/object-macros.h"
19
20namespace v8 {
21namespace internal {
22
23#include "torque-generated/src/objects/ordered-hash-table-tq-inl.inc"
24
25CAST_ACCESSOR(OrderedNameDictionary)
26CAST_ACCESSOR(SmallOrderedNameDictionary)
27CAST_ACCESSOR(OrderedHashMap)
28CAST_ACCESSOR(OrderedHashSet)
29CAST_ACCESSOR(SmallOrderedHashMap)
30CAST_ACCESSOR(SmallOrderedHashSet)
31
32template <class Derived, int entrysize>
33OrderedHashTable<Derived, entrysize>::OrderedHashTable(Address ptr)
34    : FixedArray(ptr) {}
35
36template <class Derived, int entrysize>
37bool OrderedHashTable<Derived, entrysize>::IsKey(ReadOnlyRoots roots,
38                                                 Object k) {
39  return k != roots.the_hole_value();
40}
41
42OrderedHashSet::OrderedHashSet(Address ptr)
43    : OrderedHashTable<OrderedHashSet, 1>(ptr) {
44  SLOW_DCHECK(IsOrderedHashSet());
45}
46
47OrderedHashMap::OrderedHashMap(Address ptr)
48    : OrderedHashTable<OrderedHashMap, 2>(ptr) {
49  SLOW_DCHECK(IsOrderedHashMap());
50}
51
52OrderedNameDictionary::OrderedNameDictionary(Address ptr)
53    : OrderedHashTable<OrderedNameDictionary, 3>(ptr) {
54  SLOW_DCHECK(IsOrderedNameDictionary());
55}
56
57template <class Derived>
58SmallOrderedHashTable<Derived>::SmallOrderedHashTable(Address ptr)
59    : HeapObject(ptr) {}
60
61template <class Derived>
62Object SmallOrderedHashTable<Derived>::KeyAt(InternalIndex entry) const {
63  DCHECK_LT(entry.as_int(), Capacity());
64  Offset entry_offset = GetDataEntryOffset(entry.as_int(), Derived::kKeyIndex);
65  return TaggedField<Object>::load(*this, entry_offset);
66}
67
68template <class Derived>
69Object SmallOrderedHashTable<Derived>::GetDataEntry(int entry,
70                                                    int relative_index) {
71  DCHECK_LT(entry, Capacity());
72  DCHECK_LE(static_cast<unsigned>(relative_index), Derived::kEntrySize);
73  Offset entry_offset = GetDataEntryOffset(entry, relative_index);
74  return TaggedField<Object>::load(*this, entry_offset);
75}
76
77OBJECT_CONSTRUCTORS_IMPL(SmallOrderedHashSet,
78                         SmallOrderedHashTable<SmallOrderedHashSet>)
79OBJECT_CONSTRUCTORS_IMPL(SmallOrderedHashMap,
80                         SmallOrderedHashTable<SmallOrderedHashMap>)
81OBJECT_CONSTRUCTORS_IMPL(SmallOrderedNameDictionary,
82                         SmallOrderedHashTable<SmallOrderedNameDictionary>)
83
84Handle<Map> OrderedHashSet::GetMap(ReadOnlyRoots roots) {
85  return roots.ordered_hash_set_map_handle();
86}
87
88Handle<Map> OrderedHashMap::GetMap(ReadOnlyRoots roots) {
89  return roots.ordered_hash_map_map_handle();
90}
91
92Handle<Map> OrderedNameDictionary::GetMap(ReadOnlyRoots roots) {
93  return roots.ordered_name_dictionary_map_handle();
94}
95
96Handle<Map> SmallOrderedNameDictionary::GetMap(ReadOnlyRoots roots) {
97  return roots.small_ordered_name_dictionary_map_handle();
98}
99
100Handle<Map> SmallOrderedHashMap::GetMap(ReadOnlyRoots roots) {
101  return roots.small_ordered_hash_map_map_handle();
102}
103
104Handle<Map> SmallOrderedHashSet::GetMap(ReadOnlyRoots roots) {
105  return roots.small_ordered_hash_set_map_handle();
106}
107
108inline Object OrderedHashMap::ValueAt(InternalIndex entry) {
109  DCHECK_LT(entry.as_int(), UsedCapacity());
110  return get(EntryToIndex(entry) + kValueOffset);
111}
112
113inline Object OrderedNameDictionary::ValueAt(InternalIndex entry) {
114  DCHECK_LT(entry.as_int(), UsedCapacity());
115  return get(EntryToIndex(entry) + kValueOffset);
116}
117
118Name OrderedNameDictionary::NameAt(InternalIndex entry) {
119  return Name::cast(KeyAt(entry));
120}
121
122// Parameter |roots| only here for compatibility with HashTable<...>::ToKey.
123template <class Derived, int entrysize>
124bool OrderedHashTable<Derived, entrysize>::ToKey(ReadOnlyRoots roots,
125                                                 InternalIndex entry,
126                                                 Object* out_key) {
127  Object k = KeyAt(entry);
128  if (!IsKey(roots, k)) return false;
129  *out_key = k;
130  return true;
131}
132
133// Set the value for entry.
134inline void OrderedNameDictionary::ValueAtPut(InternalIndex entry,
135                                              Object value) {
136  DCHECK_LT(entry.as_int(), UsedCapacity());
137  this->set(EntryToIndex(entry) + kValueOffset, value);
138}
139
140// Returns the property details for the property at entry.
141inline PropertyDetails OrderedNameDictionary::DetailsAt(InternalIndex entry) {
142  DCHECK_LT(entry.as_int(), this->UsedCapacity());
143  // TODO(gsathya): Optimize the cast away.
144  return PropertyDetails(
145      Smi::cast(get(EntryToIndex(entry) + kPropertyDetailsOffset)));
146}
147
148inline void OrderedNameDictionary::DetailsAtPut(InternalIndex entry,
149                                                PropertyDetails value) {
150  DCHECK_LT(entry.as_int(), this->UsedCapacity());
151  // TODO(gsathya): Optimize the cast away.
152  this->set(EntryToIndex(entry) + kPropertyDetailsOffset, value.AsSmi());
153}
154
155inline Object SmallOrderedNameDictionary::ValueAt(InternalIndex entry) {
156  return this->GetDataEntry(entry.as_int(), kValueIndex);
157}
158
159// Set the value for entry.
160inline void SmallOrderedNameDictionary::ValueAtPut(InternalIndex entry,
161                                                   Object value) {
162  this->SetDataEntry(entry.as_int(), kValueIndex, value);
163}
164
165// Returns the property details for the property at entry.
166inline PropertyDetails SmallOrderedNameDictionary::DetailsAt(
167    InternalIndex entry) {
168  // TODO(gsathya): Optimize the cast away. And store this in the data table.
169  return PropertyDetails(
170      Smi::cast(this->GetDataEntry(entry.as_int(), kPropertyDetailsIndex)));
171}
172
173// Set the details for entry.
174inline void SmallOrderedNameDictionary::DetailsAtPut(InternalIndex entry,
175                                                     PropertyDetails value) {
176  // TODO(gsathya): Optimize the cast away. And store this in the data table.
177  this->SetDataEntry(entry.as_int(), kPropertyDetailsIndex, value.AsSmi());
178}
179
180inline bool OrderedHashSet::Is(Handle<HeapObject> table) {
181  return table->IsOrderedHashSet();
182}
183
184inline bool OrderedHashMap::Is(Handle<HeapObject> table) {
185  return table->IsOrderedHashMap();
186}
187
188inline bool OrderedNameDictionary::Is(Handle<HeapObject> table) {
189  return table->IsOrderedNameDictionary();
190}
191
192inline bool SmallOrderedHashSet::Is(Handle<HeapObject> table) {
193  return table->IsSmallOrderedHashSet();
194}
195
196inline bool SmallOrderedNameDictionary::Is(Handle<HeapObject> table) {
197  return table->IsSmallOrderedNameDictionary();
198}
199
200inline bool SmallOrderedHashMap::Is(Handle<HeapObject> table) {
201  return table->IsSmallOrderedHashMap();
202}
203
204template <class Derived>
205void SmallOrderedHashTable<Derived>::SetDataEntry(int entry, int relative_index,
206                                                  Object value) {
207  DCHECK_NE(kNotFound, entry);
208  int entry_offset = GetDataEntryOffset(entry, relative_index);
209  RELAXED_WRITE_FIELD(*this, entry_offset, value);
210  WRITE_BARRIER(*this, entry_offset, value);
211}
212
213template <class Derived, class TableType>
214Object OrderedHashTableIterator<Derived, TableType>::CurrentKey() {
215  TableType table = TableType::cast(this->table());
216  int index = Smi::ToInt(this->index());
217  DCHECK_LE(0, index);
218  InternalIndex entry(index);
219  Object key = table.KeyAt(entry);
220  DCHECK(!key.IsTheHole());
221  return key;
222}
223
224inline void SmallOrderedNameDictionary::SetHash(int hash) {
225  DCHECK(PropertyArray::HashField::is_valid(hash));
226  WriteField<int>(PrefixOffset(), hash);
227}
228
229inline int SmallOrderedNameDictionary::Hash() {
230  int hash = ReadField<int>(PrefixOffset());
231  DCHECK(PropertyArray::HashField::is_valid(hash));
232  return hash;
233}
234
235inline void OrderedNameDictionary::SetHash(int hash) {
236  DCHECK(PropertyArray::HashField::is_valid(hash));
237  this->set(HashIndex(), Smi::FromInt(hash));
238}
239
240inline int OrderedNameDictionary::Hash() {
241  Object hash_obj = this->get(HashIndex());
242  int hash = Smi::ToInt(hash_obj);
243  DCHECK(PropertyArray::HashField::is_valid(hash));
244  return hash;
245}
246
247}  // namespace internal
248}  // namespace v8
249
250#include "src/objects/object-macros-undef.h"
251
252#endif  // V8_OBJECTS_ORDERED_HASH_TABLE_INL_H_
253