fixed-array.h 26.3 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_OBJECTS_FIXED_ARRAY_H_
#define V8_OBJECTS_FIXED_ARRAY_H_

8
#include "src/maybe-handles.h"
9
#include "src/objects/instance-type.h"
10
#include "src/objects/smi.h"
11
#include "torque-generated/field-offsets-tq.h"
12 13 14 15 16 17

// Has to be the last include (doesn't have include guards):
#include "src/objects/object-macros.h"

namespace v8 {
namespace internal {
18 19
using WeakArrayBodyDescriptor =
    FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>;
20

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#define FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(V)    \
  V(BYTECODE_ARRAY_CONSTANT_POOL_SUB_TYPE)       \
  V(BYTECODE_ARRAY_HANDLER_TABLE_SUB_TYPE)       \
  V(CODE_STUBS_TABLE_SUB_TYPE)                   \
  V(COMPILATION_CACHE_TABLE_SUB_TYPE)            \
  V(CONTEXT_SUB_TYPE)                            \
  V(COPY_ON_WRITE_SUB_TYPE)                      \
  V(DEOPTIMIZATION_DATA_SUB_TYPE)                \
  V(DESCRIPTOR_ARRAY_SUB_TYPE)                   \
  V(EMBEDDED_OBJECT_SUB_TYPE)                    \
  V(ENUM_CACHE_SUB_TYPE)                         \
  V(ENUM_INDICES_CACHE_SUB_TYPE)                 \
  V(DEPENDENT_CODE_SUB_TYPE)                     \
  V(DICTIONARY_ELEMENTS_SUB_TYPE)                \
  V(DICTIONARY_PROPERTIES_SUB_TYPE)              \
  V(EMPTY_PROPERTIES_DICTIONARY_SUB_TYPE)        \
  V(PACKED_ELEMENTS_SUB_TYPE)                    \
  V(FAST_PROPERTIES_SUB_TYPE)                    \
  V(FAST_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
  V(HANDLER_TABLE_SUB_TYPE)                      \
  V(JS_COLLECTION_SUB_TYPE)                      \
  V(JS_WEAK_COLLECTION_SUB_TYPE)                 \
  V(NOSCRIPT_SHARED_FUNCTION_INFOS_SUB_TYPE)     \
  V(NUMBER_STRING_CACHE_SUB_TYPE)                \
  V(OBJECT_TO_CODE_SUB_TYPE)                     \
  V(OPTIMIZED_CODE_LITERALS_SUB_TYPE)            \
  V(OPTIMIZED_CODE_MAP_SUB_TYPE)                 \
  V(PROTOTYPE_USERS_SUB_TYPE)                    \
  V(REGEXP_MULTIPLE_CACHE_SUB_TYPE)              \
  V(RETAINED_MAPS_SUB_TYPE)                      \
  V(SCOPE_INFO_SUB_TYPE)                         \
  V(SCRIPT_LIST_SUB_TYPE)                        \
53
  V(SERIALIZED_OBJECTS_SUB_TYPE)                 \
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
  V(SHARED_FUNCTION_INFOS_SUB_TYPE)              \
  V(SINGLE_CHARACTER_STRING_CACHE_SUB_TYPE)      \
  V(SLOW_TEMPLATE_INSTANTIATIONS_CACHE_SUB_TYPE) \
  V(STRING_SPLIT_CACHE_SUB_TYPE)                 \
  V(STRING_TABLE_SUB_TYPE)                       \
  V(TEMPLATE_INFO_SUB_TYPE)                      \
  V(FEEDBACK_METADATA_SUB_TYPE)                  \
  V(WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE)

enum FixedArraySubInstanceType {
#define DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE(name) name,
  FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE)
#undef DEFINE_FIXED_ARRAY_SUB_INSTANCE_TYPE
      LAST_FIXED_ARRAY_SUB_TYPE = WEAK_NEW_SPACE_OBJECT_TO_CODE_SUB_TYPE
};

// Common superclass for FixedArrays that allow implementations to share
// common accessors and some code paths.
72
class FixedArrayBase : public HeapObject {
73 74 75 76 77 78 79 80 81
 public:
  // [length]: length of the array.
  inline int length() const;
  inline void set_length(int value);

  // Get and set the length using acquire loads and release stores.
  inline int synchronized_length() const;
  inline void synchronized_set_length(int value);

82
  inline Object unchecked_synchronized_length() const;
83

84
  DECL_CAST(FixedArrayBase)
85 86 87

