fixed-array-inl.h 20.8 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 26 27 28 29

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

namespace v8 {
namespace internal {

30
OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
31 32 33 34 35
OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
36 37
OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
38 39

FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
40
    : HeapObject(ptr, allow_smi) {
41 42 43 44 45 46
  SLOW_DCHECK(
      (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      IsFixedArrayBase());
}

ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
47
    : FixedArrayBase(ptr, allow_smi) {
48 49 50 51 52
  SLOW_DCHECK(
      (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      IsByteArray());
}

53 54
NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)

55 56 57 58 59 60 61 62
CAST_ACCESSOR(ArrayList)
CAST_ACCESSOR(ByteArray)
CAST_ACCESSOR(FixedArray)
CAST_ACCESSOR(FixedArrayBase)
CAST_ACCESSOR(FixedDoubleArray)
CAST_ACCESSOR(TemplateList)
CAST_ACCESSOR(WeakFixedArray)
CAST_ACCESSOR(WeakArrayList)
63

64
SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
65
SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
66

67 68
SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
69

70 71 72 73
SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)

74
Object FixedArrayBase::unchecked_synchronized_length() const {
75
  return ACQUIRE_READ_FIELD(*this, kLengthOffset);
76 77
}

78
ObjectSlot FixedArray::GetFirstElementAddress() {
79
  return RawField(OffsetOfElementAt(0));
80 81 82
}

bool FixedArray::ContainsOnlySmisOrHoles() {
83
  Object the_hole = GetReadOnlyRoots().the_hole_value();
84 85
  ObjectSlot current = GetFirstElementAddress();
  for (int i = 0; i < length(); ++i, ++current) {
86
    Object candidate = *current;
87
    if (!candidate.IsSmi() && candidate != the_hole) return false;
88 89 90 91
  }
  return true;
}

92
Object FixedArray::get(int index) const {
93 94 95 96 97 98 99 100
  Isolate* isolate = GetIsolateForPtrCompr(*this);
  return get(isolate, index);
}

Object FixedArray::get(Isolate* isolate, int index) const {
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  return TaggedField<Object>::Relaxed_Load(isolate, *this,
                                           OffsetOfElementAt(index));
101 102
}

103
Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
104
  return handle(array.get(isolate, index), isolate);
105
}
106 107

bool FixedArray::is_the_hole(Isolate* isolate, int index) {
108
  return get(isolate, index).IsTheHole(isolate);
109 110
}

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

119
void FixedArray::set(int index, Object value) {
120
  DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
121
  DCHECK(IsFixedArray());
122 123
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  int offset = OffsetOfElementAt(index);
124 125
  RELAXED_WRITE_FIELD(*this, offset, value);
  WRITE_BARRIER(*this, offset, value);
126 127
}

128
void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
129
  DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
130 131
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  int offset = OffsetOfElementAt(index);
132 133
  RELAXED_WRITE_FIELD(*this, offset, value);
  CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
134 135
}

136
// static
137
void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
138
  DCHECK_NE(array.map(), array.GetReadOnlyRoots().fixed_cow_array_map());
139 140
  DCHECK_LT(static_cast<unsigned>(index),
            static_cast<unsigned>(array.length()));
141
  DCHECK(!ObjectInYoungGeneration(value));
142 143
  int offset = OffsetOfElementAt(index);
  RELAXED_WRITE_FIELD(array, offset, value);
144
}
145 146

void FixedArray::set_undefined(int index) {
147
  set_undefined(GetReadOnlyRoots(), index);
148 149 150
}

void FixedArray::set_undefined(Isolate* isolate, int index) {
151
  set_undefined(ReadOnlyRoots(isolate), index);
152 153
}

154
void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
155
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
156 157 158
}

void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
159 160

void FixedArray::set_null(Isolate* isolate, int index) {
161
  set_null(ReadOnlyRoots(isolate), index);
162 163
}

164
void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
165
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
166 167 168 169 170
}

