LCOV - code coverage report
Current view: top level - src/objects - fixed-array-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 219 244 89.8 %
Date: 2019-04-18 Functions: 98 123 79.7 %

          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/compressed-slots.h"
      17             : #include "src/objects/heap-number-inl.h"
      18             : #include "src/objects/map.h"
      19             : #include "src/objects/maybe-object-inl.h"
      20             : #include "src/objects/oddball.h"
      21             : #include "src/objects/slots.h"
      22             : #include "src/roots-inl.h"
      23             : 
      24             : // Has to be the last include (doesn't have include guards):
      25             : #include "src/objects/object-macros.h"
      26             : 
      27             : namespace v8 {
      28             : namespace internal {
      29             : 
      30             : OBJECT_CONSTRUCTORS_IMPL(FixedArrayBase, HeapObject)
      31             : OBJECT_CONSTRUCTORS_IMPL(FixedArray, FixedArrayBase)
      32             : OBJECT_CONSTRUCTORS_IMPL(FixedDoubleArray, FixedArrayBase)
      33             : OBJECT_CONSTRUCTORS_IMPL(FixedTypedArrayBase, FixedArrayBase)
      34             : OBJECT_CONSTRUCTORS_IMPL(ArrayList, FixedArray)
      35             : OBJECT_CONSTRUCTORS_IMPL(ByteArray, FixedArrayBase)
      36             : OBJECT_CONSTRUCTORS_IMPL(TemplateList, FixedArray)
      37             : OBJECT_CONSTRUCTORS_IMPL(WeakFixedArray, HeapObject)
      38             : OBJECT_CONSTRUCTORS_IMPL(WeakArrayList, HeapObject)
      39             : 
      40             : FixedArrayBase::FixedArrayBase(Address ptr, AllowInlineSmiStorage allow_smi)
      41             :     : HeapObject(ptr, allow_smi) {
      42             :   SLOW_DCHECK(
      43             :       (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      44             :       IsFixedArrayBase());
      45             : }
      46             : 
      47             : ByteArray::ByteArray(Address ptr, AllowInlineSmiStorage allow_smi)
      48             :     : FixedArrayBase(ptr, allow_smi) {
      49             :   SLOW_DCHECK(
      50             :       (allow_smi == AllowInlineSmiStorage::kAllowBeingASmi && IsSmi()) ||
      51             :       IsByteArray());
      52             : }
      53             : 
      54             : NEVER_READ_ONLY_SPACE_IMPL(WeakArrayList)
      55             : 
      56             : CAST_ACCESSOR(ArrayList)
      57             : CAST_ACCESSOR(ByteArray)
      58             : CAST_ACCESSOR(FixedArray)
      59             : CAST_ACCESSOR(FixedArrayBase)
      60             : CAST_ACCESSOR(FixedDoubleArray)
      61             : CAST_ACCESSOR(FixedTypedArrayBase)
      62             : CAST_ACCESSOR(TemplateList)
      63             : CAST_ACCESSOR(WeakFixedArray)
      64             : CAST_ACCESSOR(WeakArrayList)
      65             : 
      66   886096291 : SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
      67   107588467 : SYNCHRONIZED_SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
      68    83115586 : SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
      69    11088888 : SYNCHRONIZED_SMI_ACCESSORS(WeakFixedArray, length, kLengthOffset)
      70             : 
      71    17537886 : SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
      72     3780651 : SYNCHRONIZED_SMI_ACCESSORS(WeakArrayList, capacity, kCapacityOffset)
      73    66125464 : SMI_ACCESSORS(WeakArrayList, length, kLengthOffset)
      74             : 
      75             : Object FixedArrayBase::unchecked_synchronized_length() const {
      76     7511438 :   return ACQUIRE_READ_FIELD(*this, kLengthOffset);
      77             : }
      78             : 
      79    91891843 : ACCESSORS(FixedTypedArrayBase, base_pointer, Object, kBasePointerOffset)
      80             : 
      81             : ObjectSlot FixedArray::GetFirstElementAddress() {
      82             :   return RawField(OffsetOfElementAt(0));
      83             : }
      84             : 
      85             : bool FixedArray::ContainsOnlySmisOrHoles() {
      86             :   Object the_hole = GetReadOnlyRoots().the_hole_value();
      87             :   ObjectSlot current = GetFirstElementAddress();
      88             :   for (int i = 0; i < length(); ++i, ++current) {
      89             :     Object candidate = *current;
      90             :     if (!candidate->IsSmi() && candidate != the_hole) return false;
      91             :   }
      92             :   return true;
      93             : }
      94             : 
      95       92784 : Object FixedArray::get(int index) const {
      96             :   DCHECK(index >= 0 && index < this->length());
      97  6279624944 :   return RELAXED_READ_FIELD(*this, kHeaderSize + index * kTaggedSize);
      98             : }
      99             : 
     100    16454864 : Handle<Object> FixedArray::get(FixedArray array, int index, Isolate* isolate) {
     101    16454864 :   return handle(array->get(index), isolate);
     102             : }
     103             : 
     104             : template <class T>
     105     4764572 : MaybeHandle<T> FixedArray::GetValue(Isolate* isolate, int index) const {
     106             :   Object obj = get(index);
     107     4764572 :   if (obj->IsUndefined(isolate)) return MaybeHandle<T>();
     108      861834 :   return Handle<T>(T::cast(obj), isolate);
     109             : }
     110             : 
     111             : template <class T>
     112      257540 : Handle<T> FixedArray::GetValueChecked(Isolate* isolate, int index) const {
     113             :   Object obj = get(index);
     114      257540 :   CHECK(!obj->IsUndefined(isolate));
     115      257540 :   return Handle<T>(T::cast(obj), isolate);
     116             : }
     117             : 
     118             : bool FixedArray::is_the_hole(Isolate* isolate, int index) {
     119             :   return get(index)->IsTheHole(isolate);
     120             : }
     121             : 
     122             : void FixedArray::set(int index, Smi value) {
     123             :   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
     124             :   DCHECK_LT(index, this->length());
     125             :   DCHECK(Object(value).IsSmi());
     126   147362175 :   int offset = kHeaderSize + index * kTaggedSize;
     127   253265577 :   RELAXED_WRITE_FIELD(*this, offset, value);
     128             : }
     129             : 
     130   791306634 : void FixedArray::set(int index, Object value) {
     131             :   DCHECK_NE(GetReadOnlyRoots().fixed_cow_array_map(), map());
     132             :   DCHECK(IsFixedArray());
     133             :   DCHECK_GE(index, 0);
     134             :   DCHECK_LT(index, this->length());
     135   791306634 :   int offset = kHeaderSize + index * kTaggedSize;
     136   791306634 :   RELAXED_WRITE_FIELD(*this, offset, value);
     137   791306634 :   WRITE_BARRIER(*this, offset, value);
     138   791306743 : }
     139             : 
     140   244630423 : void FixedArray::set(int index, Object value, WriteBarrierMode mode) {
     141             :   DCHECK_NE(map(), GetReadOnlyRoots().fixed_cow_array_map());
     142             :   DCHECK_GE(index, 0);
     143             :   DCHECK_LT(index, this->length());
     144   244630423 :   int offset = kHeaderSize + index * kTaggedSize;
     145   244633675 :   RELAXED_WRITE_FIELD(*this, offset, value);
     146   405971233 :   CONDITIONAL_WRITE_BARRIER(*this, offset, value, mode);
     147   244630656 : }
     148             : 
     149             : void FixedArray::NoWriteBarrierSet(FixedArray array, int index, Object value) {
     150             :   DCHECK_NE(array->map(), array->GetReadOnlyRoots().fixed_cow_array_map());
     151             :   DCHECK_GE(index, 0);
     152             :   DCHECK_LT(index, array->length());
     153             :   DCHECK(!ObjectInYoungGeneration(value));
     154   354085740 :   RELAXED_WRITE_FIELD(array, kHeaderSize + index * kTaggedSize, value);
     155             : }
     156             : 
     157   332211200 : void FixedArray::set_undefined(int index) {
     158             :   set_undefined(GetReadOnlyRoots(), index);
     159   332211200 : }
     160             : 
     161             : void FixedArray::set_undefined(Isolate* isolate, int index) {
     162             :   set_undefined(ReadOnlyRoots(isolate), index);
     163             : }
     164             : 
     165             : void FixedArray::set_undefined(ReadOnlyRoots ro_roots, int index) {
     166             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.undefined_value());
     167             : }
     168             : 
     169        1166 : void FixedArray::set_null(int index) { set_null(GetReadOnlyRoots(), index); }
     170             : 
     171             : void FixedArray::set_null(Isolate* isolate, int index) {
     172             :   set_null(ReadOnlyRoots(isolate), index);
     173             : }
     174             : 
     175             : void FixedArray::set_null(ReadOnlyRoots ro_roots, int index) {
     176             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.null_value());
     177             : }
     178             : 
     179    11811186 : void FixedArray::set_the_hole(int index) {
     180             :   set_the_hole(GetReadOnlyRoots(), index);
     181    11811186 : }
     182             : 
     183           1 : void FixedArray::set_the_hole(Isolate* isolate, int index) {
     184             :   set_the_hole(ReadOnlyRoots(isolate), index);
     185           1 : }
     186             : 
     187             : void FixedArray::set_the_hole(ReadOnlyRoots ro_roots, int index) {
     188             :   FixedArray::NoWriteBarrierSet(*this, index, ro_roots.the_hole_value());
     189             : }
     190             : 
     191             : void FixedArray::FillWithHoles(int from, int to) {
     192    24148124 :   for (int i = from; i < to; i++) {
     193    11686904 :     set_the_hole(i);
     194             :   }
     195             : }
     196             : 
     197             : ObjectSlot FixedArray::data_start() {
     198             :   return RawField(OffsetOfElementAt(0));
     199             : }
     200             : 
     201             : ObjectSlot FixedArray::RawFieldOfElementAt(int index) {
     202             :   return RawField(OffsetOfElementAt(index));
     203             : }
     204             : 
     205             : void FixedArray::MoveElements(Heap* heap, int dst_index, int src_index, int len,
     206             :                               WriteBarrierMode mode) {
     207             :   DisallowHeapAllocation no_gc;
     208      180504 :   heap->MoveElements(*this, dst_index, src_index, len, mode);
     209             : }
     210             : 
     211             : void FixedArray::CopyElements(Heap* heap, int dst_index, FixedArray src,
     212             :                               int src_index, int len, WriteBarrierMode mode) {
     213             :   DisallowHeapAllocation no_gc;
     214      643743 :   heap->CopyElements(*this, src, dst_index, src_index, len, mode);
     215             : }
     216             : 
     217             : // Perform a binary search in a fixed array.
     218             : template <SearchMode search_mode, typename T>
     219    24624041 : int BinarySearch(T* array, Name name, int valid_entries,
     220             :                  int* out_insertion_index) {
     221             :   DCHECK(search_mode == ALL_ENTRIES || out_insertion_index == nullptr);
     222             :   int low = 0;
     223    24624041 :   int high = array->number_of_entries() - 1;
     224             :   uint32_t hash = name->hash_field();
     225             :   int limit = high;
     226             : 
     227             :   DCHECK(low <= high);
     228             : 
     229   213340041 :   while (low != high) {
     230   107464361 :     int mid = low + (high - low) / 2;
     231    81251761 :     Name mid_name = array->GetSortedKey(mid);
     232             :     uint32_t mid_hash = mid_name->hash_field();
     233             : 
     234   107464300 :     if (mid_hash >= hash) {
     235             :       high = mid;
     236             :     } else {
     237    50073848 :       low = mid + 1;
     238             :     }
     239             :   }
     240             : 
     241    24623980 :   for (; low <= limit; ++low) {
     242             :     int sort_index = array->GetSortedKeyIndex(low);
     243     7184271 :     Name entry = array->GetKey(sort_index);
     244             :     uint32_t current_hash = entry->hash_field();
     245    24623965 :     if (current_hash != hash) {
     246      120040 :       if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     247       59379 :         *out_insertion_index = sort_index + (current_hash > hash ? 0 : 1);
     248             :       }
     249             :       return T::kNotFound;
     250             :     }
     251    11591224 :     if (entry == name) {
     252     4526993 :       if (search_mode == ALL_ENTRIES || sort_index < valid_entries) {
     253     4352217 :         return sort_index;
     254             :       }
     255             :       return T::kNotFound;
     256             :     }
     257             :   }
     258             : 
     259           0 :   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     260           0 :     *out_insertion_index = limit + 1;
     261             :   }
     262             :   return T::kNotFound;
     263             : }
     264             : 
     265             : // Perform a linear search in this fixed array. len is the number of entry
     266             : // indices that are valid.
     267             : template <SearchMode search_mode, typename T>
     268    42241848 : int LinearSearch(T* array, Name name, int valid_entries,
     269             :                  int* out_insertion_index) {
     270    13055403 :   if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     271             :     uint32_t hash = name->hash_field();
     272             :     int len = array->number_of_entries();
     273      630706 :     for (int number = 0; number < len; number++) {
     274             :       int sorted_index = array->GetSortedKeyIndex(number);
     275      346797 :       Name entry = array->GetKey(sorted_index);
     276             :       uint32_t current_hash = entry->hash_field();
     277      346798 :       if (current_hash > hash) {
     278      105770 :         *out_insertion_index = sorted_index;
     279      105770 :         return T::kNotFound;
     280             :       }
     281      241028 :       if (entry == name) return sorted_index;
     282             :     }
     283       50984 :     *out_insertion_index = len;
     284       50984 :     return T::kNotFound;
     285             :   } else {
     286             :     DCHECK_LE(valid_entries, array->number_of_entries());
     287             :     DCHECK_NULL(out_insertion_index);  // Not supported here.
     288   180472154 :     for (int number = 0; number < valid_entries; number++) {
     289   115813012 :       if (array->GetKey(number) == name) return number;
     290             :     }
     291             :     return T::kNotFound;
     292             :   }
     293             : }
     294             : 
     295             : template <SearchMode search_mode, typename T>
     296    67191660 : int Search(T* array, Name name, int valid_entries, int* out_insertion_index) {
     297             :   SLOW_DCHECK(array->IsSortedNoDuplicates());
     298             : 
     299    67191660 :   if (valid_entries == 0) {
     300      325936 :     if (search_mode == ALL_ENTRIES && out_insertion_index != nullptr) {
     301      224467 :       *out_insertion_index = 0;
     302             :     }
     303             :     return T::kNotFound;
     304             :   }
     305             : 
     306             :   // Fast case: do linear search for small arrays.
     307             :   const int kMaxElementsForLinearSearch = 8;
     308    66865816 :   if (valid_entries <= kMaxElementsForLinearSearch) {
     309             :     return LinearSearch<search_mode>(array, name, valid_entries,
     310    42241854 :                                      out_insertion_index);
     311             :   }
     312             : 
     313             :   // Slow case: perform binary search.
     314             :   return BinarySearch<search_mode>(array, name, valid_entries,
     315    24623962 :                                    out_insertion_index);
     316             : }
     317             : 
     318         496 : double FixedDoubleArray::get_scalar(int index) {
     319             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     320             :          map() != GetReadOnlyRoots().fixed_array_map());
     321             :   DCHECK(index >= 0 && index < this->length());
     322             :   DCHECK(!is_the_hole(index));
     323     8229054 :   return READ_DOUBLE_FIELD(*this, kHeaderSize + index * kDoubleSize);
     324             : }
     325             : 
     326             : uint64_t FixedDoubleArray::get_representation(int index) {
     327             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     328             :          map() != GetReadOnlyRoots().fixed_array_map());
     329             :   DCHECK(index >= 0 && index < this->length());
     330    40231277 :   int offset = kHeaderSize + index * kDoubleSize;
     331    40231277 :   return READ_UINT64_FIELD(*this, offset);
     332             : }
     333             : 
     334     9459511 : Handle<Object> FixedDoubleArray::get(FixedDoubleArray array, int index,
     335             :                                      Isolate* isolate) {
     336     9459511 :   if (array->is_the_hole(index)) {
     337     1354952 :     return ReadOnlyRoots(isolate).the_hole_value_handle();
     338             :   } else {
     339     8104559 :     return isolate->factory()->NewNumber(array->get_scalar(index));
     340             :   }
     341             : }
     342             : 
     343    11627944 : void FixedDoubleArray::set(int index, double value) {
     344             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     345             :          map() != GetReadOnlyRoots().fixed_array_map());
     346    11627944 :   int offset = kHeaderSize + index * kDoubleSize;
     347    11627944 :   if (std::isnan(value)) {
     348        2146 :     WRITE_DOUBLE_FIELD(*this, offset, std::numeric_limits<double>::quiet_NaN());
     349             :   } else {
     350    11625798 :     WRITE_DOUBLE_FIELD(*this, offset, value);
     351             :   }
     352             :   DCHECK(!is_the_hole(index));
     353    11627944 : }
     354             : 
     355             : void FixedDoubleArray::set_the_hole(Isolate* isolate, int index) {
     356             :   set_the_hole(index);
     357             : }
     358             : 
     359             : void FixedDoubleArray::set_the_hole(int index) {
     360             :   DCHECK(map() != GetReadOnlyRoots().fixed_cow_array_map() &&
     361             :          map() != GetReadOnlyRoots().fixed_array_map());
     362    49233701 :   int offset = kHeaderSize + index * kDoubleSize;
     363    49233701 :   WRITE_UINT64_FIELD(*this, offset, kHoleNanInt64);
     364             : }
     365             : 
     366             : bool FixedDoubleArray::is_the_hole(Isolate* isolate, int index) {
     367             :   return is_the_hole(index);
     368             : }
     369             : 
     370             : bool FixedDoubleArray::is_the_hole(int index) {
     371           0 :   return get_representation(index) == kHoleNanInt64;
     372             : }
     373             : 
     374             : void FixedDoubleArray::MoveElements(Heap* heap, int dst_index, int src_index,
     375             :                                     int len, WriteBarrierMode mode) {
     376             :   DCHECK_EQ(SKIP_WRITE_BARRIER, mode);
     377             :   double* data_start =
     378           0 :       reinterpret_cast<double*>(FIELD_ADDR(*this, kHeaderSize));
     379           0 :   MemMove(data_start + dst_index, data_start + src_index, len * kDoubleSize);
     380             : }
     381             : 
     382             : void FixedDoubleArray::FillWithHoles(int from, int to) {
     383      788942 :   for (int i = from; i < to; i++) {
     384             :     set_the_hole(i);
     385             :   }
     386             : }
     387             : 
     388             : MaybeObject WeakFixedArray::Get(int index) const {
     389             :   DCHECK(index >= 0 && index < this->length());
     390   247923451 :   return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
     391             : }
     392             : 
     393    32238096 : void WeakFixedArray::Set(int index, MaybeObject value) {
     394             :   DCHECK_GE(index, 0);
     395             :   DCHECK_LT(index, length());
     396             :   int offset = OffsetOfElementAt(index);
     397    32238096 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     398    64476195 :   WEAK_WRITE_BARRIER(*this, offset, value);
     399    32238107 : }
     400             : 
     401     2393696 : void WeakFixedArray::Set(int index, MaybeObject value, WriteBarrierMode mode) {
     402             :   DCHECK_GE(index, 0);
     403             :   DCHECK_LT(index, length());
     404             :   int offset = OffsetOfElementAt(index);
     405     2393696 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     406     7181088 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     407     2393696 : }
     408             : 
     409             : MaybeObjectSlot WeakFixedArray::data_start() {
     410             :   return RawMaybeWeakField(kHeaderSize);
     411             : }
     412             : 
     413             : MaybeObjectSlot WeakFixedArray::RawFieldOfElementAt(int index) {
     414             :   return RawMaybeWeakField(OffsetOfElementAt(index));
     415             : }
     416             : 
     417         120 : MaybeObject WeakArrayList::Get(int index) const {
     418             :   DCHECK(index >= 0 && index < this->capacity());
     419    31635028 :   return RELAXED_READ_WEAK_FIELD(*this, OffsetOfElementAt(index));
     420             : }
     421             : 
     422    35726451 : void WeakArrayList::Set(int index, MaybeObject value, WriteBarrierMode mode) {
     423             :   DCHECK_GE(index, 0);
     424             :   DCHECK_LT(index, this->capacity());
     425             :   int offset = OffsetOfElementAt(index);
     426    35726451 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     427    84244196 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     428    35726449 : }
     429             : 
     430             : MaybeObjectSlot WeakArrayList::data_start() {
     431             :   return RawMaybeWeakField(kHeaderSize);
     432             : }
     433             : 
     434     5210744 : HeapObject WeakArrayList::Iterator::Next() {
     435     5210744 :   if (!array_.is_null()) {
     436    10445426 :     while (index_ < array_->length()) {
     437     5218519 :       MaybeObject item = array_->Get(index_++);
     438             :       DCHECK(item->IsWeakOrCleared());
     439     5218519 :       if (!item->IsCleared()) return item->GetHeapObjectAssumeWeak();
     440             :     }
     441        4194 :     array_ = WeakArrayList();
     442             :   }
     443        4244 :   return HeapObject();
     444             : }
     445             : 
     446       19804 : int ArrayList::Length() const {
     447       19804 :   if (FixedArray::cast(*this)->length() == 0) return 0;
     448             :   return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
     449             : }
     450             : 
     451             : void ArrayList::SetLength(int length) {
     452             :   return FixedArray::cast(*this)->set(kLengthIndex, Smi::FromInt(length));
     453             : }
     454             : 
     455             : Object ArrayList::Get(int index) const {
     456       16599 :   return FixedArray::cast(*this)->get(kFirstIndex + index);
     457             : }
     458             : 
     459             : ObjectSlot ArrayList::Slot(int index) {
     460             :   return RawField(OffsetOfElementAt(kFirstIndex + index));
     461             : }
     462             : 
     463             : void ArrayList::Set(int index, Object obj, WriteBarrierMode mode) {
     464        1949 :   FixedArray::cast(*this)->set(kFirstIndex + index, obj, mode);
     465             : }
     466             : 
     467             : void ArrayList::Clear(int index, Object undefined) {
     468             :   DCHECK(undefined->IsUndefined());
     469          10 :   FixedArray::cast(*this)->set(kFirstIndex + index, undefined,
     470           5 :                                SKIP_WRITE_BARRIER);
     471             : }
     472             : 
     473     4242374 : int ByteArray::Size() { return RoundUp(length() + kHeaderSize, kTaggedSize); }
     474             : 
     475             : byte ByteArray::get(int index) const {
     476             :   DCHECK(index >= 0 && index < this->length());
     477    61746647 :   return READ_BYTE_FIELD(*this, kHeaderSize + index * kCharSize);
     478             : }
     479             : 
     480             : void ByteArray::set(int index, byte value) {
     481             :   DCHECK(index >= 0 && index < this->length());
     482    11693029 :   WRITE_BYTE_FIELD(*this, kHeaderSize + index * kCharSize, value);
     483             : }
     484             : 
     485             : void ByteArray::copy_in(int index, const byte* buffer, int length) {
     486             :   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
     487             :          index + length <= this->length());
     488      130782 :   Address dst_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
     489      130782 :   memcpy(reinterpret_cast<void*>(dst_addr), buffer, length);
     490             : }
     491             : 
     492             : void ByteArray::copy_out(int index, byte* buffer, int length) {
     493             :   DCHECK(index >= 0 && length >= 0 && length <= kMaxInt - index &&
     494             :          index + length <= this->length());
     495   294869640 :   Address src_addr = FIELD_ADDR(*this, kHeaderSize + index * kCharSize);
     496   294869640 :   memcpy(buffer, reinterpret_cast<void*>(src_addr), length);
     497             : }
     498             : 
     499             : int ByteArray::get_int(int index) const {
     500             :   DCHECK(index >= 0 && index < this->length() / kIntSize);
     501        2264 :   return READ_INT_FIELD(*this, kHeaderSize + index * kIntSize);
     502             : }
     503             : 
     504             : void ByteArray::set_int(int index, int value) {
     505             :   DCHECK(index >= 0 && index < this->length() / kIntSize);
     506        1344 :   WRITE_INT_FIELD(*this, kHeaderSize + index * kIntSize, value);
     507             : }
     508             : 
     509             : uint32_t ByteArray::get_uint32(int index) const {
     510             :   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
     511     1016218 :   return READ_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size);
     512             : }
     513             : 
     514             : void ByteArray::set_uint32(int index, uint32_t value) {
     515             :   DCHECK(index >= 0 && index < this->length() / kUInt32Size);
     516      149491 :   WRITE_UINT32_FIELD(*this, kHeaderSize + index * kUInt32Size, value);
     517             : }
     518             : 
     519     7195015 : void ByteArray::clear_padding() {
     520     7195015 :   int data_size = length() + kHeaderSize;
     521    14390030 :   memset(reinterpret_cast<void*>(address() + data_size), 0, Size() - data_size);
     522     7195015 : }
     523             : 
     524             : ByteArray ByteArray::FromDataStartAddress(Address address) {
     525             :   DCHECK_TAG_ALIGNED(address);
     526             :   return ByteArray::cast(Object(address - kHeaderSize + kHeapObjectTag));
     527             : }
     528             : 
     529         620 : int ByteArray::DataSize() const { return RoundUp(length(), kTaggedSize); }
     530             : 
     531             : int ByteArray::ByteArraySize() { return SizeFor(this->length()); }
     532             : 
     533             : byte* ByteArray::GetDataStartAddress() {
     534   268102865 :   return reinterpret_cast<byte*>(address() + kHeaderSize);
     535             : }
     536             : 
     537             : byte* ByteArray::GetDataEndAddress() {
     538   207377503 :   return GetDataStartAddress() + length();
     539             : }
     540             : 
     541             : template <class T>
     542         320 : PodArray<T>::PodArray(Address ptr) : ByteArray(ptr) {}
     543             : 
     544             : template <class T>
     545             : PodArray<T> PodArray<T>::cast(Object object) {
     546         160 :   return PodArray<T>(object.ptr());
     547             : }
     548             : 
     549             : // static
     550             : template <class T>
     551             : Handle<PodArray<T>> PodArray<T>::New(Isolate* isolate, int length,
     552             :                                      AllocationType allocation) {
     553       13923 :   return Handle<PodArray<T>>::cast(
     554             :       isolate->factory()->NewByteArray(length * sizeof(T), allocation));
     555             : }
     556             : 
     557             : template <class T>
     558             : int PodArray<T>::length() const {
     559           0 :   return ByteArray::length() / sizeof(T);
     560             : }
     561             : 
     562             : void* FixedTypedArrayBase::external_pointer() const {
     563     7707577 :   intptr_t ptr = READ_INTPTR_FIELD(*this, kExternalPointerOffset);
     564        2158 :   return reinterpret_cast<void*>(ptr);
     565             : }
     566             : 
     567             : void FixedTypedArrayBase::set_external_pointer(void* value) {
     568       17891 :   intptr_t ptr = reinterpret_cast<intptr_t>(value);
     569       18570 :   WRITE_INTPTR_FIELD(*this, kExternalPointerOffset, ptr);
     570             : }
     571             : 
     572             : void* FixedTypedArrayBase::DataPtr() {
     573             :   return reinterpret_cast<void*>(
     574     7705319 :       base_pointer()->ptr() + reinterpret_cast<intptr_t>(external_pointer()));
     575             : }
     576             : 
     577      374247 : int FixedTypedArrayBase::ElementSize(InstanceType type) {
     578             :   int element_size;
     579      374247 :   switch (type) {
     580             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) \
     581             :   case FIXED_##TYPE##_ARRAY_TYPE:                 \
     582             :     element_size = sizeof(ctype);                 \
     583             :     break;
     584             : 
     585       25015 :     TYPED_ARRAYS(TYPED_ARRAY_CASE)
     586             : #undef TYPED_ARRAY_CASE
     587             :     default:
     588           0 :       UNREACHABLE();
     589             :   }
     590      374247 :   return element_size;
     591             : }
     592             : 
     593      863590 : int FixedTypedArrayBase::DataSize(InstanceType type) const {
     594      863590 :   if (base_pointer() == Smi::kZero) return 0;
     595      374250 :   return length() * ElementSize(type);
     596             : }
     597             : 
     598      248826 : int FixedTypedArrayBase::DataSize() const {
     599      248826 :   return DataSize(map()->instance_type());
     600             : }
     601             : 
     602             : size_t FixedTypedArrayBase::ByteLength() const {
     603             :   return static_cast<size_t>(length()) *
     604             :          static_cast<size_t>(ElementSize(map()->instance_type()));
     605             : }
     606             : 
     607             : int FixedTypedArrayBase::size() const {
     608      214011 :   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize());
     609             : }
     610             : 
     611             : int FixedTypedArrayBase::TypedArraySize(InstanceType type) const {
     612      614714 :   return OBJECT_POINTER_ALIGN(kDataOffset + DataSize(type));
     613             : }
     614             : 
     615             : // static
     616             : int FixedTypedArrayBase::TypedArraySize(InstanceType type, int length) {
     617             :   return OBJECT_POINTER_ALIGN(kDataOffset + length * ElementSize(type));
     618             : }
     619             : 
     620             : uint8_t Uint8ArrayTraits::defaultValue() { return 0; }
     621             : 
     622             : uint8_t Uint8ClampedArrayTraits::defaultValue() { return 0; }
     623             : 
     624             : int8_t Int8ArrayTraits::defaultValue() { return 0; }
     625             : 
     626             : uint16_t Uint16ArrayTraits::defaultValue() { return 0; }
     627             : 
     628             : int16_t Int16ArrayTraits::defaultValue() { return 0; }
     629             : 
     630             : uint32_t Uint32ArrayTraits::defaultValue() { return 0; }
     631             : 
     632             : int32_t Int32ArrayTraits::defaultValue() { return 0; }
     633             : 
     634             : float Float32ArrayTraits::defaultValue() {
     635             :   return std::numeric_limits<float>::quiet_NaN();
     636             : }
     637             : 
     638             : double Float64ArrayTraits::defaultValue() {
     639             :   return std::numeric_limits<double>::quiet_NaN();
     640             : }
     641             : 
     642             : template <class Traits>
     643      429193 : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar(int index) {
     644             :   // TODO(bmeurer, v8:4153): Solve this differently.
     645             :   // DCHECK((index < this->length()));
     646      429193 :   CHECK_GE(index, 0);
     647      429193 :   return FixedTypedArray<Traits>::get_scalar_from_data_ptr(DataPtr(), index);
     648             : }
     649             : 
     650             : // static
     651             : template <class Traits>
     652             : typename Traits::ElementType FixedTypedArray<Traits>::get_scalar_from_data_ptr(
     653             :     void* data_ptr, int index) {
     654             :   typename Traits::ElementType* ptr = reinterpret_cast<ElementType*>(data_ptr);
     655             :   // The JavaScript memory model allows for racy reads and writes to a
     656             :   // SharedArrayBuffer's backing store, which will always be a FixedTypedArray.
     657             :   // ThreadSanitizer will catch these racy accesses and warn about them, so we
     658             :   // disable TSAN for these reads and writes using annotations.
     659             :   //
     660             :   // We don't use relaxed atomics here, as it is not a requirement of the
     661             :   // JavaScript memory model to have tear-free reads of overlapping accesses,
     662             :   // and using relaxed atomics may introduce overhead.
     663             :   TSAN_ANNOTATE_IGNORE_READS_BEGIN;
     664             :   ElementType result;
     665             :   if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
     666             :     // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
     667             :     // fields (external pointers, doubles and BigInt data) are only kTaggedSize
     668             :     // aligned so we have to use unaligned pointer friendly way of accessing
     669             :     // them in order to avoid undefined behavior in C++ code.
     670             :     result = ReadUnalignedValue<ElementType>(reinterpret_cast<Address>(ptr) +
     671             :                                              index * sizeof(ElementType));
     672             :   } else {
     673      445042 :     result = ptr[index];
     674             :   }
     675             :   TSAN_ANNOTATE_IGNORE_READS_END;
     676             :   return result;
     677             : }
     678             : 
     679             : template <class Traits>
     680     7246554 : void FixedTypedArray<Traits>::set(int index, ElementType value) {
     681             :   // TODO(bmeurer, v8:4153): Solve this differently.
     682             :   // CHECK((index < this->length()));
     683     7246554 :   CHECK_GE(index, 0);
     684             :   // See the comment in FixedTypedArray<Traits>::get_scalar.
     685             :   auto* ptr = reinterpret_cast<ElementType*>(DataPtr());
     686             :   TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
     687             :   if (COMPRESS_POINTERS_BOOL && alignof(ElementType) > kTaggedSize) {
     688             :     // TODO(ishell, v8:8875): When pointer compression is enabled 8-byte size
     689             :     // fields (external pointers, doubles and BigInt data) are only kTaggedSize
     690             :     // aligned so we have to use unaligned pointer friendly way of accessing
     691             :     // them in order to avoid undefined behavior in C++ code.
     692             :     WriteUnalignedValue<ElementType>(
     693             :         reinterpret_cast<Address>(ptr) + index * sizeof(ElementType), value);
     694             :   } else {
     695     7246554 :     ptr[index] = value;
     696             :   }
     697             :   TSAN_ANNOTATE_IGNORE_WRITES_END;
     698     7246554 : }
     699             : 
     700             : template <class Traits>
     701             : typename Traits::ElementType FixedTypedArray<Traits>::from(int value) {
     702     4100418 :   return static_cast<ElementType>(value);
     703             : }
     704             : 
     705             : template <>
     706             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(int value) {
     707       25710 :   if (value < 0) return 0;
     708       25845 :   if (value > 0xFF) return 0xFF;
     709       25431 :   return static_cast<uint8_t>(value);
     710             : }
     711             : 
     712             : template <>
     713           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int value) {
     714           0 :   UNREACHABLE();
     715             : }
     716             : 
     717             : template <>
     718           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int value) {
     719           0 :   UNREACHABLE();
     720             : }
     721             : 
     722             : template <class Traits>
     723             : typename Traits::ElementType FixedTypedArray<Traits>::from(uint32_t value) {
     724         918 :   return static_cast<ElementType>(value);
     725             : }
     726             : 
     727             : template <>
     728             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(uint32_t value) {
     729             :   // We need this special case for Uint32 -> Uint8Clamped, because the highest
     730             :   // Uint32 values will be negative as an int, clamping to 0, rather than 255.
     731         198 :   if (value > 0xFF) return 0xFF;
     732         117 :   return static_cast<uint8_t>(value);
     733             : }
     734             : 
     735             : template <>
     736           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint32_t value) {
     737           0 :   UNREACHABLE();
     738             : }
     739             : 
     740             : template <>
     741           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint32_t value) {
     742           0 :   UNREACHABLE();
     743             : }
     744             : 
     745             : template <class Traits>
     746             : typename Traits::ElementType FixedTypedArray<Traits>::from(double value) {
     747      355257 :   return static_cast<ElementType>(DoubleToInt32(value));
     748             : }
     749             : 
     750             : template <>
     751             : inline uint8_t FixedTypedArray<Uint8ClampedArrayTraits>::from(double value) {
     752             :   // Handle NaNs and less than zero values which clamp to zero.
     753       93853 :   if (!(value > 0)) return 0;
     754       92514 :   if (value > 0xFF) return 0xFF;
     755       91785 :   return static_cast<uint8_t>(lrint(value));
     756             : }
     757             : 
     758             : template <>
     759           0 : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(double value) {
     760           0 :   UNREACHABLE();
     761             : }
     762             : 
     763             : template <>
     764           0 : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(double value) {
     765           0 :   UNREACHABLE();
     766             : }
     767             : 
     768             : template <>
     769             : inline float FixedTypedArray<Float32ArrayTraits>::from(double value) {
     770             :   using limits = std::numeric_limits<float>;
     771      134458 :   if (value > limits::max()) return limits::infinity();
     772      134358 :   if (value < limits::lowest()) return -limits::infinity();
     773      134304 :   return static_cast<float>(value);
     774             : }
     775             : 
     776             : template <>
     777             : inline double FixedTypedArray<Float64ArrayTraits>::from(double value) {
     778             :   return value;
     779             : }
     780             : 
     781             : template <class Traits>
     782           0 : typename Traits::ElementType FixedTypedArray<Traits>::from(int64_t value) {
     783           0 :   UNREACHABLE();
     784             : }
     785             : 
     786             : template <class Traits>
     787           0 : typename Traits::ElementType FixedTypedArray<Traits>::from(uint64_t value) {
     788           0 :   UNREACHABLE();
     789             : }
     790             : 
     791             : template <>
     792             : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(int64_t value) {
     793             :   return value;
     794             : }
     795             : 
     796             : template <>
     797             : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(uint64_t value) {
     798             :   return value;
     799             : }
     800             : 
     801             : template <>
     802             : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::from(int64_t value) {
     803           0 :   return static_cast<uint64_t>(value);
     804             : }
     805             : 
     806             : template <>
     807             : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::from(uint64_t value) {
     808           0 :   return static_cast<int64_t>(value);
     809             : }
     810             : 
     811             : template <class Traits>
     812         504 : typename Traits::ElementType FixedTypedArray<Traits>::FromHandle(
     813             :     Handle<Object> value, bool* lossless) {
     814        3878 :   if (value->IsSmi()) {
     815             :     return from(Smi::ToInt(*value));
     816             :   }
     817             :   DCHECK(value->IsHeapNumber());
     818             :   return from(HeapNumber::cast(*value)->value());
     819             : }
     820             : 
     821             : template <>
     822             : inline int64_t FixedTypedArray<BigInt64ArrayTraits>::FromHandle(
     823             :     Handle<Object> value, bool* lossless) {
     824             :   DCHECK(value->IsBigInt());
     825         252 :   return BigInt::cast(*value)->AsInt64(lossless);
     826             : }
     827             : 
     828             : template <>
     829             : inline uint64_t FixedTypedArray<BigUint64ArrayTraits>::FromHandle(
     830             :     Handle<Object> value, bool* lossless) {
     831             :   DCHECK(value->IsBigInt());
     832         252 :   return BigInt::cast(*value)->AsUint64(lossless);
     833             : }
     834             : 
     835             : template <class Traits>
     836      231239 : Handle<Object> FixedTypedArray<Traits>::get(Isolate* isolate,
     837             :                                             FixedTypedArray<Traits> array,
     838             :                                             int index) {
     839      637491 :   return Traits::ToHandle(isolate, array->get_scalar(index));
     840             : }
     841             : 
     842             : template <class Traits>
     843     3187559 : void FixedTypedArray<Traits>::SetValue(uint32_t index, Object value) {
     844             :   ElementType cast_value = Traits::defaultValue();
     845     3187559 :   if (value->IsSmi()) {
     846             :     int int_value = Smi::ToInt(value);
     847             :     cast_value = from(int_value);
     848     2930159 :   } else if (value->IsHeapNumber()) {
     849             :     double double_value = HeapNumber::cast(value)->value();
     850             :     cast_value = from(double_value);
     851             :   } else {
     852             :     // Clamp undefined to the default value. All other types have been
     853             :     // converted to a number type further up in the call chain.
     854             :     DCHECK(value->IsUndefined());
     855             :   }
     856     3187559 :   set(index, cast_value);
     857     3187559 : }
     858             : 
     859             : template <>
     860         679 : inline void FixedTypedArray<BigInt64ArrayTraits>::SetValue(uint32_t index,
     861             :                                                            Object value) {
     862             :   DCHECK(value->IsBigInt());
     863         679 :   set(index, BigInt::cast(value)->AsInt64());
     864         679 : }
     865             : 
     866             : template <>
     867         450 : inline void FixedTypedArray<BigUint64ArrayTraits>::SetValue(uint32_t index,
     868             :                                                             Object value) {
     869             :   DCHECK(value->IsBigInt());
     870         450 :   set(index, BigInt::cast(value)->AsUint64());
     871         450 : }
     872             : 
     873       86810 : Handle<Object> Uint8ArrayTraits::ToHandle(Isolate* isolate, uint8_t scalar) {
     874       86810 :   return handle(Smi::FromInt(scalar), isolate);
     875             : }
     876             : 
     877        2827 : Handle<Object> Uint8ClampedArrayTraits::ToHandle(Isolate* isolate,
     878             :                                                  uint8_t scalar) {
     879        2827 :   return handle(Smi::FromInt(scalar), isolate);
     880             : }
     881             : 
     882        4825 : Handle<Object> Int8ArrayTraits::ToHandle(Isolate* isolate, int8_t scalar) {
     883        4825 :   return handle(Smi::FromInt(scalar), isolate);
     884             : }
     885             : 
     886       76252 : Handle<Object> Uint16ArrayTraits::ToHandle(Isolate* isolate, uint16_t scalar) {
     887       76252 :   return handle(Smi::FromInt(scalar), isolate);
     888             : }
     889             : 
     890        4299 : Handle<Object> Int16ArrayTraits::ToHandle(Isolate* isolate, int16_t scalar) {
     891        4299 :   return handle(Smi::FromInt(scalar), isolate);
     892             : }
     893             : 
     894             : Handle<Object> Uint32ArrayTraits::ToHandle(Isolate* isolate, uint32_t scalar) {
     895       75807 :   return isolate->factory()->NewNumberFromUint(scalar);
     896             : }
     897             : 
     898             : Handle<Object> Int32ArrayTraits::ToHandle(Isolate* isolate, int32_t scalar) {
     899        4959 :   return isolate->factory()->NewNumberFromInt(scalar);
     900             : }
     901             : 
     902             : Handle<Object> Float32ArrayTraits::ToHandle(Isolate* isolate, float scalar) {
     903       75443 :   return isolate->factory()->NewNumber(scalar);
     904             : }
     905             : 
     906             : Handle<Object> Float64ArrayTraits::ToHandle(Isolate* isolate, double scalar) {
     907       74949 :   return isolate->factory()->NewNumber(scalar);
     908             : }
     909             : 
     910             : Handle<Object> BigInt64ArrayTraits::ToHandle(Isolate* isolate, int64_t scalar) {
     911          45 :   return BigInt::FromInt64(isolate, scalar);
     912             : }
     913             : 
     914             : Handle<Object> BigUint64ArrayTraits::ToHandle(Isolate* isolate,
     915             :                                               uint64_t scalar) {
     916          36 :   return BigInt::FromUint64(isolate, scalar);
     917             : }
     918             : 
     919             : // static
     920             : template <class Traits>
     921             : STATIC_CONST_MEMBER_DEFINITION const InstanceType
     922             :     FixedTypedArray<Traits>::kInstanceType;
     923             : 
     924             : template <class Traits>
     925      809096 : FixedTypedArray<Traits>::FixedTypedArray(Address ptr)
     926             :     : FixedTypedArrayBase(ptr) {
     927             :   DCHECK(IsHeapObject() && map()->instance_type() == Traits::kInstanceType);
     928      809096 : }
     929             : 
     930             : template <class Traits>
     931             : FixedTypedArray<Traits> FixedTypedArray<Traits>::cast(Object object) {
     932      809094 :   return FixedTypedArray<Traits>(object.ptr());
     933             : }
     934             : 
     935             : int TemplateList::length() const {
     936             :   return Smi::ToInt(FixedArray::cast(*this)->get(kLengthIndex));
     937             : }
     938             : 
     939             : Object TemplateList::get(int index) const {
     940       61974 :   return FixedArray::cast(*this)->get(kFirstElementIndex + index);
     941             : }
     942             : 
     943             : void TemplateList::set(int index, Object value) {
     944         151 :   FixedArray::cast(*this)->set(kFirstElementIndex + index, value);
     945             : }
     946             : 
     947             : }  // namespace internal
     948             : }  // namespace v8
     949             : 
     950             : #include "src/objects/object-macros-undef.h"
     951             : 
     952             : #endif  // V8_OBJECTS_FIXED_ARRAY_INL_H_

Generated by: LCOV version 1.10