• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_DICTIONARY_INL_H_
6 #define V8_OBJECTS_DICTIONARY_INL_H_
7 
8 #include "src/execution/isolate-utils-inl.h"
9 #include "src/numbers/hash-seed-inl.h"
10 #include "src/objects/dictionary.h"
11 #include "src/objects/hash-table-inl.h"
12 #include "src/objects/objects-inl.h"
13 #include "src/objects/oddball.h"
14 #include "src/objects/property-cell-inl.h"
15 
16 // Has to be the last include (doesn't have include guards):
17 #include "src/objects/object-macros.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 CAST_ACCESSOR(GlobalDictionary)
CAST_ACCESSOR(NameDictionary)23 CAST_ACCESSOR(NameDictionary)
24 CAST_ACCESSOR(NumberDictionary)
25 CAST_ACCESSOR(SimpleNumberDictionary)
26 
27 template <typename Derived, typename Shape>
28 Dictionary<Derived, Shape>::Dictionary(Address ptr)
29     : HashTable<Derived, Shape>(ptr) {}
30 
31 template <typename Derived, typename Shape>
ValueAt(InternalIndex entry)32 Object Dictionary<Derived, Shape>::ValueAt(InternalIndex entry) {
33   IsolateRoot isolate = GetIsolateForPtrCompr(*this);
34   return ValueAt(isolate, entry);
35 }
36 
37 template <typename Derived, typename Shape>
ValueAt(IsolateRoot isolate,InternalIndex entry)38 Object Dictionary<Derived, Shape>::ValueAt(IsolateRoot isolate,
39                                            InternalIndex entry) {
40   return this->get(isolate, DerivedHashTable::EntryToIndex(entry) +
41                                 Derived::kEntryValueIndex);
42 }
43 
44 template <typename Derived, typename Shape>
ValueAtPut(InternalIndex entry,Object value)45 void Dictionary<Derived, Shape>::ValueAtPut(InternalIndex entry, Object value) {
46   this->set(DerivedHashTable::EntryToIndex(entry) + Derived::kEntryValueIndex,
47             value);
48 }
49 
50 template <typename Derived, typename Shape>
DetailsAt(InternalIndex entry)51 PropertyDetails Dictionary<Derived, Shape>::DetailsAt(InternalIndex entry) {
52   return Shape::DetailsAt(Derived::cast(*this), entry);
53 }
54 
55 template <typename Derived, typename Shape>
DetailsAtPut(InternalIndex entry,PropertyDetails value)56 void Dictionary<Derived, Shape>::DetailsAtPut(InternalIndex entry,
57                                               PropertyDetails value) {
58   Shape::DetailsAtPut(Derived::cast(*this), entry, value);
59 }
60 
61 template <typename Derived, typename Shape>
BaseNameDictionary(Address ptr)62 BaseNameDictionary<Derived, Shape>::BaseNameDictionary(Address ptr)
63     : Dictionary<Derived, Shape>(ptr) {}
64 
65 template <typename Derived, typename Shape>
set_next_enumeration_index(int index)66 void BaseNameDictionary<Derived, Shape>::set_next_enumeration_index(int index) {
67   DCHECK_LT(0, index);
68   this->set(kNextEnumerationIndexIndex, Smi::FromInt(index));
69 }
70 
71 template <typename Derived, typename Shape>
next_enumeration_index()72 int BaseNameDictionary<Derived, Shape>::next_enumeration_index() {
73   return Smi::ToInt(this->get(kNextEnumerationIndexIndex));
74 }
75 
76 template <typename Derived, typename Shape>
SetHash(int hash)77 void BaseNameDictionary<Derived, Shape>::SetHash(int hash) {
78   DCHECK(PropertyArray::HashField::is_valid(hash));
79   this->set(kObjectHashIndex, Smi::FromInt(hash));
80 }
81 
82 template <typename Derived, typename Shape>
Hash()83 int BaseNameDictionary<Derived, Shape>::Hash() const {
84   Object hash_obj = this->get(kObjectHashIndex);
85   int hash = Smi::ToInt(hash_obj);
86   DCHECK(PropertyArray::HashField::is_valid(hash));
87   return hash;
88 }
89 
GlobalDictionary(Address ptr)90 GlobalDictionary::GlobalDictionary(Address ptr)
91     : BaseNameDictionary<GlobalDictionary, GlobalDictionaryShape>(ptr) {
92   SLOW_DCHECK(IsGlobalDictionary());
93 }
94 
NameDictionary(Address ptr)95 NameDictionary::NameDictionary(Address ptr)
96     : BaseNameDictionary<NameDictionary, NameDictionaryShape>(ptr) {
97   SLOW_DCHECK(IsNameDictionary());
98 }
99 
NumberDictionary(Address ptr)100 NumberDictionary::NumberDictionary(Address ptr)
101     : Dictionary<NumberDictionary, NumberDictionaryShape>(ptr) {
102   SLOW_DCHECK(IsNumberDictionary());
103 }
104 
SimpleNumberDictionary(Address ptr)105 SimpleNumberDictionary::SimpleNumberDictionary(Address ptr)
106     : Dictionary<SimpleNumberDictionary, SimpleNumberDictionaryShape>(ptr) {
107   SLOW_DCHECK(IsSimpleNumberDictionary());
108 }
109 
requires_slow_elements()110 bool NumberDictionary::requires_slow_elements() {
111   Object max_index_object = get(kMaxNumberKeyIndex);
112   if (!max_index_object.IsSmi()) return false;
113   return 0 != (Smi::ToInt(max_index_object) & kRequiresSlowElementsMask);
114 }
115 
max_number_key()116 uint32_t NumberDictionary::max_number_key() {
117   DCHECK(!requires_slow_elements());
118   Object max_index_object = get(kMaxNumberKeyIndex);
119   if (!max_index_object.IsSmi()) return 0;
120   uint32_t value = static_cast<uint32_t>(Smi::ToInt(max_index_object));
121   return value >> kRequiresSlowElementsTagSize;
122 }
123 
set_requires_slow_elements()124 void NumberDictionary::set_requires_slow_elements() {
125   set(kMaxNumberKeyIndex, Smi::FromInt(kRequiresSlowElementsMask));
126 }
127 
128 template <typename Derived, typename Shape>
ClearEntry(InternalIndex entry)129 void Dictionary<Derived, Shape>::ClearEntry(InternalIndex entry) {
130   Object the_hole = this->GetReadOnlyRoots().the_hole_value();
131   PropertyDetails details = PropertyDetails::Empty();
132   Derived::cast(*this).SetEntry(entry, the_hole, the_hole, details);
133 }
134 
135 template <typename Derived, typename Shape>
SetEntry(InternalIndex entry,Object key,Object value,PropertyDetails details)136 void Dictionary<Derived, Shape>::SetEntry(InternalIndex entry, Object key,
137                                           Object value,
138                                           PropertyDetails details) {
139   DCHECK(Dictionary::kEntrySize == 2 || Dictionary::kEntrySize == 3);
140   DCHECK(!key.IsName() || details.dictionary_index() > 0);
141   int index = DerivedHashTable::EntryToIndex(entry);
142   DisallowHeapAllocation no_gc;
143   WriteBarrierMode mode = this->GetWriteBarrierMode(no_gc);
144   this->set(index + Derived::kEntryKeyIndex, key, mode);
145   this->set(index + Derived::kEntryValueIndex, value, mode);
146   if (Shape::kHasDetails) DetailsAtPut(entry, details);
147 }
148 
149 template <typename Derived, typename Shape>
RawFieldOfValueAt(InternalIndex entry)150 ObjectSlot Dictionary<Derived, Shape>::RawFieldOfValueAt(InternalIndex entry) {
151   return this->RawFieldOfElementAt(DerivedHashTable::EntryToIndex(entry) +
152                                    Derived::kEntryValueIndex);
153 }
154 
155 template <typename Key>
156 template <typename Dictionary>
DetailsAt(Dictionary dict,InternalIndex entry)157 PropertyDetails BaseDictionaryShape<Key>::DetailsAt(Dictionary dict,
158                                                     InternalIndex entry) {
159   STATIC_ASSERT(Dictionary::kEntrySize == 3);
160   DCHECK(entry.is_found());
161   return PropertyDetails(Smi::cast(dict.get(Dictionary::EntryToIndex(entry) +
162                                             Dictionary::kEntryDetailsIndex)));
163 }
164 
165 template <typename Key>
166 template <typename Dictionary>
DetailsAtPut(Dictionary dict,InternalIndex entry,PropertyDetails value)167 void BaseDictionaryShape<Key>::DetailsAtPut(Dictionary dict,
168                                             InternalIndex entry,
169                                             PropertyDetails value) {
170   STATIC_ASSERT(Dictionary::kEntrySize == 3);
171   dict.set(Dictionary::EntryToIndex(entry) + Dictionary::kEntryDetailsIndex,
172            value.AsSmi());
173 }
174 
Unwrap(Object object)175 Object GlobalDictionaryShape::Unwrap(Object object) {
176   return PropertyCell::cast(object).name();
177 }
178 
GetMap(ReadOnlyRoots roots)179 Handle<Map> GlobalDictionary::GetMap(ReadOnlyRoots roots) {
180   return roots.global_dictionary_map_handle();
181 }
182 
NameAt(InternalIndex entry)183 Name NameDictionary::NameAt(InternalIndex entry) {
184   IsolateRoot isolate = GetIsolateForPtrCompr(*this);
185   return NameAt(isolate, entry);
186 }
187 
NameAt(IsolateRoot isolate,InternalIndex entry)188 Name NameDictionary::NameAt(IsolateRoot isolate, InternalIndex entry) {
189   return Name::cast(KeyAt(isolate, entry));
190 }
191 
GetMap(ReadOnlyRoots roots)192 Handle<Map> NameDictionary::GetMap(ReadOnlyRoots roots) {
193   return roots.name_dictionary_map_handle();
194 }
195 
CellAt(InternalIndex entry)196 PropertyCell GlobalDictionary::CellAt(InternalIndex entry) {
197   IsolateRoot isolate = GetIsolateForPtrCompr(*this);
198   return CellAt(isolate, entry);
199 }
200 
CellAt(IsolateRoot isolate,InternalIndex entry)201 PropertyCell GlobalDictionary::CellAt(IsolateRoot isolate,
202                                       InternalIndex entry) {
203   DCHECK(KeyAt(isolate, entry).IsPropertyCell(isolate));
204   return PropertyCell::cast(KeyAt(isolate, entry));
205 }
206 
NameAt(InternalIndex entry)207 Name GlobalDictionary::NameAt(InternalIndex entry) {
208   IsolateRoot isolate = GetIsolateForPtrCompr(*this);
209   return NameAt(isolate, entry);
210 }
211 
NameAt(IsolateRoot isolate,InternalIndex entry)212 Name GlobalDictionary::NameAt(IsolateRoot isolate, InternalIndex entry) {
213   return CellAt(isolate, entry).name(isolate);
214 }
215 
ValueAt(InternalIndex entry)216 Object GlobalDictionary::ValueAt(InternalIndex entry) {
217   IsolateRoot isolate = GetIsolateForPtrCompr(*this);
218   return ValueAt(isolate, entry);
219 }
220 
ValueAt(IsolateRoot isolate,InternalIndex entry)221 Object GlobalDictionary::ValueAt(IsolateRoot isolate, InternalIndex entry) {
222   return CellAt(isolate, entry).value(isolate);
223 }
224 
SetEntry(InternalIndex entry,Object key,Object value,PropertyDetails details)225 void GlobalDictionary::SetEntry(InternalIndex entry, Object key, Object value,
226                                 PropertyDetails details) {
227   DCHECK_EQ(key, PropertyCell::cast(value).name());
228   set(EntryToIndex(entry) + kEntryKeyIndex, value);
229   DetailsAtPut(entry, details);
230 }
231 
ClearEntry(InternalIndex entry)232 void GlobalDictionary::ClearEntry(InternalIndex entry) {
233   Object the_hole = this->GetReadOnlyRoots().the_hole_value();
234   set(EntryToIndex(entry) + kEntryKeyIndex, the_hole);
235 }
236 
ValueAtPut(InternalIndex entry,Object value)237 void GlobalDictionary::ValueAtPut(InternalIndex entry, Object value) {
238   set(EntryToIndex(entry), value);
239 }
240 
IsMatch(uint32_t key,Object other)241 bool NumberDictionaryBaseShape::IsMatch(uint32_t key, Object other) {
242   DCHECK(other.IsNumber());
243   return key == static_cast<uint32_t>(other.Number());
244 }
245 
Hash(ReadOnlyRoots roots,uint32_t key)246 uint32_t NumberDictionaryBaseShape::Hash(ReadOnlyRoots roots, uint32_t key) {
247   return ComputeSeededHash(key, HashSeed(roots));
248 }
249 
HashForObject(ReadOnlyRoots roots,Object other)250 uint32_t NumberDictionaryBaseShape::HashForObject(ReadOnlyRoots roots,
251                                                   Object other) {
252   DCHECK(other.IsNumber());
253   return ComputeSeededHash(static_cast<uint32_t>(other.Number()),
254                            HashSeed(roots));
255 }
256 
AsHandle(Isolate * isolate,uint32_t key)257 Handle<Object> NumberDictionaryBaseShape::AsHandle(Isolate* isolate,
258                                                    uint32_t key) {
259   return isolate->factory()->NewNumberFromUint(key);
260 }
261 
AsHandle(LocalIsolate * isolate,uint32_t key)262 Handle<Object> NumberDictionaryBaseShape::AsHandle(LocalIsolate* isolate,
263                                                    uint32_t key) {
264   return isolate->factory()->NewNumberFromUint<AllocationType::kOld>(key);
265 }
266 
GetMap(ReadOnlyRoots roots)267 Handle<Map> NumberDictionary::GetMap(ReadOnlyRoots roots) {
268   return roots.number_dictionary_map_handle();
269 }
270 
GetMap(ReadOnlyRoots roots)271 Handle<Map> SimpleNumberDictionary::GetMap(ReadOnlyRoots roots) {
272   return roots.simple_number_dictionary_map_handle();
273 }
274 
IsMatch(Handle<Name> key,Object other)275 bool NameDictionaryShape::IsMatch(Handle<Name> key, Object other) {
276   DCHECK(other.IsTheHole() || Name::cast(other).IsUniqueName());
277   DCHECK(key->IsUniqueName());
278   return *key == other;
279 }
280 
Hash(ReadOnlyRoots roots,Handle<Name> key)281 uint32_t NameDictionaryShape::Hash(ReadOnlyRoots roots, Handle<Name> key) {
282   return key->Hash();
283 }
284 
HashForObject(ReadOnlyRoots roots,Object other)285 uint32_t NameDictionaryShape::HashForObject(ReadOnlyRoots roots, Object other) {
286   return Name::cast(other).Hash();
287 }
288 
IsMatch(Handle<Name> key,Object other)289 bool GlobalDictionaryShape::IsMatch(Handle<Name> key, Object other) {
290   DCHECK(PropertyCell::cast(other).name().IsUniqueName());
291   return *key == PropertyCell::cast(other).name();
292 }
293 
HashForObject(ReadOnlyRoots roots,Object other)294 uint32_t GlobalDictionaryShape::HashForObject(ReadOnlyRoots roots,
295                                               Object other) {
296   return PropertyCell::cast(other).name().Hash();
297 }
298 
AsHandle(Isolate * isolate,Handle<Name> key)299 Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
300                                              Handle<Name> key) {
301   DCHECK(key->IsUniqueName());
302   return key;
303 }
304 
AsHandle(LocalIsolate * isolate,Handle<Name> key)305 Handle<Object> NameDictionaryShape::AsHandle(LocalIsolate* isolate,
306                                              Handle<Name> key) {
307   DCHECK(key->IsUniqueName());
308   return key;
309 }
310 
311 template <typename Dictionary>
DetailsAt(Dictionary dict,InternalIndex entry)312 PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict,
313                                                  InternalIndex entry) {
314   DCHECK(entry.is_found());
315   return dict.CellAt(entry).property_details();
316 }
317 
318 template <typename Dictionary>
DetailsAtPut(Dictionary dict,InternalIndex entry,PropertyDetails value)319 void GlobalDictionaryShape::DetailsAtPut(Dictionary dict, InternalIndex entry,
320                                          PropertyDetails value) {
321   DCHECK(entry.is_found());
322   PropertyCell cell = dict.CellAt(entry);
323   if (cell.property_details().IsReadOnly() != value.IsReadOnly()) {
324     cell.dependent_code().DeoptimizeDependentCodeGroup(
325         DependentCode::kPropertyCellChangedGroup);
326   }
327   cell.set_property_details(value);
328 }
329 
330 }  // namespace internal
331 }  // namespace v8
332 
333 #include "src/objects/object-macros-undef.h"
334 
335 #endif  // V8_OBJECTS_DICTIONARY_INL_H_
336