  static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);

88
  V8_EXPORT_PRIVATE bool IsCowArray() const;
89

90 91 92 93 94 95 96 97 98
// Maximal allowed size, in bytes, of a single FixedArrayBase.
// Prevents overflowing size computations, as well as extreme memory
// consumption.
#ifdef V8_HOST_ARCH_32_BIT
  static const int kMaxSize = 512 * MB;
#else
  static const int kMaxSize = 1024 * MB;
#endif  // V8_HOST_ARCH_32_BIT

99
  // Layout description.
100
  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
101
                                TORQUE_GENERATED_FIXED_ARRAY_BASE_FIELDS)
102

103 104 105
 protected:
  // Special-purpose constructor for subclasses that have fast paths where
  // their ptr() is a Smi.
106
  inline FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi);
107

108
  OBJECT_CONSTRUCTORS(FixedArrayBase, HeapObject);
109 110
};

111
// FixedArray describes fixed-sized arrays with element type Object.
112 113 114
class FixedArray : public FixedArrayBase {
 public:
  // Setter and getter for elements.
115
  inline Object get(int index) const;
116
  static inline Handle<Object> get(FixedArray array, int index,
117 118 119
                                   Isolate* isolate);

  // Return a grown copy if the index is bigger than the array's length.
120
  V8_EXPORT_PRIVATE static Handle<FixedArray> SetAndGrow(
121 122
      Isolate* isolate, Handle<FixedArray> array, int index,
      Handle<Object> value, AllocationType allocation = AllocationType::kYoung);
123 124

  // Setter that uses write barrier.
125
  inline void set(int index, Object value);
126 127 128
  inline bool is_the_hole(Isolate* isolate, int index);

  // Setter that doesn't need write barrier.
129
  inline void set(int index, Smi value);
130
  // Setter with explicit barrier mode.
131
  inline void set(int index, Object value, WriteBarrierMode mode);
132 133 134 135 136 137 138 139 140

  // Setters for frequently used oddballs located in old space.
  inline void set_undefined(int index);
  inline void set_undefined(Isolate* isolate, int index);
  inline void set_null(int index);
  inline void set_null(Isolate* isolate, int index);
  inline void set_the_hole(int index);
  inline void set_the_hole(Isolate* isolate, int index);

141
  inline ObjectSlot GetFirstElementAddress();
142
  inline bool ContainsOnlySmisOrHoles();
143 144
  // Returns true iff the elements are Numbers and sorted ascending.
  bool ContainsSortedNumbers();
145 146

  // Gives access to raw memory which stores the array's data.
147 148
  inline ObjectSlot data_start();

149 150
  inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
                           int len, WriteBarrierMode mode);
151

152
  inline void CopyElements(Isolate* isolate, int dst_index, FixedArray src,
153 154
                           int src_index, int len, WriteBarrierMode mode);

155 156
  inline void FillWithHoles(int from, int to);

157
  // Shrink the array and insert filler objects. {new_length} must be > 0.
158
  V8_EXPORT_PRIVATE void Shrink(Isolate* isolate, int new_length);
159 160
  // If {new_length} is 0, return the canonical empty FixedArray. Otherwise
  // like above.
161 162
  static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate,
                                          Handle<FixedArray> array,
163
                                          int new_length);
164 165

  // Copy a sub array from the receiver to dest.
166 167
  V8_EXPORT_PRIVATE void CopyTo(int pos, FixedArray dest, int dest_pos,
                                int len) const;
168 169 170

  // Garbage collection support.
  static constexpr int SizeFor(int length) {
171
    return kHeaderSize + length * kTaggedSize;
172 173 174 175 176 177
  }

  // Code Generation support.
  static constexpr int OffsetOfElementAt(int index) { return SizeFor(index); }

  // Garbage collection support.
178
  inline ObjectSlot RawFieldOfElementAt(int index);
179

180
  DECL_CAST(FixedArray)
181
  // Maximally allowed length of a FixedArray.
182
  static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
183 184 185
  static_assert(Internals::IsValidSmi(kMaxLength),
                "FixedArray maxLength not a Smi");

186 187 188
  // Maximally allowed length for regular (non large object space) object.
  STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
  static const int kMaxRegularLength =