void FixedArray::set_the_hole(int index) {
  set_the_hole(GetReadOnlyRoots(), index);
}
171 172

void FixedArray::set_the_hole(Isolate* isolate, int index) {
173 174 175 176
  set_the_hole(ReadOnlyRoots(isolate), index);
}

void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
177
  FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
178 179 180 181
}

void FixedArray::FillWithHoles(int from, int to) {
  for (int i = from; i < to; i++) {
182
    set_the_hole(i);
183 184 185
  }
}

186
ObjectSlot FixedArray::data_start() {
187 188
  return RawField(OffsetOfElementAt(0));
}
189

190
ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
191 192
  return RawField(OffsetOfElementAt(index));
}
193

194 195 196
void FixedArray::MoveElements(Isolate* isolate, int dst_index, int src_index,
                              int len, WriteBarrierMode mode) {
  if (len == 0) return;
197 198
  DCHECK_LE(dst_index + len, length());
  DCHECK_LE(src_index + len, length());
199
  DisallowHeapAllocation no_gc;
200 201 202
  ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
  ObjectSlot src_slot(RawFieldOfElementAt(src_index));
  isolate->heap()->MoveRange(*this, dst_slot, src_slot, len, mode);
203 204
}

205
void FixedArray::CopyElements(Isolate* isolate, int dst_index, FixedArray src,
206
                              int src_index, int len, WriteBarrierMode mode) {
207
  if (len == 0) return;
208 209
  DCHECK_LE(dst_index + len, length());
  DCHECK_LE(src_index + len, src.length());
210
  DisallowHeapAllocation no_gc;
211 212

  ObjectSlot dst_slot(RawFieldOfElementAt(dst_index));
213
  ObjectSlot src_slot(src.RawFieldOfElementAt(src_index));
214
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
215
}
216

217 218 219 220 221 222 223
// 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;
224
  uint32_t hash = name.hash_field();
225 226 227 228 229 230 231
  int limit = high;

  DCHECK(low <= high);

  while (low != high) {
    int mid = low + (high - low) / 2;
    Name mid_name = array->GetSortedKey(mid);
232
    uint32_t mid_hash = mid_name.hash_field();
233 234 235 236 237 238 239 240 241 242 243

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

  for (; low <= limit; ++low) {
    int sort_index = array->GetSortedKeyIndex(low);
    Name entry = array->GetKey(sort_index);
244
    uint32_t current_hash = entry.hash_field();
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
    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) {
271
    uint32_t hash = name.hash_field();
272 273 274 275
    int len = array->number_of_entries();
    for (int number = 0; number < len; number++) {
      int sorted_index = array->GetSortedKeyIndex(number);
      Name entry = array->GetKey(sorted_index);
276
      uint32_t current_hash = entry.hash_field();
277 278 279 280 281 282 283 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 312 313 314 315 316 317
      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++) {
      if (array->GetKey(number) == name) return number;
    }
    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);
}

318
double FixedDoubleArray::get_scalar(int index) {
319 320
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
321 322
  DCHECK(index >= 0 && index < this->length());
  DCHECK(!is_the_hole(index));
323
  return ReadField<double>(kHeaderSize + index * kDoubleSize);
324 325 326
}

uint64_t FixedDoubleArray::get_representation(int index) {
327 328
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
329 330
  DCHECK(index >= 0 && index < this->length());
  int offset = kHeaderSize + index * kDoubleSize;
331
  // Bug(v8:8875): Doubles may be unaligned.
332
  return base::ReadUnalignedValue<uint64_t>(field_address(offset));
333 334
}

335
Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
336
                                     Isolate* isolate) {
337
  if (array.is_the_hole(index)) {
338
    return ReadOnlyRoots(isolate).the_hole_value_handle();
339
  } else {
340
    return isolate->factory()->NewNumber(array.get_scalar(index));
341 342 343 344
  }
}

