fixed-array-inl.h 20 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_INL_H_
#define V8_OBJECTS_FIXED_ARRAY_INL_H_

8 9
#include "src/objects/fixed-array.h"

10
#include "src/handles/handles-inl.h"
11
#include "src/heap/heap-write-barrier-inl.h"
12
#include "src/numbers/conversions.h"
13
#include "src/objects/bigint.h"
14
#include "src/objects/compressed-slots.h"
15
#include "src/objects/heap-number-inl.h"
16
#include "src/objects/map.h"
17
#include "src/objects/maybe-object-inl.h"
18
#include "src/objects/objects-inl.h"
19
#include "src/objects/oddball.h"
20
#include "src/objects/slots.h"
21
#include "src/roots/roots-inl.h"
22
#include "src/sanitizer/tsan.h"
23

24 25
#include "torque-generated/class-definitions-tq-inl.h"

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

namespace v8 {
namespace internal {

32 33 34 35 36 37
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase)
FixedArrayBase::FixedArrayBase(Address ptr,
                               HeapObject::AllowInlineSmiStorage allow_smi)
    : TorqueGeneratedFixedArrayBase(ptr, allow_smi) {}
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray)
38
OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
39 40 41
TQ_OBJECT_CONSTRUCTORS_IMPL(ByteArray)
ByteArray::ByteArray(Address ptr, HeapObject::AllowInlineSmiStorage allow_smi)
    : TorqueGeneratedByteArray(ptr, allow_smi) {}
42
OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
43 44
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray)
TQ_OBJECT_CONSTRUCTORS_IMPL(WeakArrayList)
45

46 47
NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)

48 49
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(TemplateList)
50 51

SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
52

53
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
54

55 56
SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)

57
Object FixedArrayBase::unchecked_synchronized_length() const {
58
  return ACQUIRE_READ_FIELD(*this, kLengthOffset);
59 60
}

61
ObjectSlot FixedArray::GetFirstElementAddress() {
62
  return RawField(OffsetOfElementAt(0));
63 64 65
}

bool FixedArray::ContainsOnlySmisOrHoles() {
66
  Object the_hole = GetReadOnlyRoots().the_hole_value();
67 68
  ObjectSlot current = GetFirstElementAddress();
  for (int i = 0; i < length(); ++i, ++current) {
69
    Object candidate = *current;
70
    if (!candidate.IsSmi() && candidate != the_hole) return false;
71 72 73 74
  }
  return true;
}

75
Object FixedArray::get(int index) const {
76
  const Isolate* isolate = GetIsolateForPtrCompr(*this);
77 78 79
  return get(isolate, index);
}

80
Object FixedArray::get(const Isolate* isolate, int index) const {
81 82 83
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  return TaggedField<Object>::Relaxed_Load(isolate, *this,
                                           OffsetOfElementAt(index));
84 85
}

86
Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
87
  return handle(array.get(isolate, index), isolate);
88
}
89 90

bool FixedArray::is_the_hole(Isolate* isolate, int index) {
91
  return get(isolate, index).IsTheHole(isolate);
92 93
}

94
void FixedArray::set(int index, Smi value) {
95
  DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
96
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
97
  DCHECK(Object(value).IsSmi());
98
  int offset = OffsetOfElementAt(index);
99
  RELAXED_WRITE_FIELD(*this, offset, value);
100 101
}

102
void FixedArray::set(int index, Object value) {
103
  DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
104
  DCHECK(IsFixedArray());
105 106
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  int offset = OffsetOfElementAt(index);
107 108
  RELAXED_WRITE_FIELD(*this, offset, value);
  WRITE_BARRIER(*this, offset, value);
109 110
}

111
void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
112
  DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
113 114
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  int offset = OffsetOfElementAt(index);
115 116
  RELAXED_WRITE_FIELD(*this, offset, value);
  CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
117 118
}

119
// static
120
void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
121
  DCHECK_NE(array.map(), array.GetReadOnlyRoots().fixed_cow_array_map());
