• 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/objects-inl.h"  // Needed for write barriers
11 #include "src/objects/bigint.h"
12 #include "src/objects/maybe-object-inl.h"
13 
14 // Has to be the last include (doesn't have include guards):
15 #include "src/objects/object-macros.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(ByteArray)21 CAST_ACCESSOR(ByteArray)
22 CAST_ACCESSOR(FixedArray)
23 CAST_ACCESSOR(FixedArrayBase)
24 CAST_ACCESSOR(FixedDoubleArray)
25 CAST_ACCESSOR(FixedTypedArrayBase)
26 CAST_ACCESSOR(TemplateList)
27 CAST_ACCESSOR(WeakFixedArray)
28 CAST_ACCESSOR(WeakArrayList)
29 
30 SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
31 SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
32 SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
33 SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
34 
35 SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
36 SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
37 SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
38 
39 Object* FixedArrayBase::unchecked_synchronized_length() const {
40   return ACQUIRE_READ_FIELD(this, kLengthOffset);
41 }
42 
ACCESSORS(FixedTypedArrayBase,base_pointer,Object,kBasePointerOffset)43 ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
44 
45 Object** FixedArray::GetFirstElementAddress() {
46   return reinterpret_cast<Object**>(FIELD_ADDR(this, OffsetOfElementAt(0)));
47 }
48 
ContainsOnlySmisOrHoles()49 bool FixedArray::ContainsOnlySmisOrHoles() {
50   Object* the_hole = GetReadOnlyRoots().the_hole_value();
51   Object** current = GetFirstElementAddress();
52   for (int i = 0; i < length(); ++i) {
53     Object* candidate = *current++;
54     if (!candidate->IsSmi() && candidate != the_hole) return false;
55   }
56   return true;
57 }
58 
get(int index)59 Object* FixedArray::get(int index) const {
60   DCHECK(index >= 0 && index < this->length());
61   return RELAXED_READ_FIELD(this, kHeaderSize + index * kPointerSize);
62 }
63 
get(FixedArray * array,int index,Isolate * isolate)64 Handle<Object> FixedArray::get(FixedArray* array, int index, Isolate* isolate) {
65   return handle(array->get(index), isolate);
66 }
67 
68 template <class T>
GetValue(Isolate * isolate,int index)69 MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
70   Object* obj = get(index);
71   if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
72   return Handle<T>(T::cast(obj), isolate);
73 }
74 
75 template <class T>
GetValueChecked(Isolate * isolate,int index)76 Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
77   Object* obj = get(index);
78   CHECK(!obj->IsUndefined(isolate));
79   return Handle<T>(T::cast(obj), isolate);
80 }
81 
is_the_hole(Isolate * isolate,int index)82 bool FixedArray::is_the_hole(Isolate* isolate, int index) {
83   return get(index)->IsTheHole(isolate);
84 }
85 
set(int index,Smi * value)86 void FixedArray::set(int index, Smi* value) {
87   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
88   DCHECK_LT(index, this->length());
89   DCHECK(reinterpret_cast<Object*>(value)->IsSmi());
90   int offset = kHeaderSize + index * kPointerSize;
91   RELAXED_WRITE_FIELD(this, offset, value);
92 }
93 
set(int index,Object * value)94 void FixedArray::set(int index, Object* value) {
95   DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
96   DCHECK(IsFixedArray());
97   DCHECK_GE(index, 0);
98   DCHECK_LT(index, this->length());
99   int offset = kHeaderSize + index * kPointerSize;
100   RELAXED_WRITE_FIELD(this, offset, value);
101   WRITE_BARRIER(this, offset, value);
102 }
103 
set(int index,Object * value,WriteBarrierMode mode)104 void FixedArray::set(int index, Object* value, WriteBarrierMode mode) {
105   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
106   DCHECK_GE(index, 0);
107   DCHECK_LT(index, this->length());
108   int offset = kHeaderSize + index * kPointerSize;
109   RELAXED_WRITE_FIELD(this, offset, value);
110   CONDITIONAL_WRITE_BARRIER(this, offset, value, mode);
111 }
112 
NoWriteBarrierSet(FixedArray * array,int index,Object * value)113 void FixedArray::NoWriteBarrierSet(FixedArray* array, int index,
114                                    Object* value) {
115   DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
116   DCHECK_GE(index, 0);
117   DCHECK_LT(index, array->length());
118   DCHECK(!Heap::InNewSpace(value));
119   RELAXED_WRITE_FIELD(array, kHeaderSize + index * kPointerSize, value);
120 }
121 
set_undefined(int index)122 void FixedArray::set_undefined(int index) {
123   set_undefined(GetReadOnlyRoots(), index);
124 }
125 
set_undefined(Isolate * isolate,int index)126 void FixedArray::set_undefined(Isolate* isolate, int index) {
127   set_undefined(ReadOnlyRoots(isolate), index);
128 }
129 
set_undefined(ReadOnlyRoots ro_roots,int index)130 void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
131   FixedArray::NoWriteBarrierSet(this, index, ro_roots.undefined_value());
132 }
133 
set_null(int index)134 void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
135 
set_null(Isolate * isolate,int index)136 void FixedArray::set_null(Isolate* isolate, int index) {
137   set_null(ReadOnlyRoots(isolate), index);
138 }
139 
set_null(ReadOnlyRoots ro_roots,int index)140 void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
141   FixedArray::NoWriteBarrierSet(this, index, ro_roots.null_value());
142 }
143 
set_the_hole(int index)144 void FixedArray::set_the_hole(int index) {
145   set_the_hole(GetReadOnlyRoots(), index);
146 }
147 
set_the_hole(Isolate * isolate,int index)148 void FixedArray::set_the_hole(Isolate* isolate, int index) {
149   set_the_hole(ReadOnlyRoots(isolate), index);
150 }
151 
set_the_hole(ReadOnlyRoots ro_roots,int index)152 void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
153   FixedArray::NoWriteBarrierSet(this, index, ro_roots.the_hole_value());
154 }
155 
FillWithHoles(int from,int to)156 void FixedArray::FillWithHoles(int from, int to) {
157   for (int i = from; i < to; i++) {
158     set_the_hole(i);
159   }
160 }
161 
data_start()162 Object** FixedArray::data_start() {
163   return HeapObject::RawField(this, OffsetOfElementAt(0));
164 }
165 
RawFieldOfElementAt(int index)166 Object** FixedArray::RawFieldOfElementAt(int index) {
167   return HeapObject::RawField(this, OffsetOfElementAt(index));
168 }
169 
get_scalar(int index)170 double FixedDoubleArray::get_scalar(int index) {
171   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
172          map() != GetReadOnlyRoots().fixed_array_map());
173   DCHECK(index >= 0 && index < this->length());
174   DCHECK(!is_the_hole(index));
175   return READ_DOUBLE_FIELD(this, kHeaderSize + index * kDoubleSize);
176 }
177 
get_representation(int index)178 uint64_t FixedDoubleArray::get_representation(int index) {
179   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
180          map() != GetReadOnlyRoots().fixed_array_map());
181   DCHECK(index >= 0 && index < this->length());
182   int offset = kHeaderSize + index * kDoubleSize;
183   return READ_UINT64_FIELD(this, offset);
184 }
185 
get(FixedDoubleArray * array,int index,Isolate * isolate)186 Handle<Object> FixedDoubleArray::get(FixedDoubleArray* array, int index,
187                                      Isolate* isolate) {
188   if (array->is_the_hole(index)) {
189     return isolate->factory()->the_hole_value();
190   } else {
191     return isolate->factory()->NewNumber(array->get_scalar(index));
192   }
193 }
194 
set(int index,double value)195 void FixedDoubleArray::set(int index, double value) {
196   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
197          map() != GetReadOnlyRoots().fixed_array_map());
198   int offset = kHeaderSize + index * kDoubleSize;
199   if (std::isnan(value)) {
200     WRITE_DOUBLE_FIELD(this, offset, std::numeric_limits<double>::quiet_NaN());
201   } else {
202     WRITE_DOUBLE_FIELD(this, offset, value);
203   }
204   DCHECK(!is_the_hole(index));
205 }
206 
set_the_hole(Isolate * isolate,int index)207 void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
208   set_the_hole(index);
209 }
210 
set_the_hole(int index)211 void FixedDoubleArray::set_the_hole(int index) {
212   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
213          map() != GetReadOnlyRoots().fixed_array_map());
214   int offset = kHeaderSize + index * kDoubleSize;
215   WRITE_UINT64_FIELD(this, offset, kHoleNanInt64);
216 }
217 
is_the_hole(Isolate * isolate,int index)218 bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
219   return is_the_hole(index);
220 }
221 
is_the_hole(int index)222 bool FixedDoubleArray::is_the_hole(int index) {
223   return get_representation(index) == kHoleNanInt64;
224 }
225 
data_start()226 double* FixedDoubleArray::data_start() {
227   return reinterpret_cast<double*>(FIELD_ADDR(this, kHeaderSize));
228 }
229 
FillWithHoles(int from,int to)230 void FixedDoubleArray::FillWithHoles(int from, int to) {
231   for (int i = from; i < to; i++) {
232     set_the_hole(i);
233   }
234 }
235 
Get(int index)236 MaybeObject* WeakFixedArray::Get(int index) const {
237   DCHECK(index >= 0 && index < this->length());
238   return RELAXED_READ_WEAK_FIELD(this, OffsetOfElementAt(index));
239 }
240 
Set(int index,MaybeObject * value)241 void WeakFixedArray::Set(int index, MaybeObject* value) {
242   DCHECK_GE(index, 0);
243   DCHECK_LT(index, length());
244   int offset = OffsetOfElementAt(index);
245   RELAXED_WRITE_FIELD(this, offset, value);
246   WEAK_WRITE_BARRIER(this, offset, value);
247 }
248 
Set(int index,MaybeObject * value,WriteBarrierMode mode)249 void WeakFixedArray::Set(int index, MaybeObject* value, WriteBarrierMode mode) {
250   DCHECK_GE(index, 0);
251   DCHECK_LT(index, length());
252   int offset = OffsetOfElementAt(index);
253   RELAXED_WRITE_FIELD(this, offset, value);
254   CONDITIONAL_WEAK_WRITE_BARRIER(this, offset, value, mode);
255 }
256 
data_start()257 MaybeObject** WeakFixedArray::data_start() {
258   return HeapObject::RawMaybeWeakField(this, kHeaderSize);
259 }
260 
RawFieldOfElementAt(int index)261 MaybeObject** WeakFixedArray::RawFieldOfElementAt(int index) {
262   return HeapObject::RawMaybeWeakField(this, OffsetOfElementAt(index));
263 }
264 
GetFirstElementAddress()265 MaybeObject** WeakFixedArray::GetFirstElementAddress() {
266   return reinterpret_cast<MaybeObject**>(
267       FIELD_ADDR(this, OffsetOfElementAt(0)));
268 }
269 
Get(int index)270 MaybeObject* WeakArrayList::Get(int index) const {
271   DCHECK(index >= 0 && index < this->capacity());
272   return RELAXED_READ_WEAK_FIELD(this, OffsetOfElementAt(index));
273 }
274 
Set(int index,MaybeObject * value,WriteBarrierMode mode)275 void WeakArrayList::Set(int index, MaybeObject* value, WriteBarrierMode mode) {
276   DCHECK_GE(index, 0);
277   DCHECK_LT(index, this->capacity());
278   int offset = OffsetOfElementAt(index);
279   RELAXED_WRITE_FIELD(this, offset, value);
280   CONDITIONAL_WEAK_WRITE_BARRIER(this, offset, value, mode);
281 }
282 
data_start()283 MaybeObject** WeakArrayList::data_start() {
284   return HeapObject::RawMaybeWeakField(this, kHeaderSize);
285 }
286 
Next()287 HeapObject* WeakArrayList::Iterator::Next() {
288   if (array_ != nullptr) {
289     while (index_ < array_->length()) {
290       MaybeObject* item = array_->Get(index_++);
291       DCHECK(item->IsWeakHeapObject() || item->IsClearedWeakHeapObject());
292       if (!item->IsClearedWeakHeapObject()) return item->ToWeakHeapObject();
293     }
294     array_ = nullptr;
295   }
296   return nullptr;
297 }
298 
Length()299 int ArrayList::Length() const {
300   if (FixedArray::cast(this)->length() == 0) return 0;
301   return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
302 }
303 
SetLength(int length)304 void ArrayList::SetLength(int length) {
305   return FixedArray::cast(this)->set(kLengthIndex, Smi::FromInt(length));
306 }
307 
Get(int index)308 Object* ArrayList::Get(int index) const {
309   return FixedArray::cast(this)->get(kFirstIndex + index);
310 }
311 
Slot(int index)312 Object** ArrayList::Slot(int index) {
313   return data_start() + kFirstIndex + index;
314 }
315 
Set(int index,Object * obj,WriteBarrierMode mode)316 void ArrayList::Set(int index, Object* obj, WriteBarrierMode mode) {
317   FixedArray::cast(this)->set(kFirstIndex + index, obj, mode);
318 }
319 
Clear(int index,Object * undefined)320 void ArrayList::Clear(int index, Object* undefined) {
321   DCHECK(undefined->IsUndefined());
322   FixedArray::cast(this)->set(kFirstIndex + index, undefined,
323                               SKIP_WRITE_BARRIER);
324 }
325 
Size()326 int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kPointerSize); }
327 
get(int index)328 byte ByteArray::get(int index) const {
329   DCHECK(index >= 0 && index < this->length());
330   return READ_BYTE_FIELD(this, kHeaderSize + index * kCharSize);
331 }
332 
set(int index,byte value)333 void ByteArray::set(int index, byte value) {
334   DCHECK(index >= 0 && index < this->length());
335   WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize, value);
336 }
337 
copy_in(int index,const byte * buffer,int length)338 void ByteArray::copy_in(int index, const byte* buffer, int length) {
339   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
340          index + length <= this->length());
341   Address dst_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
342   memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
343 }
344 
copy_out(int index,byte * buffer,int length)345 void ByteArray::copy_out(int index, byte* buffer, int length) {
346   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
347          index + length <= this->length());
348   Address src_addr = FIELD_ADDR(this, kHeaderSize + index * kCharSize);
349   memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
350 }
351 
get_int(int index)352 int ByteArray::get_int(int index) const {
353   DCHECK(index >= 0 && index < this->length() / kIntSize);
354   return READ_INT_FIELD(this, kHeaderSize + index * kIntSize);
355 }
356 
set_int(int index,int value)357 void ByteArray::set_int(int index, int value) {
358   DCHECK(index >= 0 && index < this->length() / kIntSize);
359   WRITE_INT_FIELD(this, kHeaderSize + index * kIntSize, value);
360 }
361 
get_uint32(int index)362 uint32_t ByteArray::get_uint32(int index) const {
363   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
364   return READ_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size);
365 }
366 
set_uint32(int index,uint32_t value)367 void ByteArray::set_uint32(int index, uint32_t value) {
368   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
369   WRITE_UINT32_FIELD(this, kHeaderSize + index * kUInt32Size, value);
370 }
371 
clear_padding()372 void ByteArray::clear_padding() {
373   int data_size = length() + kHeaderSize;
374   memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
375 }
376 
FromDataStartAddress(Address address)377 ByteArray* ByteArray::FromDataStartAddress(Address address) {
378   DCHECK_TAG_ALIGNED(address);
379   return reinterpret_cast<ByteArray*>(address - kHeaderSize + kHeapObjectTag);
380 }
381 
DataSize()382 int ByteArray::DataSize() const { return RoundUp(length(), kPointerSize); }
383 
ByteArraySize()384 int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
385 
GetDataStartAddress()386 byte* ByteArray::GetDataStartAddress() {
387   return reinterpret_cast<byte*>(address() + kHeaderSize);
388 }
389 
390 template <class T>
cast(Object * object)391 PodArray<T>* PodArray<T>::cast(Object* object) {
392   DCHECK(object->IsByteArray());
393   return reinterpret_cast<PodArray<T>*>(object);
394 }
395 template <class T>
cast(const Object * object)396 const PodArray<T>* PodArray<T>::cast(const Object* object) {
397   DCHECK(object->IsByteArray());
398   return reinterpret_cast<const PodArray<T>*>(object);
399 }
400 
401 // static
402 template <class T>
New(Isolate * isolate,int length,PretenureFlag pretenure)403 Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
404                                      PretenureFlag pretenure) {
405   return Handle<PodArray<T>>::cast(
406       isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
407 }
408 
409 template <class T>
length()410 int PodArray<T>::length() {
411   return ByteArray::length() / sizeof(T);
412 }
413 
external_pointer()414 void* FixedTypedArrayBase::external_pointer() const {
415   intptr_t ptr = READ_INTPTR_FIELD(this, kExternalPointerOffset);
416   return reinterpret_cast<void*>(ptr);
417 }
418 
set_external_pointer(void * value,WriteBarrierMode mode)419 void FixedTypedArrayBase::set_external_pointer(void* value,
420                                                WriteBarrierMode mode) {
421   intptr_t ptr = reinterpret_cast<intptr_t>(value);
422   WRITE_INTPTR_FIELD(this, kExternalPointerOffset, ptr);
423 }
424 
DataPtr()425 void* FixedTypedArrayBase::DataPtr() {
426   return reinterpret_cast<void*>(
427       reinterpret_cast<intptr_t>(base_pointer()) +
428       reinterpret_cast<intptr_t>(external_pointer()));
429 }
430 
ElementSize(InstanceType type)431 int FixedTypedArrayBase::ElementSize(InstanceType type) {
432   int element_size;
433   switch (type) {
434 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
435   case FIXED_##TYPE##_ARRAY_TYPE:                 \
436     element_size = sizeof(ctype);                 \
437     break;
438 
439     TYPED_ARRAYS(TYPED_ARRAY_CASE)
440 #undef TYPED_ARRAY_CASE
441     default:
442       UNREACHABLE();
443   }
444   return element_size;
445 }
446 
DataSize(InstanceType type)447 int FixedTypedArrayBase::DataSize(InstanceType type) const {
448   if (base_pointer() == Smi::kZero) return 0;
449   return length() * ElementSize(type);
450 }
451 
DataSize()452 int FixedTypedArrayBase::DataSize() const {
453   return DataSize(map()->instance_type());
454 }
455 
ByteLength()456 size_t FixedTypedArrayBase::ByteLength() const {
457   return static_cast<size_t>(length()) *
458          static_cast<size_t>(ElementSize(map()->instance_type()));
459 }
460 
size()461 int FixedTypedArrayBase::size() const {
462   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
463 }
464 
TypedArraySize(InstanceType type)465 int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
466   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
467 }
468 
469 // static
TypedArraySize(InstanceType type,int length)470 int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
471   return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
472 }
473 
defaultValue()474 uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
475 
defaultValue()476 uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
477 
defaultValue()478 int8_t Int8ArrayTraits::defaultValue() { return 0; }
479 
defaultValue()480 uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
481 
defaultValue()482 int16_t Int16ArrayTraits::defaultValue() { return 0; }
483 
defaultValue()484 uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
485 
defaultValue()486 int32_t Int32ArrayTraits::defaultValue() { return 0; }
487 
defaultValue()488 float Float32ArrayTraits::defaultValue() {
489   return std::numeric_limits<float>::quiet_NaN();
490 }
491 
defaultValue()492 double Float64ArrayTraits::defaultValue() {
493   return std::numeric_limits<double>::quiet_NaN();
494 }
495 
496 template <class Traits>
get_scalar(int index)497 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
498   DCHECK((index >= 0) && (index < this->length()));
499   return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
500 }
501 
502 // static
503 template <class Traits>
get_scalar_from_data_ptr(void * data_ptr,int index)504 typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
505     void* data_ptr, int index) {
506   typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
507   // The JavaScript memory model allows for racy reads and writes to a
508   // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
509   // ThreadSanitizer will catch these racy accesses and warn about them, so we
510   // disable TSAN for these reads and writes using annotations.
511   //
512   // We don't use relaxed atomics here, as it is not a requirement of the
513   // JavaScript memory model to have tear-free reads of overlapping accesses,
514   // and using relaxed atomics may introduce overhead.
515   TSAN_ANNOTATE_IGNORE_READS_BEGIN;
516   auto result = ptr[index];
517   TSAN_ANNOTATE_IGNORE_READS_END;
518   return result;
519 }
520 
521 template <class Traits>
set(int index,ElementType value)522 void FixedTypedArray<Traits>::set(int index, ElementType value) {
523   CHECK((index >= 0) && (index < this->length()));
524   // See the comment in FixedTypedArray<Traits>::get_scalar.
525   auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
526   TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
527   ptr[index] = value;
528   TSAN_ANNOTATE_IGNORE_WRITES_END;
529 }
530 
531 template <class Traits>
from(int value)532 typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
533   return static_cast<ElementType>(value);
534 }
535 
536 template <>
from(int value)537 inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
538   if (value < 0) return 0;
539   if (value > 0xFF) return 0xFF;
540   return static_cast<uint8_t>(value);
541 }
542 
543 template <>
from(int value)544 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
545   UNREACHABLE();
546 }
547 
548 template <>
from(int value)549 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
550   UNREACHABLE();
551 }
552 
553 template <class Traits>
from(uint32_t value)554 typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
555   return static_cast<ElementType>(value);
556 }
557 
558 template <>
from(uint32_t value)559 inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
560   // We need this special case for Uint32 -> Uint8Clamped, because the highest
561   // Uint32 values will be negative as an int, clamping to 0, rather than 255.
562   if (value > 0xFF) return 0xFF;
563   return static_cast<uint8_t>(value);
564 }
565 
566 template <>
from(uint32_t value)567 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
568   UNREACHABLE();
569 }
570 
571 template <>
from(uint32_t value)572 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
573   UNREACHABLE();
574 }
575 
576 template <class Traits>
from(double value)577 typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
578   return static_cast<ElementType>(DoubleToInt32(value));
579 }
580 
581 template <>
from(double value)582 inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
583   // Handle NaNs and less than zero values which clamp to zero.
584   if (!(value > 0)) return 0;
585   if (value > 0xFF) return 0xFF;
586   return static_cast<uint8_t>(lrint(value));
587 }
588 
589 template <>
from(double value)590 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
591   UNREACHABLE();
592 }
593 
594 template <>
from(double value)595 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
596   UNREACHABLE();
597 }
598 
599 template <>
from(double value)600 inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
601   return static_cast<float>(value);
602 }
603 
604 template <>
from(double value)605 inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
606   return value;
607 }
608 
609 template <class Traits>
from(int64_t value)610 typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
611   UNREACHABLE();
612 }
613 
614 template <class Traits>
from(uint64_t value)615 typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
616   UNREACHABLE();
617 }
618 
619 template <>
from(int64_t value)620 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
621   return value;
622 }
623 
624 template <>
from(uint64_t value)625 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
626   return value;
627 }
628 
629 template <>
from(int64_t value)630 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
631   return static_cast<uint64_t>(value);
632 }
633 
634 template <>
from(uint64_t value)635 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
636   return static_cast<int64_t>(value);
637 }
638 
639 template <class Traits>
FromHandle(Handle<Object> value,bool * lossless)640 typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
641     Handle<Object> value, bool* lossless) {
642   if (value->IsSmi()) {
643     return from(Smi::ToInt(*value));
644   }
645   DCHECK(value->IsHeapNumber());
646   return from(HeapNumber::cast(*value)->value());
647 }
648 
649 template <>
FromHandle(Handle<Object> value,bool * lossless)650 inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
651     Handle<Object> value, bool* lossless) {
652   DCHECK(value->IsBigInt());
653   return BigInt::cast(*value)->AsInt64(lossless);
654 }
655 
656 template <>
FromHandle(Handle<Object> value,bool * lossless)657 inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
658     Handle<Object> value, bool* lossless) {
659   DCHECK(value->IsBigInt());
660   return BigInt::cast(*value)->AsUint64(lossless);
661 }
662 
663 template <class Traits>
get(Isolate * isolate,FixedTypedArray<Traits> * array,int index)664 Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
665                                             FixedTypedArray<Traits>* array,
666                                             int index) {
667   return Traits::ToHandle(isolate, array->get_scalar(index));
668 }
669 
670 template <class Traits>
SetValue(uint32_t index,Object * value)671 void FixedTypedArray<Traits>::SetValue(uint32_t index, Object* value) {
672   ElementType cast_value = Traits::defaultValue();
673   if (value->IsSmi()) {
674     int int_value = Smi::ToInt(value);
675     cast_value = from(int_value);
676   } else if (value->IsHeapNumber()) {
677     double double_value = HeapNumber::cast(value)->value();
678     cast_value = from(double_value);
679   } else {
680     // Clamp undefined to the default value. All other types have been
681     // converted to a number type further up in the call chain.
682     DCHECK(value->IsUndefined());
683   }
684   set(index, cast_value);
685 }
686 
687 template <>
SetValue(uint32_t index,Object * value)688 inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
689                                                            Object* value) {
690   DCHECK(value->IsBigInt());
691   set(index, BigInt::cast(value)->AsInt64());
692 }
693 
694 template <>
SetValue(uint32_t index,Object * value)695 inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
696                                                             Object* value) {
697   DCHECK(value->IsBigInt());
698   set(index, BigInt::cast(value)->AsUint64());
699 }
700 
ToHandle(Isolate * isolate,uint8_t scalar)701 Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
702   return handle(Smi::FromInt(scalar), isolate);
703 }
704 
ToHandle(Isolate * isolate,uint8_t scalar)705 Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
706                                                  uint8_t scalar) {
707   return handle(Smi::FromInt(scalar), isolate);
708 }
709 
ToHandle(Isolate * isolate,int8_t scalar)710 Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
711   return handle(Smi::FromInt(scalar), isolate);
712 }
713 
ToHandle(Isolate * isolate,uint16_t scalar)714 Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
715   return handle(Smi::FromInt(scalar), isolate);
716 }
717 
ToHandle(Isolate * isolate,int16_t scalar)718 Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
719   return handle(Smi::FromInt(scalar), isolate);
720 }
721 
ToHandle(Isolate * isolate,uint32_t scalar)722 Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
723   return isolate->factory()->NewNumberFromUint(scalar);
724 }
725 
ToHandle(Isolate * isolate,int32_t scalar)726 Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
727   return isolate->factory()->NewNumberFromInt(scalar);
728 }
729 
ToHandle(Isolate * isolate,float scalar)730 Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
731   return isolate->factory()->NewNumber(scalar);
732 }
733 
ToHandle(Isolate * isolate,double scalar)734 Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
735   return isolate->factory()->NewNumber(scalar);
736 }
737 
ToHandle(Isolate * isolate,int64_t scalar)738 Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
739   return BigInt::FromInt64(isolate, scalar);
740 }
741 
ToHandle(Isolate * isolate,uint64_t scalar)742 Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
743                                               uint64_t scalar) {
744   return BigInt::FromUint64(isolate, scalar);
745 }
746 
747 // static
748 template <class Traits>
749 STATIC_CONST_MEMBER_DEFINITION const InstanceType
750     FixedTypedArray<Traits>::kInstanceType;
751 
752 template <class Traits>
cast(Object * object)753 FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(Object* object) {
754   DCHECK(object->IsHeapObject() &&
755          HeapObject::cast(object)->map()->instance_type() ==
756              Traits::kInstanceType);
757   return reinterpret_cast<FixedTypedArray<Traits>*>(object);
758 }
759 
760 template <class Traits>
cast(const Object * object)761 const FixedTypedArray<Traits>* FixedTypedArray<Traits>::cast(
762     const Object* object) {
763   DCHECK(object->IsHeapObject() &&
764          HeapObject::cast(object)->map()->instance_type() ==
765              Traits::kInstanceType);
766   return reinterpret_cast<FixedTypedArray<Traits>*>(object);
767 }
768 
length()769 int TemplateList::length() const {
770   return Smi::ToInt(FixedArray::cast(this)->get(kLengthIndex));
771 }
772 
get(int index)773 Object* TemplateList::get(int index) const {
774   return FixedArray::cast(this)->get(kFirstElementIndex + index);
775 }
776 
set(int index,Object * value)777 void TemplateList::set(int index, Object* value) {
778   FixedArray::cast(this)->set(kFirstElementIndex + index, value);
779 }
780 
781 }  // namespace internal
782 }  // namespace v8
783 
784 #include "src/objects/object-macros-undef.h"
785 
786 #endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_
787