| // 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_DESCRIPTOR_ARRAY_INL_H_ | 
 | #define V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_ | 
 |  | 
 | #include "src/objects/descriptor-array.h" | 
 |  | 
 | #include "src/execution/isolate.h" | 
 | #include "src/handles/maybe-handles-inl.h" | 
 | #include "src/heap/heap-write-barrier.h" | 
 | #include "src/heap/heap.h" | 
 | #include "src/objects/field-type.h" | 
 | #include "src/objects/heap-object-inl.h" | 
 | #include "src/objects/lookup-cache-inl.h" | 
 | #include "src/objects/maybe-object-inl.h" | 
 | #include "src/objects/property.h" | 
 | #include "src/objects/struct-inl.h" | 
 |  | 
 | // Has to be the last include (doesn't have include guards): | 
 | #include "src/objects/object-macros.h" | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 |  | 
 | #include "torque-generated/src/objects/descriptor-array-tq-inl.inc" | 
 |  | 
 | TQ_OBJECT_CONSTRUCTORS_IMPL(DescriptorArray) | 
 | TQ_OBJECT_CONSTRUCTORS_IMPL(EnumCache) | 
 |  | 
 | RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_all_descriptors, | 
 |                         kNumberOfAllDescriptorsOffset) | 
 | RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_descriptors, | 
 |                         kNumberOfDescriptorsOffset) | 
 | RELAXED_INT16_ACCESSORS(DescriptorArray, raw_number_of_marked_descriptors, | 
 |                         kRawNumberOfMarkedDescriptorsOffset) | 
 | RELAXED_INT16_ACCESSORS(DescriptorArray, filler16bits, kFiller16BitsOffset) | 
 |  | 
 | inline int16_t DescriptorArray::number_of_slack_descriptors() const { | 
 |   return number_of_all_descriptors() - number_of_descriptors(); | 
 | } | 
 |  | 
 | inline int DescriptorArray::number_of_entries() const { | 
 |   return number_of_descriptors(); | 
 | } | 
 |  | 
 | inline int16_t DescriptorArray::CompareAndSwapRawNumberOfMarkedDescriptors( | 
 |     int16_t expected, int16_t value) { | 
 |   return base::Relaxed_CompareAndSwap( | 
 |       reinterpret_cast<base::Atomic16*>( | 
 |           FIELD_ADDR(*this, kRawNumberOfMarkedDescriptorsOffset)), | 
 |       expected, value); | 
 | } | 
 |  | 
 | void DescriptorArray::CopyEnumCacheFrom(DescriptorArray array) { | 
 |   set_enum_cache(array.enum_cache()); | 
 | } | 
 |  | 
 | InternalIndex DescriptorArray::Search(Name name, int valid_descriptors, | 
 |                                       bool concurrent_search) { | 
 |   DCHECK(name.IsUniqueName()); | 
 |   return InternalIndex(internal::Search<VALID_ENTRIES>( | 
 |       this, name, valid_descriptors, nullptr, concurrent_search)); | 
 | } | 
 |  | 
 | InternalIndex DescriptorArray::Search(Name name, Map map, | 
 |                                       bool concurrent_search) { | 
 |   DCHECK(name.IsUniqueName()); | 
 |   int number_of_own_descriptors = map.NumberOfOwnDescriptors(); | 
 |   if (number_of_own_descriptors == 0) return InternalIndex::NotFound(); | 
 |   return Search(name, number_of_own_descriptors, concurrent_search); | 
 | } | 
 |  | 
 | InternalIndex DescriptorArray::SearchWithCache(Isolate* isolate, Name name, | 
 |                                                Map map) { | 
 |   DCHECK(name.IsUniqueName()); | 
 |   int number_of_own_descriptors = map.NumberOfOwnDescriptors(); | 
 |   if (number_of_own_descriptors == 0) return InternalIndex::NotFound(); | 
 |  | 
 |   DescriptorLookupCache* cache = isolate->descriptor_lookup_cache(); | 
 |   int number = cache->Lookup(map, name); | 
 |  | 
 |   if (number == DescriptorLookupCache::kAbsent) { | 
 |     InternalIndex result = Search(name, number_of_own_descriptors); | 
 |     number = result.is_found() ? result.as_int() : DescriptorArray::kNotFound; | 
 |     cache->Update(map, name, number); | 
 |   } | 
 |   if (number == DescriptorArray::kNotFound) return InternalIndex::NotFound(); | 
 |   return InternalIndex(number); | 
 | } | 
 |  | 
 | ObjectSlot DescriptorArray::GetFirstPointerSlot() { | 
 |   static_assert(kEndOfStrongFieldsOffset == kStartOfWeakFieldsOffset, | 
 |                 "Weak and strong fields are continuous."); | 
 |   static_assert(kEndOfWeakFieldsOffset == kHeaderSize, | 
 |                 "Weak fields extend up to the end of the header."); | 
 |   return RawField(DescriptorArray::kStartOfStrongFieldsOffset); | 
 | } | 
 |  | 
 | ObjectSlot DescriptorArray::GetDescriptorSlot(int descriptor) { | 
 |   // Allow descriptor == number_of_all_descriptors() for computing the slot | 
 |   // address that comes after the last descriptor (for iterating). | 
 |   DCHECK_LE(descriptor, number_of_all_descriptors()); | 
 |   return RawField(OffsetOfDescriptorAt(descriptor)); | 
 | } | 
 |  | 
 | Name DescriptorArray::GetKey(InternalIndex descriptor_number) const { | 
 |   IsolateRoot isolate = GetIsolateForPtrCompr(*this); | 
 |   return GetKey(isolate, descriptor_number); | 
 | } | 
 |  | 
 | Name DescriptorArray::GetKey(IsolateRoot isolate, | 
 |                              InternalIndex descriptor_number) const { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   return Name::cast(EntryKeyField::Relaxed_Load(isolate, *this, entry_offset)); | 
 | } | 
 |  | 
 | void DescriptorArray::SetKey(InternalIndex descriptor_number, Name key) { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   EntryKeyField::Relaxed_Store(*this, entry_offset, key); | 
 |   WRITE_BARRIER(*this, entry_offset + kEntryKeyOffset, key); | 
 | } | 
 |  | 
 | int DescriptorArray::GetSortedKeyIndex(int descriptor_number) { | 
 |   return GetDetails(InternalIndex(descriptor_number)).pointer(); | 
 | } | 
 |  | 
 | Name DescriptorArray::GetSortedKey(int descriptor_number) { | 
 |   IsolateRoot isolate = GetIsolateForPtrCompr(*this); | 
 |   return GetSortedKey(isolate, descriptor_number); | 
 | } | 
 |  | 
 | Name DescriptorArray::GetSortedKey(IsolateRoot isolate, int descriptor_number) { | 
 |   return GetKey(isolate, InternalIndex(GetSortedKeyIndex(descriptor_number))); | 
 | } | 
 |  | 
 | void DescriptorArray::SetSortedKey(int descriptor_number, int pointer) { | 
 |   PropertyDetails details = GetDetails(InternalIndex(descriptor_number)); | 
 |   SetDetails(InternalIndex(descriptor_number), details.set_pointer(pointer)); | 
 | } | 
 |  | 
 | Object DescriptorArray::GetStrongValue(InternalIndex descriptor_number) { | 
 |   IsolateRoot isolate = GetIsolateForPtrCompr(*this); | 
 |   return GetStrongValue(isolate, descriptor_number); | 
 | } | 
 |  | 
 | Object DescriptorArray::GetStrongValue(IsolateRoot isolate, | 
 |                                        InternalIndex descriptor_number) { | 
 |   return GetValue(isolate, descriptor_number).cast<Object>(); | 
 | } | 
 |  | 
 | void DescriptorArray::SetValue(InternalIndex descriptor_number, | 
 |                                MaybeObject value) { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   EntryValueField::Relaxed_Store(*this, entry_offset, value); | 
 |   WEAK_WRITE_BARRIER(*this, entry_offset + kEntryValueOffset, value); | 
 | } | 
 |  | 
 | MaybeObject DescriptorArray::GetValue(InternalIndex descriptor_number) { | 
 |   IsolateRoot isolate = GetIsolateForPtrCompr(*this); | 
 |   return GetValue(isolate, descriptor_number); | 
 | } | 
 |  | 
 | MaybeObject DescriptorArray::GetValue(IsolateRoot isolate, | 
 |                                       InternalIndex descriptor_number) { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   return EntryValueField::Relaxed_Load(isolate, *this, entry_offset); | 
 | } | 
 |  | 
 | PropertyDetails DescriptorArray::GetDetails(InternalIndex descriptor_number) { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   Smi details = EntryDetailsField::Relaxed_Load(*this, entry_offset); | 
 |   return PropertyDetails(details); | 
 | } | 
 |  | 
 | void DescriptorArray::SetDetails(InternalIndex descriptor_number, | 
 |                                  PropertyDetails details) { | 
 |   DCHECK_LT(descriptor_number.as_int(), number_of_descriptors()); | 
 |   int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int()); | 
 |   EntryDetailsField::Relaxed_Store(*this, entry_offset, details.AsSmi()); | 
 | } | 
 |  | 
 | int DescriptorArray::GetFieldIndex(InternalIndex descriptor_number) { | 
 |   DCHECK_EQ(GetDetails(descriptor_number).location(), kField); | 
 |   return GetDetails(descriptor_number).field_index(); | 
 | } | 
 |  | 
 | FieldType DescriptorArray::GetFieldType(InternalIndex descriptor_number) { | 
 |   IsolateRoot isolate = GetIsolateForPtrCompr(*this); | 
 |   return GetFieldType(isolate, descriptor_number); | 
 | } | 
 |  | 
 | FieldType DescriptorArray::GetFieldType(IsolateRoot isolate, | 
 |                                         InternalIndex descriptor_number) { | 
 |   DCHECK_EQ(GetDetails(descriptor_number).location(), kField); | 
 |   MaybeObject wrapped_type = GetValue(isolate, descriptor_number); | 
 |   return Map::UnwrapFieldType(wrapped_type); | 
 | } | 
 |  | 
 | void DescriptorArray::Set(InternalIndex descriptor_number, Name key, | 
 |                           MaybeObject value, PropertyDetails details) { | 
 |   SetKey(descriptor_number, key); | 
 |   SetDetails(descriptor_number, details); | 
 |   SetValue(descriptor_number, value); | 
 | } | 
 |  | 
 | void DescriptorArray::Set(InternalIndex descriptor_number, Descriptor* desc) { | 
 |   Name key = *desc->GetKey(); | 
 |   MaybeObject value = *desc->GetValue(); | 
 |   Set(descriptor_number, key, value, desc->GetDetails()); | 
 | } | 
 |  | 
 | void DescriptorArray::Append(Descriptor* desc) { | 
 |   DisallowHeapAllocation no_gc; | 
 |   int descriptor_number = number_of_descriptors(); | 
 |   DCHECK_LE(descriptor_number + 1, number_of_all_descriptors()); | 
 |   set_number_of_descriptors(descriptor_number + 1); | 
 |   Set(InternalIndex(descriptor_number), desc); | 
 |  | 
 |   uint32_t hash = desc->GetKey()->Hash(); | 
 |  | 
 |   int insertion; | 
 |  | 
 |   for (insertion = descriptor_number; insertion > 0; --insertion) { | 
 |     Name key = GetSortedKey(insertion - 1); | 
 |     if (key.hash() <= hash) break; | 
 |     SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1)); | 
 |   } | 
 |  | 
 |   SetSortedKey(insertion, descriptor_number); | 
 | } | 
 |  | 
 | void DescriptorArray::SwapSortedKeys(int first, int second) { | 
 |   int first_key = GetSortedKeyIndex(first); | 
 |   SetSortedKey(first, GetSortedKeyIndex(second)); | 
 |   SetSortedKey(second, first_key); | 
 | } | 
 |  | 
 | }  // namespace internal | 
 | }  // namespace v8 | 
 |  | 
 | #include "src/objects/object-macros-undef.h" | 
 |  | 
 | #endif  // V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_ |