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/handles/maybe-handles.h"
9#include "src/objects/instance-type.h"
10#include "src/objects/objects.h"
11#include "src/objects/smi.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 {
18
19#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V)    \
20  V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE)       \
21  V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE)       \
22  V(CODE_STUBS_TABLE_SUB_TYPE)                   \
23  V(COMPILATION_CACHE_TABLE_SUB_TYPE)            \
24  V(CONTEXT_SUB_TYPE)                            \
25  V(COPY_ON_WRITE_SUB_TYPE)                      \
26  V(DEOPTIMIZATION_DATA_SUB_TYPE)                \
27  V(DESCRIPTOR_ARRAY_SUB_TYPE)                   \
28  V(EMBEDDED_OBJECT_SUB_TYPE)                    \
29  V(ENUM_CACHE_SUB_TYPE)                         \
30  V(ENUM_INDICES_CACHE_SUB_TYPE)                 \
31  V(DEPENDENT_CODE_SUB_TYPE)                     \
32  V(DICTIONARY_ELEMENTS_SUB_TYPE)                \
33  V(DICTIONARY_PROPERTIES_SUB_TYPE)              \
34  V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE)        \
35  V(PACKED_ELEMENTS_SUB_TYPE)                    \
36  V(FAST_PROPERTIES_SUB_TYPE)                    \
37  V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
38  V(HANDLER_TABLE_SUB_TYPE)                      \
39  V(JS_COLLECTION_SUB_TYPE)                      \
40  V(JS_WEAK_COLLECTION_SUB_TYPE)                 \
41  V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE)     \
42  V(NUMBER_STRING_CACHE_SUB_TYPE)                \
43  V(OBJECT_TO_CODE_SUB_TYPE)                     \
44  V(OPTIMIZED_CODE_LITERALS_SUB_TYPE)            \
45  V(OPTIMIZED_CODE_MAP_SUB_TYPE)                 \
46  V(PROTOTYPE_USERS_SUB_TYPE)                    \
47  V(REGEXP_MULTIPLE_CACHE_SUB_TYPE)              \
48  V(RETAINED_MAPS_SUB_TYPE)                      \
49  V(SCOPE_INFO_SUB_TYPE)                         \
50  V(SCRIPT_LIST_SUB_TYPE)                        \
51  V(SERIALIZED_OBJECTS_SUB_TYPE)                 \
52  V(SHARED_FUNCTION_INFOS_SUB_TYPE)              \
53  V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE)      \
54  V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
55  V(STRING_SPLIT_CACHE_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
60enum 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#include "torque-generated/src/objects/fixed-array-tq.inc"
68
69// Common superclass for FixedArrays that allow implementations to share
70// common accessors and some code paths.
71class FixedArrayBase
72    : public TorqueGeneratedFixedArrayBase<FixedArrayBase, HeapObject> {
73 public:
74  // Forward declare the non-atomic (set_)length defined in torque.
75  using TorqueGeneratedFixedArrayBase::length;
76  using TorqueGeneratedFixedArrayBase::set_length;
77  DECL_RELEASE_ACQUIRE_INT_ACCESSORS(length)
78
79  inline Object unchecked_length(AcquireLoadTag) const;
80
81  static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);
82
83  V8_EXPORT_PRIVATE bool IsCowArray() const;
84
85  // Maximal allowed size, in bytes, of a single FixedArrayBase.
86  // Prevents overflowing size computations, as well as extreme memory
87  // consumption. It's either (512Mb - kTaggedSize) or (1024Mb - kTaggedSize).
88  // -kTaggedSize is here to ensure that this max size always fits into Smi
89  // which is necessary for being able to create a free space filler for the
90  // whole array of kMaxSize.
91  static const int kMaxSize = 128 * kTaggedSize * MB - kTaggedSize;
92  STATIC_ASSERT(Smi::IsValid(kMaxSize));
93
94 protected:
95  TQ_OBJECT_CONSTRUCTORS(FixedArrayBase)
96  inline FixedArrayBase(Address ptr,
97                        HeapObject::AllowInlineSmiStorage allow_smi);
98};
99
100// FixedArray describes fixed-sized arrays with element type Object.
101class FixedArray
102    : public TorqueGeneratedFixedArray<FixedArray, FixedArrayBase> {
103 public:
104  // Setter and getter for elements.
105  inline Object get(int index) const;
106  inline Object get(PtrComprCageBase cage_base, int index) const;
107
108  static inline Handle<Object> get(FixedArray array, int index,
109                                   Isolate* isolate);
110
111  // Return a grown copy if the index is bigger than the array's length.
112  V8_EXPORT_PRIVATE static Handle<FixedArray> SetAndGrow(
113      Isolate* isolate, Handle<FixedArray> array, int index,
114      Handle<Object> value);
115
116  // Relaxed accessors.
117  inline Object get(int index, RelaxedLoadTag) const;
118  inline Object get(PtrComprCageBase cage_base, int index,
119                    RelaxedLoadTag) const;
120  inline void set(int index, Object value, RelaxedStoreTag,
121                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
122  inline void set(int index, Smi value, RelaxedStoreTag);
123
124  // Acquire/release accessors.
125  inline Object get(int index, AcquireLoadTag) const;
126  inline Object get(PtrComprCageBase cage_base, int index,
127                    AcquireLoadTag) const;
128  inline void set(int index, Object value, ReleaseStoreTag,
129                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
130  inline void set(int index, Smi value, ReleaseStoreTag);
131
132  // Setter that uses write barrier.
133  inline void set(int index, Object value);
134  inline bool is_the_hole(Isolate* isolate, int index);
135
136  // Setter that doesn't need write barrier.
137#if !defined(_WIN32) || (defined(_WIN64) && _MSC_VER < 1930 && __cplusplus < 201703L)
138  inline void set(int index, Smi value);
139#else
140  inline void set(int index, Smi value) {
141#if !defined(_WIN32)
142    DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
143#endif
144    DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
145    DCHECK(Object(value).IsSmi());
146    int offset = OffsetOfElementAt(index);
147    RELAXED_WRITE_FIELD(*this, offset, value);
148  }
149#endif
150
151  // Setter with explicit barrier mode.
152  inline void set(int index, Object value, WriteBarrierMode mode);
153
154  // Setters for frequently used oddballs located in old space.
155  inline void set_undefined(int index);
156  inline void set_undefined(Isolate* isolate, int index);
157  inline void set_undefined(ReadOnlyRoots ro_roots, int index);
158  inline void set_null(int index);
159  inline void set_null(Isolate* isolate, int index);
160  inline void set_null(ReadOnlyRoots ro_roots, int index);
161  inline void set_the_hole(int index);
162  inline void set_the_hole(Isolate* isolate, int index);
163  inline void set_the_hole(ReadOnlyRoots ro_roots, int index);
164
165  inline ObjectSlot GetFirstElementAddress();
166  inline bool ContainsOnlySmisOrHoles();
167
168  // Gives access to raw memory which stores the array's data.
169  inline ObjectSlot data_start();
170
171  inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
172                           int len, WriteBarrierMode mode);
173
174  inline void CopyElements(Isolate* isolate, int dst_index, FixedArray src,
175                           int src_index, int len, WriteBarrierMode mode);
176
177  inline void FillWithHoles(int from, int to);
178
179  // Shrink the array and insert filler objects. {new_length} must be > 0.
180  V8_EXPORT_PRIVATE void Shrink(Isolate* isolate, int new_length);
181  // If {new_length} is 0, return the canonical empty FixedArray. Otherwise
182  // like above.
183  static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate,
184                                          Handle<FixedArray> array,
185                                          int new_length);
186
187  // Copy a sub array from the receiver to dest.
188  V8_EXPORT_PRIVATE void CopyTo(int pos, FixedArray dest, int dest_pos,
189                                int len) const;
190
191  // Garbage collection support.
192  static constexpr int SizeFor(int length) {
193    return kHeaderSize + length * kTaggedSize;
194  }
195
196  // Code Generation support.
197  static constexpr int OffsetOfElementAt(int index) {
198    STATIC_ASSERT(kObjectsOffset == SizeFor(0));
199    return SizeFor(index);
200  }
201
202  // Garbage collection support.
203  inline ObjectSlot RawFieldOfElementAt(int index);
204
205  // Maximally allowed length of a FixedArray.
206  static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
207  static_assert(Internals::IsValidSmi(kMaxLength),
208                "FixedArray maxLength not a Smi");
209
210  // Maximally allowed length for regular (non large object space) object.
211  STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
212  static const int kMaxRegularLength =
213      (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize;
214
215  // Dispatched behavior.
216  DECL_PRINTER(FixedArray)
217  DECL_VERIFIER(FixedArray)
218
219  int AllocatedSize();
220
221  class BodyDescriptor;
222
223  static constexpr int kObjectsOffset = kHeaderSize;
224
225 protected:
226  // Set operation on FixedArray without using write barriers. Can
227  // only be used for storing old space objects or smis.
228  static inline void NoWriteBarrierSet(FixedArray array, int index,
229                                       Object value);
230
231 private:
232  STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);
233
234  TQ_OBJECT_CONSTRUCTORS(FixedArray)
235};
236
237// FixedArray alias added only because of IsFixedArrayExact() predicate, which
238// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
239// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
240class FixedArrayExact final : public FixedArray {};
241
242// FixedDoubleArray describes fixed-sized arrays with element type double.
243class FixedDoubleArray
244    : public TorqueGeneratedFixedDoubleArray<FixedDoubleArray, FixedArrayBase> {
245 public:
246  // Setter and getter for elements.
247  inline double get_scalar(int index);
248  inline uint64_t get_representation(int index);
249  static inline Handle<Object> get(FixedDoubleArray array, int index,
250                                   Isolate* isolate);
251  inline void set(int index, double value);
252  inline void set_the_hole(Isolate* isolate, int index);
253  inline void set_the_hole(int index);
254
255  // Checking for the hole.
256  inline bool is_the_hole(Isolate* isolate, int index);
257  inline bool is_the_hole(int index);
258
259  // Garbage collection support.
260  inline static int SizeFor(int length) {
261    return kHeaderSize + length * kDoubleSize;
262  }
263
264  inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
265                           int len, WriteBarrierMode mode);
266
267  inline void FillWithHoles(int from, int to);
268
269  // Code Generation support.
270  static int OffsetOfElementAt(int index) { return SizeFor(index); }
271
272  // Start offset of elements.
273  static constexpr int kFloatsOffset = kHeaderSize;
274
275  // Maximally allowed length of a FixedDoubleArray.
276  static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
277  static_assert(Internals::IsValidSmi(kMaxLength),
278                "FixedDoubleArray maxLength not a Smi");
279
280  // Dispatched behavior.
281  DECL_PRINTER(FixedDoubleArray)
282  DECL_VERIFIER(FixedDoubleArray)
283
284  class BodyDescriptor;
285
286  TQ_OBJECT_CONSTRUCTORS(FixedDoubleArray)
287};
288
289// WeakFixedArray describes fixed-sized arrays with element type
290// MaybeObject.
291class WeakFixedArray
292    : public TorqueGeneratedWeakFixedArray<WeakFixedArray, HeapObject> {
293 public:
294  inline MaybeObject Get(int index) const;
295  inline MaybeObject Get(PtrComprCageBase cage_base, int index) const;
296
297  inline void Set(
298      int index, MaybeObject value,
299      WriteBarrierMode mode = WriteBarrierMode::UPDATE_WRITE_BARRIER);
300
301  static inline Handle<WeakFixedArray> EnsureSpace(Isolate* isolate,
302                                                   Handle<WeakFixedArray> array,
303                                                   int length);
304
305  // Forward declare the non-atomic (set_)length defined in torque.
306  using TorqueGeneratedWeakFixedArray::length;
307  using TorqueGeneratedWeakFixedArray::set_length;
308  DECL_RELEASE_ACQUIRE_INT_ACCESSORS(length)
309
310  // Gives access to raw memory which stores the array's data.
311  inline MaybeObjectSlot data_start();
312
313  inline MaybeObjectSlot RawFieldOfElementAt(int index);
314
315  inline void CopyElements(Isolate* isolate, int dst_index, WeakFixedArray src,
316                           int src_index, int len, WriteBarrierMode mode);
317
318  DECL_PRINTER(WeakFixedArray)
319  DECL_VERIFIER(WeakFixedArray)
320
321  class BodyDescriptor;
322
323  static const int kMaxLength =
324      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
325  static_assert(Internals::IsValidSmi(kMaxLength),
326                "WeakFixedArray maxLength not a Smi");
327
328  int AllocatedSize();
329
330  static int OffsetOfElementAt(int index) {
331    STATIC_ASSERT(kObjectsOffset == SizeFor(0));
332    return SizeFor(index);
333  }
334
335 private:
336  friend class Heap;
337
338  static const int kFirstIndex = 1;
339
340  TQ_OBJECT_CONSTRUCTORS(WeakFixedArray)
341};
342
343// WeakArrayList is like a WeakFixedArray with static convenience methods for
344// adding more elements. length() returns the number of elements in the list and
345// capacity() returns the allocated size. The number of elements is stored at
346// kLengthOffset and is updated with every insertion. The array grows
347// dynamically with O(1) amortized insertion.
348class WeakArrayList
349    : public TorqueGeneratedWeakArrayList<WeakArrayList, HeapObject> {
350 public:
351  NEVER_READ_ONLY_SPACE
352  DECL_PRINTER(WeakArrayList)
353
354  V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
355      Isolate* isolate, Handle<WeakArrayList> array,
356      const MaybeObjectHandle& value);
357
358  // A version that adds to elements. This ensures that the elements are
359  // inserted atomically w.r.t GC.
360  V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
361      Isolate* isolate, Handle<WeakArrayList> array,
362      const MaybeObjectHandle& value1, const MaybeObjectHandle& value2);
363
364  // Appends an element to the array and possibly compacts and shrinks live weak
365  // references to the start of the collection. Only use this method when
366  // indices to elements can change.
367  static Handle<WeakArrayList> Append(
368      Isolate* isolate, Handle<WeakArrayList> array,
369      const MaybeObjectHandle& value,
370      AllocationType allocation = AllocationType::kYoung);
371
372  // Compact weak references to the beginning of the array.
373  V8_EXPORT_PRIVATE void Compact(Isolate* isolate);
374
375  inline MaybeObject Get(int index) const;
376  inline MaybeObject Get(PtrComprCageBase cage_base, int index) const;
377
378  // Set the element at index to obj. The underlying array must be large enough.
379  // If you need to grow the WeakArrayList, use the static AddToEnd() method
380  // instead.
381  inline void Set(int index, MaybeObject value,
382                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
383  inline void Set(int index, Smi value);
384
385  static constexpr int SizeForCapacity(int capacity) {
386    return SizeFor(capacity);
387  }
388
389  static constexpr int CapacityForLength(int length) {
390    return length + std::max(length / 2, 2);
391  }
392
393  // Gives access to raw memory which stores the array's data.
394  inline MaybeObjectSlot data_start();
395
396  inline void CopyElements(Isolate* isolate, int dst_index, WeakArrayList src,
397                           int src_index, int len, WriteBarrierMode mode);
398
399  V8_EXPORT_PRIVATE bool IsFull() const;
400
401  int AllocatedSize();
402
403  class BodyDescriptor;
404
405  static const int kMaxCapacity =
406      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
407
408  static Handle<WeakArrayList> EnsureSpace(
409      Isolate* isolate, Handle<WeakArrayList> array, int length,
410      AllocationType allocation = AllocationType::kYoung);
411
412  // Returns the number of non-cleaned weak references in the array.
413  int CountLiveWeakReferences() const;
414
415  // Returns the number of non-cleaned elements in the array.
416  int CountLiveElements() const;
417
418  // Returns whether an entry was found and removed. Will move the elements
419  // around in the array - this method can only be used in cases where the user
420  // doesn't care about the indices! Users should make sure there are no
421  // duplicates.
422  V8_EXPORT_PRIVATE bool RemoveOne(const MaybeObjectHandle& value);
423
424  class Iterator;
425
426 private:
427  static int OffsetOfElementAt(int index) {
428    return kHeaderSize + index * kTaggedSize;
429  }
430
431  TQ_OBJECT_CONSTRUCTORS(WeakArrayList)
432};
433
434class WeakArrayList::Iterator {
435 public:
436  explicit Iterator(WeakArrayList array) : index_(0), array_(array) {}
437  Iterator(const Iterator&) = delete;
438  Iterator& operator=(const Iterator&) = delete;
439
440  inline HeapObject Next();
441
442 private:
443  int index_;
444  WeakArrayList array_;
445  DISALLOW_GARBAGE_COLLECTION(no_gc_)
446};
447
448// Generic array grows dynamically with O(1) amortized insertion.
449//
450// ArrayList is a FixedArray with static convenience methods for adding more
451// elements. The Length() method returns the number of elements in the list, not
452// the allocated size. The number of elements is stored at kLengthIndex and is
453// updated with every insertion. The elements of the ArrayList are stored in the
454// underlying FixedArray starting at kFirstIndex.
455class ArrayList : public TorqueGeneratedArrayList<ArrayList, FixedArray> {
456 public:
457  V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
458                                                 Handle<ArrayList> array,
459                                                 Handle<Object> obj);
460  V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
461                                                 Handle<ArrayList> array,
462                                                 Handle<Object> obj1,
463                                                 Handle<Object> obj2);
464  V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
465                                                 Handle<ArrayList> array,
466                                                 Handle<Object> obj1, Smi obj2,
467                                                 Smi obj3, Smi obj4);
468  static Handle<ArrayList> New(Isolate* isolate, int size);
469
470  // Returns the number of elements in the list, not the allocated size, which
471  // is length(). Lower and upper case length() return different results!
472  inline int Length() const;
473
474  // Sets the Length() as used by Elements(). Does not change the underlying
475  // storage capacity, i.e., length().
476  inline void SetLength(int length);
477  inline Object Get(int index) const;
478  inline Object Get(PtrComprCageBase cage_base, int index) const;
479  inline ObjectSlot Slot(int index);
480
481  // Set the element at index to obj. The underlying array must be large enough.
482  // If you need to grow the ArrayList, use the static Add() methods instead.
483  inline void Set(int index, Object obj,
484                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
485
486  inline void Set(int index, Smi obj);
487
488  // Set the element at index to undefined. This does not change the Length().
489  inline void Clear(int index, Object undefined);
490
491  // Return a copy of the list of size Length() without the first entry. The
492  // number returned by Length() is stored in the first entry.
493  static Handle<FixedArray> Elements(Isolate* isolate, Handle<ArrayList> array);
494
495  static const int kHeaderFields = 1;
496
497  static const int kLengthIndex = 0;
498  static const int kFirstIndex = 1;
499  STATIC_ASSERT(kHeaderFields == kFirstIndex);
500
501  DECL_VERIFIER(ArrayList)
502
503 private:
504  static Handle<ArrayList> EnsureSpace(Isolate* isolate,
505                                       Handle<ArrayList> array, int length);
506  TQ_OBJECT_CONSTRUCTORS(ArrayList)
507};
508
509enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };
510
511template <SearchMode search_mode, typename T>
512inline int Search(T* array, Name name, int valid_entries = 0,
513                  int* out_insertion_index = nullptr,
514                  bool concurrent_search = false);
515
516// ByteArray represents fixed sized byte arrays.  Used for the relocation info
517// that is attached to code objects.
518class ByteArray : public TorqueGeneratedByteArray<ByteArray, FixedArrayBase> {
519 public:
520  inline int Size();
521
522  // Setter and getter.
523  inline byte get(int index) const;
524  inline void set(int index, byte value);
525
526  // Copy in / copy out whole byte slices.
527  inline void copy_out(int index, byte* buffer, int slice_length);
528  inline void copy_in(int index, const byte* buffer, int slice_length);
529
530  // Treat contents as an int array.
531  inline int get_int(int index) const;
532  inline void set_int(int index, int value);
533
534  inline uint32_t get_uint32(int index) const;
535  inline void set_uint32(int index, uint32_t value);
536
537  inline uint32_t get_uint32_relaxed(int index) const;
538  inline void set_uint32_relaxed(int index, uint32_t value);
539
540  inline uint16_t get_uint16(int index) const;
541  inline void set_uint16(int index, uint16_t value);
542
543  // Clear uninitialized padding space. This ensures that the snapshot content
544  // is deterministic.
545  inline void clear_padding();
546
547  static int SizeFor(int length) {
548    return OBJECT_POINTER_ALIGN(kHeaderSize + length);
549  }
550  // We use byte arrays for free blocks in the heap.  Given a desired size in
551  // bytes that is a multiple of the word size and big enough to hold a byte
552  // array, this function returns the number of elements a byte array should
553  // have.
554  static int LengthFor(int size_in_bytes) {
555    DCHECK(IsAligned(size_in_bytes, kTaggedSize));
556    DCHECK_GE(size_in_bytes, kHeaderSize);
557    return size_in_bytes - kHeaderSize;
558  }
559
560  // Returns data start address.
561  inline byte* GetDataStartAddress();
562  // Returns address of the past-the-end element.
563  inline byte* GetDataEndAddress();
564
565  inline int DataSize() const;
566
567  // Returns a pointer to the ByteArray object for a given data start address.
568  static inline ByteArray FromDataStartAddress(Address address);
569
570  // Dispatched behavior.
571  inline int ByteArraySize();
572  DECL_PRINTER(ByteArray)
573
574  // Layout description.
575  static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);
576
577  // Maximal length of a single ByteArray.
578  static const int kMaxLength = kMaxSize - kHeaderSize;
579  static_assert(Internals::IsValidSmi(kMaxLength),
580                "ByteArray maxLength not a Smi");
581
582  class BodyDescriptor;
583
584 protected:
585  TQ_OBJECT_CONSTRUCTORS(ByteArray)
586  inline ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi);
587};
588
589// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
590// as they can be copied with memcpy.
591template <class T>
592class PodArray : public ByteArray {
593 public:
594  static Handle<PodArray<T>> New(
595      Isolate* isolate, int length,
596      AllocationType allocation = AllocationType::kYoung);
597  void copy_out(int index, T* result, int length) {
598    ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
599                        length * sizeof(T));
600  }
601
602  void copy_in(int index, const T* buffer, int length) {
603    ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer),
604                       length * sizeof(T));
605  }
606
607  bool matches(const T* buffer, int length) {
608    DCHECK_LE(length, this->length());
609    return memcmp(GetDataStartAddress(), buffer, length * sizeof(T)) == 0;
610  }
611
612  bool matches(int offset, const T* buffer, int length) {
613    DCHECK_LE(offset, this->length());
614    DCHECK_LE(offset + length, this->length());
615    return memcmp(GetDataStartAddress() + sizeof(T) * offset, buffer,
616                  length * sizeof(T)) == 0;
617  }
618
619  T get(int index) {
620    T result;
621    copy_out(index, &result, 1);
622    return result;
623  }
624
625  void set(int index, const T& value) { copy_in(index, &value, 1); }
626
627  inline int length() const;
628  DECL_CAST(PodArray<T>)
629
630  OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray);
631};
632
633class TemplateList
634    : public TorqueGeneratedTemplateList<TemplateList, FixedArray> {
635 public:
636  static Handle<TemplateList> New(Isolate* isolate, int size);
637  inline int length() const;
638  inline Object get(int index) const;
639  inline Object get(PtrComprCageBase cage_base, int index) const;
640  inline void set(int index, Object value);
641  static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
642                                  Handle<Object> value);
643 private:
644  static const int kLengthIndex = 0;
645  static const int kFirstElementIndex = kLengthIndex + 1;
646
647  TQ_OBJECT_CONSTRUCTORS(TemplateList)
648};
649
650}  // namespace internal
651}  // namespace v8
652
653#include "src/objects/object-macros-undef.h"
654
655#endif  // V8_OBJECTS_FIXED_ARRAY_H_
656