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