189
      (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize;
190 191 192 193 194

  // Dispatched behavior.
  DECL_PRINTER(FixedArray)
  DECL_VERIFIER(FixedArray)

195
  using BodyDescriptor = FlexibleBodyDescriptor<kHeaderSize>;
196

197 198
  static constexpr int kObjectsOffset = kHeaderSize;

199 200 201
 protected:
  // Set operation on FixedArray without using write barriers. Can
  // only be used for storing old space objects or smis.
202
  static inline void NoWriteBarrierSet(FixedArray array, int index,
203
                                       Object value);
204 205 206 207

 private:
  STATIC_ASSERT(kHeaderSize == Internals::kFixedArrayHeaderSize);

208 209 210 211
  inline void set_undefined(ReadOnlyRoots ro_roots, int index);
  inline void set_null(ReadOnlyRoots ro_roots, int index);
  inline void set_the_hole(ReadOnlyRoots ro_roots, int index);

212
  OBJECT_CONSTRUCTORS(FixedArray, FixedArrayBase);
213 214
};

215 216 217
// FixedArray alias added only because of IsFixedArrayExact() predicate, which
// checks for the exact instance type FIXED_ARRAY_TYPE instead of a range
// check: [FIRST_FIXED_ARRAY_TYPE, LAST_FIXED_ARRAY_TYPE].
218
class FixedArrayExact final : public FixedArray {};
219 220

// FixedDoubleArray describes fixed-sized arrays with element type double.
221
class FixedDoubleArray : public FixedArrayBase {
222 223 224 225
 public:
  // Setter and getter for elements.
  inline double get_scalar(int index);
  inline uint64_t get_representation(int index);
226
  static inline Handle<Object> get(FixedDoubleArray array, int index,
227 228 229 230 231 232 233 234 235 236 237 238 239 240
                                   Isolate* isolate);
  inline void set(int index, double value);
  inline void set_the_hole(Isolate* isolate, int index);
  inline void set_the_hole(int index);

  // Checking for the hole.
  inline bool is_the_hole(Isolate* isolate, int index);
  inline bool is_the_hole(int index);

  // Garbage collection support.
  inline static int SizeFor(int length) {
    return kHeaderSize + length * kDoubleSize;
  }

241 242
  inline void MoveElements(Isolate* isolate, int dst_index, int src_index,
                           int len, WriteBarrierMode mode);
243 244 245 246 247 248

  inline void FillWithHoles(int from, int to);

  // Code Generation support.
  static int OffsetOfElementAt(int index) { return SizeFor(index); }

249
  DECL_CAST(FixedDoubleArray)
250 251 252

  // Maximally allowed length of a FixedArray.
  static const int kMaxLength = (kMaxSize - kHeaderSize) / kDoubleSize;
253 254
  static_assert(Internals::IsValidSmi(kMaxLength),
                "FixedDoubleArray maxLength not a Smi");
255 256 257 258 259 260 261

  // Dispatched behavior.
  DECL_PRINTER(FixedDoubleArray)
  DECL_VERIFIER(FixedDoubleArray)

  class BodyDescriptor;

262
  OBJECT_CONSTRUCTORS(FixedDoubleArray, FixedArrayBase);
263 264
};

265
// WeakFixedArray describes fixed-sized arrays with element type
266
// MaybeObject.
267
class WeakFixedArray : public HeapObject {
268
 public:
269
  DECL_CAST(WeakFixedArray)
270

271
  inline MaybeObject Get(int index) const;
272 273

  // Setter that uses write barrier.
274
  inline void Set(int index, MaybeObject value);
275

276
  // Setter with explicit barrier mode.
277
  inline void Set(int index, MaybeObject value, WriteBarrierMode mode);
278

279
  static constexpr int SizeFor(int length) {
280
    return kHeaderSize + length * kTaggedSize;
281 282 283 284 285 286 287 288 289
  }

  DECL_INT_ACCESSORS(length)

  // Get and set the length using acquire loads and release stores.
  inline int synchronized_length() const;
  inline void synchronized_set_length(int value);