122 123
  DCHECK_LT(static_cast<unsigned>(index),
            static_cast<unsigned>(array.length()));
124
  DCHECK(!ObjectInYoungGeneration(value));
125 126
  int offset = OffsetOfElementAt(index);
  RELAXED_WRITE_FIELD(array, offset, value);
127
}
128 129

void FixedArray::set_undefined(int index) {
130
  set_undefined(GetReadOnlyRoots(), index);
131 132 133
}

void FixedArray::set_undefined(Isolate* isolate, int index) {
134
  set_undefined(ReadOnlyRoots(isolate), index);
135 136
}

137
void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
138
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
139 140 141
}

void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
142 143

void FixedArray::set_null(Isolate* isolate, int index) {
144
  set_null(ReadOnlyRoots(isolate), index);
145 146
}

147
void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
148
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
149 150 151 152 153
}

void FixedArray::set_the_hole(int index) {
  set_the_hole(GetReadOnlyRoots(), index);
}
154 155

void FixedArray::set_the_hole(Isolate* isolate, int index) {
156 157 158 159
  set_the_hole(ReadOnlyRoots(isolate), index);
}

void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
160
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
161 162 163 164
}

void FixedArray::FillWithHoles(int from, int to) {
  for (int i = from; i < to; i++) {
165
    set_the_hole(i);
166 167 168
  }
}

169
ObjectSlot FixedArray::data_start() { return RawField(OffsetOfElementAt(0)); }
170

171
ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
172 173
  return RawField(OffsetOfElementAt(index));
}
174

175 176 177
void FixedArray::MoveElements(Isolate* isolate, int dst_index, int src_index,
                              int len, WriteBarrierMode mode) {
  if (len == 0) return;
178 179
  DCHECK_LE(dst_index + len, length());
  DCHECK_LE(src_index + len, length());
180
  DisallowHeapAllocation no_gc;
181 182 183
  ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
  ObjectSlot src_slot(RawFieldOfElementAt(src_index));
  isolate->heap()->MoveRange(*this, dst_slot, src_slot, len, mode);
184 185
}

186
void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src,
187
                              int src_index, int len, WriteBarrierMode mode) {
188
  if (len == 0) return;
189 190
  DCHECK_LE(dst_index + len, length());
  DCHECK_LE(src_index + len, src.length());
191
  DisallowHeapAllocation no_gc;
192 193

  ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
194
  ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
195
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
196
}
197

198 199 200 201 202 203 204 205 206 207 208 209 210
// Due to left- and right-trimming, concurrent visitors need to read the length
// with acquire semantics.
// TODO(ulan): Acquire should not be needed anymore.
inline int FixedArray::AllocatedSize() {
  return SizeFor(synchronized_length());
}
inline int WeakFixedArray::AllocatedSize() {
  return SizeFor(synchronized_length());
}
inline int WeakArrayList::AllocatedSize() {
  return SizeFor(synchronized_capacity());
}

211 212 213 214 215 216 217
// Perform a binary search in a fixed array.
template <SearchMode search_mode, typename T>
int BinarySearch(T* array, Name name, int valid_entries,
                 int* out_insertion_index) {
  DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
  int low = 0;
  int high = array->number_of_entries() - 1;
218
  uint32_t hash = name.hash_field();
219 220 221 222 223 224 225
  int limit = high;

  DCHECK(low <= high);

  while (low != high) {
    int mid = low + (high - low) / 2;
    Name mid_name = array->GetSortedKey(mid);
226
    uint32_t mid_hash = mid_name.hash_field();
227 228 229 230 231 232 233 234 235 236

    if (mid_hash >= hash) {
      high = mid;
    } else {
      low = mid + 1;
    }
  }

  for (; low <= limit; ++low) {
    int sort_index = array->GetSortedKeyIndex(low);
237
    Name entry = array->GetKey(InternalIndex(sort_index));
238
    uint32_t current_hash = entry.hash_field();
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
    if (current_hash != hash) {
      if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
        *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
      }
      return T::kNotFound;
    }
    if (entry == name) {
      if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
        return sort_index;
      }
      return T::kNotFound;
    }
  }

  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
    *out_insertion_index = limit + 1;
  }
  return T::kNotFound;
}

