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_DESCRIPTOR_ARRAY_INL_H_
6#define V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_
7
8#include "src/execution/isolate.h"
9#include "src/handles/maybe-handles-inl.h"
10#include "src/heap/heap-write-barrier.h"
11#include "src/heap/heap.h"
12#include "src/objects/descriptor-array.h"
13#include "src/objects/field-type.h"
14#include "src/objects/heap-object-inl.h"
15#include "src/objects/lookup-cache-inl.h"
16#include "src/objects/maybe-object-inl.h"
17#include "src/objects/property.h"
18#include "src/objects/struct-inl.h"
19
20// Has to be the last include (doesn't have include guards):
21#include "src/objects/object-macros.h"
22
23namespace v8 {
24namespace internal {
25
26#include "torque-generated/src/objects/descriptor-array-tq-inl.inc"
27
28TQ_OBJECT_CONSTRUCTORS_IMPL(DescriptorArray)
29TQ_OBJECT_CONSTRUCTORS_IMPL(EnumCache)
30
31RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_all_descriptors,
32                        kNumberOfAllDescriptorsOffset)
33RELAXED_INT16_ACCESSORS(DescriptorArray, number_of_descriptors,
34                        kNumberOfDescriptorsOffset)
35RELAXED_INT16_ACCESSORS(DescriptorArray, raw_number_of_marked_descriptors,
36                        kRawNumberOfMarkedDescriptorsOffset)
37RELAXED_INT16_ACCESSORS(DescriptorArray, filler16bits, kFiller16BitsOffset)
38
39inline int16_t DescriptorArray::number_of_slack_descriptors() const {
40  return number_of_all_descriptors() - number_of_descriptors();
41}
42
43inline int DescriptorArray::number_of_entries() const {
44  return number_of_descriptors();
45}
46
47inline int16_t DescriptorArray::CompareAndSwapRawNumberOfMarkedDescriptors(
48    int16_t expected, int16_t value) {
49  return base::Relaxed_CompareAndSwap(
50      reinterpret_cast<base::Atomic16*>(
51          FIELD_ADDR(*this, kRawNumberOfMarkedDescriptorsOffset)),
52      expected, value);
53}
54
55void DescriptorArray::CopyEnumCacheFrom(DescriptorArray array) {
56  set_enum_cache(array.enum_cache());
57}
58
59InternalIndex DescriptorArray::Search(Name name, int valid_descriptors,
60                                      bool concurrent_search) {
61  DCHECK(name.IsUniqueName());
62  return InternalIndex(internal::Search<VALID_ENTRIES>(
63      this, name, valid_descriptors, nullptr, concurrent_search));
64}
65
66InternalIndex DescriptorArray::Search(Name name, Map map,
67                                      bool concurrent_search) {
68  DCHECK(name.IsUniqueName());
69  int number_of_own_descriptors = map.NumberOfOwnDescriptors();
70  if (number_of_own_descriptors == 0) return InternalIndex::NotFound();
71  return Search(name, number_of_own_descriptors, concurrent_search);
72}
73
74InternalIndex DescriptorArray::SearchWithCache(Isolate* isolate, Name name,
75                                               Map map) {
76  DCHECK(name.IsUniqueName());
77  int number_of_own_descriptors = map.NumberOfOwnDescriptors();
78  if (number_of_own_descriptors == 0) return InternalIndex::NotFound();
79
80  DescriptorLookupCache* cache = isolate->descriptor_lookup_cache();
81  int number = cache->Lookup(map, name);
82
83  if (number == DescriptorLookupCache::kAbsent) {
84    InternalIndex result = Search(name, number_of_own_descriptors);
85    number = result.is_found() ? result.as_int() : DescriptorArray::kNotFound;
86    cache->Update(map, name, number);
87  }
88  if (number == DescriptorArray::kNotFound) return InternalIndex::NotFound();
89  return InternalIndex(number);
90}
91
92ObjectSlot DescriptorArray::GetFirstPointerSlot() {
93  static_assert(kEndOfStrongFieldsOffset == kStartOfWeakFieldsOffset,
94                "Weak and strong fields are continuous.");
95  static_assert(kEndOfWeakFieldsOffset == kHeaderSize,
96                "Weak fields extend up to the end of the header.");
97  return RawField(DescriptorArray::kStartOfStrongFieldsOffset);
98}
99
100ObjectSlot DescriptorArray::GetDescriptorSlot(int descriptor) {
101  // Allow descriptor == number_of_all_descriptors() for computing the slot
102  // address that comes after the last descriptor (for iterating).
103  DCHECK_LE(descriptor, number_of_all_descriptors());
104  return RawField(OffsetOfDescriptorAt(descriptor));
105}
106
107Name DescriptorArray::GetKey(InternalIndex descriptor_number) const {
108  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
109  return GetKey(cage_base, descriptor_number);
110}
111
112Name DescriptorArray::GetKey(PtrComprCageBase cage_base,
113                             InternalIndex descriptor_number) const {
114  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
115  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
116  return Name::cast(
117      EntryKeyField::Relaxed_Load(cage_base, *this, entry_offset));
118}
119
120void DescriptorArray::SetKey(InternalIndex descriptor_number, Name key) {
121  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
122  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
123  EntryKeyField::Relaxed_Store(*this, entry_offset, key);
124  WRITE_BARRIER(*this, entry_offset + kEntryKeyOffset, key);
125}
126
127int DescriptorArray::GetSortedKeyIndex(int descriptor_number) {
128  return GetDetails(InternalIndex(descriptor_number)).pointer();
129}
130
131Name DescriptorArray::GetSortedKey(int descriptor_number) {
132  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
133  return GetSortedKey(cage_base, descriptor_number);
134}
135
136Name DescriptorArray::GetSortedKey(PtrComprCageBase cage_base,
137                                   int descriptor_number) {
138  return GetKey(cage_base, InternalIndex(GetSortedKeyIndex(descriptor_number)));
139}
140
141void DescriptorArray::SetSortedKey(int descriptor_number, int pointer) {
142  PropertyDetails details = GetDetails(InternalIndex(descriptor_number));
143  SetDetails(InternalIndex(descriptor_number), details.set_pointer(pointer));
144}
145
146Object DescriptorArray::GetStrongValue(InternalIndex descriptor_number) {
147  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
148  return GetStrongValue(cage_base, descriptor_number);
149}
150
151Object DescriptorArray::GetStrongValue(PtrComprCageBase cage_base,
152                                       InternalIndex descriptor_number) {
153  return GetValue(cage_base, descriptor_number).cast<Object>();
154}
155
156void DescriptorArray::SetValue(InternalIndex descriptor_number,
157                               MaybeObject value) {
158  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
159  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
160  EntryValueField::Relaxed_Store(*this, entry_offset, value);
161  WEAK_WRITE_BARRIER(*this, entry_offset + kEntryValueOffset, value);
162}
163
164MaybeObject DescriptorArray::GetValue(InternalIndex descriptor_number) {
165  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
166  return GetValue(cage_base, descriptor_number);
167}
168
169MaybeObject DescriptorArray::GetValue(PtrComprCageBase cage_base,
170                                      InternalIndex descriptor_number) {
171  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
172  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
173  return EntryValueField::Relaxed_Load(cage_base, *this, entry_offset);
174}
175
176PropertyDetails DescriptorArray::GetDetails(InternalIndex descriptor_number) {
177  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
178  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
179  Smi details = EntryDetailsField::Relaxed_Load(*this, entry_offset);
180  return PropertyDetails(details);
181}
182
183void DescriptorArray::SetDetails(InternalIndex descriptor_number,
184                                 PropertyDetails details) {
185  DCHECK_LT(descriptor_number.as_int(), number_of_descriptors());
186  int entry_offset = OffsetOfDescriptorAt(descriptor_number.as_int());
187  EntryDetailsField::Relaxed_Store(*this, entry_offset, details.AsSmi());
188}
189
190int DescriptorArray::GetFieldIndex(InternalIndex descriptor_number) {
191  DCHECK_EQ(GetDetails(descriptor_number).location(), PropertyLocation::kField);
192  return GetDetails(descriptor_number).field_index();
193}
194
195FieldType DescriptorArray::GetFieldType(InternalIndex descriptor_number) {
196  PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
197  return GetFieldType(cage_base, descriptor_number);
198}
199
200FieldType DescriptorArray::GetFieldType(PtrComprCageBase cage_base,
201                                        InternalIndex descriptor_number) {
202  DCHECK_EQ(GetDetails(descriptor_number).location(), PropertyLocation::kField);
203  MaybeObject wrapped_type = GetValue(cage_base, descriptor_number);
204  return Map::UnwrapFieldType(wrapped_type);
205}
206
207void DescriptorArray::Set(InternalIndex descriptor_number, Name key,
208                          MaybeObject value, PropertyDetails details) {
209  SetKey(descriptor_number, key);
210  SetDetails(descriptor_number, details);
211  SetValue(descriptor_number, value);
212}
213
214void DescriptorArray::Set(InternalIndex descriptor_number, Descriptor* desc) {
215  Name key = *desc->GetKey();
216  MaybeObject value = *desc->GetValue();
217  Set(descriptor_number, key, value, desc->GetDetails());
218}
219
220void DescriptorArray::Append(Descriptor* desc) {
221  DisallowGarbageCollection no_gc;
222  int descriptor_number = number_of_descriptors();
223  DCHECK_LE(descriptor_number + 1, number_of_all_descriptors());
224  set_number_of_descriptors(descriptor_number + 1);
225  Set(InternalIndex(descriptor_number), desc);
226
227  uint32_t hash = desc->GetKey()->hash();
228
229  int insertion;
230
231  for (insertion = descriptor_number; insertion > 0; --insertion) {
232    Name key = GetSortedKey(insertion - 1);
233    if (key.hash() <= hash) break;
234    SetSortedKey(insertion, GetSortedKeyIndex(insertion - 1));
235  }
236
237  SetSortedKey(insertion, descriptor_number);
238}
239
240void DescriptorArray::SwapSortedKeys(int first, int second) {
241  int first_key = GetSortedKeyIndex(first);
242  SetSortedKey(first, GetSortedKeyIndex(second));
243  SetSortedKey(second, first_key);
244}
245
246}  // namespace internal
247}  // namespace v8
248
249#include "src/objects/object-macros-undef.h"
250
251#endif  // V8_OBJECTS_DESCRIPTOR_ARRAY_INL_H_
252