  // Gives access to raw memory which stores the array's data.
290
  inline MaybeObjectSlot data_start();
291

292
  inline MaybeObjectSlot RawFieldOfElementAt(int index);
293

294 295 296
  inline void CopyElements(Isolate* isolate, int dst_index, WeakFixedArray src,
                           int src_index, int len, WriteBarrierMode mode);

297
  DECL_PRINTER(WeakFixedArray)
298 299
  DECL_VERIFIER(WeakFixedArray)

300
  using BodyDescriptor = WeakArrayBodyDescriptor;
301

302
  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
303 304
                                TORQUE_GENERATED_WEAK_FIXED_ARRAY_FIELDS)
  static constexpr int kHeaderSize = kSize;
305 306

  static const int kMaxLength =
307
      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
308 309
  static_assert(Internals::IsValidSmi(kMaxLength),
                "WeakFixedArray maxLength not a Smi");
310

311
 protected:
312
  static int OffsetOfElementAt(int index) {
313
    return kHeaderSize + index * kTaggedSize;
314 315
  }

316
 private:
317 318 319 320
  friend class Heap;

  static const int kFirstIndex = 1;

321
  OBJECT_CONSTRUCTORS(WeakFixedArray, HeapObject);
322 323
};

324 325 326 327 328
// WeakArrayList is like a WeakFixedArray with static convenience methods for
// adding more elements. length() returns the number of elements in the list and
// capacity() returns the allocated size. The number of elements is stored at
// kLengthOffset and is updated with every insertion. The array grows
// dynamically with O(1) amortized insertion.
329
class WeakArrayList : public HeapObject {
330
 public:
331
  NEVER_READ_ONLY_SPACE
332
  DECL_CAST(WeakArrayList)
333 334 335
  DECL_VERIFIER(WeakArrayList)
  DECL_PRINTER(WeakArrayList)

336 337 338
  V8_EXPORT_PRIVATE static Handle<WeakArrayList> AddToEnd(
      Isolate* isolate, Handle<WeakArrayList> array,
      const MaybeObjectHandle& value);
339

340
  inline MaybeObject Get(int index) const;
341 342

  // Set the element at index to obj. The underlying array must be large enough.
343
  // If you need to grow the WeakArrayList, use the static AddToEnd() method
344
  // instead.
345
  inline void Set(int index, MaybeObject value,
346 347 348
                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

  static constexpr int SizeForCapacity(int capacity) {
349
    return kHeaderSize + capacity * kTaggedSize;
350 351 352
  }

  // Gives access to raw memory which stores the array's data.
353
  inline MaybeObjectSlot data_start();
354

355 356 357
  inline void CopyElements(Isolate* isolate, int dst_index, WeakArrayList src,
                           int src_index, int len, WriteBarrierMode mode);

358
  V8_EXPORT_PRIVATE bool IsFull();
359 360 361 362 363 364 365 366 367

  DECL_INT_ACCESSORS(capacity)
  DECL_INT_ACCESSORS(length)

  // Get and set the capacity using acquire loads and release stores.
  inline int synchronized_capacity() const;
  inline void synchronized_set_capacity(int value);


368
  // Layout description.
369 370 371 372 373 374 375 376
#define WEAK_ARRAY_LIST_FIELDS(V) \
  V(kCapacityOffset, kTaggedSize) \
  V(kLengthOffset, kTaggedSize)   \
  /* Header size. */              \
  V(kHeaderSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, WEAK_ARRAY_LIST_FIELDS)
#undef WEAK_ARRAY_LIST_FIELDS
377

378
  using BodyDescriptor = WeakArrayBodyDescriptor;
379

380
  static const int kMaxCapacity =
381
      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
382

383 384
  static Handle<WeakArrayList> EnsureSpace(
      Isolate* isolate, Handle<WeakArrayList> array, int length,
385
      AllocationType allocation = AllocationType::kYoung);
386

387 388 389
  // Returns the number of non-cleaned weak references in the array.
  int CountLiveWeakReferences() const;

390 391 392 393
  // Returns whether an entry was found and removed. Will move the elements
  // around in the array - this method can only be used in cases where the user
  // doesn't care about the indices! Users should make sure there are no
  // duplicates.
394
  V8_EXPORT_PRIVATE bool RemoveOne(const MaybeObjectHandle& value);
395

396
  class Iterator;
397

398 399
 private:
  static int OffsetOfElementAt(int index) {
400
    return kHeaderSize + index * kTaggedSize;
401 402
  }

403
  OBJECT_CONSTRUCTORS(WeakArrayList, HeapObject);
404 405 406 407 408 409
};

class WeakArrayList::Iterator {
 public:
  explicit Iterator(WeakArrayList array) : index_(0), array_(array) {}

410
  inline HeapObject Next();
411 412 413 414 415 416 417 418

