fixed-array.h 24.7 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/slots.h"
11
#include "src/objects/smi.h"
12
#include "torque-generated/class-definitions-from-dsl.h"
13 14 15 16 17 18

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

namespace v8 {
namespace internal {
19 20
typedef FlexibleWeakBodyDescriptor<HeapObject::kHeaderSize>
    WeakArrayBodyDescriptor;
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 53
#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)                        \
54
  V(SERIALIZED_OBJECTS_SUB_TYPE)                 \
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
  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.
73
class FixedArrayBase : public HeapObject {
74 75 76 77 78 79 80 81 82
 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);

83
  inline Object unchecked_synchronized_length() const;
84

85
  DECL_CAST(FixedArrayBase)
86 87 88 89 90

  static int GetMaxLengthForNewSpaceAllocation(ElementsKind kind);

  bool IsCowArray() const;

91 92 93 94 95 96 97 98 99
// 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

100
  // Layout description.
101 102
  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
                                FIXED_ARRAY_BASE_FIELDS)
103 104

  static const int kHeaderSize = kSize;
105

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

111
  OBJECT_CONSTRUCTORS(FixedArrayBase, HeapObject);
112 113
};

114
// FixedArray describes fixed-sized arrays with element type Object.
115 116 117
class FixedArray : public FixedArrayBase {
 public:
  // Setter and getter for elements.
118
  inline Object get(int index) const;
119
  static inline Handle<Object> get(FixedArray array, int index,
120 121 122 123 124 125 126 127
                                   Isolate* isolate);
  template <class T>
  MaybeHandle<T> GetValue(Isolate* isolate, int index) const;

  template <class T>
  Handle<T> GetValueChecked(Isolate* isolate, int index) const;

  // Return a grown copy if the index is bigger than the array's length.
128 129
  static Handle<FixedArray> SetAndGrow(Isolate* isolate,
                                       Handle<FixedArray> array, int index,
130 131
                                       Handle<Object> value,
                                       PretenureFlag pretenure = NOT_TENURED);
132 133

  // Setter that uses write barrier.
134
  inline void set(int index, Object value);
135 136 137
  inline bool is_the_hole(Isolate* isolate, int index);

  // Setter that doesn't need write barrier.
138
  inline void set(int index, Smi value);
139
  // Setter with explicit barrier mode.
140
  inline void set(int index, Object value, WriteBarrierMode mode);
141 142 143 144 145 146 147 148 149

  // 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);

150
  inline ObjectSlot GetFirstElementAddress();
151
  inline bool ContainsOnlySmisOrHoles();
152 153
  // Returns true iff the elements are Numbers and sorted ascending.
  bool ContainsSortedNumbers();
154 155

  // Gives access to raw memory which stores the array's data.
156 157 158 159
  inline ObjectSlot data_start();

  inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
                           WriteBarrierMode mode);
160 161 162

  inline void FillWithHoles(int from, int to);

163
  // Shrink the array and insert filler objects. {new_length} must be > 0.
164
  void Shrink(Isolate* isolate, int new_length);
165 166
  // If {new_length} is 0, return the canonical empty FixedArray. Otherwise
  // like above.
167 168
  static Handle<FixedArray> ShrinkOrEmpty(Isolate* isolate,
                                          Handle<FixedArray> array,
169
                                          int new_length);
170 171

  // Copy a sub array from the receiver to dest.
172
  void CopyTo(int pos, FixedArray dest, int dest_pos, int len) const;
173 174 175

  // Garbage collection support.
  static constexpr int SizeFor(int length) {
176
    return kHeaderSize + length * kTaggedSize;
177 178 179 180 181 182
  }

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

  // Garbage collection support.
183
  inline ObjectSlot RawFieldOfElementAt(int index);
184

185
  DECL_CAST(FixedArray)
186
  // Maximally allowed length of a FixedArray.
187
  static const int kMaxLength = (kMaxSize - kHeaderSize) / kTaggedSize;
188 189 190
  static_assert(Internals::IsValidSmi(kMaxLength),
                "FixedArray maxLength not a Smi");

191 192 193
  // Maximally allowed length for regular (non large object space) object.
  STATIC_ASSERT(kMaxRegularHeapObjectSize < kMaxSize);
  static const int kMaxRegularLength =
194
      (kMaxRegularHeapObjectSize - kHeaderSize) / kTaggedSize;
195 196 197 198 199 200 201 202 203 204

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

  typedef FlexibleBodyDescriptor<kHeaderSize> BodyDescriptor;

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

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

211 212 213 214
  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);

215
  OBJECT_CONSTRUCTORS(FixedArray, FixedArrayBase);
216 217
};

218 219 220
// 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].
221
class FixedArrayExact final : public FixedArray {};
222 223