// Perform a linear search in this fixed array. len is the number of entry
// indices that are valid.
template <SearchMode search_mode, typename T>
int LinearSearch(T* array, Name name, int valid_entries,
                 int* out_insertion_index) {
  if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
265
    uint32_t hash = name.hash_field();
266 267 268
    int len = array->number_of_entries();
    for (int number = 0; number < len; number++) {
      int sorted_index = array->GetSortedKeyIndex(number);
269
      Name entry = array->GetKey(InternalIndex(sorted_index));
270
      uint32_t current_hash = entry.hash_field();
271 272 273 274 275 276 277 278 279 280 281 282
      if (current_hash > hash) {
        *out_insertion_index = sorted_index;
        return T::kNotFound;
      }
      if (entry == name) return sorted_index;
    }
    *out_insertion_index = len;
    return T::kNotFound;
  } else {
    DCHECK_LE(valid_entries, array->number_of_entries());
    DCHECK_NULL(out_insertion_index);  // Not supported here.
    for (int number = 0; number < valid_entries; number++) {
283
      if (array->GetKey(InternalIndex(number)) == name) return number;
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
    }
    return T::kNotFound;
  }
}

template <SearchMode search_mode, typename T>
int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
  SLOW_DCHECK(array->IsSortedNoDuplicates());

  if (valid_entries == 0) {
    if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
      *out_insertion_index = 0;
    }
    return T::kNotFound;
  }

  // Fast case: do linear search for small arrays.
  const int kMaxElementsForLinearSearch = 8;
  if (valid_entries <= kMaxElementsForLinearSearch) {
    return LinearSearch<search_mode>(array, name, valid_entries,
                                     out_insertion_index);
  }

  // Slow case: perform binary search.
  return BinarySearch<search_mode>(array, name, valid_entries,
                                   out_insertion_index);
}

312
double FixedDoubleArray::get_scalar(int index) {
313 314
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
315 316
  DCHECK(index >= 0 && index < this->length());
  DCHECK(!is_the_hole(index));
317
  return ReadField<double>(kHeaderSize + index * kDoubleSize);
318 319 320
}

uint64_t FixedDoubleArray::get_representation(int index) {
321 322
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
323 324
  DCHECK(index >= 0 && index < this->length());
  int offset = kHeaderSize + index * kDoubleSize;
325
  // Bug(v8:8875): Doubles may be unaligned.
326
  return base::ReadUnalignedValue<uint64_t>(field_address(offset));
327 328
}

329
Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
330
                                     Isolate* isolate) {
331
  if (array.is_the_hole(index)) {
332
    return ReadOnlyRoots(isolate).the_hole_value_handle();
333
  } else {
334
    return isolate->factory()->NewNumber(array.get_scalar(index));
335 336 337 338
  }
}

void FixedDoubleArray::set(int index, double value) {
339 340
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
341 342
  int offset = kHeaderSize + index * kDoubleSize;
  if (std::isnan(value)) {
343
    WriteField<double>(offset, std::numeric_limits<double>::quiet_NaN());
344
  } else {
345
    WriteField<double>(offset, value);
346 347 348 349 350 351 352 353 354
  }
  DCHECK(!is_the_hole(index));
}

void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
  set_the_hole(index);
}

void FixedDoubleArray::set_the_hole(int index) {
355 356
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
357
  int offset = kHeaderSize + index * kDoubleSize;
358
  base::WriteUnalignedValue<uint64_t>(field_address(offset), kHoleNanInt64);
359 360 361 362 363 364 365 366 367 368
}

bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
  return is_the_hole(index);
}

bool FixedDoubleArray::is_the_hole(int index) {
  return get_representation(index) == kHoleNanInt64;
}

369 370 371
void FixedDoubleArray::MoveElements(Isolate* isolate, int dst_index,
                                    int src_index, int len,
                                    WriteBarrierMode mode) {
372
  DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
373 374
  double* data_start =
      reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
375
  MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
376 377 378 379 380 381 382 383
}