 private:
  int index_;
  WeakArrayList array_;
#ifdef DEBUG
  DisallowHeapAllocation no_gc_;
#endif  // DEBUG
  DISALLOW_COPY_AND_ASSIGN(Iterator);
419 420
};

421 422 423 424 425 426 427
// Generic array grows dynamically with O(1) amortized insertion.
//
// ArrayList is a FixedArray with static convenience methods for adding more
// elements. The Length() method returns the number of elements in the list, not
// the allocated size. The number of elements is stored at kLengthIndex and is
// updated with every insertion. The elements of the ArrayList are stored in the
// underlying FixedArray starting at kFirstIndex.
428
class ArrayList : public FixedArray {
429
 public:
430 431 432 433 434 435 436
  V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
                                                 Handle<ArrayList> array,
                                                 Handle<Object> obj);
  V8_EXPORT_PRIVATE static Handle<ArrayList> Add(Isolate* isolate,
                                                 Handle<ArrayList> array,
                                                 Handle<Object> obj1,
                                                 Handle<Object> obj2);
437 438 439 440 441 442 443 444 445
  static Handle<ArrayList> New(Isolate* isolate, int size);

  // Returns the number of elements in the list, not the allocated size, which
  // is length(). Lower and upper case length() return different results!
  inline int Length() const;

  // Sets the Length() as used by Elements(). Does not change the underlying
  // storage capacity, i.e., length().
  inline void SetLength(int length);
446
  inline Object Get(int index) const;
447
  inline ObjectSlot Slot(int index);
448 449 450

  // Set the element at index to obj. The underlying array must be large enough.
  // If you need to grow the ArrayList, use the static Add() methods instead.
451
  inline void Set(int index, Object obj,
452 453 454
                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

  // Set the element at index to undefined. This does not change the Length().
455
  inline void Clear(int index, Object undefined);
456 457 458

  // Return a copy of the list of size Length() without the first entry. The
  // number returned by Length() is stored in the first entry.
459
  static Handle<FixedArray> Elements(Isolate* isolate, Handle<ArrayList> array);
460
  DECL_CAST(ArrayList)
461 462

 private:
463 464
  static Handle<ArrayList> EnsureSpace(Isolate* isolate,
                                       Handle<ArrayList> array, int length);
465 466
  static const int kLengthIndex = 0;
  static const int kFirstIndex = 1;
467
  OBJECT_CONSTRUCTORS(ArrayList, FixedArray);
468 469 470 471 472
};

enum SearchMode { ALL_ENTRIES, VALID_ENTRIES };

template <SearchMode search_mode, typename T>
473
inline int Search(T* array, Name name, int valid_entries = 0,
474 475 476 477
                  int* out_insertion_index = nullptr);

// ByteArray represents fixed sized byte arrays.  Used for the relocation info
// that is attached to code objects.
478
class ByteArray : public FixedArrayBase {
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508
 public:
  inline int Size();

  // Setter and getter.
  inline byte get(int index) const;
  inline void set(int index, byte value);

  // Copy in / copy out whole byte slices.
  inline void copy_out(int index, byte* buffer, int length);
  inline void copy_in(int index, const byte* buffer, int length);

  // Treat contents as an int array.
  inline int get_int(int index) const;
  inline void set_int(int index, int value);

  inline uint32_t get_uint32(int index) const;
  inline void set_uint32(int index, uint32_t value);

  // Clear uninitialized padding space. This ensures that the snapshot content
  // is deterministic.
  inline void clear_padding();

  static int SizeFor(int length) {
    return OBJECT_POINTER_ALIGN(kHeaderSize + length);
  }
  // We use byte arrays for free blocks in the heap.  Given a desired size in
  // bytes that is a multiple of the word size and big enough to hold a byte
  // array, this function returns the number of elements a byte array should
  // have.
  static int LengthFor(int size_in_bytes) {
509
    DCHECK(IsAligned(size_in_bytes, kTaggedSize));
510 511 512 513 514
    DCHECK_GE(size_in_bytes, kHeaderSize);
    return size_in_bytes - kHeaderSize;
  }

  // Returns data start address.
515
  inline byte* GetDataStartAddress();
516 517
  // Returns address of the past-the-end element.
  inline byte* GetDataEndAddress();
518 519 520 521