void FixedDoubleArray::set(int index, double value) {
345 346
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
347 348
  int offset = kHeaderSize + index * kDoubleSize;
  if (std::isnan(value)) {
349
    WriteField<double>(offset, std::numeric_limits<double>::quiet_NaN());
350
  } else {
351
    WriteField<double>(offset, value);
352 353 354 355 356 357 358 359 360
  }
  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) {
361 362
  DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
         map() != GetReadOnlyRoots().fixed_array_map());
363
  int offset = kHeaderSize + index * kDoubleSize;
364
  base::WriteUnalignedValue<uint64_t>(field_address(offset), kHoleNanInt64);
365 366 367 368 369 370 371 372 373 374
}

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

375 376 377
void FixedDoubleArray::MoveElements(Isolate* isolate, int dst_index,
                                    int src_index, int len,
                                    WriteBarrierMode mode) {
378
  DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
379 380
  double* data_start =
      reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
381
  MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
382 383 384 385 386 387 388 389
}

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

390
MaybeObject WeakFixedArray::Get(int index) const {
391 392 393 394 395 396 397 398
  Isolate* isolate = GetIsolateForPtrCompr(*this);
  return Get(isolate, index);
}

MaybeObject WeakFixedArray::Get(Isolate* isolate, int index) const {
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(length()));
  return TaggedField<MaybeObject>::Relaxed_Load(isolate, *this,
                                                OffsetOfElementAt(index));
399 400
}

401
void WeakFixedArray::Set(int index, MaybeObject value) {
402 403 404
  DCHECK_GE(index, 0);
  DCHECK_LT(index, length());
  int offset = OffsetOfElementAt(index);
405 406
  RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
  WEAK_WRITE_BARRIER(*this, offset, value);
407 408
}

409
void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
410 411 412
  DCHECK_GE(index, 0);
  DCHECK_LT(index, length());
  int offset = OffsetOfElementAt(index);
413 414
  RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
  CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
415 416
}

417
MaybeObjectSlot WeakFixedArray::data_start() {
418
  return RawMaybeWeakField(kHeaderSize);
419 420
}

421
MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
422
  return RawMaybeWeakField(OffsetOfElementAt(index));
423 424
}

425 426 427 428 429 430 431 432 433
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);
434
  MaybeObjectSlot src_slot(src.data_start() + src_index);
435 436 437
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}

438
MaybeObject WeakArrayList::Get(int index) const {
439 440 441 442 443 444 445 446
  Isolate* isolate = GetIsolateForPtrCompr(*this);
  return Get(isolate, index);
}

MaybeObject WeakArrayList::Get(Isolate* isolate, int index) const {
  DCHECK_LT(static_cast<unsigned>(index), static_cast<unsigned>(capacity()));
  return TaggedField<MaybeObject>::Relaxed_Load(isolate, *this,
                                                OffsetOfElementAt(index));
447 448
}

449
void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
450 451 452
  DCHECK_GE(index, 0);
  DCHECK_LT(index, this->capacity());
  int offset = OffsetOfElementAt(index);
453 454
  RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
  CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
455 456
}

457
MaybeObjectSlot WeakArrayList::data_start() {
458
  return RawMaybeWeakField(kHeaderSize);
459 460
}

461 462 463 464 465 466 467 468 469
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);
470
  MaybeObjectSlot src_slot(src.data_start() + src_index);
471 472 473
  isolate->heap()->CopyRange(*this, dst_slot, src_slot, len, mode);
}

474
HeapObject WeakArrayList::Iterator::Next() {
475
  if (!array_.is_null()) {
476 477
    while (index_ < array_.length()) {
      MaybeObject item = array_.Get(index_++);
478 479
      DCHECK(item->IsWeakOrCleared());
      if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
480
    }
481
    array_ = WeakArrayList();
482
  }
483
  return HeapObject();
484 485
}

486
int ArrayList::Length() const {
487 488
  if (FixedArray::cast(*this).length() == 0) return 0;
  return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
489 490 491
}