void FixedDoubleArray::FillWithHoles(int from, int to) {
  for (int i = from; i < to; i++) {
    set_the_hole(i);
  }
}

384
MaybeObject WeakFixedArray::Get(int index) const {
385
  const Isolate* isolate = GetIsolateForPtrCompr(*this);
386 387 388
  return Get(isolate, index);
}

389
MaybeObject WeakFixedArray::Get(const Isolate* isolate, int index) const {
390
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
391
  return objects(isolate, index);
392 393
}

394
void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
395
  set_objects(index, value, mode);
396 397
}

398
MaybeObjectSlot WeakFixedArray::data_start() {
399
  return RawMaybeWeakField(kObjectsOffset);
400 401
}

402
MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
403
  return RawMaybeWeakField(OffsetOfElementAt(index));
404 405
}

406 407 408 409 410 411 412 413 414
void WeakFixedArray::CopyElements(Isolate* isolate, int dst_index,
                                  WeakFixedArray src, int src_index, int len,
                                  WriteBarrierMode mode) {
  if (len == 0) return;
  DCHECK_LE(dst_index + len, length());
  DCHECK_LE(src_index + len, src.length());
  DisallowHeapAllocation no_gc;

  MaybeObjectSlot dst_slot(data_start() + dst_index);
415
  MaybeObjectSlot src_slot(src.data_start() + src_index);
416 417 418
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}

419
MaybeObject WeakArrayList::Get(int index) const {
420
  const Isolate* isolate = GetIsolateForPtrCompr(*this);
421 422 423
  return Get(isolate, index);
}

424
MaybeObject WeakArrayList::Get(const Isolate* isolate, int index) const {
425
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(capacity()));
426
  return objects(isolate, index);
427 428
}

429
void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
430
  set_objects(index, value, mode);
431 432
}

433
MaybeObjectSlot WeakArrayList::data_start() {
434
  return RawMaybeWeakField(kObjectsOffset);
435 436
}

437 438 439 440 441 442 443 444 445
void WeakArrayList::CopyElements(Isolate* isolate, int dst_index,
                                 WeakArrayList src, int src_index, int len,
                                 WriteBarrierMode mode) {
  if (len == 0) return;
  DCHECK_LE(dst_index + len, capacity());
  DCHECK_LE(src_index + len, src.capacity());
  DisallowHeapAllocation no_gc;

  MaybeObjectSlot dst_slot(data_start() + dst_index);
446
  MaybeObjectSlot src_slot(src.data_start() + src_index);
447 448 449
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}

450
HeapObject WeakArrayList::Iterator::Next() {
451
  if (!array_.is_null()) {
452 453
    while (index_ < array_.length()) {
      MaybeObject item = array_.Get(index_++);
454 455
      DCHECK(item->IsWeakOrCleared());
      if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
456
    }
457
    array_ = WeakArrayList();
458
  }
459
  return HeapObject();
460 461
}

462
int ArrayList::Length() const {
463 464
  if (FixedArray::cast(*this).length() == 0) return 0;
  return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
465 466 467
}

void ArrayList::SetLength(int length) {
468
  return FixedArray::cast(*this).set(kLengthIndex, Smi::FromInt(length));
469 470
}

471
Object ArrayList::Get(int index) const {
472
  return FixedArray::cast(*this).get(kFirstIndex + index);
473 474
}

475
Object ArrayList::Get(const Isolate* isolate, int index) const {
476 477 478
  return FixedArray::cast(*this).get(isolate, kFirstIndex + index);
}

479
ObjectSlot ArrayList::Slot(int index) {
480
  return RawField(OffsetOfElementAt(kFirstIndex + index));
481 482
}

483
void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
484
  FixedArray::cast(*this).set(kFirstIndex + index, obj, mode);
485 486
}

487
void ArrayList::Clear(int index, Object undefined) {
488 489 490
  DCHECK(undefined.IsUndefined());
  FixedArray::cast(*this).set(kFirstIndex + index, undefined,
                              SKIP_WRITE_BARRIER);
491 492
}