  inline int DataSize() const;

  // Returns a pointer to the ByteArray object for a given data start address.
522
  static inline ByteArray FromDataStartAddress(Address address);
523

524
  DECL_CAST(ByteArray)
525 526 527 528 529 530 531 532 533 534 535

  // Dispatched behavior.
  inline int ByteArraySize();
  DECL_PRINTER(ByteArray)
  DECL_VERIFIER(ByteArray)

  // Layout description.
  static const int kAlignedSize = OBJECT_POINTER_ALIGN(kHeaderSize);

  // Maximal length of a single ByteArray.
  static const int kMaxLength = kMaxSize - kHeaderSize;
536 537
  static_assert(Internals::IsValidSmi(kMaxLength),
                "ByteArray maxLength not a Smi");
538 539 540

  class BodyDescriptor;

541 542 543 544 545
 protected:
  // Special-purpose constructor for subclasses that have fast paths where
  // their ptr() is a Smi.
  inline ByteArray(Address ptr, AllowInlineSmiStorage allow_smi);

546
  OBJECT_CONSTRUCTORS(ByteArray, FixedArrayBase);
547 548 549 550 551 552 553
};

// Wrapper class for ByteArray which can store arbitrary C++ classes, as long
// as they can be copied with memcpy.
template <class T>
class PodArray : public ByteArray {
 public:
554 555 556
  static Handle<PodArray<T>> New(
      Isolate* isolate, int length,
      AllocationType allocation = AllocationType::kYoung);
557 558 559 560
  void copy_out(int index, T* result) {
    ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
                        sizeof(T));
  }
561 562 563 564 565 566

  void copy_in(int index, const T* buffer, int length) {
    ByteArray::copy_in(index * sizeof(T), reinterpret_cast<const byte*>(buffer),
                       length * sizeof(T));
  }

567 568 569 570 571
  T get(int index) {
    T result;
    copy_out(index, &result);
    return result;
  }
572 573 574

  void set(int index, const T& value) { copy_in(index, &value, 1); }

575
  inline int length() const;
576
  DECL_CAST(PodArray<T>)
577

578
  OBJECT_CONSTRUCTORS(PodArray<T>, ByteArray);
579 580
};

581
class FixedTypedArrayBase : public FixedArrayBase {
582 583
 public:
  // [base_pointer]: Either points to the FixedTypedArrayBase itself or nullptr.
584
  DECL_ACCESSORS(base_pointer, Object)
585 586 587 588

  // [external_pointer]: Contains the offset between base_pointer and the start
  // of the data. If the base_pointer is a nullptr, the external_pointer
  // therefore points to the actual backing store.
589
  DECL_PRIMITIVE_ACCESSORS(external_pointer, void*)
590 591

  // Dispatched behavior.
592
  DECL_CAST(FixedTypedArrayBase)
593

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
  // [number_of_elements_onheap]: This length is the number of elements stored
  // in this FixedTypedArray if it is on-heap. It is always 0 for the off-heap
  // case (where the base_pointer == 0). It is only useful for printing,
  // verification and object setup as it does not represent the length of the
  // associated JSTypedArray object anymore.
  inline int number_of_elements_onheap_only() const;
  inline void set_number_of_elements_onheap_only(int value);

  // These length accessors are deleted because the meaning of length() has
  // changed (see comment above). For the length of a JSTypedArray, use
  // JSTypedArray::length(). For the number of elements in an on-heap
  // FixedTypedArray, use number_of_elements_onheap_only() above.
  inline int length() const = delete;
  inline void set_length(int) = delete;

609
  DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
610
                                TORQUE_GENERATED_FIXED_TYPED_ARRAY_BASE_FIELDS)
611
  static const int kHeaderSize = kSize;
612

613 614 615 616 617 618 619
#ifdef V8_COMPRESS_POINTERS
  // TODO(ishell, v8:8875): When pointer compression is enabled the kHeaderSize
  // is only kTaggedSize aligned but we can keep using unaligned access since
  // both x64 and arm64 architectures (where pointer compression supported)
  // allow unaligned access to doubles.
  STATIC_ASSERT(IsAligned(kHeaderSize, kTaggedSize));
#else
620
  STATIC_ASSERT(IsAligned(kHeaderSize, kDoubleAlignment));
