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_H_
6#define V8_OBJECTS_FIXED_ARRAY_H_
7
8#include "src/maybe-handles.h"
9#include "src/objects/instance-type.h"
10#include "src/objects/smi.h"
11#include "torque-generated/class-definitions-from-dsl.h"
12
13// Has to be the last include (doesn't have include guards):
14#include "src/objects/object-macros.h"
15
16namespace v8 {
17namespace internal {
18using WeakArrayBodyDescriptor =
19 FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>;
20
21#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V) \
22 V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE) \
23 V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE) \
24 V(CODE_STUBS_TABLE_SUB_TYPE) \
25 V(COMPILATION_CACHE_TABLE_SUB_TYPE) \
26 V(CONTEXT_SUB_TYPE) \
27 V(COPY_ON_WRITE_SUB_TYPE) \
28 V(DEOPTIMIZATION_DATA_SUB_TYPE) \
29 V(DESCRIPTOR_ARRAY_SUB_TYPE) \
30 V(EMBEDDED_OBJECT_SUB_TYPE) \
31 V(ENUM_CACHE_SUB_TYPE) \
32 V(ENUM_INDICES_CACHE_SUB_TYPE) \
33 V(DEPENDENT_CODE_SUB_TYPE) \
34 V(DICTIONARY_ELEMENTS_SUB_TYPE) \
35 V(DICTIONARY_PROPERTIES_SUB_TYPE) \
36 V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE) \
37 V(PACKED_ELEMENTS_SUB_TYPE) \
38 V(FAST_PROPERTIES_SUB_TYPE) \
39 V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
40 V(HANDLER_TABLE_SUB_TYPE) \
41 V(JS_COLLECTION_SUB_TYPE) \
42 V(JS_WEAK_COLLECTION_SUB_TYPE) \
43 V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE) \
44 V(NUMBER_STRING_CACHE_SUB_TYPE) \
45 V(OBJECT_TO_CODE_SUB_TYPE) \
46 V(OPTIMIZED_CODE_LITERALS_SUB_TYPE) \
47 V(OPTIMIZED_CODE_MAP_SUB_TYPE) \
48 V(PROTOTYPE_USERS_SUB_TYPE) \
49 V(REGEXP_MULTIPLE_CACHE_SUB_TYPE) \
50 V(RETAINED_MAPS_SUB_TYPE) \
51 V(SCOPE_INFO_SUB_TYPE) \
52 V(SCRIPT_LIST_SUB_TYPE) \
53 V(SERIALIZED_OBJECTS_SUB_TYPE) \
54 V(SHARED_FUNCTION_INFOS_SUB_TYPE) \
55 V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE) \
56 V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
57 V(STRING_SPLIT_CACHE_SUB_TYPE) \
58 V(STRING_TABLE_SUB_TYPE) \
59 V(TEMPLATE_INFO_SUB_TYPE) \
60 V(FEEDBACK_METADATA_SUB_TYPE) \
61 V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)
62
63enum FixedArraySubInstanceType {
64#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
65 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
66#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
67 LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE
68};
69
70// Common superclass for FixedArrays that allow implementations to share
71// common accessors and some code paths.
72class FixedArrayBase : public HeapObject {
73 public:
74 // [length]: length of the array.
75 inline int length() const;
76 inline void set_length(int value);
77
78 // Get and set the length using acquire loads and release stores.
79 inline int synchronized_length() const;
80 inline void synchronized_set_length(int value);
81
82 inline Object unchecked_synchronized_length() const;
83
84 DECL_CAST(FixedArrayBase)
85
86 static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
87
88 V8_EXPORT_PRIVATE bool IsCowArray() const;
89
90// Maximal allowed size, in bytes, of a single FixedArrayBase.
91// Prevents overflowing size computations, as well as extreme memory
92// consumption.
93#ifdef V8_HOST_ARCH_32_BIT
94 static const int kMaxSize = 512 * MB;
95#else
96 static const int kMaxSize = 1024 * MB;
97#endif // V8_HOST_ARCH_32_BIT
98
99 // Layout description.
100 DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
101 TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS)
102
103 static const int kHeaderSize = kSize;
104
105 protected:
106 // Special-purpose constructor for subclasses that have fast paths where
107 // their ptr() is a Smi.
108 inline FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi);
109
110 OBJECT_CONSTRUCTORS(FixedArrayBase, HeapObject);
111};
112
113// FixedArray describes fixed-sized arrays with element type Object.
114class FixedArray : public FixedArrayBase {
115 public:
116 // Setter and getter for elements.
117 inline Object get(int index) const;
118 static inline Handle<Object> get(FixedArray array, int index,
119 Isolate* isolate);
120 template <class T>
121 MaybeHandle<T> GetValue(Isolate* isolate, int index) const;
122
123 template <class T>
124 Handle<T> GetValueChecked(Isolate* isolate, int index) const;
125
126 // Return a grown copy if the index is bigger than the array's length.
127 V8_EXPORT_PRIVATE static Handle<FixedArray> SetAndGrow(
128 Isolate* isolate, Handle<FixedArray> array, int index,
129 Handle<Object> value, AllocationType allocation = AllocationType::kYoung);
130
131 // Setter that uses write barrier.
132 inline void set(int index, Object value);
133 inline bool is_the_hole(Isolate* isolate, int index);
134
135 // Setter that doesn't need write barrier.
136 inline void set(int index, Smi value);
137 // Setter with explicit barrier mode.
138 inline void set(int index, Object value, WriteBarrierMode mode);
139
140 // Setters for frequently used oddballs located in old space.
141 inline void set_undefined(int index);
142 inline void set_undefined(Isolate* isolate, int index);
143 inline void set_null(int index);
144 inline void set_null(Isolate* isolate, int index);
145 inline void set_the_hole(int index);
146 inline void set_the_hole(Isolate* isolate, int index);
147
148 inline ObjectSlot GetFirstElementAddress();
149 inline bool ContainsOnlySmisOrHoles();
150 // Returns true iff the elements are Numbers and sorted ascending.
151 bool ContainsSortedNumbers();
152
153 // Gives access to raw memory which stores the array's data.
154 inline ObjectSlot data_start();
155
156 inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
157 WriteBarrierMode mode);
158
159 inline void CopyElements(Heap* heap, int dst_index, FixedArray src,
160 int src_index, int len, WriteBarrierMode mode);
161
162 inline void FillWithHoles(int from, int to);
163
164 // Shrink the array and insert filler objects. {new_length} must be > 0.
165 V8_EXPORT_PRIVATE void Shrink(Isolate* isolate, int new_length);
166 // If {new_length} is 0, return the canonical empty FixedArray. Otherwise
167 // like above.
168 static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate,
169 Handle<FixedArray> array,
170 int new_length);
171
172 // Copy a sub array from the receiver to dest.
173 V8_EXPORT_PRIVATE void CopyTo(int pos, FixedArray dest, int dest_pos,
174 int len) const;
175
176 // Garbage collection support.
177 static constexpr int SizeFor(int length) {
178 return kHeaderSize + length * kTaggedSize;
179 }
180
181 // Code Generation support.
182 static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }
183
184 // Garbage collection support.
185 inline ObjectSlot RawFieldOfElementAt(int index);
186
187 DECL_CAST(FixedArray)
188 // Maximally allowed length of a FixedArray.
189 static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
190 static_assert(Internals::IsValidSmi(kMaxLength),
191 "FixedArray maxLength not a Smi");
192
193 // Maximally allowed length for regular (non large object space) object.
194 STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
195 static const int kMaxRegularLength =
196 (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize;
197
198 // Dispatched behavior.
199 DECL_PRINTER(FixedArray)
200 DECL_VERIFIER(FixedArray)
201
202 using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
203
204 protected:
205 // Set operation on FixedArray without using write barriers. Can
206 // only be used for storing old space objects or smis.
207 static inline void NoWriteBarrierSet(FixedArray array, int index,
208 Object value);
209
210 private:
211 STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
212
213 inline void set_undefined(ReadOnlyRoots ro_roots, int index);
214 inline void set_null(ReadOnlyRoots ro_roots, int index);
215 inline void set_the_hole(ReadOnlyRoots ro_roots, int index);
216
217 OBJECT_CONSTRUCTORS(FixedArray, FixedArrayBase);
218};
219
220// FixedArray alias added only because of IsFixedArrayExact() predicate, which
221// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
222// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
223class FixedArrayExact final : public FixedArray {};
224
225// FixedDoubleArray describes fixed-sized arrays with element type double.
226class FixedDoubleArray : public FixedArrayBase {
227 public:
228 // Setter and getter for elements.
229 inline double get_scalar(int index);
230 inline uint64_t get_representation(int index);
231 static inline Handle<Object> get(FixedDoubleArray array, int index,
232 Isolate* isolate);
233 inline void set(int index, double value);
234 inline void set_the_hole(Isolate* isolate, int index);
235 inline void set_the_hole(int index);
236
237 // Checking for the hole.
238 inline bool is_the_hole(Isolate* isolate, int index);
239 inline bool is_the_hole(int index);
240
241 // Garbage collection support.
242 inline static int SizeFor(int length) {
243 return kHeaderSize + length * kDoubleSize;
244 }
245
246 inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
247 WriteBarrierMode mode);
248
249 inline void FillWithHoles(int from, int to);
250
251 // Code Generation support.
252 static int OffsetOfElementAt(int index) { return SizeFor(index); }
253
254 DECL_CAST(FixedDoubleArray)
255
256 // Maximally allowed length of a FixedArray.
257 static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
258 static_assert(Internals::IsValidSmi(kMaxLength),
259 "FixedDoubleArray maxLength not a Smi");
260
261 // Dispatched behavior.
262 DECL_PRINTER(FixedDoubleArray)
263 DECL_VERIFIER(FixedDoubleArray)
264
265 class BodyDescriptor;
266
267 OBJECT_CONSTRUCTORS(FixedDoubleArray, FixedArrayBase);
268};
269
270// WeakFixedArray describes fixed-sized arrays with element type
271// MaybeObject.
272class WeakFixedArray : public HeapObject {
273 public:
274 DECL_CAST(WeakFixedArray)
275
276 inline MaybeObject Get(int index) const;
277
278 // Setter that uses write barrier.
279 inline void Set(int index, MaybeObject value);
280
281 // Setter with explicit barrier mode.
282 inline void Set(int index, MaybeObject value, WriteBarrierMode mode);
283
284 static constexpr int SizeFor(int length) {
285 return kHeaderSize + length * kTaggedSize;
286 }
287
288 DECL_INT_ACCESSORS(length)
289
290 // Get and set the length using acquire loads and release stores.
291 inline int synchronized_length() const;
292 inline void synchronized_set_length(int value);
293
294 // Gives access to raw memory which stores the array's data.
295 inline MaybeObjectSlot data_start();
296
297 inline MaybeObjectSlot RawFieldOfElementAt(int index);
298
299 DECL_PRINTER(WeakFixedArray)
300 DECL_VERIFIER(WeakFixedArray)
301
302 using BodyDescriptor = WeakArrayBodyDescriptor;
303
304 // Layout description.
305#define WEAK_FIXED_ARRAY_FIELDS(V) \
306 V(kLengthOffset, kTaggedSize) \
307 /* Header size. */ \
308 V(kHeaderSize, 0)
309
310 DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
311 WEAK_FIXED_ARRAY_FIELDS)
312#undef WEAK_FIXED_ARRAY_FIELDS
313
314 static const int kMaxLength =
315 (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
316 static_assert(Internals::IsValidSmi(kMaxLength),
317 "WeakFixedArray maxLength not a Smi");
318
319 protected:
320 static int OffsetOfElementAt(int index) {
321 return kHeaderSize + index * kTaggedSize;
322 }
323
324 private:
325 friend class Heap;
326
327 static const int kFirstIndex = 1;
328
329 OBJECT_CONSTRUCTORS(WeakFixedArray, HeapObject);
330};
331
332// WeakArrayList is like a WeakFixedArray with static convenience methods for
333// adding more elements. length() returns the number of elements in the list and
334// capacity() returns the allocated size. The number of elements is stored at
335// kLengthOffset and is updated with every insertion. The array grows
336// dynamically with O(1) amortized insertion.
337class WeakArrayList : public HeapObject {
338 public:
339 NEVER_READ_ONLY_SPACE
340 DECL_CAST(WeakArrayList)
341 DECL_VERIFIER(WeakArrayList)
342 DECL_PRINTER(WeakArrayList)
343
344 V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
345 Isolate* isolate, Handle<WeakArrayList> array,
346 const MaybeObjectHandle& value);
347
348 inline MaybeObject Get(int index) const;
349
350 // Set the element at index to obj. The underlying array must be large enough.
351 // If you need to grow the WeakArrayList, use the static AddToEnd() method
352 // instead.
353 inline void Set(int index, MaybeObject value,
354 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
355
356 static constexpr int SizeForCapacity(int capacity) {
357 return kHeaderSize + capacity * kTaggedSize;
358 }
359
360 // Gives access to raw memory which stores the array's data.
361 inline MaybeObjectSlot data_start();
362
363 V8_EXPORT_PRIVATE bool IsFull();
364
365 DECL_INT_ACCESSORS(capacity)
366 DECL_INT_ACCESSORS(length)
367
368 // Get and set the capacity using acquire loads and release stores.
369 inline int synchronized_capacity() const;
370 inline void synchronized_set_capacity(int value);
371
372
373 // Layout description.
374#define WEAK_ARRAY_LIST_FIELDS(V) \
375 V(kCapacityOffset, kTaggedSize) \
376 V(kLengthOffset, kTaggedSize) \
377 /* Header size. */ \
378 V(kHeaderSize, 0)
379
380 DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_ARRAY_LIST_FIELDS)
381#undef WEAK_ARRAY_LIST_FIELDS
382
383 using BodyDescriptor = WeakArrayBodyDescriptor;
384
385 static const int kMaxCapacity =
386 (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
387
388 static Handle<WeakArrayList> EnsureSpace(
389 Isolate* isolate, Handle<WeakArrayList> array, int length,
390 AllocationType allocation = AllocationType::kYoung);
391
392 // Returns the number of non-cleaned weak references in the array.
393 int CountLiveWeakReferences() const;
394
395 // Returns whether an entry was found and removed. Will move the elements
396 // around in the array - this method can only be used in cases where the user
397 // doesn't care about the indices! Users should make sure there are no
398 // duplicates.
399 V8_EXPORT_PRIVATE bool RemoveOne(const MaybeObjectHandle& value);
400
401 class Iterator;
402
403 private:
404 static int OffsetOfElementAt(int index) {
405 return kHeaderSize + index * kTaggedSize;
406 }
407
408 OBJECT_CONSTRUCTORS(WeakArrayList, HeapObject);
409};
410
411class WeakArrayList::Iterator {
412 public:
413 explicit Iterator(WeakArrayList array) : index_(0), array_(array) {}
414
415 inline HeapObject Next();
416
417 private:
418 int index_;
419 WeakArrayList array_;
420#ifdef DEBUG
421 DisallowHeapAllocation no_gc_;
422#endif // DEBUG
423 DISALLOW_COPY_AND_ASSIGN(Iterator);
424};
425
426// Generic array grows dynamically with O(1) amortized insertion.
427//
428// ArrayList is a FixedArray with static convenience methods for adding more
429// elements. The Length() method returns the number of elements in the list, not
430// the allocated size. The number of elements is stored at kLengthIndex and is
431// updated with every insertion. The elements of the ArrayList are stored in the
432// underlying FixedArray starting at kFirstIndex.
433class ArrayList : public FixedArray {
434 public:
435 V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
436 Handle<ArrayList> array,
437 Handle<Object> obj);
438 V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
439 Handle<ArrayList> array,
440 Handle<Object> obj1,
441 Handle<Object> obj2);
442 static Handle<ArrayList> New(Isolate* isolate, int size);
443
444 // Returns the number of elements in the list, not the allocated size, which
445 // is length(). Lower and upper case length() return different results!
446 inline int Length() const;
447
448 // Sets the Length() as used by Elements(). Does not change the underlying
449 // storage capacity, i.e., length().
450 inline void SetLength(int length);
451 inline Object Get(int index) const;
452 inline ObjectSlot Slot(int index);
453
454 // Set the element at index to obj. The underlying array must be large enough.
455 // If you need to grow the ArrayList, use the static Add() methods instead.
456 inline void Set(int index, Object obj,
457 WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
458
459 // Set the element at index to undefined. This does not change the Length().
460 inline void Clear(int index, Object undefined);
461
462 // Return a copy of the list of size Length() without the first entry. The
463 // number returned by Length() is stored in the first entry.
464 static Handle<FixedArray> Elements(Isolate* isolate, Handle<ArrayList> array);
465 DECL_CAST(ArrayList)
466
467 private:
468 static Handle<ArrayList> EnsureSpace(Isolate* isolate,
469 Handle<ArrayList> array, int length);
470 static const int kLengthIndex = 0;
471 static const int kFirstIndex = 1;
472 OBJECT_CONSTRUCTORS(ArrayList, FixedArray);
473};
474
475enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
476
477template <SearchMode search_mode, typename T>
478inline int Search(T* array, Name name, int valid_entries = 0,
479 int* out_insertion_index = nullptr);
480
481// ByteArray represents fixed sized byte arrays. Used for the relocation info
482// that is attached to code objects.
483class ByteArray : public FixedArrayBase {
484 public:
485 inline int Size();
486
487 // Setter and getter.
488 inline byte get(int index) const;
489 inline void set(int index, byte value);
490
491 // Copy in / copy out whole byte slices.
492 inline void copy_out(int index, byte* buffer, int length);
493 inline void copy_in(int index, const byte* buffer, int length);
494
495 // Treat contents as an int array.
496 inline int get_int(int index) const;
497 inline void set_int(int index, int value);
498
499 inline uint32_t get_uint32(int index) const;
500 inline void set_uint32(int index, uint32_t value);
501
502 // Clear uninitialized padding space. This ensures that the snapshot content
503 // is deterministic.
504 inline void clear_padding();
505
506 static int SizeFor(int length) {
507 return OBJECT_POINTER_ALIGN(kHeaderSize + length);
508 }
509 // We use byte arrays for free blocks in the heap. Given a desired size in
510 // bytes that is a multiple of the word size and big enough to hold a byte
511 // array, this function returns the number of elements a byte array should
512 // have.
513 static int LengthFor(int size_in_bytes) {
514 DCHECK(IsAligned(size_in_bytes, kTaggedSize));
515 DCHECK_GE(size_in_bytes, kHeaderSize);
516 return size_in_bytes - kHeaderSize;
517 }
518
519 // Returns data start address.
520 inline byte* GetDataStartAddress();
521 // Returns address of the past-the-end element.
522 inline byte* GetDataEndAddress();
523
524 inline int DataSize() const;
525
526 // Returns a pointer to the ByteArray object for a given data start address.
527 static inline ByteArray FromDataStartAddress(Address address);
528
529 DECL_CAST(ByteArray)
530
531 // Dispatched behavior.
532 inline int ByteArraySize();
533 DECL_PRINTER(ByteArray)
534 DECL_VERIFIER(ByteArray)
535
536 // Layout description.
537 static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
538
539 // Maximal length of a single ByteArray.
540 static const int kMaxLength = kMaxSize - kHeaderSize;
541 static_assert(Internals::IsValidSmi(kMaxLength),
542 "ByteArray maxLength not a Smi");
543
544 class BodyDescriptor;
545
546 protected:
547 // Special-purpose constructor for subclasses that have fast paths where
548 // their ptr() is a Smi.
549 inline ByteArray(Address ptr, AllowInlineSmiStorage allow_smi);
550
551 OBJECT_CONSTRUCTORS(ByteArray, FixedArrayBase);
552};
553
554// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
555// as they can be copied with memcpy.
556template <class T>
557class PodArray : public ByteArray {
558 public:
559 static Handle<PodArray<T>> New(
560 Isolate* isolate, int length,
561 AllocationType allocation = AllocationType::kYoung);
562 void copy_out(int index, T* result) {
563 ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
564 sizeof(T));
565 }
566
567 void copy_in(int index, const T* buffer, int length) {
568 ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer),
569 length * sizeof(T));
570 }
571
572 T get(int index) {
573 T result;
574 copy_out(index, &result);
575 return result;
576 }
577
578 void set(int index, const T& value) { copy_in(index, &value, 1); }
579
580 inline int length() const;
581 DECL_CAST(PodArray<T>)
582
583 OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray);
584};
585
586class FixedTypedArrayBase : public FixedArrayBase {
587 public:
588 // [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
589 DECL_ACCESSORS(base_pointer, Object)
590
591 // [external_pointer]: Contains the offset between base_pointer and the start
592 // of the data. If the base_pointer is a nullptr, the external_pointer
593 // therefore points to the actual backing store.
594 DECL_PRIMITIVE_ACCESSORS(external_pointer, void*)
595
596 // Dispatched behavior.
597 DECL_CAST(FixedTypedArrayBase)
598
599 DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
600 TORQUE_GENERATED_FIXED_TYPED_ARRAY_BASE_FIELDS)
601 static const int kHeaderSize = kSize;
602
603#ifdef V8_COMPRESS_POINTERS
604 // TODO(ishell, v8:8875): When pointer compression is enabled the kHeaderSize
605 // is only kTaggedSize aligned but we can keep using unaligned access since
606 // both x64 and arm64 architectures (where pointer compression supported)
607 // allow unaligned access to doubles.
608 STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
609#else
610 STATIC_ASSERT(IsAligned(kHeaderSize, kDoubleAlignment));
611#endif
612
613 static const int kDataOffset = kHeaderSize;
614
615 static const int kMaxElementSize = 8;
616
617#ifdef V8_HOST_ARCH_32_BIT
618 static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
619#else
620 static const size_t kMaxByteLength =
621 static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
622#endif // V8_HOST_ARCH_32_BIT
623
624 static const size_t kMaxLength = Smi::kMaxValue;
625
626 class BodyDescriptor;
627
628 inline int size() const;
629
630 static inline int TypedArraySize(InstanceType type, int length);
631 inline int TypedArraySize(InstanceType type) const;
632
633 // Use with care: returns raw pointer into heap.
634 inline void* DataPtr();
635
636 inline int DataSize() const;
637
638 inline size_t ByteLength() const;
639
640 static inline intptr_t ExternalPointerValueForOnHeapArray() {
641 return FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
642 }
643
644 static inline void* ExternalPointerPtrForOnHeapArray() {
645 return reinterpret_cast<void*>(ExternalPointerValueForOnHeapArray());
646 }
647
648 private:
649 static inline int ElementSize(InstanceType type);
650
651 inline int DataSize(InstanceType type) const;
652
653 OBJECT_CONSTRUCTORS(FixedTypedArrayBase, FixedArrayBase);
654};
655
656template <class Traits>
657class FixedTypedArray : public FixedTypedArrayBase {
658 public:
659 using ElementType = typename Traits::ElementType;
660 static const InstanceType kInstanceType = Traits::kInstanceType;
661
662 DECL_CAST(FixedTypedArray<Traits>)
663
664 static inline ElementType get_scalar_from_data_ptr(void* data_ptr, int index);
665 inline ElementType get_scalar(int index);
666 static inline Handle<Object> get(Isolate* isolate, FixedTypedArray array,
667 int index);
668 inline void set(int index, ElementType value);
669
670 static inline ElementType from(int value);
671 static inline ElementType from(uint32_t value);
672 static inline ElementType from(double value);
673 static inline ElementType from(int64_t value);
674 static inline ElementType from(uint64_t value);
675
676 static inline ElementType FromHandle(Handle<Object> value,
677 bool* lossless = nullptr);
678
679 // This accessor applies the correct conversion from Smi, HeapNumber
680 // and undefined.
681 inline void SetValue(uint32_t index, Object value);
682
683 DECL_PRINTER(FixedTypedArray)
684 DECL_VERIFIER(FixedTypedArray)
685
686 private:
687 OBJECT_CONSTRUCTORS(FixedTypedArray, FixedTypedArrayBase);
688};
689
690#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType) \
691 STATIC_ASSERT(sizeof(elementType) <= FixedTypedArrayBase::kMaxElementSize); \
692 class Type##ArrayTraits { \
693 public: /* NOLINT */ \
694 using ElementType = elementType; \
695 static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE; \
696 static const char* ArrayTypeName() { return "Fixed" #Type "Array"; } \
697 static inline Handle<Object> ToHandle(Isolate* isolate, \
698 elementType scalar); \
699 static inline elementType defaultValue(); \
700 }; \
701 \
702 using Fixed##Type##Array = FixedTypedArray<Type##ArrayTraits>;
703
704TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)
705
706#undef FIXED_TYPED_ARRAY_TRAITS
707
708class TemplateList : public FixedArray {
709 public:
710 static Handle<TemplateList> New(Isolate* isolate, int size);
711 inline int length() const;
712 inline Object get(int index) const;
713 inline void set(int index, Object value);
714 static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
715 Handle<Object> value);
716 DECL_CAST(TemplateList)
717 private:
718 static const int kLengthIndex = 0;
719 static const int kFirstElementIndex = kLengthIndex + 1;
720
721 OBJECT_CONSTRUCTORS(TemplateList, FixedArray);
722};
723
724} // namespace internal
725} // namespace v8
726
727#include "src/objects/object-macros-undef.h"
728
729#endif // V8_OBJECTS_FIXED_ARRAY_H_
730