| // 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/objects/dictionary.h" |
| |
| #include "src/numbers/hash-seed-inl.h" |
| #include "src/objects/hash-table-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> |
| BaseNameDictionary<Derived, Shape>::BaseNameDictionary(Address ptr) |
| : Dictionary<Derived, Shape>(ptr) {} |
| |
| 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(Isolate* isolate, int entry) { |
| Object the_hole = this->GetReadOnlyRoots().the_hole_value(); |
| PropertyDetails details = PropertyDetails::Empty(); |
| Derived::cast(*this).SetEntry(isolate, entry, the_hole, the_hole, details); |
| } |
| |
| template <typename Derived, typename Shape> |
| void Dictionary<Derived, Shape>::SetEntry(Isolate* isolate, int 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(isolate, entry, details); |
| } |
| |
| Object GlobalDictionaryShape::Unwrap(Object object) { |
| return PropertyCell::cast(object).name(); |
| } |
| |
| RootIndex GlobalDictionaryShape::GetMapRootIndex() { |
| return RootIndex::kGlobalDictionaryMap; |
| } |
| |
| Name NameDictionary::NameAt(int entry) { |
| Isolate* isolate = GetIsolateForPtrCompr(*this); |
| return NameAt(isolate, entry); |
| } |
| |
| Name NameDictionary::NameAt(Isolate* isolate, int entry) { |
| return Name::cast(KeyAt(isolate, entry)); |
| } |
| |
| RootIndex NameDictionaryShape::GetMapRootIndex() { |
| return RootIndex::kNameDictionaryMap; |
| } |
| |
| PropertyCell GlobalDictionary::CellAt(int entry) { |
| Isolate* isolate = GetIsolateForPtrCompr(*this); |
| return CellAt(isolate, entry); |
| } |
| |
| PropertyCell GlobalDictionary::CellAt(Isolate* isolate, int entry) { |
| DCHECK(KeyAt(isolate, entry).IsPropertyCell(isolate)); |
| return PropertyCell::cast(KeyAt(isolate, entry)); |
| } |
| |
| bool GlobalDictionaryShape::IsLive(ReadOnlyRoots roots, Object k) { |
| DCHECK_NE(roots.the_hole_value(), k); |
| return k != roots.undefined_value(); |
| } |
| |
| bool GlobalDictionaryShape::IsKey(ReadOnlyRoots roots, Object k) { |
| return IsLive(roots, k) && !PropertyCell::cast(k).value().IsTheHole(roots); |
| } |
| |
| Name GlobalDictionary::NameAt(int entry) { |
| Isolate* isolate = GetIsolateForPtrCompr(*this); |
| return NameAt(isolate, entry); |
| } |
| |
| Name GlobalDictionary::NameAt(Isolate* isolate, int entry) { |
| return CellAt(isolate, entry).name(isolate); |
| } |
| |
| Object GlobalDictionary::ValueAt(int entry) { |
| Isolate* isolate = GetIsolateForPtrCompr(*this); |
| return ValueAt(isolate, entry); |
| } |
| |
| Object GlobalDictionary::ValueAt(Isolate* isolate, int entry) { |
| return CellAt(isolate, entry).value(isolate); |
| } |
| |
| void GlobalDictionary::SetEntry(Isolate* isolate, int entry, Object key, |
| Object value, PropertyDetails details) { |
| DCHECK_EQ(key, PropertyCell::cast(value).name()); |
| set(EntryToIndex(entry) + kEntryKeyIndex, value); |
| DetailsAtPut(isolate, entry, details); |
| } |
| |
| void GlobalDictionary::ValueAtPut(int 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(Isolate* isolate, uint32_t key) { |
| return ComputeSeededHash(key, HashSeed(isolate)); |
| } |
| |
| 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); |
| } |
| |
| RootIndex NumberDictionaryShape::GetMapRootIndex() { |
| return RootIndex::kNumberDictionaryMap; |
| } |
| |
| RootIndex SimpleNumberDictionaryShape::GetMapRootIndex() { |
| return RootIndex::kSimpleNumberDictionaryMap; |
| } |
| |
| 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(Isolate* isolate, 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; |
| } |
| |
| template <typename Dictionary> |
| PropertyDetails GlobalDictionaryShape::DetailsAt(Dictionary dict, int entry) { |
| DCHECK_LE(0, entry); // Not found is -1, which is not caught by get(). |
| return dict.CellAt(entry).property_details(); |
| } |
| |
| template <typename Dictionary> |
| void GlobalDictionaryShape::DetailsAtPut(Isolate* isolate, Dictionary dict, |
| int entry, PropertyDetails value) { |
| DCHECK_LE(0, entry); // Not found is -1, which is not caught by get(). |
| PropertyCell cell = dict.CellAt(entry); |
| if (cell.property_details().IsReadOnly() != value.IsReadOnly()) { |
| cell.dependent_code().DeoptimizeDependentCodeGroup( |
| isolate, DependentCode::kPropertyCellChangedGroup); |
| } |
| cell.set_property_details(value); |
| } |
| |
| } // namespace internal |
| } // namespace v8 |
| |
| #include "src/objects/object-macros-undef.h" |
| |
| #endif // V8_OBJECTS_DICTIONARY_INL_H_ |