621
#endif
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647

  static const int kDataOffset = kHeaderSize;

  static const int kMaxElementSize = 8;

#ifdef V8_HOST_ARCH_32_BIT
  static const size_t kMaxByteLength = std::numeric_limits<size_t>::max();
#else
  static const size_t kMaxByteLength =
      static_cast<size_t>(Smi::kMaxValue) * kMaxElementSize;
#endif  // V8_HOST_ARCH_32_BIT

  static const size_t kMaxLength = Smi::kMaxValue;

  class BodyDescriptor;

  inline int size() const;

  static inline int TypedArraySize(InstanceType type, int length);
  inline int TypedArraySize(InstanceType type) const;

  // Use with care: returns raw pointer into heap.
  inline void* DataPtr();

  inline int DataSize() const;

648 649 650 651 652 653 654 655
  static inline intptr_t ExternalPointerValueForOnHeapArray() {
    return FixedTypedArrayBase::kDataOffset - kHeapObjectTag;
  }

  static inline void* ExternalPointerPtrForOnHeapArray() {
    return reinterpret_cast<void*>(ExternalPointerValueForOnHeapArray());
  }

656 657 658 659 660
 private:
  static inline int ElementSize(InstanceType type);

  inline int DataSize(InstanceType type) const;

661
  OBJECT_CONSTRUCTORS(FixedTypedArrayBase, FixedArrayBase);
662 663 664 665 666
};

template <class Traits>
class FixedTypedArray : public FixedTypedArrayBase {
 public:
667
  using ElementType = typename Traits::ElementType;
668 669
  static const InstanceType kInstanceType = Traits::kInstanceType;

670
  DECL_CAST(FixedTypedArray<Traits>)
671

672
  static inline ElementType get_scalar_from_data_ptr(void* data_ptr, int index);
673
  inline ElementType get_scalar(int index);
674
  static inline Handle<Object> get(Isolate* isolate, FixedTypedArray array,
675
                                   int index);
676 677 678 679 680
  inline void set(int index, ElementType value);

  static inline ElementType from(int value);
  static inline ElementType from(uint32_t value);
  static inline ElementType from(double value);
681 682 683 684 685
  static inline ElementType from(int64_t value);
  static inline ElementType from(uint64_t value);

  static inline ElementType FromHandle(Handle<Object> value,
                                       bool* lossless = nullptr);
686 687 688

  // This accessor applies the correct conversion from Smi, HeapNumber
  // and undefined.
689
  inline void SetValue(uint32_t index, Object value);
690 691 692 693 694

  DECL_PRINTER(FixedTypedArray)
  DECL_VERIFIER(FixedTypedArray)

 private:
695
  OBJECT_CONSTRUCTORS(FixedTypedArray, FixedTypedArrayBase);
696 697
};

698 699 700 701
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType)               \
  STATIC_ASSERT(sizeof(elementType) <= FixedTypedArrayBase::kMaxElementSize); \
  class Type##ArrayTraits {                                                   \
   public: /* NOLINT */                                                       \
702
    using ElementType = elementType;                                          \
703
    static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE;      \
704
    static const char* ArrayTypeName() { return "Fixed" #Type "Array"; }      \
705 706 707 708 709
    static inline Handle<Object> ToHandle(Isolate* isolate,                   \
                                          elementType scalar);                \
    static inline elementType defaultValue();                                 \
  };                                                                          \
                                                                              \
710
  using Fixed##Type##Array = FixedTypedArray<Type##ArrayTraits>;
711 712 713 714 715

TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)

#undef FIXED_TYPED_ARRAY_TRAITS

716
class TemplateList : public FixedArray {
717 718 719
 public:
  static Handle<TemplateList> New(Isolate* isolate, int size);
  inline int length() const;
720 721
  inline Object get(int index) const;
  inline void set(int index, Object value);
722 723
  static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
                                  Handle<Object> value);
724
  DECL_CAST(TemplateList)
725 726 727
 private:
  static const int kLengthIndex = 0;
  static const int kFirstElementIndex = kLengthIndex + 1;
728

729
  OBJECT_CONSTRUCTORS(TemplateList, FixedArray);
730 731 732 733 734 735 736 737
};

}  // namespace internal
}  // namespace v8

#include "src/objects/object-macros-undef.h"

#endif  // V8_OBJECTS_FIXED_ARRAY_H_