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