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