LCOV - code coverage report
Current view: top level - src/objects - fixed-array-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 286 312 91.7 %
Date: 2019-02-19 Functions: 142 167 85.0 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_OBJECTS_FIXED_ARRAY_INL_H_
       6             : #define V8_OBJECTS_FIXED_ARRAY_INL_H_
       7             : 
       8             : #include "src/objects/fixed-array.h"
       9             : 
      10             : #include "src/base/tsan.h"
      11             : #include "src/conversions.h"
      12             : #include "src/handles-inl.h"
      13             : #include "src/heap/heap-write-barrier-inl.h"
      14             : #include "src/objects-inl.h"
      15             : #include "src/objects/bigint.h"
      16             : #include "src/objects/heap-number-inl.h"
      17             : #include "src/objects/map.h"
      18             : #include "src/objects/maybe-object-inl.h"
      19             : #include "src/objects/oddball.h"
      20             : #include "src/objects/slots.h"
      21             : #include "src/roots-inl.h"
      22             : 
      23             : // Has to be the last include (doesn't have include guards):
      24             : #include "src/objects/object-macros.h"
      25             : 
      26             : namespace v8 {
      27             : namespace internal {
      28             : 
      29   777468541 : OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
      30  1096788346 : OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
      31    54855648 : OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
      32    82800095 : OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
      33        9376 : OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
      34   137913192 : OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
      35    17152032 : OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
      36    45025677 : OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
      37    19371956 : OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
      38             : 
      39        5824 : FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
      40        5824 :     : HeapObject(ptr, allow_smi) {
      41             :   SLOW_DCHECK(
      42             :       (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      43             :       IsFixedArrayBase());
      44        5824 : }
      45             : 
      46        5824 : ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
      47        5824 :     : FixedArrayBase(ptr, allow_smi) {
      48             :   SLOW_DCHECK(
      49             :       (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      50             :       IsByteArray());
      51        5824 : }
      52             : 
      53             : NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
      54             : 
      55        4688 : CAST_ACCESSOR(ArrayList)
      56    68982303 : CAST_ACCESSOR(ByteArray)
      57   548164683 : CAST_ACCESSOR(FixedArray)
      58   388162586 : CAST_ACCESSOR(FixedArrayBase)
      59    27426981 : CAST_ACCESSOR(FixedDoubleArray)
      60    41404044 : CAST_ACCESSOR(FixedTypedArrayBase)
      61     8576016 : CAST_ACCESSOR(TemplateList)
      62    22514050 : CAST_ACCESSOR(WeakFixedArray)
      63     9686780 : CAST_ACCESSOR(WeakArrayList)
      64             : 
      65  1833344595 : SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
      66   323865369 : SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
      67   159427952 : SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
      68    34569358 : SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
      69             : 
      70    30371918 : SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
      71    11698551 : SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
      72   112623239 : SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
      73             : 
      74             : Object FixedArrayBase::unchecked_synchronized_length() const {
      75     9055746 :   return ACQUIRE_READ_FIELD(*this, kLengthOffset);
      76             : }
      77             : 
      78    47417632 : ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
      79             : 
      80             : ObjectSlot FixedArray::GetFirstElementAddress() {
      81             :   return RawField(OffsetOfElementAt(0));
      82             : }
      83             : 
      84             : bool FixedArray::ContainsOnlySmisOrHoles() {
      85             :   Object the_hole = GetReadOnlyRoots().the_hole_value();
      86             :   ObjectSlot current = GetFirstElementAddress();
      87             :   for (int i = 0; i < length(); ++i, ++current) {
      88             :     Object candidate = *current;
      89             :     if (!candidate->IsSmi() && candidate != the_hole) return false;
      90             :   }
      91             :   return true;
      92             : }
      93             : 
      94      465570 : Object FixedArray::get(int index) const {
      95             :   DCHECK(index >= 0 && index < this->length());
      96  6726582493 :   return RELAXED_READ_FIELD(*this, kHeaderSize + index * kTaggedSize);
      97             : }
      98             : 
      99    16447426 : Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
     100    16447426 :   return handle(array->get(index), isolate);
     101             : }
     102             : 
     103             : template <class T>
     104     4560062 : MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
     105     4560062 :   Object obj = get(index);
     106     4560062 :   if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
     107      845141 :   return Handle<T>(T::cast(obj), isolate);
     108             : }
     109             : 
     110             : template <class T>
     111      261319 : Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
     112      261319 :   Object obj = get(index);
     113      261320 :   CHECK(!obj->IsUndefined(isolate));
     114      261320 :   return Handle<T>(T::cast(obj), isolate);
     115             : }
     116             : 
     117   309015670 : bool FixedArray::is_the_hole(Isolate* isolate, int index) {
     118   618031340 :   return get(index)->IsTheHole(isolate);
     119             : }
     120             : 
     121         664 : void FixedArray::set(int index, Smi value) {
     122             :   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
     123             :   DCHECK_LT(index, this->length());
     124             :   DCHECK(Object(value).IsSmi());
     125   145494988 :   int offset = kHeaderSize + index * kTaggedSize;
     126   248642951 :   RELAXED_WRITE_FIELD(*this, offset, value);
     127         664 : }
     128             : 
     129   468959918 : void FixedArray::set(int index, Object value) {
     130             :   DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
     131             :   DCHECK(IsFixedArray());
     132             :   DCHECK_GE(index, 0);
     133             :   DCHECK_LT(index, this->length());
     134   468959918 :   int offset = kHeaderSize + index * kTaggedSize;
     135   468959918 :   RELAXED_WRITE_FIELD(*this, offset, value);
     136   937919869 :   WRITE_BARRIER(*this, offset, value);
     137   468959934 : }
     138             : 
     139  1268032792 : void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
     140             :   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
     141             :   DCHECK_GE(index, 0);
     142             :   DCHECK_LT(index, this->length());
     143  1268032792 :   int offset = kHeaderSize + index * kTaggedSize;
     144  1268032792 :   RELAXED_WRITE_FIELD(*this, offset, value);
     145  2766081673 :   CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
     146  1268032859 : }
     147             : 
     148             : void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
     149             :   DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
     150             :   DCHECK_GE(index, 0);
     151             :   DCHECK_LT(index, array->length());
     152             :   DCHECK(!ObjectInYoungGeneration(value));
     153   353800193 :   RELAXED_WRITE_FIELD(array, kHeaderSize + index * kTaggedSize, value);
     154             : }
     155             : 
     156   332976128 : void FixedArray::set_undefined(int index) {
     157   332976128 :   set_undefined(GetReadOnlyRoots(), index);
     158   332976128 : }
     159             : 
     160        1476 : void FixedArray::set_undefined(Isolate* isolate, int index) {
     161        1476 :   set_undefined(ReadOnlyRoots(isolate), index);
     162        1476 : }
     163             : 
     164   332977604 : void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
     165             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
     166   332977604 : }
     167             : 
     168         529 : void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
     169             : 
     170             : void FixedArray::set_null(Isolate* isolate, int index) {
     171             :   set_null(ReadOnlyRoots(isolate), index);
     172             : }
     173             : 
     174         529 : void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
     175             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
     176         529 : }
     177             : 
     178    11509017 : void FixedArray::set_the_hole(int index) {
     179    11509017 :   set_the_hole(GetReadOnlyRoots(), index);
     180    11509017 : }
     181             : 
     182     8121392 : void FixedArray::set_the_hole(Isolate* isolate, int index) {
     183     8121392 :   set_the_hole(ReadOnlyRoots(isolate), index);
     184     8121392 : }
     185             : 
     186    19630409 : void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
     187             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
     188    19630409 : }
     189             : 
     190             : void FixedArray::FillWithHoles(int from, int to) {
     191    11459309 :   for (int i = from; i < to; i++) {
     192    11459309 :     set_the_hole(i);
     193             :   }
     194             : }
     195             : 
     196           0 : ObjectSlot FixedArray::data_start() {
     197           0 :   return RawField(OffsetOfElementAt(0));
     198             : }
     199             : 
     200      147320 : ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
     201      147320 :   return RawField(OffsetOfElementAt(index));
     202             : }
     203             : 
     204             : void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
     205             :                               WriteBarrierMode mode) {
     206             :   DisallowHeapAllocation no_gc;
     207        1426 :   heap->MoveElements(*this, dst_index, src_index, len, mode);
     208             : }
     209             : 
     210             : // Perform a binary search in a fixed array.
     211             : template <SearchMode search_mode, typename T>
     212    22271166 : int BinarySearch(T* array, Name name, int valid_entries,
     213             :                  int* out_insertion_index) {
     214             :   DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
     215             :   int low = 0;
     216    22271166 :   int high = array->number_of_entries() - 1;
     217             :   uint32_t hash = name->hash_field();
     218             :   int limit = high;
     219             : 
     220             :   DCHECK(low <= high);
     221             : 
     222   141357880 :   while (low != high) {
     223    96815594 :     int mid = low + (high - low) / 2;
     224    69626947 :     Name mid_name = array->GetSortedKey(mid);
     225             :     uint32_t mid_hash = mid_name->hash_field();
     226             : 
     227    96815548 :     if (mid_hash >= hash) {
     228             :       high = mid;
     229             :     } else {
     230    41716538 :       low = mid + 1;
     231             :     }
     232             :   }
     233             : 
     234           0 :   for (; low <= limit; ++low) {
     235             :     int sort_index = array->GetSortedKeyIndex(low);
     236    22271109 :     Name entry = array->GetKey(sort_index);
     237             :     uint32_t current_hash = entry->hash_field();
     238    22271106 :     if (current_hash != hash) {
     239      120843 :       if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     240       60589 :         *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
     241             :       }
     242             :       return T::kNotFound;
     243             :     }
     244    10956073 :     if (entry == name) {
     245     3880668 :       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
     246     3709673 :         return sort_index;
     247             :       }
     248             :       return T::kNotFound;
     249             :     }
     250             :   }
     251             : 
     252           0 :   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     253           0 :     *out_insertion_index = limit + 1;
     254             :   }
     255             :   return T::kNotFound;
     256             : }
     257             : 
     258             : // Perform a linear search in this fixed array. len is the number of entry
     259             : // indices that are valid.
     260             : template <SearchMode search_mode, typename T>
     261    12937772 : int LinearSearch(T* array, Name name, int valid_entries,
     262             :                  int* out_insertion_index) {
     263    12937772 :   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     264             :     uint32_t hash = name->hash_field();
     265             :     int len = array->number_of_entries();
     266      338265 :     for (int number = 0; number < len; number++) {
     267             :       int sorted_index = array->GetSortedKeyIndex(number);
     268      289453 :       Name entry = array->GetKey(sorted_index);
     269             :       uint32_t current_hash = entry->hash_field();
     270      289461 :       if (current_hash > hash) {
     271      105403 :         *out_insertion_index = sorted_index;
     272      105403 :         return T::kNotFound;
     273             :       }
     274      184058 :       if (entry == name) return sorted_index;
     275             :     }
     276       48812 :     *out_insertion_index = len;
     277       48812 :     return T::kNotFound;
     278             :   } else {
     279             :     DCHECK_LE(valid_entries, array->number_of_entries());
     280             :     DCHECK_NULL(out_insertion_index);  // Not supported here.
     281    61543274 :     for (int number = 0; number < valid_entries; number++) {
     282   172713913 :       if (array->GetKey(number) == name) return number;
     283             :     }
     284             :     return T::kNotFound;
     285             :   }
     286             : }
     287             : 
     288             : template <SearchMode search_mode, typename T>
     289    60830078 : int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
     290             :   SLOW_DCHECK(array->IsSortedNoDuplicates());
     291             : 
     292    60830078 :   if (valid_entries == 0) {
     293      236632 :     if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     294      226349 :       *out_insertion_index = 0;
     295             :     }
     296             :     return T::kNotFound;
     297             :   }
     298             : 
     299             :   // Fast case: do linear search for small arrays.
     300             :   const int kMaxElementsForLinearSearch = 8;
     301    60593474 :   if (valid_entries <= kMaxElementsForLinearSearch) {
     302             :     return LinearSearch<search_mode>(array, name, valid_entries,
     303    38322357 :                                      out_insertion_index);
     304             :   }
     305             : 
     306             :   // Slow case: perform binary search.
     307             :   return BinarySearch<search_mode>(array, name, valid_entries,
     308    22271117 :                                    out_insertion_index);
     309             : }
     310             : 
     311         532 : double FixedDoubleArray::get_scalar(int index) {
     312             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     313             :          map() != GetReadOnlyRoots().fixed_array_map());
     314             :   DCHECK(index >= 0 && index < this->length());
     315             :   DCHECK(!is_the_hole(index));
     316     7491475 :   return READ_DOUBLE_FIELD(*this, kHeaderSize + index * kDoubleSize);
     317             : }
     318             : 
     319             : uint64_t FixedDoubleArray::get_representation(int index) {
     320             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     321             :          map() != GetReadOnlyRoots().fixed_array_map());
     322             :   DCHECK(index >= 0 && index < this->length());
     323    37317906 :   int offset = kHeaderSize + index * kDoubleSize;
     324    37317906 :   return READ_UINT64_FIELD(*this, offset);
     325             : }
     326             : 
     327     8471553 : Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
     328             :                                      Isolate* isolate) {
     329     8471553 :   if (array->is_the_hole(index)) {
     330     1097502 :     return ReadOnlyRoots(isolate).the_hole_value_handle();
     331             :   } else {
     332     7374051 :     return isolate->factory()->NewNumber(array->get_scalar(index));
     333             :   }
     334             : }
     335             : 
     336    11985711 : void FixedDoubleArray::set(int index, double value) {
     337             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     338             :          map() != GetReadOnlyRoots().fixed_array_map());
     339    11985711 :   int offset = kHeaderSize + index * kDoubleSize;
     340    11985711 :   if (std::isnan(value)) {
     341        2146 :     WRITE_DOUBLE_FIELD(*this, offset, std::numeric_limits<double>::quiet_NaN());
     342             :   } else {
     343    11983565 :     WRITE_DOUBLE_FIELD(*this, offset, value);
     344             :   }
     345             :   DCHECK(!is_the_hole(index));
     346    11985711 : }
     347             : 
     348             : void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
     349             :   set_the_hole(index);
     350             : }
     351             : 
     352             : void FixedDoubleArray::set_the_hole(int index) {
     353             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     354             :          map() != GetReadOnlyRoots().fixed_array_map());
     355    45683927 :   int offset = kHeaderSize + index * kDoubleSize;
     356    45683927 :   WRITE_UINT64_FIELD(*this, offset, kHoleNanInt64);
     357             : }
     358             : 
     359             : bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
     360             :   return is_the_hole(index);
     361             : }
     362             : 
     363             : bool FixedDoubleArray::is_the_hole(int index) {
     364           0 :   return get_representation(index) == kHoleNanInt64;
     365             : }
     366             : 
     367          16 : void FixedDoubleArray::MoveElements(Heap* heap, int dst_index, int src_index,
     368             :                                     int len, WriteBarrierMode mode) {
     369             :   DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
     370             :   double* data_start =
     371          16 :       reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
     372          16 :   MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
     373          16 : }
     374             : 
     375             : void FixedDoubleArray::FillWithHoles(int from, int to) {
     376      381510 :   for (int i = from; i < to; i++) {
     377             :     set_the_hole(i);
     378             :   }
     379             : }
     380             : 
     381   237454152 : MaybeObject WeakFixedArray::Get(int index) const {
     382             :   DCHECK(index >= 0 && index < this->length());
     383   474908304 :   return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
     384             : }
     385             : 
     386    33355549 : void WeakFixedArray::Set(int index, MaybeObject value) {
     387             :   DCHECK_GE(index, 0);
     388             :   DCHECK_LT(index, length());
     389             :   int offset = OffsetOfElementAt(index);
     390    33355549 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     391    66711105 :   WEAK_WRITE_BARRIER(*this, offset, value);
     392    33355560 : }
     393             : 
     394     2332684 : void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
     395             :   DCHECK_GE(index, 0);
     396             :   DCHECK_LT(index, length());
     397             :   int offset = OffsetOfElementAt(index);
     398     2332684 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     399     6998052 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     400     2332684 : }
     401             : 
     402             : MaybeObjectSlot WeakFixedArray::data_start() {
     403             :   return RawMaybeWeakField(kHeaderSize);
     404             : }
     405             : 
     406             : MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
     407             :   return RawMaybeWeakField(OffsetOfElementAt(index));
     408             : }
     409             : 
     410    30654688 : MaybeObject WeakArrayList::Get(int index) const {
     411             :   DCHECK(index >= 0 && index < this->capacity());
     412    61309376 :   return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
     413             : }
     414             : 
     415    33188587 : void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
     416             :   DCHECK_GE(index, 0);
     417             :   DCHECK_LT(index, this->capacity());
     418             :   int offset = OffsetOfElementAt(index);
     419    33188587 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     420    77988898 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     421    33188590 : }
     422             : 
     423             : MaybeObjectSlot WeakArrayList::data_start() {
     424             :   return RawMaybeWeakField(kHeaderSize);
     425             : }
     426             : 
     427     5200804 : HeapObject WeakArrayList::Iterator::Next() {
     428     5200804 :   if (!array_.is_null()) {
     429    10425546 :     while (index_ < array_->length()) {
     430     5208616 :       MaybeObject item = array_->Get(index_++);
     431             :       DCHECK(item->IsWeakOrCleared());
     432    10405213 :       if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
     433             :     }
     434        4157 :     array_ = WeakArrayList();
     435             :   }
     436        4207 :   return HeapObject();
     437             : }
     438             : 
     439       19355 : int ArrayList::Length() const {
     440       19355 :   if (FixedArray::cast(*this)->length() == 0) return 0;
     441       18923 :   return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
     442             : }
     443             : 
     444        2318 : void ArrayList::SetLength(int length) {
     445        2318 :   return FixedArray::cast(*this)->set(kLengthIndex, Smi::FromInt(length));
     446             : }
     447             : 
     448       16204 : Object ArrayList::Get(int index) const {
     449       32408 :   return FixedArray::cast(*this)->get(kFirstIndex + index);
     450             : }
     451             : 
     452             : ObjectSlot ArrayList::Slot(int index) {
     453             :   return RawField(OffsetOfElementAt(kFirstIndex + index));
     454             : }
     455             : 
     456        1944 : void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
     457        3888 :   FixedArray::cast(*this)->set(kFirstIndex + index, obj, mode);
     458        1944 : }
     459             : 
     460           5 : void ArrayList::Clear(int index, Object undefined) {
     461             :   DCHECK(undefined->IsUndefined());
     462             :   FixedArray::cast(*this)->set(kFirstIndex + index, undefined,
     463          10 :                                SKIP_WRITE_BARRIER);
     464           5 : }
     465             : 
     466    34076900 : int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
     467             : 
     468             : byte ByteArray::get(int index) const {
     469             :   DCHECK(index >= 0 && index < this->length());
     470    60974188 :   return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
     471             : }
     472             : 
     473             : void ByteArray::set(int index, byte value) {
     474             :   DCHECK(index >= 0 && index < this->length());
     475    11529471 :   WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize, value);
     476             : }
     477             : 
     478             : void ByteArray::copy_in(int index, const byte* buffer, int length) {
     479             :   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
     480             :          index + length <= this->length());
     481      129761 :   Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
     482      192934 :   memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
     483             : }
     484             : 
     485             : void ByteArray::copy_out(int index, byte* buffer, int length) {
     486             :   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
     487             :          index + length <= this->length());
     488   261747581 :   Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
     489   261747581 :   memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
     490             : }
     491             : 
     492             : int ByteArray::get_int(int index) const {
     493             :   DCHECK(index >= 0 && index < this->length() / kIntSize);
     494        2264 :   return READ_INT_FIELD(*this, kHeaderSize + index * kIntSize);
     495             : }
     496             : 
     497             : void ByteArray::set_int(int index, int value) {
     498             :   DCHECK(index >= 0 && index < this->length() / kIntSize);
     499        1344 :   WRITE_INT_FIELD(*this, kHeaderSize + index * kIntSize, value);
     500             : }
     501             : 
     502     1016188 : uint32_t ByteArray::get_uint32(int index) const {
     503             :   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
     504     1016188 :   return READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
     505             : }
     506             : 
     507      149482 : void ByteArray::set_uint32(int index, uint32_t value) {
     508             :   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
     509      149482 :   WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
     510      149482 : }
     511             : 
     512     7124513 : void ByteArray::clear_padding() {
     513     7124516 :   int data_size = length() + kHeaderSize;
     514    14249035 :   memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
     515     7124519 : }
     516             : 
     517             : ByteArray ByteArray::FromDataStartAddress(Address address) {
     518             :   DCHECK_TAG_ALIGNED(address);
     519             :   return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
     520             : }
     521             : 
     522         862 : int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
     523             : 
     524             : int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
     525             : 
     526         388 : byte* ByteArray::GetDataStartAddress() {
     527   488014412 :   return reinterpret_cast<byte*>(address() + kHeaderSize);
     528             : }
     529             : 
     530   213750612 : byte* ByteArray::GetDataEndAddress() {
     531   213523948 :   return GetDataStartAddress() + length();
     532             : }
     533             : 
     534             : template <class T>
     535     1040884 : PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
     536             : 
     537             : template <class T>
     538             : PodArray<T> PodArray<T>::cast(Object object) {
     539      520442 :   return PodArray<T>(object.ptr());
     540             : }
     541             : 
     542             : // static
     543             : template <class T>
     544       13374 : Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
     545             :                                      PretenureFlag pretenure) {
     546             :   return Handle<PodArray<T>>::cast(
     547       13470 :       isolate->factory()->NewByteArray(length * sizeof(T), pretenure));
     548             : }
     549             : 
     550             : template <class T>
     551             : int PodArray<T>::length() const {
     552           0 :   return ByteArray::length() / sizeof(T);
     553             : }
     554             : 
     555             : void* FixedTypedArrayBase::external_pointer() const {
     556     5532968 :   intptr_t ptr = READ_INTPTR_FIELD(*this, kExternalPointerOffset);
     557        2384 :   return reinterpret_cast<void*>(ptr);
     558             : }
     559             : 
     560         616 : void FixedTypedArrayBase::set_external_pointer(void* value,
     561             :                                                WriteBarrierMode mode) {
     562       11973 :   intptr_t ptr = reinterpret_cast<intptr_t>(value);
     563       11978 :   WRITE_INTPTR_FIELD(*this, kExternalPointerOffset, ptr);
     564         616 : }
     565             : 
     566         342 : void* FixedTypedArrayBase::DataPtr() {
     567             :   return reinterpret_cast<void*>(
     568     5530826 :       base_pointer()->ptr() + reinterpret_cast<intptr_t>(external_pointer()));
     569             : }
     570             : 
     571      335602 : int FixedTypedArrayBase::ElementSize(InstanceType type) {
     572             :   int element_size;
     573      335602 :   switch (type) {
     574             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
     575             :   case FIXED_##TYPE##_ARRAY_TYPE:                 \
     576             :     element_size = sizeof(ctype);                 \
     577             :     break;
     578             : 
     579       24845 :     TYPED_ARRAYS(TYPED_ARRAY_CASE)
     580             : #undef TYPED_ARRAY_CASE
     581             :     default:
     582           0 :       UNREACHABLE();
     583             :   }
     584      335602 :   return element_size;
     585             : }
     586             : 
     587      774343 : int FixedTypedArrayBase::DataSize(InstanceType type) const {
     588      774343 :   if (base_pointer() == Smi::kZero) return 0;
     589      335623 :   return length() * ElementSize(type);
     590             : }
     591             : 
     592      223953 : int FixedTypedArrayBase::DataSize() const {
     593      223953 :   return DataSize(map()->instance_type());
     594             : }
     595             : 
     596             : size_t FixedTypedArrayBase::ByteLength() const {
     597             :   return static_cast<size_t>(length()) *
     598             :          static_cast<size_t>(ElementSize(map()->instance_type()));
     599             : }
     600             : 
     601             : int FixedTypedArrayBase::size() const {
     602      202166 :   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
     603             : }
     604             : 
     605             : int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
     606      550433 :   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
     607             : }
     608             : 
     609             : // static
     610             : int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
     611             :   return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
     612             : }
     613             : 
     614             : uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
     615             : 
     616             : uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
     617             : 
     618             : int8_t Int8ArrayTraits::defaultValue() { return 0; }
     619             : 
     620             : uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
     621             : 
     622             : int16_t Int16ArrayTraits::defaultValue() { return 0; }
     623             : 
     624             : uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
     625             : 
     626             : int32_t Int32ArrayTraits::defaultValue() { return 0; }
     627             : 
     628             : float Float32ArrayTraits::defaultValue() {
     629             :   return std::numeric_limits<float>::quiet_NaN();
     630             : }
     631             : 
     632             : double Float64ArrayTraits::defaultValue() {
     633             :   return std::numeric_limits<double>::quiet_NaN();
     634             : }
     635             : 
     636             : template <class Traits>
     637             : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
     638             :   DCHECK((index >= 0) && (index < this->length()));
     639             :   return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
     640             : }
     641             : 
     642             : // static
     643             : template <class Traits>
     644             : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
     645             :     void* data_ptr, int index) {
     646             :   typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
     647             :   // The JavaScript memory model allows for racy reads and writes to a
     648             :   // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
     649             :   // ThreadSanitizer will catch these racy accesses and warn about them, so we
     650             :   // disable TSAN for these reads and writes using annotations.
     651             :   //
     652             :   // We don't use relaxed atomics here, as it is not a requirement of the
     653             :   // JavaScript memory model to have tear-free reads of overlapping accesses,
     654             :   // and using relaxed atomics may introduce overhead.
     655             :   TSAN_ANNOTATE_IGNORE_READS_BEGIN;
     656      440131 :   auto result = ptr[index];
     657             :   TSAN_ANNOTATE_IGNORE_READS_END;
     658             :   return result;
     659             : }
     660             : 
     661             : template <class Traits>
     662     5083905 : void FixedTypedArray<Traits>::set(int index, ElementType value) {
     663    10167810 :   CHECK((index >= 0) && (index < this->length()));
     664             :   // See the comment in FixedTypedArray<Traits>::get_scalar.
     665             :   auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
     666             :   TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
     667     5083905 :   ptr[index] = value;
     668             :   TSAN_ANNOTATE_IGNORE_WRITES_END;
     669     5083905 : }
     670             : 
     671             : template <class Traits>
     672             : typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
     673     2469376 :   return static_cast<ElementType>(value);
     674             : }
     675             : 
     676             : template <>
     677             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
     678       25692 :   if (value < 0) return 0;
     679       25827 :   if (value > 0xFF) return 0xFF;
     680       25413 :   return static_cast<uint8_t>(value);
     681             : }
     682             : 
     683             : template <>
     684           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
     685           0 :   UNREACHABLE();
     686             : }
     687             : 
     688             : template <>
     689           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
     690           0 :   UNREACHABLE();
     691             : }
     692             : 
     693             : template <class Traits>
     694             : typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
     695        1314 :   return static_cast<ElementType>(value);
     696             : }
     697             : 
     698             : template <>
     699             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
     700             :   // We need this special case for Uint32 -> Uint8Clamped, because the highest
     701             :   // Uint32 values will be negative as an int, clamping to 0, rather than 255.
     702         198 :   if (value > 0xFF) return 0xFF;
     703         117 :   return static_cast<uint8_t>(value);
     704             : }
     705             : 
     706             : template <>
     707           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
     708           0 :   UNREACHABLE();
     709             : }
     710             : 
     711             : template <>
     712           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
     713           0 :   UNREACHABLE();
     714             : }
     715             : 
     716             : template <class Traits>
     717             : typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
     718      348222 :   return static_cast<ElementType>(DoubleToInt32(value));
     719             : }
     720             : 
     721             : template <>
     722             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
     723             :   // Handle NaNs and less than zero values which clamp to zero.
     724       93853 :   if (!(value > 0)) return 0;
     725       92514 :   if (value > 0xFF) return 0xFF;
     726       91785 :   return static_cast<uint8_t>(lrint(value));
     727             : }
     728             : 
     729             : template <>
     730           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
     731           0 :   UNREACHABLE();
     732             : }
     733             : 
     734             : template <>
     735           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
     736           0 :   UNREACHABLE();
     737             : }
     738             : 
     739             : template <>
     740             : inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
     741      134449 :   return static_cast<float>(value);
     742             : }
     743             : 
     744             : template <>
     745             : inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
     746             :   return value;
     747             : }
     748             : 
     749             : template <class Traits>
     750           0 : typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
     751           0 :   UNREACHABLE();
     752             : }
     753             : 
     754             : template <class Traits>
     755           0 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
     756           0 :   UNREACHABLE();
     757             : }
     758             : 
     759             : template <>
     760             : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
     761             :   return value;
     762             : }
     763             : 
     764             : template <>
     765             : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
     766             :   return value;
     767             : }
     768             : 
     769             : template <>
     770             : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
     771           0 :   return static_cast<uint64_t>(value);
     772             : }
     773             : 
     774             : template <>
     775             : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
     776           0 :   return static_cast<int64_t>(value);
     777             : }
     778             : 
     779             : template <class Traits>
     780        3707 : typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
     781             :     Handle<Object> value, bool* lossless) {
     782        7414 :   if (value->IsSmi()) {
     783        6262 :     return from(Smi::ToInt(*value));
     784             :   }
     785             :   DCHECK(value->IsHeapNumber());
     786             :   return from(HeapNumber::cast(*value)->value());
     787             : }
     788             : 
     789             : template <>
     790         252 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
     791             :     Handle<Object> value, bool* lossless) {
     792             :   DCHECK(value->IsBigInt());
     793         252 :   return BigInt::cast(*value)->AsInt64(lossless);
     794             : }
     795             : 
     796             : template <>
     797         252 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
     798             :     Handle<Object> value, bool* lossless) {
     799             :   DCHECK(value->IsBigInt());
     800         252 :   return BigInt::cast(*value)->AsUint64(lossless);
     801             : }
     802             : 
     803             : template <class Traits>
     804      401341 : Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
     805             :                                             FixedTypedArray<Traits> array,
     806             :                                             int index) {
     807      401341 :   return Traits::ToHandle(isolate, array->get_scalar(index));
     808             : }
     809             : 
     810             : template <class Traits>
     811     2660537 : void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
     812             :   ElementType cast_value = Traits::defaultValue();
     813     2660537 :   if (value->IsSmi()) {
     814      254675 :     int int_value = Smi::ToInt(value);
     815             :     cast_value = from(int_value);
     816     2405862 :   } else if (value->IsHeapNumber()) {
     817             :     double double_value = HeapNumber::cast(value)->value();
     818             :     cast_value = from(double_value);
     819             :   } else {
     820             :     // Clamp undefined to the default value. All other types have been
     821             :     // converted to a number type further up in the call chain.
     822             :     DCHECK(value->IsUndefined());
     823             :   }
     824     2660537 :   set(index, cast_value);
     825     2660537 : }
     826             : 
     827             : template <>
     828         675 : inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
     829             :                                                            Object value) {
     830             :   DCHECK(value->IsBigInt());
     831         675 :   set(index, BigInt::cast(value)->AsInt64());
     832         675 : }
     833             : 
     834             : template <>
     835         450 : inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
     836             :                                                             Object value) {
     837             :   DCHECK(value->IsBigInt());
     838         450 :   set(index, BigInt::cast(value)->AsUint64());
     839         450 : }
     840             : 
     841       86576 : Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
     842       86576 :   return handle(Smi::FromInt(scalar), isolate);
     843             : }
     844             : 
     845        2233 : Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
     846             :                                                  uint8_t scalar) {
     847        2233 :   return handle(Smi::FromInt(scalar), isolate);
     848             : }
     849             : 
     850        4338 : Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
     851        4338 :   return handle(Smi::FromInt(scalar), isolate);
     852             : }
     853             : 
     854       75658 : Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
     855       75658 :   return handle(Smi::FromInt(scalar), isolate);
     856             : }
     857             : 
     858        3685 : Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
     859        3685 :   return handle(Smi::FromInt(scalar), isolate);
     860             : }
     861             : 
     862             : Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
     863       75213 :   return isolate->factory()->NewNumberFromUint(scalar);
     864             : }
     865             : 
     866             : Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
     867        4353 :   return isolate->factory()->NewNumberFromInt(scalar);
     868             : }
     869             : 
     870             : Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
     871       74849 :   return isolate->factory()->NewNumber(scalar);
     872             : }
     873             : 
     874             : Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
     875       74355 :   return isolate->factory()->NewNumber(scalar);
     876             : }
     877             : 
     878             : Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
     879          45 :   return BigInt::FromInt64(isolate, scalar);
     880             : }
     881             : 
     882             : Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
     883             :                                               uint64_t scalar) {
     884          36 :   return BigInt::FromUint64(isolate, scalar);
     885             : }
     886             : 
     887             : // static
     888             : template <class Traits>
     889             : STATIC_CONST_MEMBER_DEFINITION const InstanceType
     890             :     FixedTypedArray<Traits>::kInstanceType;
     891             : 
     892             : template <class Traits>
     893     1263934 : FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
     894             :     : FixedTypedArrayBase(ptr) {
     895             :   DCHECK(IsHeapObject() && map()->instance_type() == Traits::kInstanceType);
     896     1263934 : }
     897             : 
     898             : template <class Traits>
     899             : FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
     900     1263939 :   return FixedTypedArray<Traits>(object.ptr());
     901             : }
     902             : 
     903     6541875 : int TemplateList::length() const {
     904     6541875 :   return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
     905             : }
     906             : 
     907     8557661 : Object TemplateList::get(int index) const {
     908    17115322 :   return FixedArray::cast(*this)->get(kFirstElementIndex + index);
     909             : }
     910             : 
     911         151 : void TemplateList::set(int index, Object value) {
     912         302 :   FixedArray::cast(*this)->set(kFirstElementIndex + index, value);
     913         151 : }
     914             : 
     915             : }  // namespace internal
     916             : }  // namespace v8
     917             : 
     918             : #include "src/objects/object-macros-undef.h"
     919             : 
     920             : #endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_

Generated by: LCOV version 1.10