493
int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
494 495 496

byte ByteArray::get(int index) const {
  DCHECK(index >= 0 && index < this->length());
497
  return ReadField<byte>(kHeaderSize + index * kCharSize);
498 499 500 501
}

void ByteArray::set(int index, byte value) {
  DCHECK(index >= 0 && index < this->length());
502
  WriteField<byte>(kHeaderSize + index * kCharSize, value);
503 504 505 506 507
}

void ByteArray::copy_in(int index, const byte* buffer, int length) {
  DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
         index + length <= this->length());
508
  Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
509
  memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
510 511 512 513 514
}

void ByteArray::copy_out(int index, byte* buffer, int length) {
  DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
         index + length <= this->length());
515
  Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
516
  memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
517 518 519 520
}

int ByteArray::get_int(int index) const {
  DCHECK(index >= 0 && index < this->length() / kIntSize);
521
  return ReadField<int>(kHeaderSize + index * kIntSize);
522 523 524 525
}

void ByteArray::set_int(int index, int value) {
  DCHECK(index >= 0 && index < this->length() / kIntSize);
526
  WriteField<int>(kHeaderSize + index * kIntSize, value);
527 528 529 530
}

uint32_t ByteArray::get_uint32(int index) const {
  DCHECK(index >= 0 && index < this->length() / kUInt32Size);
531
  return ReadField<uint32_t>(kHeaderSize + index * kUInt32Size);
532 533 534 535
}

void ByteArray::set_uint32(int index, uint32_t value) {
  DCHECK(index >= 0 && index < this->length() / kUInt32Size);
536
  WriteField<uint32_t>(kHeaderSize + index * kUInt32Size, value);
537 538
}

539 540 541 542 543 544 545 546 547 548
uint32_t ByteArray::get_uint32_relaxed(int index) const {
  DCHECK(index >= 0 && index < this->length() / kUInt32Size);
  return RELAXED_READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
}

void ByteArray::set_uint32_relaxed(int index, uint32_t value) {
  DCHECK(index >= 0 && index < this->length() / kUInt32Size);
  RELAXED_WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
}

549 550
void ByteArray::clear_padding() {
  int data_size = length() + kHeaderSize;
551
  memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
552 553
}

554
ByteArray ByteArray::FromDataStartAddress(Address address) {
555
  DCHECK_TAG_ALIGNED(address);
556
  return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
557 558
}

559
int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
560 561 562

int ByteArray::ByteArraySize() { return SizeFor(this->length()); }

563 564
byte* ByteArray::GetDataStartAddress() {
  return reinterpret_cast<byte*>(address() + kHeaderSize);
565 566
}

567 568 569 570
byte* ByteArray::GetDataEndAddress() {
  return GetDataStartAddress() + length();
}

571
template <class T>
572 573
PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}

574
template <class T>
575
PodArray<T> PodArray<T>::cast(Object object) {
576
  return PodArray<T>(object.ptr());
577 578 579 580 581
}

// static
template <class T>
Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
582
                                     AllocationType allocation) {
583
  return Handle<PodArray<T>>::cast(
584
      isolate->factory()->NewByteArray(length * sizeof(T), allocation));
585 586
}

587
template <class T>
588
int PodArray<T>::length() const {
589 590 591
  return ByteArray::length() / sizeof(T);
}

592
int TemplateList::length() const {
593
  return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
594 595
}

596
Object TemplateList::get(int index) const {
597
  return FixedArray::cast(*this).get(kFirstElementIndex + index);
598 599
}

600
Object TemplateList::get(const Isolate* isolate, int index) const {
601 602 603
  return FixedArray::cast(*this).get(isolate, kFirstElementIndex + index);
}

604
void TemplateList::set(int index, Object value) {
605
  FixedArray::cast(*this).set(kFirstElementIndex + index, value);
606 607 608 609 610 611 612 613
}

}  // namespace internal
}  // namespace v8

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

#endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_