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