• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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_FIXED_ARRAY_INL_H_
6 #define V8_OBJECTS_FIXED_ARRAY_INL_H_
7 
8 #include "src/handles/handles-inl.h"
9 #include "src/heap/heap-write-barrier-inl.h"
10 #include "src/numbers/conversions.h"
11 #include "src/objects/bigint.h"
12 #include "src/objects/compressed-slots.h"
13 #include "src/objects/fixed-array.h"
14 #include "src/objects/map.h"
15 #include "src/objects/maybe-object-inl.h"
16 #include "src/objects/objects-inl.h"
17 #include "src/objects/oddball.h"
18 #include "src/objects/slots.h"
19 #include "src/roots/roots-inl.h"
20 
21 // Has to be the last include (doesn't have include guards):
22 #include "src/objects/object-macros.h"
23 
24 namespace v8 {
25 namespace internal {
26 
27 #include "torque-generated/src/objects/fixed-array-tq-inl.inc"
28 
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase)29 TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase)
30 FixedArrayBase::FixedArrayBase(Address ptr,
31                                HeapObject::AllowInlineSmiStorage allow_smi)
32     : TorqueGeneratedFixedArrayBase(ptr, allow_smi) {}
33 TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray)34 TQ_OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray)
35 TQ_OBJECT_CONSTRUCTORS_IMPL(ArrayList)
36 TQ_OBJECT_CONSTRUCTORS_IMPL(ByteArray)
37 ByteArray::ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi)
38     : TorqueGeneratedByteArray(ptr, allow_smi) {}
39 TQ_OBJECT_CONSTRUCTORS_IMPL(TemplateList)
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray)40 TQ_OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray)
41 TQ_OBJECT_CONSTRUCTORS_IMPL(WeakArrayList)
42 
43 NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
44 
45 RELEASE_ACQUIRE_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
46 
47 RELEASE_ACQUIRE_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
48 
49 Object FixedArrayBase::unchecked_length(AcquireLoadTag) const {
50   return ACQUIRE_READ_FIELD(*this, kLengthOffset);
51 }
52 
GetFirstElementAddress()53 ObjectSlot FixedArray::GetFirstElementAddress() {
54   return RawField(OffsetOfElementAt(0));
55 }
56 
ContainsOnlySmisOrHoles()57 bool FixedArray::ContainsOnlySmisOrHoles() {
58   Object the_hole = GetReadOnlyRoots().the_hole_value();
59   ObjectSlot current = GetFirstElementAddress();
60   for (int i = 0; i < length(); ++i, ++current) {
61     Object candidate = *current;
62     if (!candidate.IsSmi() && candidate != the_hole) return false;
63   }
64   return true;
65 }
66 
get(int index)67 Object FixedArray::get(int index) const {
68   PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
69   return get(cage_base, index);
70 }
71 
get(PtrComprCageBase cage_base,int index)72 Object FixedArray::get(PtrComprCageBase cage_base, int index) const {
73   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
74   return TaggedField<Object>::Relaxed_Load(cage_base, *this,
75                                            OffsetOfElementAt(index));
76 }
77 
get(FixedArray array,int index,Isolate * isolate)78 Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
79   return handle(array.get(isolate, index), isolate);
80 }
81 
is_the_hole(Isolate * isolate,int index)82 bool FixedArray::is_the_hole(Isolate* isolate, int index) {
83   return get(isolate, index).IsTheHole(isolate);
84 }
85 
86 #if !defined(_WIN32) || (defined(_WIN64) && _MSC_VER < 1930 && __cplusplus < 201703L)
set(int index,Smi value)87 void FixedArray::set(int index, Smi value) {
88   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
89   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
90   DCHECK(Object(value).IsSmi());
91   int offset = OffsetOfElementAt(index);
92   RELAXED_WRITE_FIELD(*this, offset, value);
93 }
94 #endif
95 
set(int index,Object value)96 void FixedArray::set(int index, Object value) {
97   DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
98   DCHECK(IsFixedArray());
99   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
100   int offset = OffsetOfElementAt(index);
101   RELAXED_WRITE_FIELD(*this, offset, value);
102   WRITE_BARRIER(*this, offset, value);
103 }
104 
set(int index,Object value,WriteBarrierMode mode)105 void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
106   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
107   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
108   int offset = OffsetOfElementAt(index);
109   RELAXED_WRITE_FIELD(*this, offset, value);
110   CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
111 }
112 
113 // static
NoWriteBarrierSet(FixedArray array,int index,Object value)114 void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
115   DCHECK_NE(array.map(), array.GetReadOnlyRoots().fixed_cow_array_map());
116   DCHECK_LT(static_cast<unsigned>(index),
117             static_cast<unsigned>(array.length()));
118   DCHECK(!ObjectInYoungGeneration(value));
119   int offset = OffsetOfElementAt(index);
120   RELAXED_WRITE_FIELD(array, offset, value);
121 }
122 
get(int index,RelaxedLoadTag)123 Object FixedArray::get(int index, RelaxedLoadTag) const {
124   PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
125   return get(cage_base, index);
126 }
127 
get(PtrComprCageBase cage_base,int index,RelaxedLoadTag)128 Object FixedArray::get(PtrComprCageBase cage_base, int index,
129                        RelaxedLoadTag) const {
130   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
131   return RELAXED_READ_FIELD(*this, OffsetOfElementAt(index));
132 }
133 
set(int index,Object value,RelaxedStoreTag,WriteBarrierMode mode)134 void FixedArray::set(int index, Object value, RelaxedStoreTag,
135                      WriteBarrierMode mode) {
136   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
137   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
138   RELAXED_WRITE_FIELD(*this, OffsetOfElementAt(index), value);
139   CONDITIONAL_WRITE_BARRIER(*this, OffsetOfElementAt(index), value, mode);
140 }
141 
set(int index,Smi value,RelaxedStoreTag tag)142 void FixedArray::set(int index, Smi value, RelaxedStoreTag tag) {
143   DCHECK(Object(value).IsSmi());
144   set(index, value, tag, SKIP_WRITE_BARRIER);
145 }
146 
get(int index,AcquireLoadTag)147 Object FixedArray::get(int index, AcquireLoadTag) const {
148   PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
149   return get(cage_base, index);
150 }
151 
get(PtrComprCageBase cage_base,int index,AcquireLoadTag)152 Object FixedArray::get(PtrComprCageBase cage_base, int index,
153                        AcquireLoadTag) const {
154   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
155   return ACQUIRE_READ_FIELD(*this, OffsetOfElementAt(index));
156 }
157 
set(int index,Object value,ReleaseStoreTag,WriteBarrierMode mode)158 void FixedArray::set(int index, Object value, ReleaseStoreTag,
159                      WriteBarrierMode mode) {
160   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
161   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
162   RELEASE_WRITE_FIELD(*this, OffsetOfElementAt(index), value);
163   CONDITIONAL_WRITE_BARRIER(*this, OffsetOfElementAt(index), value, mode);
164 }
165 
set(int index,Smi value,ReleaseStoreTag tag)166 void FixedArray::set(int index, Smi value, ReleaseStoreTag tag) {
167   DCHECK(Object(value).IsSmi());
168   set(index, value, tag, SKIP_WRITE_BARRIER);
169 }
170 
set_undefined(int index)171 void FixedArray::set_undefined(int index) {
172   set_undefined(GetReadOnlyRoots(), index);
173 }
174 
set_undefined(Isolate * isolate,int index)175 void FixedArray::set_undefined(Isolate* isolate, int index) {
176   set_undefined(ReadOnlyRoots(isolate), index);
177 }
178 
set_undefined(ReadOnlyRoots ro_roots,int index)179 void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
180   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
181 }
182 
set_null(int index)183 void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
184 
set_null(Isolate * isolate,int index)185 void FixedArray::set_null(Isolate* isolate, int index) {
186   set_null(ReadOnlyRoots(isolate), index);
187 }
188 
set_null(ReadOnlyRoots ro_roots,int index)189 void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
190   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
191 }
192 
set_the_hole(int index)193 void FixedArray::set_the_hole(int index) {
194   set_the_hole(GetReadOnlyRoots(), index);
195 }
196 
set_the_hole(Isolate * isolate,int index)197 void FixedArray::set_the_hole(Isolate* isolate, int index) {
198   set_the_hole(ReadOnlyRoots(isolate), index);
199 }
200 
set_the_hole(ReadOnlyRoots ro_roots,int index)201 void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
202   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
203 }
204 
FillWithHoles(int from,int to)205 void FixedArray::FillWithHoles(int from, int to) {
206   for (int i = from; i < to; i++) {
207     set_the_hole(i);
208   }
209 }
210 
data_start()211 ObjectSlot FixedArray::data_start() { return RawField(OffsetOfElementAt(0)); }
212 
RawFieldOfElementAt(int index)213 ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
214   return RawField(OffsetOfElementAt(index));
215 }
216 
MoveElements(Isolate * isolate,int dst_index,int src_index,int len,WriteBarrierMode mode)217 void FixedArray::MoveElements(Isolate* isolate, int dst_index, int src_index,
218                               int len, WriteBarrierMode mode) {
219   if (len == 0) return;
220   DCHECK_LE(dst_index + len, length());
221   DCHECK_LE(src_index + len, length());
222   DisallowGarbageCollection no_gc;
223   ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
224   ObjectSlot src_slot(RawFieldOfElementAt(src_index));
225   isolate->heap()->MoveRange(*this, dst_slot, src_slot, len, mode);
226 }
227 
CopyElements(Isolate * isolate,int dst_index,FixedArray src,int src_index,int len,WriteBarrierMode mode)228 void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src,
229                               int src_index, int len, WriteBarrierMode mode) {
230   if (len == 0) return;
231   DCHECK_LE(dst_index + len, length());
232   DCHECK_LE(src_index + len, src.length());
233   DisallowGarbageCollection no_gc;
234 
235   ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
236   ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
237   isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
238 }
239 
240 // Due to left- and right-trimming, concurrent visitors need to read the length
241 // with acquire semantics.
242 // TODO(ulan): Acquire should not be needed anymore.
AllocatedSize()243 inline int FixedArray::AllocatedSize() { return SizeFor(length(kAcquireLoad)); }
AllocatedSize()244 inline int WeakFixedArray::AllocatedSize() {
245   return SizeFor(length(kAcquireLoad));
246 }
AllocatedSize()247 inline int WeakArrayList::AllocatedSize() { return SizeFor(capacity()); }
248 
249 // Perform a binary search in a fixed array.
250 template <SearchMode search_mode, typename T>
BinarySearch(T * array,Name name,int valid_entries,int * out_insertion_index)251 int BinarySearch(T* array, Name name, int valid_entries,
252                  int* out_insertion_index) {
253   DCHECK_IMPLIES(search_mode == VALID_ENTRIES, out_insertion_index == nullptr);
254   int low = 0;
255   // We have to search on all entries, even when search_mode == VALID_ENTRIES.
256   // This is because the InternalIndex might be different from the SortedIndex
257   // (i.e the first added item in {array} could be the last in the sorted
258   // index). After doing the binary search and getting the correct internal
259   // index we check to have the index lower than valid_entries, if needed.
260   int high = array->number_of_entries() - 1;
261   uint32_t hash = name.hash();
262   int limit = high;
263 
264   DCHECK(low <= high);
265 
266   while (low != high) {
267     int mid = low + (high - low) / 2;
268     Name mid_name = array->GetSortedKey(mid);
269     uint32_t mid_hash = mid_name.hash();
270 
271     if (mid_hash >= hash) {
272       high = mid;
273     } else {
274       low = mid + 1;
275     }
276   }
277 
278   for (; low <= limit; ++low) {
279     int sort_index = array->GetSortedKeyIndex(low);
280     Name entry = array->GetKey(InternalIndex(sort_index));
281     uint32_t current_hash = entry.hash();
282     if (current_hash != hash) {
283       // 'search_mode == ALL_ENTRIES' here and below is not needed since
284       // 'out_insertion_index != nullptr' implies 'search_mode == ALL_ENTRIES'.
285       // Having said that, when creating the template for <VALID_ENTRIES> these
286       // ifs can be elided by the C++ compiler if we add 'search_mode ==
287       // ALL_ENTRIES'.
288       if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
289         *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
290       }
291       return T::kNotFound;
292     }
293     if (entry == name) {
294       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
295         return sort_index;
296       }
297       return T::kNotFound;
298     }
299   }
300 
301   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
302     *out_insertion_index = limit + 1;
303   }
304   return T::kNotFound;
305 }
306 
307 // Perform a linear search in this fixed array. len is the number of entry
308 // indices that are valid.
309 template <SearchMode search_mode, typename T>
LinearSearch(T * array,Name name,int valid_entries,int * out_insertion_index)310 int LinearSearch(T* array, Name name, int valid_entries,
311                  int* out_insertion_index) {
312   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
313     uint32_t hash = name.hash();
314     int len = array->number_of_entries();
315     for (int number = 0; number < len; number++) {
316       int sorted_index = array->GetSortedKeyIndex(number);
317       Name entry = array->GetKey(InternalIndex(sorted_index));
318       uint32_t current_hash = entry.hash();
319       if (current_hash > hash) {
320         *out_insertion_index = sorted_index;
321         return T::kNotFound;
322       }
323       if (entry == name) return sorted_index;
324     }
325     *out_insertion_index = len;
326     return T::kNotFound;
327   } else {
328     DCHECK_LE(valid_entries, array->number_of_entries());
329     DCHECK_NULL(out_insertion_index);  // Not supported here.
330     for (int number = 0; number < valid_entries; number++) {
331       if (array->GetKey(InternalIndex(number)) == name) return number;
332     }
333     return T::kNotFound;
334   }
335 }
336 
337 template <SearchMode search_mode, typename T>
Search(T * array,Name name,int valid_entries,int * out_insertion_index,bool concurrent_search)338 int Search(T* array, Name name, int valid_entries, int* out_insertion_index,
339            bool concurrent_search) {
340   SLOW_DCHECK_IMPLIES(!concurrent_search, array->IsSortedNoDuplicates());
341 
342   if (valid_entries == 0) {
343     if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
344       *out_insertion_index = 0;
345     }
346     return T::kNotFound;
347   }
348 
349   // Do linear search for small arrays, and for searches in the background
350   // thread.
351   const int kMaxElementsForLinearSearch = 8;
352   if (valid_entries <= kMaxElementsForLinearSearch || concurrent_search) {
353     return LinearSearch<search_mode>(array, name, valid_entries,
354                                      out_insertion_index);
355   }
356 
357   return BinarySearch<search_mode>(array, name, valid_entries,
358                                    out_insertion_index);
359 }
360 
get_scalar(int index)361 double FixedDoubleArray::get_scalar(int index) {
362   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
363          map() != GetReadOnlyRoots().fixed_array_map());
364   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
365   DCHECK(!is_the_hole(index));
366   return ReadField<double>(kHeaderSize + index * kDoubleSize);
367 }
368 
get_representation(int index)369 uint64_t FixedDoubleArray::get_representation(int index) {
370   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
371          map() != GetReadOnlyRoots().fixed_array_map());
372   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
373   int offset = kHeaderSize + index * kDoubleSize;
374   // Bug(v8:8875): Doubles may be unaligned.
375   return base::ReadUnalignedValue<uint64_t>(field_address(offset));
376 }
377 
get(FixedDoubleArray array,int index,Isolate * isolate)378 Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
379                                      Isolate* isolate) {
380   if (array.is_the_hole(index)) {
381     return ReadOnlyRoots(isolate).the_hole_value_handle();
382   } else {
383     return isolate->factory()->NewNumber(array.get_scalar(index));
384   }
385 }
386 
set(int index,double value)387 void FixedDoubleArray::set(int index, double value) {
388   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
389          map() != GetReadOnlyRoots().fixed_array_map());
390   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
391   int offset = kHeaderSize + index * kDoubleSize;
392   if (std::isnan(value)) {
393     WriteField<double>(offset, std::numeric_limits<double>::quiet_NaN());
394   } else {
395     WriteField<double>(offset, value);
396   }
397   DCHECK(!is_the_hole(index));
398 }
399 
set_the_hole(Isolate * isolate,int index)400 void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
401   set_the_hole(index);
402 }
403 
set_the_hole(int index)404 void FixedDoubleArray::set_the_hole(int index) {
405   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
406          map() != GetReadOnlyRoots().fixed_array_map());
407   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
408   int offset = kHeaderSize + index * kDoubleSize;
409   base::WriteUnalignedValue<uint64_t>(field_address(offset), kHoleNanInt64);
410 }
411 
is_the_hole(Isolate * isolate,int index)412 bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
413   return is_the_hole(index);
414 }
415 
is_the_hole(int index)416 bool FixedDoubleArray::is_the_hole(int index) {
417   return get_representation(index) == kHoleNanInt64;
418 }
419 
MoveElements(Isolate * isolate,int dst_index,int src_index,int len,WriteBarrierMode mode)420 void FixedDoubleArray::MoveElements(Isolate* isolate, int dst_index,
421                                     int src_index, int len,
422                                     WriteBarrierMode mode) {
423   DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
424   double* data_start = reinterpret_cast<double*>(field_address(kHeaderSize));
425   MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
426 }
427 
FillWithHoles(int from,int to)428 void FixedDoubleArray::FillWithHoles(int from, int to) {
429   for (int i = from; i < to; i++) {
430     set_the_hole(i);
431   }
432 }
433 
Get(int index)434 MaybeObject WeakFixedArray::Get(int index) const {
435   PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
436   return Get(cage_base, index);
437 }
438 
Get(PtrComprCageBase cage_base,int index)439 MaybeObject WeakFixedArray::Get(PtrComprCageBase cage_base, int index) const {
440   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
441   return objects(cage_base, index, kRelaxedLoad);
442 }
443 
Set(int index,MaybeObject value,WriteBarrierMode mode)444 void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
445   set_objects(index, value, mode);
446 }
447 
EnsureSpace(Isolate * isolate,Handle<WeakFixedArray> array,int length)448 Handle<WeakFixedArray> WeakFixedArray::EnsureSpace(Isolate* isolate,
449                                                    Handle<WeakFixedArray> array,
450                                                    int length) {
451   if (array->length() < length) {
452     int grow_by = length - array->length();
453     array = isolate->factory()->CopyWeakFixedArrayAndGrow(array, grow_by);
454   }
455   return array;
456 }
457 
data_start()458 MaybeObjectSlot WeakFixedArray::data_start() {
459   return RawMaybeWeakField(kObjectsOffset);
460 }
461 
RawFieldOfElementAt(int index)462 MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
463   return RawMaybeWeakField(OffsetOfElementAt(index));
464 }
465 
CopyElements(Isolate * isolate,int dst_index,WeakFixedArray src,int src_index,int len,WriteBarrierMode mode)466 void WeakFixedArray::CopyElements(Isolate* isolate, int dst_index,
467                                   WeakFixedArray src, int src_index, int len,
468                                   WriteBarrierMode mode) {
469   if (len == 0) return;
470   DCHECK_LE(dst_index + len, length());
471   DCHECK_LE(src_index + len, src.length());
472   DisallowGarbageCollection no_gc;
473 
474   MaybeObjectSlot dst_slot(data_start() + dst_index);
475   MaybeObjectSlot src_slot(src.data_start() + src_index);
476   isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
477 }
478 
Get(int index)479 MaybeObject WeakArrayList::Get(int index) const {
480   PtrComprCageBase cage_base = GetPtrComprCageBase(*this);
481   return Get(cage_base, index);
482 }
483 
Get(PtrComprCageBase cage_base,int index)484 MaybeObject WeakArrayList::Get(PtrComprCageBase cage_base, int index) const {
485   DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(capacity()));
486   return objects(cage_base, index, kRelaxedLoad);
487 }
488 
Set(int index,MaybeObject value,WriteBarrierMode mode)489 void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
490   set_objects(index, value, mode);
491 }
492 
Set(int index,Smi value)493 void WeakArrayList::Set(int index, Smi value) {
494   Set(index, MaybeObject::FromSmi(value), SKIP_WRITE_BARRIER);
495 }
496 
data_start()497 MaybeObjectSlot WeakArrayList::data_start() {
498   return RawMaybeWeakField(kObjectsOffset);
499 }
500 
CopyElements(Isolate * isolate,int dst_index,WeakArrayList src,int src_index,int len,WriteBarrierMode mode)501 void WeakArrayList::CopyElements(Isolate* isolate, int dst_index,
502                                  WeakArrayList src, int src_index, int len,
503                                  WriteBarrierMode mode) {
504   if (len == 0) return;
505   DCHECK_LE(dst_index + len, capacity());
506   DCHECK_LE(src_index + len, src.capacity());
507   DisallowGarbageCollection no_gc;
508 
509   MaybeObjectSlot dst_slot(data_start() + dst_index);
510   MaybeObjectSlot src_slot(src.data_start() + src_index);
511   isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
512 }
513 
Next()514 HeapObject WeakArrayList::Iterator::Next() {
515   if (!array_.is_null()) {
516     while (index_ < array_.length()) {
517       MaybeObject item = array_.Get(index_++);
518       DCHECK(item->IsWeakOrCleared());
519       if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
520     }
521     array_ = WeakArrayList();
522   }
523   return HeapObject();
524 }
525 
Length()526 int ArrayList::Length() const {
527   if (FixedArray::cast(*this).length() == 0) return 0;
528   return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
529 }
530 
SetLength(int length)531 void ArrayList::SetLength(int length) {
532   return FixedArray::cast(*this).set(kLengthIndex, Smi::FromInt(length));
533 }
534 
Get(int index)535 Object ArrayList::Get(int index) const {
536   return FixedArray::cast(*this).get(kFirstIndex + index);
537 }
538 
Get(PtrComprCageBase cage_base,int index)539 Object ArrayList::Get(PtrComprCageBase cage_base, int index) const {
540   return FixedArray::cast(*this).get(cage_base, kFirstIndex + index);
541 }
542 
Slot(int index)543 ObjectSlot ArrayList::Slot(int index) {
544   return RawField(OffsetOfElementAt(kFirstIndex + index));
545 }
546 
Set(int index,Object obj,WriteBarrierMode mode)547 void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
548   FixedArray::cast(*this).set(kFirstIndex + index, obj, mode);
549 }
550 
Set(int index,Smi value)551 void ArrayList::Set(int index, Smi value) {
552   DCHECK(Object(value).IsSmi());
553   Set(index, value, SKIP_WRITE_BARRIER);
554 }
Clear(int index,Object undefined)555 void ArrayList::Clear(int index, Object undefined) {
556   DCHECK(undefined.IsUndefined());
557   FixedArray::cast(*this).set(kFirstIndex + index, undefined,
558                               SKIP_WRITE_BARRIER);
559 }
560 
Size()561 int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
562 
get(int index)563 byte ByteArray::get(int index) const {
564   DCHECK_GE(index, 0);
565   DCHECK_LT(index, length());
566   return ReadField<byte>(kHeaderSize + index * kCharSize);
567 }
568 
set(int index,byte value)569 void ByteArray::set(int index, byte value) {
570   DCHECK_GE(index, 0);
571   DCHECK_LT(index, length());
572   WriteField<byte>(kHeaderSize + index * kCharSize, value);
573 }
574 
copy_in(int index,const byte * buffer,int slice_length)575 void ByteArray::copy_in(int index, const byte* buffer, int slice_length) {
576   DCHECK_GE(index, 0);
577   DCHECK_GE(slice_length, 0);
578   DCHECK_LE(slice_length, kMaxInt - index);
579   DCHECK_LE(index + slice_length, length());
580   Address dst_addr = field_address(kHeaderSize + index * kCharSize);
581   memcpy(reinterpret_cast<void*>(dst_addr), buffer, slice_length);
582 }
583 
copy_out(int index,byte * buffer,int slice_length)584 void ByteArray::copy_out(int index, byte* buffer, int slice_length) {
585   DCHECK_GE(index, 0);
586   DCHECK_GE(slice_length, 0);
587   DCHECK_LE(slice_length, kMaxInt - index);
588   DCHECK_LE(index + slice_length, length());
589   Address src_addr = field_address(kHeaderSize + index * kCharSize);
590   memcpy(buffer, reinterpret_cast<void*>(src_addr), slice_length);
591 }
592 
get_int(int index)593 int ByteArray::get_int(int index) const {
594   DCHECK_GE(index, 0);
595   DCHECK_LT(index, length() / kIntSize);
596   return ReadField<int>(kHeaderSize + index * kIntSize);
597 }
598 
set_int(int index,int value)599 void ByteArray::set_int(int index, int value) {
600   DCHECK_GE(index, 0);
601   DCHECK_LT(index, length() / kIntSize);
602   WriteField<int>(kHeaderSize + index * kIntSize, value);
603 }
604 
get_uint32(int index)605 uint32_t ByteArray::get_uint32(int index) const {
606   DCHECK_GE(index, 0);
607   DCHECK_LT(index, length() / kUInt32Size);
608   return ReadField<uint32_t>(kHeaderSize + index * kUInt32Size);
609 }
610 
set_uint32(int index,uint32_t value)611 void ByteArray::set_uint32(int index, uint32_t value) {
612   DCHECK_GE(index, 0);
613   DCHECK_LT(index, length() / kUInt32Size);
614   WriteField<uint32_t>(kHeaderSize + index * kUInt32Size, value);
615 }
616 
get_uint32_relaxed(int index)617 uint32_t ByteArray::get_uint32_relaxed(int index) const {
618   DCHECK_GE(index, 0);
619   DCHECK_LT(index, length() / kUInt32Size);
620   return RELAXED_READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
621 }
622 
set_uint32_relaxed(int index,uint32_t value)623 void ByteArray::set_uint32_relaxed(int index, uint32_t value) {
624   DCHECK_GE(index, 0);
625   DCHECK_LT(index, length() / kUInt32Size);
626   RELAXED_WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
627 }
628 
get_uint16(int index)629 uint16_t ByteArray::get_uint16(int index) const {
630   DCHECK_GE(index, 0);
631   DCHECK_LT(index, length() / kUInt16Size);
632   return ReadField<uint16_t>(kHeaderSize + index * kUInt16Size);
633 }
634 
set_uint16(int index,uint16_t value)635 void ByteArray::set_uint16(int index, uint16_t value) {
636   DCHECK_GE(index, 0);
637   DCHECK_LT(index, length() / kUInt16Size);
638   WriteField<uint16_t>(kHeaderSize + index * kUInt16Size, value);
639 }
640 
clear_padding()641 void ByteArray::clear_padding() {
642   int data_size = length() + kHeaderSize;
643   memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
644 }
645 
FromDataStartAddress(Address address)646 ByteArray ByteArray::FromDataStartAddress(Address address) {
647   DCHECK_TAG_ALIGNED(address);
648   return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
649 }
650 
DataSize()651 int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
652 
ByteArraySize()653 int ByteArray::ByteArraySize() { return SizeFor(length()); }
654 
GetDataStartAddress()655 byte* ByteArray::GetDataStartAddress() {
656   return reinterpret_cast<byte*>(address() + kHeaderSize);
657 }
658 
GetDataEndAddress()659 byte* ByteArray::GetDataEndAddress() {
660   return GetDataStartAddress() + length();
661 }
662 
663 template <class T>
PodArray(Address ptr)664 PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
665 
666 template <class T>
cast(Object object)667 PodArray<T> PodArray<T>::cast(Object object) {
668   return PodArray<T>(object.ptr());
669 }
670 
671 // static
672 template <class T>
New(Isolate * isolate,int length,AllocationType allocation)673 Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
674                                      AllocationType allocation) {
675   return Handle<PodArray<T>>::cast(
676       isolate->factory()->NewByteArray(length * sizeof(T), allocation));
677 }
678 
679 template <class T>
length()680 int PodArray<T>::length() const {
681   return ByteArray::length() / sizeof(T);
682 }
683 
length()684 int TemplateList::length() const {
685   return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
686 }
687 
get(int index)688 Object TemplateList::get(int index) const {
689   return FixedArray::cast(*this).get(kFirstElementIndex + index);
690 }
691 
get(PtrComprCageBase cage_base,int index)692 Object TemplateList::get(PtrComprCageBase cage_base, int index) const {
693   return FixedArray::cast(*this).get(cage_base, kFirstElementIndex + index);
694 }
695 
set(int index,Object value)696 void TemplateList::set(int index, Object value) {
697   FixedArray::cast(*this).set(kFirstElementIndex + index, value);
698 }
699 
700 }  // namespace internal
701 }  // namespace v8
702 
703 #include "src/base/platform/wrappers.h"
704 #include "src/objects/object-macros-undef.h"
705 
706 #endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_
707