// FixedDoubleArray describes fixed-sized arrays with element type double.
224
class FixedDoubleArray : public FixedArrayBase {
225 226 227 228
 public:
  // Setter and getter for elements.
  inline double get_scalar(int index);
  inline uint64_t get_representation(int index);
229
  static inline Handle<Object> get(FixedDoubleArray array, int index,
230 231 232 233 234 235 236 237 238 239 240 241 242 243
                                   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;
  }

244 245
  inline void MoveElements(Heap* heap, int dst_index, int src_index, int len,
                           WriteBarrierMode mode);
246 247 248 249 250 251

  inline void FillWithHoles(int from, int to);

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

252
  DECL_CAST(FixedDoubleArray)
253 254 255

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

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

  class BodyDescriptor;

265
  OBJECT_CONSTRUCTORS(FixedDoubleArray, FixedArrayBase);
266 267
};

268
// WeakFixedArray describes fixed-sized arrays with element type
269
// MaybeObject.
270
class WeakFixedArray : public HeapObject {
271
 public:
272
  DECL_CAST(WeakFixedArray)
273

274
  inline MaybeObject Get(int index) const;
275 276

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

279
  // Setter with explicit barrier mode.
280
  inline void Set(int index, MaybeObject value, WriteBarrierMode mode);
281

282
  static constexpr int SizeFor(int length) {
283
    return kHeaderSize + length * kTaggedSize;
284 285 286 287 288 289 290 291 292
  }

  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.
293
  inline MaybeObjectSlot data_start();
294

295
  inline MaybeObjectSlot RawFieldOfElementAt(int index);
296

297
  DECL_PRINTER(WeakFixedArray)
298 299
  DECL_VERIFIER(WeakFixedArray)

300
  typedef WeakArrayBodyDescriptor BodyDescriptor;
301

302 303 304 305 306 307 308 309 310
  // Layout description.
#define WEAK_FIXED_ARRAY_FIELDS(V) \
  V(kLengthOffset, kTaggedSize)    \
  /* Header size. */               \
  V(kHeaderSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize,
                                WEAK_FIXED_ARRAY_FIELDS)
#undef WEAK_FIXED_ARRAY_FIELDS
311 312

  static const int kMaxLength =
313
      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
314 315
  static_assert(Internals::IsValidSmi(kMaxLength),
                "WeakFixedArray maxLength not a Smi");
316

317
 protected:
318
  static int OffsetOfElementAt(int index) {
319
    return kHeaderSize + index * kTaggedSize;
320 321
  }

322
 private:
323 324 325 326
  friend class Heap;

  static const int kFirstIndex = 1;

327
  OBJECT_CONSTRUCTORS(WeakFixedArray, HeapObject);
328 329
};

330 331 332 333 334
// 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.
335
class WeakArrayList : public HeapObject {
336
 public:
337
  NEVER_READ_ONLY_SPACE
338
  DECL_CAST(WeakArrayList)
339 340 341
  DECL_VERIFIER(WeakArrayList)
  DECL_PRINTER(WeakArrayList)

342 343
  static Handle<WeakArrayList> AddToEnd(Isolate* isolate,
                                        Handle<WeakArrayList> array,
344
                                        const MaybeObjectHandle& value);
345

346
  inline MaybeObject Get(int index) const;
347 348

  // Set the element at index to obj. The underlying array must be large enough.
349
  // If you need to grow the WeakArrayList, use the static AddToEnd() method
350
  // instead.
351
  inline void Set(int index, MaybeObject value,
352 353 354
                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);

  static constexpr int SizeForCapacity(int capacity) {
355
    return kHeaderSize + capacity * kTaggedSize;
356 357 358
  }

  // Gives access to raw memory which stores the array's data.
359
  inline MaybeObjectSlot data_start();
360 361 362 363 364 365 366 367 368 369 370

  bool IsFull();

  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);


371 372 373 374 375 376 377 378 379
  // Layout description.
#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
380

381 382
  typedef WeakArrayBodyDescriptor BodyDescriptor;

383
  static const int kMaxCapacity =
384
      (FixedArray::kMaxSize - kHeaderSize) / kTaggedSize;
385

386 387 388
  static Handle<WeakArrayList> EnsureSpace(
      Isolate* isolate, Handle<WeakArrayList> array, int length,
      PretenureFlag pretenure = NOT_TENURED);
389

390 391 392
  // Returns the number of non-cleaned weak references in the array.
  int CountLiveWeakReferences() const;

393 394 395 396
  // 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.
397
  bool RemoveOne(const MaybeObjectHandle& value);
398

399
  class Iterator;
400

401 402
 private:
  static int OffsetOfElementAt(int index) {
403
    return kHeaderSize + index * kTaggedSize;
404 405
  }

406
  OBJECT_CONSTRUCTORS(WeakArrayList, HeapObject);
407 408 409 410 411 412
};

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

413
  inline HeapObject Next();
414 415 416 417 418 419 420 421

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