void ArrayList::SetLength(int length) {
492
  return FixedArray::cast(*this).set(kLengthIndex, Smi::FromInt(length));
493 494
}

495
Object ArrayList::Get(int index) const {
496
  return FixedArray::cast(*this).get(kFirstIndex + index);
497 498
}

499 500 501 502
Object ArrayList::Get(Isolate* isolate, int index) const {
  return FixedArray::cast(*this).get(isolate, kFirstIndex + index);
}

503
ObjectSlot ArrayList::Slot(int index) {
504
  return RawField(OffsetOfElementAt(kFirstIndex + index));
505 506
}

507
void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
508
  FixedArray::cast(*this).set(kFirstIndex + index, obj, mode);
509 510
}

511
void ArrayList::Clear(int index, Object undefined) {
512 513 514
  DCHECK(undefined.IsUndefined());
  FixedArray::cast(*this).set(kFirstIndex + index, undefined,
                              SKIP_WRITE_BARRIER);
515 516
}

517
int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
518 519 520

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

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

void ByteArray::copy_in(int index, const byte* buffer, int length) {
  DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
         index + length <= this->length());
532
  Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
533
  memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
534 535 536 537 538
}

void ByteArray::copy_out(int index, byte* buffer, int length) {
  DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
         index + length <= this->length());
539
  Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
540
  memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
541 542 543 544
}

int ByteArray::get_int(int index) const {
  DCHECK(index >= 0 && index < this->length() / kIntSize);
545
  return ReadField<int>(kHeaderSize + index * kIntSize);
546 547 548 549
}

void ByteArray::set_int(int index, int value) {
  DCHECK(index >= 0 && index < this->length() / kIntSize);
550
  WriteField<int>(kHeaderSize + index * kIntSize, value);
551 552 553 554
}

uint32_t ByteArray::get_uint32(int index) const {
  DCHECK(index >= 0 && index < this->length() / kUInt32Size);
555
  return ReadField<uint32_t>(kHeaderSize + index * kUInt32Size);
556 557 558 559
}

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

563 564 565 566 567 568 569 570 571 572
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);
}

573 574
void ByteArray::clear_padding() {
  int data_size = length() + kHeaderSize;
575
  memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
576 577
}

578
ByteArray ByteArray::FromDataStartAddress(Address address) {
579
  DCHECK_TAG_ALIGNED(address);
580
  return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
581 582
}

583
int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
584 585 586

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

587 588
byte* ByteArray::GetDataStartAddress() {
  return reinterpret_cast<byte*>(address() + kHeaderSize);
589 590
}

591 592 593 594
byte* ByteArray::GetDataEndAddress() {
  return GetDataStartAddress() + length();
}

595
template <class T>
596 597
PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}

598
template <class T>
599
PodArray<T> PodArray<T>::cast(Object object) {
600
  return PodArray<T>(object.ptr());
601 602 603 604 605
}

// static
template <class T>
Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
606
                                     AllocationType allocation) {
607
  return Handle<PodArray<T>>::cast(
608
      isolate->factory()->NewByteArray(length * sizeof(T), allocation));
609 610
}

611
template <class T>
612
int PodArray<T>::length() const {
613 614 615
  return ByteArray::length() / sizeof(T);
}

616
int TemplateList::length() const {
617
  return Smi::ToInt(FixedArray::cast(*this).get(kLengthIndex));
618 619
}

620
Object TemplateList::get(int index) const {
621
  return FixedArray::cast(*this).get(kFirstElementIndex + index);
622 623
}

624 625 626 627
Object TemplateList::get(Isolate* isolate, int index) const {
  return FixedArray::cast(*this).get(isolate, kFirstElementIndex + index);
}

628
void TemplateList::set(int index, Object value) {
629
  FixedArray::cast(*this).set(kFirstElementIndex + index, value);
630 631 632 633 634 635 636 637
}

}  // namespace internal
}  // namespace v8

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

#endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_