424 425 426 427 428 429 430
// 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.
431
class ArrayList : public FixedArray {
432
 public:
433 434 435 436
  static Handle<ArrayList> Add(Isolate* isolate, Handle<ArrayList> array,
                               Handle<Object> obj);
  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 554 555 556 557 558 559
};

// 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:
  static Handle<PodArray<T>> New(Isolate* isolate, int length,
                                 PretenureFlag pretenure = NOT_TENURED);
  void copy_out(int index, T* result) {
    ByteArray::copy_out(index * sizeof(T), reinterpret_cast<byte*>(result),
                        sizeof(T));
  }
560 561 562 563 564 565

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

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

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

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

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

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

  // [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.
588
  DECL_ACCESSORS(external_pointer, void*)
589 590

  // Dispatched behavior.
591
  DECL_CAST(FixedTypedArrayBase)
592

593 594 595 596 597 598 599 600 601 602 603
#define FIXED_TYPED_ARRAY_BASE_FIELDS(V)        \
  V(kBasePointerOffset, kTaggedSize)            \
  V(kExternalPointerOffset, kSystemPointerSize) \
  /* Header size. */                            \
  V(kHeaderSize, 0)

  DEFINE_FIELD_OFFSET_CONSTANTS(FixedArrayBase::kHeaderSize,
                                FIXED_TYPED_ARRAY_BASE_FIELDS)
#undef FIXED_TYPED_ARRAY_BASE_FIELDS

  STATIC_ASSERT(IsAligned(kHeaderSize, kDoubleAlignment));
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636

  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;

  inline size_t ByteLength() const;

 private:
  static inline int ElementSize(InstanceType type);

  inline int DataSize(InstanceType type) const;

637
  OBJECT_CONSTRUCTORS(FixedTypedArrayBase, FixedArrayBase);
638 639 640 641 642 643 644 645
};

template <class Traits>
class FixedTypedArray : public FixedTypedArrayBase {
 public:
  typedef typename Traits::ElementType ElementType;
  static const InstanceType kInstanceType = Traits::kInstanceType;

646
  DECL_CAST(FixedTypedArray<Traits>)
647

648
  static inline ElementType get_scalar_from_data_ptr(void* data_ptr, int index);
649
  inline ElementType get_scalar(int index);
650
  static inline Handle<Object> get(Isolate* isolate, FixedTypedArray array,
651
                                   int index);
652 653 654 655 656
  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);
657 658 659 660 661
  static inline ElementType from(int64_t value);
  static inline ElementType from(uint64_t value);

  static inline ElementType FromHandle(Handle<Object> value,
                                       bool* lossless = nullptr);
662 663 664

  // This accessor applies the correct conversion from Smi, HeapNumber
  // and undefined.
665
  inline void SetValue(uint32_t index, Object value);
666 667 668 669 670

  DECL_PRINTER(FixedTypedArray)
  DECL_VERIFIER(FixedTypedArray)

 private:
671
  OBJECT_CONSTRUCTORS(FixedTypedArray, FixedTypedArrayBase);
672 673
};

674 675 676 677 678 679 680 681 682 683 684 685
#define FIXED_TYPED_ARRAY_TRAITS(Type, type, TYPE, elementType)               \
  STATIC_ASSERT(sizeof(elementType) <= FixedTypedArrayBase::kMaxElementSize); \
  class Type##ArrayTraits {                                                   \
   public: /* NOLINT */                                                       \
    typedef elementType ElementType;                                          \
    static const InstanceType kInstanceType = FIXED_##TYPE##_ARRAY_TYPE;      \
    static const char* Designator() { return #type " array"; }                \
    static inline Handle<Object> ToHandle(Isolate* isolate,                   \
                                          elementType scalar);                \
    static inline elementType defaultValue();                                 \
  };                                                                          \
                                                                              \
686 687 688 689 690 691
  typedef FixedTypedArray<Type##ArrayTraits> Fixed##Type##Array;

TYPED_ARRAYS(FIXED_TYPED_ARRAY_TRAITS)

#undef FIXED_TYPED_ARRAY_TRAITS

692
class TemplateList : public FixedArray {
693 694 695
 public:
  static Handle<TemplateList> New(Isolate* isolate, int size);
  inline int length() const;
696 697
  inline Object get(int index) const;
  inline void set(int index, Object value);
698 699
  static Handle<TemplateList> Add(Isolate* isolate, Handle<TemplateList> list,
                                  Handle<Object> value);
700
  DECL_CAST(TemplateList)
701 702 703
 private:
  static const int kLengthIndex = 0;
  static const int kFirstElementIndex = kLengthIndex + 1;
704

705
  OBJECT_CONSTRUCTORS(TemplateList, FixedArray);
706 707 708 709 710 711 712 713
};

}  // namespace internal
}  // namespace v8

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

#endif  // V8_OBJECTS_FIXED_ARRAY_H_