LCOV - code coverage report
Current view: top level - src - elements.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1408 1678 83.9 %
Date: 2019-02-19 Functions: 947 1926 49.2 %

          Line data    Source code
       1             : // Copyright 2012 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             : #include "src/elements.h"
       6             : 
       7             : #include "src/arguments.h"
       8             : #include "src/conversions.h"
       9             : #include "src/frames.h"
      10             : #include "src/heap/factory.h"
      11             : #include "src/heap/heap-inl.h"  // For MaxNumberToStringCacheSize.
      12             : #include "src/heap/heap-write-barrier-inl.h"
      13             : #include "src/isolate-inl.h"
      14             : #include "src/keys.h"
      15             : #include "src/message-template.h"
      16             : #include "src/objects-inl.h"
      17             : #include "src/objects/arguments-inl.h"
      18             : #include "src/objects/hash-table-inl.h"
      19             : #include "src/objects/js-array-buffer-inl.h"
      20             : #include "src/objects/js-array-inl.h"
      21             : #include "src/objects/slots-atomic-inl.h"
      22             : #include "src/objects/slots.h"
      23             : #include "src/utils.h"
      24             : 
      25             : // Each concrete ElementsAccessor can handle exactly one ElementsKind,
      26             : // several abstract ElementsAccessor classes are used to allow sharing
      27             : // common code.
      28             : //
      29             : // Inheritance hierarchy:
      30             : // - ElementsAccessorBase                        (abstract)
      31             : //   - FastElementsAccessor                      (abstract)
      32             : //     - FastSmiOrObjectElementsAccessor
      33             : //       - FastPackedSmiElementsAccessor
      34             : //       - FastHoleySmiElementsAccessor
      35             : //       - FastPackedObjectElementsAccessor
      36             : //       - FastHoleyObjectElementsAccessor
      37             : //     - FastDoubleElementsAccessor
      38             : //       - FastPackedDoubleElementsAccessor
      39             : //       - FastHoleyDoubleElementsAccessor
      40             : //   - TypedElementsAccessor: template, with instantiations:
      41             : //     - FixedUint8ElementsAccessor
      42             : //     - FixedInt8ElementsAccessor
      43             : //     - FixedUint16ElementsAccessor
      44             : //     - FixedInt16ElementsAccessor
      45             : //     - FixedUint32ElementsAccessor
      46             : //     - FixedInt32ElementsAccessor
      47             : //     - FixedFloat32ElementsAccessor
      48             : //     - FixedFloat64ElementsAccessor
      49             : //     - FixedUint8ClampedElementsAccessor
      50             : //     - FixedBigUint64ElementsAccessor
      51             : //     - FixedBigInt64ElementsAccessor
      52             : //   - DictionaryElementsAccessor
      53             : //   - SloppyArgumentsElementsAccessor
      54             : //     - FastSloppyArgumentsElementsAccessor
      55             : //     - SlowSloppyArgumentsElementsAccessor
      56             : //   - StringWrapperElementsAccessor
      57             : //     - FastStringWrapperElementsAccessor
      58             : //     - SlowStringWrapperElementsAccessor
      59             : 
      60             : namespace v8 {
      61             : namespace internal {
      62             : 
      63             : 
      64             : namespace {
      65             : 
      66             : 
      67             : static const int kPackedSizeNotKnown = -1;
      68             : 
      69             : enum Where { AT_START, AT_END };
      70             : 
      71             : 
      72             : // First argument in list is the accessor class, the second argument is the
      73             : // accessor ElementsKind, and the third is the backing store class.  Use the
      74             : // fast element handler for smi-only arrays.  The implementation is currently
      75             : // identical.  Note that the order must match that of the ElementsKind enum for
      76             : // the |accessor_array[]| below to work.
      77             : #define ELEMENTS_LIST(V)                                                      \
      78             :   V(FastPackedSmiElementsAccessor, PACKED_SMI_ELEMENTS, FixedArray)           \
      79             :   V(FastHoleySmiElementsAccessor, HOLEY_SMI_ELEMENTS, FixedArray)             \
      80             :   V(FastPackedObjectElementsAccessor, PACKED_ELEMENTS, FixedArray)            \
      81             :   V(FastHoleyObjectElementsAccessor, HOLEY_ELEMENTS, FixedArray)              \
      82             :   V(FastPackedDoubleElementsAccessor, PACKED_DOUBLE_ELEMENTS,                 \
      83             :     FixedDoubleArray)                                                         \
      84             :   V(FastHoleyDoubleElementsAccessor, HOLEY_DOUBLE_ELEMENTS, FixedDoubleArray) \
      85             :   V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, NumberDictionary)        \
      86             :   V(FastSloppyArgumentsElementsAccessor, FAST_SLOPPY_ARGUMENTS_ELEMENTS,      \
      87             :     FixedArray)                                                               \
      88             :   V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS,      \
      89             :     FixedArray)                                                               \
      90             :   V(FastStringWrapperElementsAccessor, FAST_STRING_WRAPPER_ELEMENTS,          \
      91             :     FixedArray)                                                               \
      92             :   V(SlowStringWrapperElementsAccessor, SLOW_STRING_WRAPPER_ELEMENTS,          \
      93             :     FixedArray)                                                               \
      94             :   V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array)              \
      95             :   V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array)                 \
      96             :   V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array)           \
      97             :   V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array)              \
      98             :   V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array)           \
      99             :   V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array)              \
     100             :   V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array)        \
     101             :   V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array)        \
     102             :   V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS,                \
     103             :     FixedUint8ClampedArray)                                                   \
     104             :   V(FixedBigUint64ElementsAccessor, BIGUINT64_ELEMENTS, FixedBigUint64Array)  \
     105             :   V(FixedBigInt64ElementsAccessor, BIGINT64_ELEMENTS, FixedBigInt64Array)
     106             : 
     107             : template<ElementsKind Kind> class ElementsKindTraits {
     108             :  public:
     109             :   typedef FixedArrayBase BackingStore;
     110             : };
     111             : 
     112             : #define ELEMENTS_TRAITS(Class, KindParam, Store)    \
     113             :   template <>                                       \
     114             :   class ElementsKindTraits<KindParam> {             \
     115             :    public: /* NOLINT */                             \
     116             :     static constexpr ElementsKind Kind = KindParam; \
     117             :     typedef Store BackingStore;                     \
     118             :   };                                                \
     119             :   constexpr ElementsKind ElementsKindTraits<KindParam>::Kind;
     120             : ELEMENTS_LIST(ELEMENTS_TRAITS)
     121             : #undef ELEMENTS_TRAITS
     122             : 
     123             : V8_WARN_UNUSED_RESULT
     124         108 : MaybeHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) {
     125         108 :   THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength),
     126             :                   Object);
     127             : }
     128             : 
     129             : WriteBarrierMode GetWriteBarrierMode(ElementsKind kind) {
     130         479 :   if (IsSmiElementsKind(kind)) return SKIP_WRITE_BARRIER;
     131         329 :   if (IsDoubleElementsKind(kind)) return SKIP_WRITE_BARRIER;
     132             :   return UPDATE_WRITE_BARRIER;
     133             : }
     134             : 
     135     1601870 : void CopyObjectToObjectElements(Isolate* isolate, FixedArrayBase from_base,
     136             :                                 ElementsKind from_kind, uint32_t from_start,
     137             :                                 FixedArrayBase to_base, ElementsKind to_kind,
     138             :                                 uint32_t to_start, int raw_copy_size) {
     139             :   ReadOnlyRoots roots(isolate);
     140             :   DCHECK(to_base->map() != roots.fixed_cow_array_map());
     141             :   DisallowHeapAllocation no_allocation;
     142             :   int copy_size = raw_copy_size;
     143     1601870 :   if (raw_copy_size < 0) {
     144             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     145             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     146             :     copy_size = Min(from_base->length() - from_start,
     147     2676650 :                     to_base->length() - to_start);
     148      892218 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     149      892219 :       int start = to_start + copy_size;
     150      892218 :       int length = to_base->length() - start;
     151      892218 :       if (length > 0) {
     152             :         MemsetTagged(FixedArray::cast(to_base)->RawFieldOfElementAt(start),
     153      892209 :                      roots.the_hole_value(), length);
     154             :       }
     155             :     }
     156             :   }
     157             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     158             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     159     2421617 :   if (copy_size == 0) return;
     160             :   FixedArray from = FixedArray::cast(from_base);
     161      782137 :   FixedArray to = FixedArray::cast(to_base);
     162             :   DCHECK(IsSmiOrObjectElementsKind(from_kind));
     163             :   DCHECK(IsSmiOrObjectElementsKind(to_kind));
     164             : 
     165             :   WriteBarrierMode write_barrier_mode =
     166      619528 :       (IsObjectElementsKind(from_kind) && IsObjectElementsKind(to_kind))
     167             :           ? UPDATE_WRITE_BARRIER
     168      782137 :           : SKIP_WRITE_BARRIER;
     169  1014706971 :   for (int i = 0; i < copy_size; i++) {
     170  2027849678 :     Object value = from->get(from_start + i);
     171  1013924839 :     to->set(to_start + i, value, write_barrier_mode);
     172             :   }
     173             : }
     174             : 
     175         479 : static void CopyDictionaryToObjectElements(
     176             :     Isolate* isolate, FixedArrayBase from_base, uint32_t from_start,
     177             :     FixedArrayBase to_base, ElementsKind to_kind, uint32_t to_start,
     178             :     int raw_copy_size) {
     179             :   DisallowHeapAllocation no_allocation;
     180         479 :   NumberDictionary from = NumberDictionary::cast(from_base);
     181             :   int copy_size = raw_copy_size;
     182         479 :   if (raw_copy_size < 0) {
     183             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     184             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     185         479 :     copy_size = from->max_number_key() + 1 - from_start;
     186         479 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     187         479 :       int start = to_start + copy_size;
     188         479 :       int length = to_base->length() - start;
     189         479 :       if (length > 0) {
     190             :         MemsetTagged(FixedArray::cast(to_base)->RawFieldOfElementAt(start),
     191         142 :                      ReadOnlyRoots(isolate).the_hole_value(), length);
     192             :       }
     193             :     }
     194             :   }
     195             :   DCHECK(to_base != from_base);
     196             :   DCHECK(IsSmiOrObjectElementsKind(to_kind));
     197         479 :   if (copy_size == 0) return;
     198         479 :   FixedArray to = FixedArray::cast(to_base);
     199         479 :   uint32_t to_length = to->length();
     200         479 :   if (to_start + copy_size > to_length) {
     201          18 :     copy_size = to_length - to_start;
     202             :   }
     203             :   WriteBarrierMode write_barrier_mode = GetWriteBarrierMode(to_kind);
     204     4581631 :   for (int i = 0; i < copy_size; i++) {
     205     4581152 :     int entry = from->FindEntry(isolate, i + from_start);
     206     4581152 :     if (entry != NumberDictionary::kNotFound) {
     207     1154154 :       Object value = from->ValueAt(entry);
     208             :       DCHECK(!value->IsTheHole(isolate));
     209     1154154 :       to->set(i + to_start, value, write_barrier_mode);
     210             :     } else {
     211     3426998 :       to->set_the_hole(isolate, i + to_start);
     212             :     }
     213             :   }
     214             : }
     215             : 
     216             : // NOTE: this method violates the handlified function signature convention:
     217             : // raw pointer parameters in the function that allocates.
     218             : // See ElementsAccessorBase::CopyElements() for details.
     219        1375 : static void CopyDoubleToObjectElements(Isolate* isolate,
     220             :                                        FixedArrayBase from_base,
     221             :                                        uint32_t from_start,
     222             :                                        FixedArrayBase to_base,
     223             :                                        uint32_t to_start, int raw_copy_size) {
     224             :   int copy_size = raw_copy_size;
     225        1375 :   if (raw_copy_size < 0) {
     226             :     DisallowHeapAllocation no_allocation;
     227             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     228             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     229             :     copy_size = Min(from_base->length() - from_start,
     230        4029 :                     to_base->length() - to_start);
     231        1343 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     232             :       // Also initialize the area that will be copied over since HeapNumber
     233             :       // allocation below can cause an incremental marking step, requiring all
     234             :       // existing heap objects to be propertly initialized.
     235        1343 :       int start = to_start;
     236        1343 :       int length = to_base->length() - start;
     237        1343 :       if (length > 0) {
     238             :         MemsetTagged(FixedArray::cast(to_base)->RawFieldOfElementAt(start),
     239        1343 :                      ReadOnlyRoots(isolate).the_hole_value(), length);
     240             :       }
     241             :     }
     242             :   }
     243             : 
     244             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     245             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     246        2750 :   if (copy_size == 0) return;
     247             : 
     248             :   // From here on, the code below could actually allocate. Therefore the raw
     249             :   // values are wrapped into handles.
     250             :   Handle<FixedDoubleArray> from(FixedDoubleArray::cast(from_base), isolate);
     251             :   Handle<FixedArray> to(FixedArray::cast(to_base), isolate);
     252             : 
     253             :   // Use an outer loop to not waste too much time on creating HandleScopes.
     254             :   // On the other hand we might overflow a single handle scope depending on
     255             :   // the copy_size.
     256             :   int offset = 0;
     257       75677 :   while (offset < copy_size) {
     258             :     HandleScope scope(isolate);
     259       72927 :     offset += 100;
     260     7237009 :     for (int i = offset - 100; i < offset && i < copy_size; ++i) {
     261             :       Handle<Object> value =
     262    14328164 :           FixedDoubleArray::get(*from, i + from_start, isolate);
     263    14328164 :       to->set(i + to_start, *value, UPDATE_WRITE_BARRIER);
     264             :     }
     265             :   }
     266             : }
     267             : 
     268         932 : static void CopyDoubleToDoubleElements(FixedArrayBase from_base,
     269             :                                        uint32_t from_start,
     270             :                                        FixedArrayBase to_base,
     271             :                                        uint32_t to_start, int raw_copy_size) {
     272             :   DisallowHeapAllocation no_allocation;
     273             :   int copy_size = raw_copy_size;
     274         932 :   if (raw_copy_size < 0) {
     275             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     276             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     277             :     copy_size = Min(from_base->length() - from_start,
     278        2541 :                     to_base->length() - to_start);
     279         847 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     280    43519530 :       for (int i = to_start + copy_size; i < to_base->length(); ++i) {
     281             :         FixedDoubleArray::cast(to_base)->set_the_hole(i);
     282             :       }
     283             :     }
     284             :   }
     285             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     286             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     287        1864 :   if (copy_size == 0) return;
     288             :   FixedDoubleArray from = FixedDoubleArray::cast(from_base);
     289             :   FixedDoubleArray to = FixedDoubleArray::cast(to_base);
     290         845 :   Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
     291         845 :   Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
     292         845 :   to_address += kDoubleSize * to_start;
     293         845 :   from_address += kDoubleSize * from_start;
     294             :   int words_per_double = (kDoubleSize / kSystemPointerSize);
     295             :   CopyWords(to_address, from_address,
     296         845 :             static_cast<size_t>(words_per_double * copy_size));
     297             : }
     298             : 
     299        1512 : static void CopySmiToDoubleElements(FixedArrayBase from_base,
     300             :                                     uint32_t from_start, FixedArrayBase to_base,
     301             :                                     uint32_t to_start, int raw_copy_size) {
     302             :   DisallowHeapAllocation no_allocation;
     303             :   int copy_size = raw_copy_size;
     304        1512 :   if (raw_copy_size < 0) {
     305             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     306             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     307        1512 :     copy_size = from_base->length() - from_start;
     308        1512 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     309        6192 :       for (int i = to_start + copy_size; i < to_base->length(); ++i) {
     310             :         FixedDoubleArray::cast(to_base)->set_the_hole(i);
     311             :       }
     312             :     }
     313             :   }
     314             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     315             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     316        1548 :   if (copy_size == 0) return;
     317        1476 :   FixedArray from = FixedArray::cast(from_base);
     318        1476 :   FixedDoubleArray to = FixedDoubleArray::cast(to_base);
     319        2952 :   Object the_hole = from->GetReadOnlyRoots().the_hole_value();
     320    25754344 :   for (uint32_t from_end = from_start + static_cast<uint32_t>(copy_size);
     321             :        from_start < from_end; from_start++, to_start++) {
     322    25752868 :     Object hole_or_smi = from->get(from_start);
     323    25752868 :     if (hole_or_smi == the_hole) {
     324    23192075 :       to->set_the_hole(to_start);
     325             :     } else {
     326     2560793 :       to->set(to_start, Smi::ToInt(hole_or_smi));
     327             :     }
     328             :   }
     329             : }
     330             : 
     331      208345 : static void CopyPackedSmiToDoubleElements(FixedArrayBase from_base,
     332             :                                           uint32_t from_start,
     333             :                                           FixedArrayBase to_base,
     334             :                                           uint32_t to_start, int packed_size,
     335             :                                           int raw_copy_size) {
     336             :   DisallowHeapAllocation no_allocation;
     337             :   int copy_size = raw_copy_size;
     338             :   uint32_t to_end;
     339      208345 :   if (raw_copy_size < 0) {
     340             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     341             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     342      208308 :     copy_size = packed_size - from_start;
     343      208308 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     344      208308 :       to_end = to_base->length();
     345      472148 :       for (uint32_t i = to_start + copy_size; i < to_end; ++i) {
     346      263840 :         FixedDoubleArray::cast(to_base)->set_the_hole(i);
     347             :       }
     348             :     } else {
     349             :       to_end = to_start + static_cast<uint32_t>(copy_size);
     350             :     }
     351             :   } else {
     352             :     to_end = to_start + static_cast<uint32_t>(copy_size);
     353             :   }
     354             :   DCHECK(static_cast<int>(to_end) <= to_base->length());
     355             :   DCHECK(packed_size >= 0 && packed_size <= copy_size);
     356             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     357             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     358      209064 :   if (copy_size == 0) return;
     359             :   FixedArray from = FixedArray::cast(from_base);
     360      207626 :   FixedDoubleArray to = FixedDoubleArray::cast(to_base);
     361     2796963 :   for (uint32_t from_end = from_start + static_cast<uint32_t>(packed_size);
     362             :        from_start < from_end; from_start++, to_start++) {
     363     5178674 :     Object smi = from->get(from_start);
     364             :     DCHECK(!smi->IsTheHole());
     365     2589337 :     to->set(to_start, Smi::ToInt(smi));
     366             :   }
     367             : }
     368             : 
     369        3306 : static void CopyObjectToDoubleElements(FixedArrayBase from_base,
     370             :                                        uint32_t from_start,
     371             :                                        FixedArrayBase to_base,
     372             :                                        uint32_t to_start, int raw_copy_size) {
     373             :   DisallowHeapAllocation no_allocation;
     374             :   int copy_size = raw_copy_size;
     375        3306 :   if (raw_copy_size < 0) {
     376             :     DCHECK(raw_copy_size == ElementsAccessor::kCopyToEnd ||
     377             :            raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     378           0 :     copy_size = from_base->length() - from_start;
     379           0 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     380           0 :       for (int i = to_start + copy_size; i < to_base->length(); ++i) {
     381             :         FixedDoubleArray::cast(to_base)->set_the_hole(i);
     382             :       }
     383             :     }
     384             :   }
     385             :   DCHECK((copy_size + static_cast<int>(to_start)) <= to_base->length() &&
     386             :          (copy_size + static_cast<int>(from_start)) <= from_base->length());
     387        3306 :   if (copy_size == 0) return;
     388        3306 :   FixedArray from = FixedArray::cast(from_base);
     389        3306 :   FixedDoubleArray to = FixedDoubleArray::cast(to_base);
     390        6612 :   Object the_hole = from->GetReadOnlyRoots().the_hole_value();
     391      416104 :   for (uint32_t from_end = from_start + copy_size;
     392             :        from_start < from_end; from_start++, to_start++) {
     393      825596 :     Object hole_or_object = from->get(from_start);
     394      412798 :     if (hole_or_object == the_hole) {
     395         969 :       to->set_the_hole(to_start);
     396             :     } else {
     397      411829 :       to->set(to_start, hole_or_object->Number());
     398             :     }
     399             :   }
     400             : }
     401             : 
     402           9 : static void CopyDictionaryToDoubleElements(
     403             :     Isolate* isolate, FixedArrayBase from_base, uint32_t from_start,
     404             :     FixedArrayBase to_base, uint32_t to_start, int raw_copy_size) {
     405             :   DisallowHeapAllocation no_allocation;
     406           9 :   NumberDictionary from = NumberDictionary::cast(from_base);
     407             :   int copy_size = raw_copy_size;
     408           9 :   if (copy_size < 0) {
     409             :     DCHECK(copy_size == ElementsAccessor::kCopyToEnd ||
     410             :            copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
     411           9 :     copy_size = from->max_number_key() + 1 - from_start;
     412           9 :     if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
     413          18 :       for (int i = to_start + copy_size; i < to_base->length(); ++i) {
     414             :         FixedDoubleArray::cast(to_base)->set_the_hole(i);
     415             :       }
     416             :     }
     417             :   }
     418           9 :   if (copy_size == 0) return;
     419           9 :   FixedDoubleArray to = FixedDoubleArray::cast(to_base);
     420           9 :   uint32_t to_length = to->length();
     421           9 :   if (to_start + copy_size > to_length) {
     422           0 :     copy_size = to_length - to_start;
     423             :   }
     424       91488 :   for (int i = 0; i < copy_size; i++) {
     425       91479 :     int entry = from->FindEntry(isolate, i + from_start);
     426       91479 :     if (entry != NumberDictionary::kNotFound) {
     427        6838 :       to->set(i + to_start, from->ValueAt(entry)->Number());
     428             :     } else {
     429       84641 :       to->set_the_hole(i + to_start);
     430             :     }
     431             :   }
     432             : }
     433             : 
     434           0 : static void TraceTopFrame(Isolate* isolate) {
     435           0 :   StackFrameIterator it(isolate);
     436           0 :   if (it.done()) {
     437           0 :     PrintF("unknown location (no JavaScript frames present)");
     438           0 :     return;
     439             :   }
     440             :   StackFrame* raw_frame = it.frame();
     441           0 :   if (raw_frame->is_internal()) {
     442             :     Code current_code_object =
     443           0 :         isolate->heap()->GcSafeFindCodeForInnerPointer(raw_frame->pc());
     444           0 :     if (current_code_object->builtin_index() ==
     445             :         Builtins::kFunctionPrototypeApply) {
     446           0 :       PrintF("apply from ");
     447           0 :       it.Advance();
     448             :       raw_frame = it.frame();
     449             :     }
     450             :   }
     451           0 :   JavaScriptFrame::PrintTop(isolate, stdout, false, true);
     452             : }
     453             : 
     454        8632 : static void SortIndices(
     455             :     Isolate* isolate, Handle<FixedArray> indices, uint32_t sort_size,
     456             :     WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER) {
     457             :   // Use AtomicSlot wrapper to ensure that std::sort uses atomic load and
     458             :   // store operations that are safe for concurrent marking.
     459             :   AtomicSlot start(indices->GetFirstElementAddress());
     460             :   std::sort(start, start + sort_size,
     461       28150 :             [isolate](Tagged_t elementA, Tagged_t elementB) {
     462             :               // TODO(ishell): revisit the code below
     463             :               STATIC_ASSERT(kTaggedSize == kSystemPointerSize);
     464             : #ifdef V8_COMPRESS_POINTERS
     465             :               Object a(DecompressTaggedAny(isolate->isolate_root(), elementA));
     466             :               Object b(DecompressTaggedAny(isolate->isolate_root(), elementB));
     467             : #else
     468             :               Object a(elementA);
     469             :               Object b(elementB);
     470             : #endif
     471       35792 :               if (a->IsSmi() || !a->IsUndefined(isolate)) {
     472       35666 :                 if (!b->IsSmi() && b->IsUndefined(isolate)) {
     473             :                   return true;
     474             :                 }
     475       28150 :                 return a->Number() < b->Number();
     476             :               }
     477           0 :               return !b->IsSmi() && b->IsUndefined(isolate);
     478       17264 :             });
     479        8632 :   if (write_barrier_mode != SKIP_WRITE_BARRIER) {
     480       17264 :     FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(isolate->heap(), *indices, 0, sort_size);
     481             :   }
     482        8632 : }
     483             : 
     484           0 : static Maybe<bool> IncludesValueSlowPath(Isolate* isolate,
     485             :                                          Handle<JSObject> receiver,
     486             :                                          Handle<Object> value,
     487             :                                          uint32_t start_from, uint32_t length) {
     488           0 :   bool search_for_hole = value->IsUndefined(isolate);
     489           0 :   for (uint32_t k = start_from; k < length; ++k) {
     490           0 :     LookupIterator it(isolate, receiver, k);
     491           0 :     if (!it.IsFound()) {
     492           0 :       if (search_for_hole) return Just(true);
     493           0 :       continue;
     494             :     }
     495             :     Handle<Object> element_k;
     496           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k,
     497             :                                      Object::GetProperty(&it), Nothing<bool>());
     498             : 
     499           0 :     if (value->SameValueZero(*element_k)) return Just(true);
     500             :   }
     501             : 
     502             :   return Just(false);
     503             : }
     504             : 
     505           0 : static Maybe<int64_t> IndexOfValueSlowPath(Isolate* isolate,
     506             :                                            Handle<JSObject> receiver,
     507             :                                            Handle<Object> value,
     508             :                                            uint32_t start_from,
     509             :                                            uint32_t length) {
     510           0 :   for (uint32_t k = start_from; k < length; ++k) {
     511           0 :     LookupIterator it(isolate, receiver, k);
     512           0 :     if (!it.IsFound()) {
     513           0 :       continue;
     514             :     }
     515             :     Handle<Object> element_k;
     516           0 :     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     517             :         isolate, element_k, Object::GetProperty(&it), Nothing<int64_t>());
     518             : 
     519           0 :     if (value->StrictEquals(*element_k)) return Just<int64_t>(k);
     520             :   }
     521             : 
     522             :   return Just<int64_t>(-1);
     523             : }
     524             : 
     525             : // The InternalElementsAccessor is a helper class to expose otherwise protected
     526             : // methods to its subclasses. Namely, we don't want to publicly expose methods
     527             : // that take an entry (instead of an index) as an argument.
     528     1286252 : class InternalElementsAccessor : public ElementsAccessor {
     529             :  public:
     530             :   explicit InternalElementsAccessor(const char* name)
     531     1310826 :       : ElementsAccessor(name) {}
     532             : 
     533             :   uint32_t GetEntryForIndex(Isolate* isolate, JSObject holder,
     534             :                             FixedArrayBase backing_store,
     535             :                             uint32_t index) override = 0;
     536             : 
     537             :   PropertyDetails GetDetails(JSObject holder, uint32_t entry) override = 0;
     538             : };
     539             : 
     540             : // Base class for element handler implementations. Contains the
     541             : // the common logic for objects with different ElementsKinds.
     542             : // Subclasses must specialize method for which the element
     543             : // implementation differs from the base class implementation.
     544             : //
     545             : // This class is intended to be used in the following way:
     546             : //
     547             : //   class SomeElementsAccessor :
     548             : //       public ElementsAccessorBase<SomeElementsAccessor,
     549             : //                                   BackingStoreClass> {
     550             : //     ...
     551             : //   }
     552             : //
     553             : // This is an example of the Curiously Recurring Template Pattern (see
     554             : // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
     555             : // CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
     556             : // specialization of SomeElementsAccessor methods).
     557             : template <typename Subclass, typename ElementsTraitsParam>
     558     1286252 : class ElementsAccessorBase : public InternalElementsAccessor {
     559             :  public:
     560             :   explicit ElementsAccessorBase(const char* name)
     561     1310826 :       : InternalElementsAccessor(name) {}
     562             : 
     563             :   typedef ElementsTraitsParam ElementsTraits;
     564             :   typedef typename ElementsTraitsParam::BackingStore BackingStore;
     565             : 
     566             :   static ElementsKind kind() { return ElementsTraits::Kind; }
     567             : 
     568             :   static void ValidateContents(JSObject holder, int length) {}
     569             : 
     570           0 :   static void ValidateImpl(JSObject holder) {
     571           0 :     FixedArrayBase fixed_array_base = holder->elements();
     572           0 :     if (!fixed_array_base->IsHeapObject()) return;
     573             :     // Arrays that have been shifted in place can't be verified.
     574           0 :     if (fixed_array_base->IsFiller()) return;
     575             :     int length = 0;
     576           0 :     if (holder->IsJSArray()) {
     577           0 :       Object length_obj = JSArray::cast(holder)->length();
     578           0 :       if (length_obj->IsSmi()) {
     579           0 :         length = Smi::ToInt(length_obj);
     580             :       }
     581             :     } else {
     582             :       length = fixed_array_base->length();
     583             :     }
     584             :     Subclass::ValidateContents(holder, length);
     585             :   }
     586             : 
     587           0 :   void Validate(JSObject holder) final {
     588             :     DisallowHeapAllocation no_gc;
     589           0 :     Subclass::ValidateImpl(holder);
     590           0 :   }
     591             : 
     592           0 :   static bool IsPackedImpl(JSObject holder, FixedArrayBase backing_store,
     593             :                            uint32_t start, uint32_t end) {
     594             :     DisallowHeapAllocation no_gc;
     595             :     if (IsFastPackedElementsKind(kind())) return true;
     596             :     Isolate* isolate = holder->GetIsolate();
     597           0 :     for (uint32_t i = start; i < end; i++) {
     598           0 :       if (!Subclass::HasElementImpl(isolate, holder, i, backing_store,
     599             :                                     ALL_PROPERTIES)) {
     600             :         return false;
     601             :       }
     602             :     }
     603             :     return true;
     604             :   }
     605             : 
     606           0 :   static void TryTransitionResultArrayToPacked(Handle<JSArray> array) {
     607           0 :     if (!IsHoleyElementsKind(kind())) return;
     608           0 :     Handle<FixedArrayBase> backing_store(array->elements(),
     609           0 :                                          array->GetIsolate());
     610           0 :     int length = Smi::ToInt(array->length());
     611           0 :     if (!Subclass::IsPackedImpl(*array, *backing_store, 0, length)) return;
     612             : 
     613             :     ElementsKind packed_kind = GetPackedElementsKind(kind());
     614             :     Handle<Map> new_map =
     615           0 :         JSObject::GetElementsTransitionMap(array, packed_kind);
     616           0 :     JSObject::MigrateToMap(array, new_map);
     617             :     if (FLAG_trace_elements_transitions) {
     618             :       JSObject::PrintElementsTransition(stdout, array, kind(), backing_store,
     619             :                                         packed_kind, backing_store);
     620             :     }
     621             :   }
     622             : 
     623      270027 :   bool HasElement(JSObject holder, uint32_t index, FixedArrayBase backing_store,
     624             :                   PropertyFilter filter) final {
     625             :     return Subclass::HasElementImpl(holder->GetIsolate(), holder, index,
     626      270027 :                                     backing_store, filter);
     627             :   }
     628             : 
     629     3519963 :   static bool HasElementImpl(Isolate* isolate, JSObject holder, uint32_t index,
     630             :                              FixedArrayBase backing_store,
     631             :                              PropertyFilter filter = ALL_PROPERTIES) {
     632             :     return Subclass::GetEntryForIndexImpl(isolate, holder, backing_store, index,
     633    12179976 :                                           filter) != kMaxUInt32;
     634             :   }
     635             : 
     636         222 :   bool HasEntry(JSObject holder, uint32_t entry) final {
     637             :     return Subclass::HasEntryImpl(holder->GetIsolate(), holder->elements(),
     638         444 :                                   entry);
     639             :   }
     640             : 
     641           0 :   static bool HasEntryImpl(Isolate* isolate, FixedArrayBase backing_store,
     642             :                            uint32_t entry) {
     643           0 :     UNIMPLEMENTED();
     644             :   }
     645             : 
     646      595526 :   bool HasAccessors(JSObject holder) final {
     647      595526 :     return Subclass::HasAccessorsImpl(holder, holder->elements());
     648             :   }
     649             : 
     650             :   static bool HasAccessorsImpl(JSObject holder, FixedArrayBase backing_store) {
     651             :     return false;
     652             :   }
     653             : 
     654     5885344 :   Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) final {
     655     5885344 :     return Subclass::GetInternalImpl(holder, entry);
     656             :   }
     657             : 
     658     5864184 :   static Handle<Object> GetInternalImpl(Handle<JSObject> holder,
     659             :                                         uint32_t entry) {
     660    11728368 :     return Subclass::GetImpl(holder->GetIsolate(), holder->elements(), entry);
     661             :   }
     662             : 
     663     6410493 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
     664             :                                 uint32_t entry) {
     665             :     uint32_t index = GetIndexForEntryImpl(backing_store, entry);
     666    12820986 :     return handle(BackingStore::cast(backing_store)->get(index), isolate);
     667             :   }
     668             : 
     669      917688 :   void Set(Handle<JSObject> holder, uint32_t entry, Object value) final {
     670      917688 :     Subclass::SetImpl(holder, entry, value);
     671      917691 :   }
     672             : 
     673       19360 :   void Reconfigure(Handle<JSObject> object, Handle<FixedArrayBase> store,
     674             :                    uint32_t entry, Handle<Object> value,
     675             :                    PropertyAttributes attributes) final {
     676       19360 :     Subclass::ReconfigureImpl(object, store, entry, value, attributes);
     677       19360 :   }
     678             : 
     679           0 :   static void ReconfigureImpl(Handle<JSObject> object,
     680             :                               Handle<FixedArrayBase> store, uint32_t entry,
     681             :                               Handle<Object> value,
     682             :                               PropertyAttributes attributes) {
     683           0 :     UNREACHABLE();
     684             :   }
     685             : 
     686     6201325 :   void Add(Handle<JSObject> object, uint32_t index, Handle<Object> value,
     687             :            PropertyAttributes attributes, uint32_t new_capacity) final {
     688     6195052 :     Subclass::AddImpl(object, index, value, attributes, new_capacity);
     689     6201327 :   }
     690             : 
     691           0 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
     692             :                       Handle<Object> value, PropertyAttributes attributes,
     693             :                       uint32_t new_capacity) {
     694           0 :     UNREACHABLE();
     695             :   }
     696             : 
     697     9373984 :   uint32_t Push(Handle<JSArray> receiver, Arguments* args,
     698             :                 uint32_t push_size) final {
     699     9373984 :     return Subclass::PushImpl(receiver, args, push_size);
     700             :   }
     701             : 
     702           0 :   static uint32_t PushImpl(Handle<JSArray> receiver, Arguments* args,
     703             :                            uint32_t push_sized) {
     704           0 :     UNREACHABLE();
     705             :   }
     706             : 
     707        5846 :   uint32_t Unshift(Handle<JSArray> receiver, Arguments* args,
     708             :                    uint32_t unshift_size) final {
     709        5846 :     return Subclass::UnshiftImpl(receiver, args, unshift_size);
     710             :   }
     711             : 
     712           0 :   static uint32_t UnshiftImpl(Handle<JSArray> receiver, Arguments* args,
     713             :                               uint32_t unshift_size) {
     714           0 :     UNREACHABLE();
     715             :   }
     716             : 
     717           0 :   Handle<JSObject> Slice(Handle<JSObject> receiver, uint32_t start,
     718             :                          uint32_t end) final {
     719           0 :     return Subclass::SliceImpl(receiver, start, end);
     720             :   }
     721             : 
     722           0 :   static Handle<JSObject> SliceImpl(Handle<JSObject> receiver, uint32_t start,
     723             :                                     uint32_t end) {
     724           0 :     UNREACHABLE();
     725             :   }
     726             : 
     727       50719 :   Handle<Object> Pop(Handle<JSArray> receiver) final {
     728       50719 :     return Subclass::PopImpl(receiver);
     729             :   }
     730             : 
     731           0 :   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
     732           0 :     UNREACHABLE();
     733             :   }
     734             : 
     735      183049 :   Handle<Object> Shift(Handle<JSArray> receiver) final {
     736      183049 :     return Subclass::ShiftImpl(receiver);
     737             :   }
     738             : 
     739           0 :   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
     740           0 :     UNREACHABLE();
     741             :   }
     742             : 
     743      484666 :   void SetLength(Handle<JSArray> array, uint32_t length) final {
     744      484666 :     Subclass::SetLengthImpl(array->GetIsolate(), array, length,
     745      969332 :                             handle(array->elements(), array->GetIsolate()));
     746      484666 :   }
     747             : 
     748      710335 :   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
     749             :                             uint32_t length,
     750             :                             Handle<FixedArrayBase> backing_store) {
     751             :     DCHECK(!array->SetLengthWouldNormalize(length));
     752             :     DCHECK(IsFastElementsKind(array->GetElementsKind()));
     753      710335 :     uint32_t old_length = 0;
     754     1420670 :     CHECK(array->length()->ToArrayIndex(&old_length));
     755             : 
     756      710335 :     if (old_length < length) {
     757      448416 :       ElementsKind kind = array->GetElementsKind();
     758      448416 :       if (!IsHoleyElementsKind(kind)) {
     759             :         kind = GetHoleyElementsKind(kind);
     760        2218 :         JSObject::TransitionElementsKind(array, kind);
     761             :       }
     762             :     }
     763             : 
     764             :     // Check whether the backing store should be shrunk.
     765      710335 :     uint32_t capacity = backing_store->length();
     766     1420670 :     old_length = Min(old_length, capacity);
     767      710335 :     if (length == 0) {
     768       16055 :       array->initialize_elements();
     769      694280 :     } else if (length <= capacity) {
     770             :       if (IsSmiOrObjectElementsKind(kind())) {
     771      226809 :         JSObject::EnsureWritableFastElements(array);
     772      453618 :         if (array->elements() != *backing_store) {
     773        2130 :           backing_store = handle(array->elements(), isolate);
     774             :         }
     775             :       }
     776      248327 :       if (2 * length + JSObject::kMinAddedElementsCapacity <= capacity) {
     777             :         // If more than half the elements won't be used, trim the array.
     778             :         // Do not trim from short arrays to prevent frequent trimming on
     779             :         // repeated pop operations.
     780             :         // Leave some space to allow for subsequent push operations.
     781             :         int elements_to_trim = length + 1 == old_length
     782             :                                    ? (capacity - length) / 2
     783       32710 :                                    : capacity - length;
     784       32710 :         isolate->heap()->RightTrimFixedArray(*backing_store, elements_to_trim);
     785             :         // Fill the non-trimmed elements with holes.
     786       98130 :         BackingStore::cast(*backing_store)
     787             :             ->FillWithHoles(length,
     788       65420 :                             std::min(old_length, capacity - elements_to_trim));
     789             :       } else {
     790             :         // Otherwise, fill the unused tail with holes.
     791      646851 :         BackingStore::cast(*backing_store)->FillWithHoles(length, old_length);
     792             :       }
     793             :     } else {
     794             :       // Check whether the backing store should be expanded.
     795             :       capacity = Max(length, JSObject::NewElementsCapacity(capacity));
     796      445953 :       Subclass::GrowCapacityAndConvertImpl(array, capacity);
     797             :     }
     798             : 
     799     2131005 :     array->set_length(Smi::FromInt(length));
     800      710335 :     JSObject::ValidateElements(*array);
     801      710335 :   }
     802             : 
     803        6444 :   uint32_t NumberOfElements(JSObject receiver) final {
     804       12870 :     return Subclass::NumberOfElementsImpl(receiver, receiver->elements());
     805             :   }
     806             : 
     807             :   static uint32_t NumberOfElementsImpl(JSObject receiver,
     808             :                                        FixedArrayBase backing_store) {
     809             :     UNREACHABLE();
     810             :   }
     811             : 
     812   175010934 :   static uint32_t GetMaxIndex(JSObject receiver, FixedArrayBase elements) {
     813   175010937 :     if (receiver->IsJSArray()) {
     814             :       DCHECK(JSArray::cast(receiver)->length()->IsSmi());
     815             :       return static_cast<uint32_t>(
     816    90550067 :           Smi::ToInt(JSArray::cast(receiver)->length()));
     817             :     }
     818    84460871 :     return Subclass::GetCapacityImpl(receiver, elements);
     819             :   }
     820             : 
     821             :   static uint32_t GetMaxNumberOfEntries(JSObject receiver,
     822             :                                         FixedArrayBase elements) {
     823      137901 :     return Subclass::GetMaxIndex(receiver, elements);
     824             :   }
     825             : 
     826             :   static Handle<FixedArrayBase> ConvertElementsWithCapacity(
     827             :       Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
     828             :       ElementsKind from_kind, uint32_t capacity) {
     829             :     return ConvertElementsWithCapacity(
     830             :         object, old_elements, from_kind, capacity, 0, 0,
     831      960006 :         ElementsAccessor::kCopyToEndAndInitializeToHole);
     832             :   }
     833             : 
     834             :   static Handle<FixedArrayBase> ConvertElementsWithCapacity(
     835             :       Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
     836             :       ElementsKind from_kind, uint32_t capacity, int copy_size) {
     837             :     return ConvertElementsWithCapacity(object, old_elements, from_kind,
     838             :                                        capacity, 0, 0, copy_size);
     839             :   }
     840             : 
     841     1104711 :   static Handle<FixedArrayBase> ConvertElementsWithCapacity(
     842             :       Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
     843             :       ElementsKind from_kind, uint32_t capacity, uint32_t src_index,
     844             :       uint32_t dst_index, int copy_size) {
     845             :     Isolate* isolate = object->GetIsolate();
     846             :     Handle<FixedArrayBase> new_elements;
     847             :     if (IsDoubleElementsKind(kind())) {
     848      210676 :       new_elements = isolate->factory()->NewFixedDoubleArray(capacity);
     849             :     } else {
     850      894038 :       new_elements = isolate->factory()->NewUninitializedFixedArray(capacity);
     851             :     }
     852             : 
     853             :     int packed_size = kPackedSizeNotKnown;
     854     1840825 :     if (IsFastPackedElementsKind(from_kind) && object->IsJSArray()) {
     855      367853 :       packed_size = Smi::ToInt(JSArray::cast(*object)->length());
     856             :     }
     857             : 
     858     1104716 :     Subclass::CopyElementsImpl(isolate, *old_elements, src_index, *new_elements,
     859     1104715 :                                from_kind, dst_index, packed_size, copy_size);
     860             : 
     861     1104714 :     return new_elements;
     862             :   }
     863             : 
     864      204889 :   static void TransitionElementsKindImpl(Handle<JSObject> object,
     865             :                                          Handle<Map> to_map) {
     866             :     Handle<Map> from_map = handle(object->map(), object->GetIsolate());
     867             :     ElementsKind from_kind = from_map->elements_kind();
     868             :     ElementsKind to_kind = to_map->elements_kind();
     869      204889 :     if (IsHoleyElementsKind(from_kind)) {
     870             :       to_kind = GetHoleyElementsKind(to_kind);
     871             :     }
     872      204889 :     if (from_kind != to_kind) {
     873             :       // This method should never be called for any other case.
     874             :       DCHECK(IsFastElementsKind(from_kind));
     875             :       DCHECK(IsFastElementsKind(to_kind));
     876             :       DCHECK_NE(TERMINAL_FAST_ELEMENTS_KIND, from_kind);
     877             : 
     878             :       Handle<FixedArrayBase> from_elements(object->elements(),
     879      409778 :                                            object->GetIsolate());
     880      819556 :       if (object->elements() ==
     881      409778 :               object->GetReadOnlyRoots().empty_fixed_array() ||
     882             :           IsDoubleElementsKind(from_kind) == IsDoubleElementsKind(to_kind)) {
     883             :         // No change is needed to the elements() buffer, the transition
     884             :         // only requires a map change.
     885           0 :         JSObject::MigrateToMap(object, to_map);
     886             :       } else {
     887             :         DCHECK(
     888             :             (IsSmiElementsKind(from_kind) && IsDoubleElementsKind(to_kind)) ||
     889             :             (IsDoubleElementsKind(from_kind) && IsObjectElementsKind(to_kind)));
     890      409778 :         uint32_t capacity = static_cast<uint32_t>(object->elements()->length());
     891             :         Handle<FixedArrayBase> elements = ConvertElementsWithCapacity(
     892      204889 :             object, from_elements, from_kind, capacity);
     893      204889 :         JSObject::SetMapAndElements(object, to_map, elements);
     894             :       }
     895             :       if (FLAG_trace_elements_transitions) {
     896             :         JSObject::PrintElementsTransition(
     897             :             stdout, object, from_kind, from_elements, to_kind,
     898             :             handle(object->elements(), object->GetIsolate()));
     899             :       }
     900             :     }
     901      204889 :   }
     902             : 
     903      734240 :   static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
     904             :                                          uint32_t capacity) {
     905      734240 :     ElementsKind from_kind = object->GetElementsKind();
     906      734240 :     if (IsSmiOrObjectElementsKind(from_kind)) {
     907             :       // Array optimizations rely on the prototype lookups of Array objects
     908             :       // always returning undefined. If there is a store to the initial
     909             :       // prototype object, make sure all of these optimizations are invalidated.
     910             :       object->GetIsolate()->UpdateNoElementsProtectorOnSetLength(object);
     911             :     }
     912             :     Handle<FixedArrayBase> old_elements(object->elements(),
     913     1468480 :                                         object->GetIsolate());
     914             :     // This method should only be called if there's a reason to update the
     915             :     // elements.
     916             :     DCHECK(IsDoubleElementsKind(from_kind) != IsDoubleElementsKind(kind()) ||
     917             :            IsDictionaryElementsKind(from_kind) ||
     918             :            static_cast<uint32_t>(old_elements->length()) < capacity);
     919      734240 :     Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
     920      734240 :                                               kind(), capacity);
     921      734240 :   }
     922             : 
     923      734520 :   static void BasicGrowCapacityAndConvertImpl(
     924             :       Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
     925             :       ElementsKind from_kind, ElementsKind to_kind, uint32_t capacity) {
     926             :     Handle<FixedArrayBase> elements =
     927      734520 :         ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
     928             : 
     929      734520 :     if (IsHoleyElementsKind(from_kind)) {
     930             :       to_kind = GetHoleyElementsKind(to_kind);
     931             :     }
     932      734520 :     Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, to_kind);
     933      734520 :     JSObject::SetMapAndElements(object, new_map, elements);
     934             : 
     935             :     // Transition through the allocation site as well if present.
     936      734520 :     JSObject::UpdateAllocationSite(object, to_kind);
     937             : 
     938             :     if (FLAG_trace_elements_transitions) {
     939             :       JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements,
     940             :                                         to_kind, elements);
     941             :     }
     942      734520 :   }
     943             : 
     944      204889 :   void TransitionElementsKind(Handle<JSObject> object, Handle<Map> map) final {
     945      204889 :     Subclass::TransitionElementsKindImpl(object, map);
     946      204889 :   }
     947             : 
     948        4634 :   void GrowCapacityAndConvert(Handle<JSObject> object,
     949             :                               uint32_t capacity) final {
     950        4634 :     Subclass::GrowCapacityAndConvertImpl(object, capacity);
     951        4634 :   }
     952             : 
     953         710 :   bool GrowCapacity(Handle<JSObject> object, uint32_t index) final {
     954             :     // This function is intended to be called from optimized code. We don't
     955             :     // want to trigger lazy deopts there, so refuse to handle cases that would.
     956        2130 :     if (object->map()->is_prototype_map() ||
     957        1420 :         object->WouldConvertToSlowElements(index)) {
     958             :       return false;
     959             :     }
     960             :     Handle<FixedArrayBase> old_elements(object->elements(),
     961        1304 :                                         object->GetIsolate());
     962         652 :     uint32_t new_capacity = JSObject::NewElementsCapacity(index + 1);
     963             :     DCHECK(static_cast<uint32_t>(old_elements->length()) < new_capacity);
     964             :     Handle<FixedArrayBase> elements =
     965             :         ConvertElementsWithCapacity(object, old_elements, kind(), new_capacity);
     966             : 
     967             :     DCHECK_EQ(object->GetElementsKind(), kind());
     968             :     // Transition through the allocation site as well if present.
     969         652 :     if (JSObject::UpdateAllocationSite<AllocationSiteUpdateMode::kCheckOnly>(
     970             :             object, kind())) {
     971             :       return false;
     972             :     }
     973             : 
     974         652 :     object->set_elements(*elements);
     975         652 :     return true;
     976             :   }
     977             : 
     978      103310 :   void Delete(Handle<JSObject> obj, uint32_t entry) final {
     979      103310 :     Subclass::DeleteImpl(obj, entry);
     980      103310 :   }
     981             : 
     982           0 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
     983             :                                uint32_t from_start, FixedArrayBase to,
     984             :                                ElementsKind from_kind, uint32_t to_start,
     985             :                                int packed_size, int copy_size) {
     986           0 :     UNREACHABLE();
     987             :   }
     988             : 
     989      568278 :   void CopyElements(JSObject from_holder, uint32_t from_start,
     990             :                     ElementsKind from_kind, Handle<FixedArrayBase> to,
     991             :                     uint32_t to_start, int copy_size) final {
     992             :     int packed_size = kPackedSizeNotKnown;
     993             :     bool is_packed = IsFastPackedElementsKind(from_kind) &&
     994      592084 :         from_holder->IsJSArray();
     995      568278 :     if (is_packed) {
     996       23806 :       packed_size = Smi::ToInt(JSArray::cast(from_holder)->length());
     997         122 :       if (copy_size >= 0 && packed_size > copy_size) {
     998             :         packed_size = copy_size;
     999             :       }
    1000             :     }
    1001      568278 :     FixedArrayBase from = from_holder->elements();
    1002             :     // NOTE: the Subclass::CopyElementsImpl() methods
    1003             :     // violate the handlified function signature convention:
    1004             :     // raw pointer parameters in the function that allocates. This is done
    1005             :     // intentionally to avoid ArrayConcat() builtin performance degradation.
    1006             :     //
    1007             :     // Details: The idea is that allocations actually happen only in case of
    1008             :     // copying from object with fast double elements to object with object
    1009             :     // elements. In all the other cases there are no allocations performed and
    1010             :     // handle creation causes noticeable performance degradation of the builtin.
    1011      568278 :     Subclass::CopyElementsImpl(from_holder->GetIsolate(), from, from_start, *to,
    1012      568278 :                                from_kind, to_start, packed_size, copy_size);
    1013      568278 :   }
    1014             : 
    1015        3306 :   void CopyElements(Isolate* isolate, Handle<FixedArrayBase> source,
    1016             :                     ElementsKind source_kind,
    1017             :                     Handle<FixedArrayBase> destination, int size) override {
    1018        3306 :     Subclass::CopyElementsImpl(isolate, *source, 0, *destination, source_kind,
    1019        3306 :                                0, kPackedSizeNotKnown, size);
    1020        3306 :   }
    1021             : 
    1022        2034 :   void CopyTypedArrayElementsSlice(JSTypedArray source,
    1023             :                                    JSTypedArray destination, size_t start,
    1024             :                                    size_t end) override {
    1025        2034 :     Subclass::CopyTypedArrayElementsSliceImpl(source, destination, start, end);
    1026        2034 :   }
    1027             : 
    1028           0 :   static void CopyTypedArrayElementsSliceImpl(JSTypedArray source,
    1029             :                                               JSTypedArray destination,
    1030             :                                               size_t start, size_t end) {
    1031           0 :     UNREACHABLE();
    1032             :   }
    1033             : 
    1034       30411 :   Object CopyElements(Handle<Object> source, Handle<JSObject> destination,
    1035             :                       size_t length, uint32_t offset) final {
    1036             :     return Subclass::CopyElementsHandleImpl(source, destination, length,
    1037       30411 :                                             offset);
    1038             :   }
    1039             : 
    1040           0 :   static Object CopyElementsHandleImpl(Handle<Object> source,
    1041             :                                        Handle<JSObject> destination,
    1042             :                                        size_t length, uint32_t offset) {
    1043           0 :     UNREACHABLE();
    1044             :   }
    1045             : 
    1046      293053 :   Handle<NumberDictionary> Normalize(Handle<JSObject> object) final {
    1047             :     return Subclass::NormalizeImpl(
    1048      586106 :         object, handle(object->elements(), object->GetIsolate()));
    1049             :   }
    1050             : 
    1051           0 :   static Handle<NumberDictionary> NormalizeImpl(
    1052             :       Handle<JSObject> object, Handle<FixedArrayBase> elements) {
    1053           0 :     UNREACHABLE();
    1054             :   }
    1055             : 
    1056        1008 :   Maybe<bool> CollectValuesOrEntries(Isolate* isolate, Handle<JSObject> object,
    1057             :                                      Handle<FixedArray> values_or_entries,
    1058             :                                      bool get_entries, int* nof_items,
    1059             :                                      PropertyFilter filter) override {
    1060             :     return Subclass::CollectValuesOrEntriesImpl(
    1061        1008 :         isolate, object, values_or_entries, get_entries, nof_items, filter);
    1062             :   }
    1063             : 
    1064         504 :   static Maybe<bool> CollectValuesOrEntriesImpl(
    1065             :       Isolate* isolate, Handle<JSObject> object,
    1066             :       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
    1067             :       PropertyFilter filter) {
    1068             :     DCHECK_EQ(*nof_items, 0);
    1069             :     KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly,
    1070             :                                ALL_PROPERTIES);
    1071         504 :     Subclass::CollectElementIndicesImpl(
    1072        1008 :         object, handle(object->elements(), isolate), &accumulator);
    1073         504 :     Handle<FixedArray> keys = accumulator.GetKeys();
    1074             : 
    1075             :     int count = 0;
    1076             :     int i = 0;
    1077         504 :     ElementsKind original_elements_kind = object->GetElementsKind();
    1078             : 
    1079        3024 :     for (; i < keys->length(); ++i) {
    1080             :       Handle<Object> key(keys->get(i), isolate);
    1081             :       uint32_t index;
    1082        1260 :       if (!key->ToUint32(&index)) continue;
    1083             : 
    1084             :       DCHECK_EQ(object->GetElementsKind(), original_elements_kind);
    1085             :       uint32_t entry = Subclass::GetEntryForIndexImpl(
    1086        3024 :           isolate, *object, object->elements(), index, filter);
    1087        1008 :       if (entry == kMaxUInt32) continue;
    1088         261 :       PropertyDetails details = Subclass::GetDetailsImpl(*object, entry);
    1089             : 
    1090             :       Handle<Object> value;
    1091         756 :       if (details.kind() == kData) {
    1092         585 :         value = Subclass::GetImpl(isolate, object->elements(), entry);
    1093             :       } else {
    1094             :         // This might modify the elements and/or change the elements kind.
    1095         342 :         LookupIterator it(isolate, object, index, LookupIterator::OWN);
    1096         342 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
    1097             :             isolate, value, Object::GetProperty(&it), Nothing<bool>());
    1098             :       }
    1099         756 :       if (get_entries) value = MakeEntryPair(isolate, index, value);
    1100        1512 :       values_or_entries->set(count++, *value);
    1101         756 :       if (object->GetElementsKind() != original_elements_kind) break;
    1102             :     }
    1103             : 
    1104             :     // Slow path caused by changes in elements kind during iteration.
    1105         504 :     for (; i < keys->length(); i++) {
    1106             :       Handle<Object> key(keys->get(i), isolate);
    1107             :       uint32_t index;
    1108           0 :       if (!key->ToUint32(&index)) continue;
    1109             : 
    1110           0 :       if (filter & ONLY_ENUMERABLE) {
    1111             :         InternalElementsAccessor* accessor =
    1112             :             reinterpret_cast<InternalElementsAccessor*>(
    1113           0 :                 object->GetElementsAccessor());
    1114             :         uint32_t entry = accessor->GetEntryForIndex(isolate, *object,
    1115           0 :                                                     object->elements(), index);
    1116           0 :         if (entry == kMaxUInt32) continue;
    1117           0 :         PropertyDetails details = accessor->GetDetails(*object, entry);
    1118           0 :         if (!details.IsEnumerable()) continue;
    1119             :       }
    1120             : 
    1121             :       Handle<Object> value;
    1122           0 :       LookupIterator it(isolate, object, index, LookupIterator::OWN);
    1123           0 :       ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::GetProperty(&it),
    1124             :                                        Nothing<bool>());
    1125             : 
    1126           0 :       if (get_entries) value = MakeEntryPair(isolate, index, value);
    1127           0 :       values_or_entries->set(count++, *value);
    1128             :     }
    1129             : 
    1130         504 :     *nof_items = count;
    1131             :     return Just(true);
    1132             :   }
    1133             : 
    1134     1227788 :   void CollectElementIndices(Handle<JSObject> object,
    1135             :                              Handle<FixedArrayBase> backing_store,
    1136     1227788 :                              KeyAccumulator* keys) final {
    1137     2455576 :     if (keys->filter() & ONLY_ALL_CAN_READ) return;
    1138     1227740 :     Subclass::CollectElementIndicesImpl(object, backing_store, keys);
    1139             :   }
    1140             : 
    1141     1223554 :   static void CollectElementIndicesImpl(Handle<JSObject> object,
    1142             :                                         Handle<FixedArrayBase> backing_store,
    1143     1223554 :                                         KeyAccumulator* keys) {
    1144             :     DCHECK_NE(DICTIONARY_ELEMENTS, kind());
    1145             :     // Non-dictionary elements can't have all-can-read accessors.
    1146     1223554 :     uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
    1147             :     PropertyFilter filter = keys->filter();
    1148             :     Isolate* isolate = keys->isolate();
    1149             :     Factory* factory = isolate->factory();
    1150     5349763 :     for (uint32_t i = 0; i < length; i++) {
    1151     4126209 :       if (Subclass::HasElementImpl(isolate, *object, i, *backing_store,
    1152             :                                    filter)) {
    1153     3511849 :         keys->AddKey(factory->NewNumberFromUint(i));
    1154             :       }
    1155             :     }
    1156     1223554 :   }
    1157             : 
    1158      137683 :   static Handle<FixedArray> DirectCollectElementIndicesImpl(
    1159             :       Isolate* isolate, Handle<JSObject> object,
    1160             :       Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
    1161             :       PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
    1162             :       uint32_t insertion_index = 0) {
    1163      137683 :     uint32_t length = Subclass::GetMaxIndex(*object, *backing_store);
    1164             :     uint32_t const kMaxStringTableEntries =
    1165      137683 :         isolate->heap()->MaxNumberToStringCacheSize();
    1166     7760118 :     for (uint32_t i = 0; i < length; i++) {
    1167     7760118 :       if (Subclass::HasElementImpl(isolate, *object, i, *backing_store,
    1168             :                                    filter)) {
    1169     1552455 :         if (convert == GetKeysConversion::kConvertToString) {
    1170     1552323 :           bool use_cache = i < kMaxStringTableEntries;
    1171             :           Handle<String> index_string =
    1172     1552323 :               isolate->factory()->Uint32ToString(i, use_cache);
    1173     3104646 :           list->set(insertion_index, *index_string);
    1174             :         } else {
    1175         264 :           list->set(insertion_index, Smi::FromInt(i));
    1176             :         }
    1177     1552455 :         insertion_index++;
    1178             :       }
    1179             :     }
    1180      137683 :     *nof_indices = insertion_index;
    1181      137683 :     return list;
    1182             :   }
    1183             : 
    1184      141538 :   MaybeHandle<FixedArray> PrependElementIndices(
    1185             :       Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
    1186             :       Handle<FixedArray> keys, GetKeysConversion convert,
    1187             :       PropertyFilter filter) final {
    1188             :     return Subclass::PrependElementIndicesImpl(object, backing_store, keys,
    1189      141538 :                                                convert, filter);
    1190             :   }
    1191             : 
    1192      141538 :   static MaybeHandle<FixedArray> PrependElementIndicesImpl(
    1193             :       Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
    1194             :       Handle<FixedArray> keys, GetKeysConversion convert,
    1195             :       PropertyFilter filter) {
    1196             :     Isolate* isolate = object->GetIsolate();
    1197      141538 :     uint32_t nof_property_keys = keys->length();
    1198             :     uint32_t initial_list_length =
    1199         206 :         Subclass::GetMaxNumberOfEntries(*object, *backing_store);
    1200             : 
    1201      141538 :     initial_list_length += nof_property_keys;
    1202      141538 :     if (initial_list_length > FixedArray::kMaxLength ||
    1203             :         initial_list_length < nof_property_keys) {
    1204             :       return isolate->Throw<FixedArray>(isolate->factory()->NewRangeError(
    1205           0 :           MessageTemplate::kInvalidArrayLength));
    1206             :     }
    1207             : 
    1208             :     // Collect the element indices into a new list.
    1209             :     MaybeHandle<FixedArray> raw_array =
    1210      141538 :         isolate->factory()->TryNewFixedArray(initial_list_length);
    1211             :     Handle<FixedArray> combined_keys;
    1212             : 
    1213             :     // If we have a holey backing store try to precisely estimate the backing
    1214             :     // store size as a last emergency measure if we cannot allocate the big
    1215             :     // array.
    1216      141538 :     if (!raw_array.ToHandle(&combined_keys)) {
    1217             :       if (IsHoleyOrDictionaryElementsKind(kind())) {
    1218             :         // If we overestimate the result list size we might end up in the
    1219             :         // large-object space which doesn't free memory on shrinking the list.
    1220             :         // Hence we try to estimate the final size for holey backing stores more
    1221             :         // precisely here.
    1222          45 :         initial_list_length =
    1223             :             Subclass::NumberOfElementsImpl(*object, *backing_store);
    1224          45 :         initial_list_length += nof_property_keys;
    1225             :       }
    1226          45 :       combined_keys = isolate->factory()->NewFixedArray(initial_list_length);
    1227             :     }
    1228             : 
    1229      141538 :     uint32_t nof_indices = 0;
    1230             :     bool needs_sorting = IsDictionaryElementsKind(kind()) ||
    1231             :                          IsSloppyArgumentsElementsKind(kind());
    1232      141538 :     combined_keys = Subclass::DirectCollectElementIndicesImpl(
    1233             :         isolate, object, backing_store,
    1234             :         needs_sorting ? GetKeysConversion::kKeepNumbers : convert, filter,
    1235             :         combined_keys, &nof_indices);
    1236             : 
    1237             :     if (needs_sorting) {
    1238        3942 :       SortIndices(isolate, combined_keys, nof_indices);
    1239             :       // Indices from dictionary elements should only be converted after
    1240             :       // sorting.
    1241        3942 :       if (convert == GetKeysConversion::kConvertToString) {
    1242        9627 :         for (uint32_t i = 0; i < nof_indices; i++) {
    1243             :           Handle<Object> index_string = isolate->factory()->Uint32ToString(
    1244       19254 :               combined_keys->get(i)->Number());
    1245        9627 :           combined_keys->set(i, *index_string);
    1246             :         }
    1247             :       }
    1248             :     }
    1249             : 
    1250             :     // Copy over the passed-in property keys.
    1251      283076 :     CopyObjectToObjectElements(isolate, *keys, PACKED_ELEMENTS, 0,
    1252             :                                *combined_keys, PACKED_ELEMENTS, nof_indices,
    1253      424614 :                                nof_property_keys);
    1254             : 
    1255             :     // For holey elements and arguments we might have to shrink the collected
    1256             :     // keys since the estimates might be off.
    1257             :     if (IsHoleyOrDictionaryElementsKind(kind()) ||
    1258             :         IsSloppyArgumentsElementsKind(kind())) {
    1259             :       // Shrink combined_keys to the final size.
    1260       91835 :       int final_size = nof_indices + nof_property_keys;
    1261             :       DCHECK_LE(final_size, combined_keys->length());
    1262       91835 :       return FixedArray::ShrinkOrEmpty(isolate, combined_keys, final_size);
    1263             :     }
    1264             : 
    1265       49703 :     return combined_keys;
    1266             :   }
    1267             : 
    1268         309 :   void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
    1269             :                                    KeyAccumulator* accumulator,
    1270             :                                    AddKeyConversion convert) final {
    1271         309 :     Subclass::AddElementsToKeyAccumulatorImpl(receiver, accumulator, convert);
    1272         309 :   }
    1273             : 
    1274             :   static uint32_t GetCapacityImpl(JSObject holder,
    1275             :                                   FixedArrayBase backing_store) {
    1276    89567285 :     return backing_store->length();
    1277             :   }
    1278             : 
    1279        1458 :   uint32_t GetCapacity(JSObject holder, FixedArrayBase backing_store) final {
    1280        1458 :     return Subclass::GetCapacityImpl(holder, backing_store);
    1281             :   }
    1282             : 
    1283           0 :   static Object FillImpl(Handle<JSObject> receiver, Handle<Object> obj_value,
    1284             :                          uint32_t start, uint32_t end) {
    1285           0 :     UNREACHABLE();
    1286             :   }
    1287             : 
    1288       10565 :   Object Fill(Handle<JSObject> receiver, Handle<Object> obj_value,
    1289             :               uint32_t start, uint32_t end) override {
    1290       10565 :     return Subclass::FillImpl(receiver, obj_value, start, end);
    1291             :   }
    1292             : 
    1293             :   static Maybe<bool> IncludesValueImpl(Isolate* isolate,
    1294             :                                        Handle<JSObject> receiver,
    1295             :                                        Handle<Object> value,
    1296             :                                        uint32_t start_from, uint32_t length) {
    1297           0 :     return IncludesValueSlowPath(isolate, receiver, value, start_from, length);
    1298             :   }
    1299             : 
    1300       93937 :   Maybe<bool> IncludesValue(Isolate* isolate, Handle<JSObject> receiver,
    1301             :                             Handle<Object> value, uint32_t start_from,
    1302             :                             uint32_t length) final {
    1303             :     return Subclass::IncludesValueImpl(isolate, receiver, value, start_from,
    1304       93937 :                                        length);
    1305             :   }
    1306             : 
    1307             :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    1308             :                                          Handle<JSObject> receiver,
    1309             :                                          Handle<Object> value,
    1310             :                                          uint32_t start_from, uint32_t length) {
    1311           0 :     return IndexOfValueSlowPath(isolate, receiver, value, start_from, length);
    1312             :   }
    1313             : 
    1314        3145 :   Maybe<int64_t> IndexOfValue(Isolate* isolate, Handle<JSObject> receiver,
    1315             :                               Handle<Object> value, uint32_t start_from,
    1316             :                               uint32_t length) final {
    1317             :     return Subclass::IndexOfValueImpl(isolate, receiver, value, start_from,
    1318        3145 :                                       length);
    1319             :   }
    1320             : 
    1321           0 :   static Maybe<int64_t> LastIndexOfValueImpl(Handle<JSObject> receiver,
    1322             :                                              Handle<Object> value,
    1323             :                                              uint32_t start_from) {
    1324           0 :     UNREACHABLE();
    1325             :   }
    1326             : 
    1327        1107 :   Maybe<int64_t> LastIndexOfValue(Handle<JSObject> receiver,
    1328             :                                   Handle<Object> value,
    1329             :                                   uint32_t start_from) final {
    1330        1107 :     return Subclass::LastIndexOfValueImpl(receiver, value, start_from);
    1331             :   }
    1332             : 
    1333           0 :   static void ReverseImpl(JSObject receiver) { UNREACHABLE(); }
    1334             : 
    1335         234 :   void Reverse(JSObject receiver) final { Subclass::ReverseImpl(receiver); }
    1336             : 
    1337             :   static uint32_t GetIndexForEntryImpl(FixedArrayBase backing_store,
    1338             :                                        uint32_t entry) {
    1339             :     return entry;
    1340             :   }
    1341             : 
    1342   166064221 :   static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject holder,
    1343             :                                        FixedArrayBase backing_store,
    1344             :                                        uint32_t index, PropertyFilter filter) {
    1345             :     DCHECK(IsFastElementsKind(kind()));
    1346   173505308 :     uint32_t length = Subclass::GetMaxIndex(holder, backing_store);
    1347             :     if (IsHoleyElementsKind(kind())) {
    1348             :       return index < length &&
    1349   197281749 :                      !BackingStore::cast(backing_store)
    1350             :                           ->is_the_hole(isolate, index)
    1351             :                  ? index
    1352   182005695 :                  : kMaxUInt32;
    1353             :     } else {
    1354     7441089 :       return index < length ? index : kMaxUInt32;
    1355             :     }
    1356             :   }
    1357             : 
    1358   238529073 :   uint32_t GetEntryForIndex(Isolate* isolate, JSObject holder,
    1359             :                             FixedArrayBase backing_store,
    1360             :                             uint32_t index) final {
    1361             :     return Subclass::GetEntryForIndexImpl(isolate, holder, backing_store, index,
    1362   238529075 :                                           ALL_PROPERTIES);
    1363             :   }
    1364             : 
    1365             :   static PropertyDetails GetDetailsImpl(FixedArrayBase backing_store,
    1366             :                                         uint32_t entry) {
    1367             :     return PropertyDetails(kData, NONE, PropertyCellType::kNoCell);
    1368             :   }
    1369             : 
    1370             :   static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
    1371             :     return PropertyDetails(kData, NONE, PropertyCellType::kNoCell);
    1372             :   }
    1373             : 
    1374     7403201 :   PropertyDetails GetDetails(JSObject holder, uint32_t entry) final {
    1375     7403201 :     return Subclass::GetDetailsImpl(holder, entry);
    1376             :   }
    1377             : 
    1378         711 :   Handle<FixedArray> CreateListFromArrayLike(Isolate* isolate,
    1379             :                                              Handle<JSObject> object,
    1380             :                                              uint32_t length) final {
    1381         711 :     return Subclass::CreateListFromArrayLikeImpl(isolate, object, length);
    1382             :   }
    1383             : 
    1384           0 :   static Handle<FixedArray> CreateListFromArrayLikeImpl(Isolate* isolate,
    1385             :                                                         Handle<JSObject> object,
    1386             :                                                         uint32_t length) {
    1387           0 :     UNREACHABLE();
    1388             :   }
    1389             : 
    1390             :  private:
    1391             :   DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
    1392             : };
    1393             : 
    1394             : 
    1395      116932 : class DictionaryElementsAccessor
    1396             :     : public ElementsAccessorBase<DictionaryElementsAccessor,
    1397             :                                   ElementsKindTraits<DICTIONARY_ELEMENTS> > {
    1398             :  public:
    1399             :   explicit DictionaryElementsAccessor(const char* name)
    1400             :       : ElementsAccessorBase<DictionaryElementsAccessor,
    1401       59583 :                              ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
    1402             : 
    1403             :   static uint32_t GetMaxIndex(JSObject receiver, FixedArrayBase elements) {
    1404             :     // We cannot properly estimate this for dictionaries.
    1405             :     UNREACHABLE();
    1406             :   }
    1407             : 
    1408             :   static uint32_t GetMaxNumberOfEntries(JSObject receiver,
    1409             :                                         FixedArrayBase backing_store) {
    1410        8241 :     return NumberOfElementsImpl(receiver, backing_store);
    1411             :   }
    1412             : 
    1413        8241 :   static uint32_t NumberOfElementsImpl(JSObject receiver,
    1414             :                                        FixedArrayBase backing_store) {
    1415        8241 :     NumberDictionary dict = NumberDictionary::cast(backing_store);
    1416        8241 :     return dict->NumberOfElements();
    1417             :   }
    1418             : 
    1419        8099 :   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
    1420             :                             uint32_t length,
    1421             :                             Handle<FixedArrayBase> backing_store) {
    1422             :     Handle<NumberDictionary> dict =
    1423        8099 :         Handle<NumberDictionary>::cast(backing_store);
    1424        8099 :     int capacity = dict->Capacity();
    1425        8099 :     uint32_t old_length = 0;
    1426       16198 :     CHECK(array->length()->ToArrayLength(&old_length));
    1427             :     {
    1428             :       DisallowHeapAllocation no_gc;
    1429             :       ReadOnlyRoots roots(isolate);
    1430        8099 :       if (length < old_length) {
    1431        3601 :         if (dict->requires_slow_elements()) {
    1432             :           // Find last non-deletable element in range of elements to be
    1433             :           // deleted and adjust range accordingly.
    1434       13725 :           for (int entry = 0; entry < capacity; entry++) {
    1435       13725 :             Object index = dict->KeyAt(entry);
    1436       13725 :             if (dict->IsKey(roots, index)) {
    1437        1656 :               uint32_t number = static_cast<uint32_t>(index->Number());
    1438        1656 :               if (length <= number && number < old_length) {
    1439        1512 :                 PropertyDetails details = dict->DetailsAt(entry);
    1440        1512 :                 if (!details.IsConfigurable()) length = number + 1;
    1441             :               }
    1442             :             }
    1443             :           }
    1444             :         }
    1445             : 
    1446        3601 :         if (length == 0) {
    1447             :           // Flush the backing store.
    1448        3303 :           array->initialize_elements();
    1449             :         } else {
    1450             :           // Remove elements that should be deleted.
    1451             :           int removed_entries = 0;
    1452        1489 :           for (int entry = 0; entry < capacity; entry++) {
    1453        1489 :             Object index = dict->KeyAt(entry);
    1454        1489 :             if (dict->IsKey(roots, index)) {
    1455         660 :               uint32_t number = static_cast<uint32_t>(index->Number());
    1456         660 :               if (length <= number && number < old_length) {
    1457         218 :                 dict->ClearEntry(isolate, entry);
    1458         218 :                 removed_entries++;
    1459             :               }
    1460             :             }
    1461             :           }
    1462             : 
    1463         298 :           if (removed_entries > 0) {
    1464             :             // Update the number of elements.
    1465         136 :             dict->ElementsRemoved(removed_entries);
    1466             :           }
    1467             :         }
    1468             :       }
    1469             :     }
    1470             : 
    1471        8099 :     Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length);
    1472        8099 :     array->set_length(*length_obj);
    1473        8099 :   }
    1474             : 
    1475           0 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
    1476             :                                uint32_t from_start, FixedArrayBase to,
    1477             :                                ElementsKind from_kind, uint32_t to_start,
    1478             :                                int packed_size, int copy_size) {
    1479           0 :     UNREACHABLE();
    1480             :   }
    1481             : 
    1482           0 :   static Handle<JSObject> SliceImpl(Handle<JSObject> receiver, uint32_t start,
    1483             :                                     uint32_t end) {
    1484             :     Isolate* isolate = receiver->GetIsolate();
    1485           0 :     uint32_t result_length = end < start ? 0u : end - start;
    1486             : 
    1487             :     // Result must also be a dictionary.
    1488             :     Handle<JSArray> result_array =
    1489           0 :         isolate->factory()->NewJSArray(0, HOLEY_ELEMENTS);
    1490           0 :     JSObject::NormalizeElements(result_array);
    1491           0 :     result_array->set_length(Smi::FromInt(result_length));
    1492             :     Handle<NumberDictionary> source_dict(
    1493           0 :         NumberDictionary::cast(receiver->elements()), isolate);
    1494           0 :     int entry_count = source_dict->Capacity();
    1495             :     ReadOnlyRoots roots(isolate);
    1496           0 :     for (int i = 0; i < entry_count; i++) {
    1497           0 :       Object key = source_dict->KeyAt(i);
    1498           0 :       if (!source_dict->ToKey(roots, i, &key)) continue;
    1499           0 :       uint64_t key_value = NumberToInt64(key);
    1500           0 :       if (key_value >= start && key_value < end) {
    1501             :         Handle<NumberDictionary> dest_dict(
    1502           0 :             NumberDictionary::cast(result_array->elements()), isolate);
    1503           0 :         Handle<Object> value(source_dict->ValueAt(i), isolate);
    1504           0 :         PropertyDetails details = source_dict->DetailsAt(i);
    1505             :         PropertyAttributes attr = details.attributes();
    1506             :         AddImpl(result_array, static_cast<uint32_t>(key_value) - start, value,
    1507           0 :                 attr, 0);
    1508             :       }
    1509             :     }
    1510             : 
    1511           0 :     return result_array;
    1512             :   }
    1513             : 
    1514        3950 :   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
    1515        7900 :     Handle<NumberDictionary> dict(NumberDictionary::cast(obj->elements()),
    1516        7900 :                                   obj->GetIsolate());
    1517        7900 :     dict = NumberDictionary::DeleteEntry(obj->GetIsolate(), dict, entry);
    1518        7900 :     obj->set_elements(*dict);
    1519        3950 :   }
    1520             : 
    1521        1172 :   static bool HasAccessorsImpl(JSObject holder, FixedArrayBase backing_store) {
    1522             :     DisallowHeapAllocation no_gc;
    1523        1172 :     NumberDictionary dict = NumberDictionary::cast(backing_store);
    1524        1172 :     if (!dict->requires_slow_elements()) return false;
    1525         972 :     int capacity = dict->Capacity();
    1526         972 :     ReadOnlyRoots roots = holder->GetReadOnlyRoots();
    1527        3627 :     for (int i = 0; i < capacity; i++) {
    1528        3024 :       Object key = dict->KeyAt(i);
    1529        4563 :       if (!dict->IsKey(roots, key)) continue;
    1530        1485 :       PropertyDetails details = dict->DetailsAt(i);
    1531        1485 :       if (details.kind() == kAccessor) return true;
    1532             :     }
    1533             :     return false;
    1534             :   }
    1535             : 
    1536      183841 :   static Object GetRaw(FixedArrayBase store, uint32_t entry) {
    1537      183841 :     NumberDictionary backing_store = NumberDictionary::cast(store);
    1538      183841 :     return backing_store->ValueAt(entry);
    1539             :   }
    1540             : 
    1541      183591 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
    1542             :                                 uint32_t entry) {
    1543      367182 :     return handle(GetRaw(backing_store, entry), isolate);
    1544             :   }
    1545             : 
    1546       22674 :   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
    1547             :                              Object value) {
    1548       22674 :     SetImpl(holder->elements(), entry, value);
    1549       22674 :   }
    1550             : 
    1551       22871 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    1552             :                              Object value) {
    1553       68613 :     NumberDictionary::cast(backing_store)->ValueAtPut(entry, value);
    1554       22871 :   }
    1555             : 
    1556       19199 :   static void ReconfigureImpl(Handle<JSObject> object,
    1557             :                               Handle<FixedArrayBase> store, uint32_t entry,
    1558             :                               Handle<Object> value,
    1559             :                               PropertyAttributes attributes) {
    1560       19199 :     NumberDictionary dictionary = NumberDictionary::cast(*store);
    1561       38389 :     if (attributes != NONE) object->RequireSlowElements(dictionary);
    1562       19199 :     dictionary->ValueAtPut(entry, *value);
    1563       19199 :     PropertyDetails details = dictionary->DetailsAt(entry);
    1564             :     details = PropertyDetails(kData, attributes, PropertyCellType::kNoCell,
    1565             :                               details.dictionary_index());
    1566             : 
    1567       19199 :     dictionary->DetailsAtPut(object->GetIsolate(), entry, details);
    1568       19199 :   }
    1569             : 
    1570     1048304 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
    1571             :                       Handle<Object> value, PropertyAttributes attributes,
    1572             :                       uint32_t new_capacity) {
    1573             :     PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
    1574             :     Handle<NumberDictionary> dictionary =
    1575     3690620 :         object->HasFastElements() || object->HasFastStringWrapperElements()
    1576             :             ? JSObject::NormalizeElements(object)
    1577     1845220 :             : handle(NumberDictionary::cast(object->elements()),
    1578     3144912 :                      object->GetIsolate());
    1579             :     Handle<NumberDictionary> new_dictionary = NumberDictionary::Add(
    1580     1048304 :         object->GetIsolate(), dictionary, index, value, details);
    1581     1048304 :     new_dictionary->UpdateMaxNumberKey(index, object);
    1582     1067448 :     if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
    1583     2091846 :     if (dictionary.is_identical_to(new_dictionary)) return;
    1584        9524 :     object->set_elements(*new_dictionary);
    1585             :   }
    1586             : 
    1587           0 :   static bool HasEntryImpl(Isolate* isolate, FixedArrayBase store,
    1588             :                            uint32_t entry) {
    1589             :     DisallowHeapAllocation no_gc;
    1590           0 :     NumberDictionary dict = NumberDictionary::cast(store);
    1591           0 :     Object index = dict->KeyAt(entry);
    1592           0 :     return !index->IsTheHole(isolate);
    1593             :   }
    1594             : 
    1595             :   static uint32_t GetIndexForEntryImpl(FixedArrayBase store, uint32_t entry) {
    1596             :     DisallowHeapAllocation no_gc;
    1597             :     NumberDictionary dict = NumberDictionary::cast(store);
    1598             :     uint32_t result = 0;
    1599             :     CHECK(dict->KeyAt(entry)->ToArrayIndex(&result));
    1600             :     return result;
    1601             :   }
    1602             : 
    1603    75314119 :   static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject holder,
    1604             :                                        FixedArrayBase store, uint32_t index,
    1605             :                                        PropertyFilter filter) {
    1606             :     DisallowHeapAllocation no_gc;
    1607    75314119 :     NumberDictionary dictionary = NumberDictionary::cast(store);
    1608    75314119 :     int entry = dictionary->FindEntry(isolate, index);
    1609    75314119 :     if (entry == NumberDictionary::kNotFound) return kMaxUInt32;
    1610      189248 :     if (filter != ALL_PROPERTIES) {
    1611         675 :       PropertyDetails details = dictionary->DetailsAt(entry);
    1612             :       PropertyAttributes attr = details.attributes();
    1613         675 :       if ((attr & filter) != 0) return kMaxUInt32;
    1614             :     }
    1615      189221 :     return static_cast<uint32_t>(entry);
    1616             :   }
    1617             : 
    1618             :   static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
    1619      187059 :     return GetDetailsImpl(holder->elements(), entry);
    1620             :   }
    1621             : 
    1622      190067 :   static PropertyDetails GetDetailsImpl(FixedArrayBase backing_store,
    1623             :                                         uint32_t entry) {
    1624      380134 :     return NumberDictionary::cast(backing_store)->DetailsAt(entry);
    1625             :   }
    1626             : 
    1627       17227 :   static uint32_t FilterKey(Handle<NumberDictionary> dictionary, int entry,
    1628             :                             Object raw_key, PropertyFilter filter) {
    1629             :     DCHECK(raw_key->IsNumber());
    1630             :     DCHECK_LE(raw_key->Number(), kMaxUInt32);
    1631       17227 :     PropertyDetails details = dictionary->DetailsAt(entry);
    1632             :     PropertyAttributes attr = details.attributes();
    1633       17227 :     if ((attr & filter) != 0) return kMaxUInt32;
    1634       16664 :     return static_cast<uint32_t>(raw_key->Number());
    1635             :   }
    1636             : 
    1637       21140 :   static uint32_t GetKeyForEntryImpl(Isolate* isolate,
    1638             :                                      Handle<NumberDictionary> dictionary,
    1639             :                                      int entry, PropertyFilter filter) {
    1640             :     DisallowHeapAllocation no_gc;
    1641       21140 :     Object raw_key = dictionary->KeyAt(entry);
    1642       21140 :     if (!dictionary->IsKey(ReadOnlyRoots(isolate), raw_key)) return kMaxUInt32;
    1643       10069 :     return FilterKey(dictionary, entry, raw_key, filter);
    1644             :   }
    1645             : 
    1646        4361 :   static void CollectElementIndicesImpl(Handle<JSObject> object,
    1647             :                                         Handle<FixedArrayBase> backing_store,
    1648       13083 :                                         KeyAccumulator* keys) {
    1649        4361 :     if (keys->filter() & SKIP_STRINGS) return;
    1650             :     Isolate* isolate = keys->isolate();
    1651             :     Handle<NumberDictionary> dictionary =
    1652        4361 :         Handle<NumberDictionary>::cast(backing_store);
    1653        4361 :     int capacity = dictionary->Capacity();
    1654             :     Handle<FixedArray> elements = isolate->factory()->NewFixedArray(
    1655        4361 :         GetMaxNumberOfEntries(*object, *backing_store));
    1656             :     int insertion_index = 0;
    1657             :     PropertyFilter filter = keys->filter();
    1658             :     ReadOnlyRoots roots(isolate);
    1659       20224 :     for (int i = 0; i < capacity; i++) {
    1660       15863 :       Object raw_key = dictionary->KeyAt(i);
    1661       24694 :       if (!dictionary->IsKey(roots, raw_key)) continue;
    1662        7158 :       uint32_t key = FilterKey(dictionary, i, raw_key, filter);
    1663        7158 :       if (key == kMaxUInt32) {
    1664         126 :         keys->AddShadowingKey(raw_key);
    1665         126 :         continue;
    1666             :       }
    1667        7032 :       elements->set(insertion_index, raw_key);
    1668        7032 :       insertion_index++;
    1669             :     }
    1670        4361 :     SortIndices(isolate, elements, insertion_index);
    1671       11393 :     for (int i = 0; i < insertion_index; i++) {
    1672        7032 :       keys->AddKey(elements->get(i));
    1673             :     }
    1674             :   }
    1675             : 
    1676        4184 :   static Handle<FixedArray> DirectCollectElementIndicesImpl(
    1677             :       Isolate* isolate, Handle<JSObject> object,
    1678             :       Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
    1679             :       PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
    1680             :       uint32_t insertion_index = 0) {
    1681        4184 :     if (filter & SKIP_STRINGS) return list;
    1682        4184 :     if (filter & ONLY_ALL_CAN_READ) return list;
    1683             : 
    1684             :     Handle<NumberDictionary> dictionary =
    1685        4184 :         Handle<NumberDictionary>::cast(backing_store);
    1686        4184 :     uint32_t capacity = dictionary->Capacity();
    1687       21140 :     for (uint32_t i = 0; i < capacity; i++) {
    1688       21140 :       uint32_t key = GetKeyForEntryImpl(isolate, dictionary, i, filter);
    1689       32648 :       if (key == kMaxUInt32) continue;
    1690        9632 :       Handle<Object> index = isolate->factory()->NewNumberFromUint(key);
    1691       19264 :       list->set(insertion_index, *index);
    1692        9632 :       insertion_index++;
    1693             :     }
    1694        4184 :     *nof_indices = insertion_index;
    1695        4184 :     return list;
    1696             :   }
    1697             : 
    1698           0 :   static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
    1699           0 :                                               KeyAccumulator* accumulator,
    1700             :                                               AddKeyConversion convert) {
    1701             :     Isolate* isolate = accumulator->isolate();
    1702             :     Handle<NumberDictionary> dictionary(
    1703           0 :         NumberDictionary::cast(receiver->elements()), isolate);
    1704           0 :     int capacity = dictionary->Capacity();
    1705             :     ReadOnlyRoots roots(isolate);
    1706           0 :     for (int i = 0; i < capacity; i++) {
    1707           0 :       Object k = dictionary->KeyAt(i);
    1708           0 :       if (!dictionary->IsKey(roots, k)) continue;
    1709           0 :       Object value = dictionary->ValueAt(i);
    1710             :       DCHECK(!value->IsTheHole(isolate));
    1711             :       DCHECK(!value->IsAccessorPair());
    1712             :       DCHECK(!value->IsAccessorInfo());
    1713           0 :       accumulator->AddKey(value, convert);
    1714             :     }
    1715           0 :   }
    1716             : 
    1717         225 :   static bool IncludesValueFastPath(Isolate* isolate, Handle<JSObject> receiver,
    1718             :                                     Handle<Object> value, uint32_t start_from,
    1719             :                                     uint32_t length, Maybe<bool>* result) {
    1720             :     DisallowHeapAllocation no_gc;
    1721         450 :     NumberDictionary dictionary = NumberDictionary::cast(receiver->elements());
    1722         225 :     int capacity = dictionary->Capacity();
    1723             :     Object the_hole = ReadOnlyRoots(isolate).the_hole_value();
    1724             :     Object undefined = ReadOnlyRoots(isolate).undefined_value();
    1725             : 
    1726             :     // Scan for accessor properties. If accessors are present, then elements
    1727             :     // must be accessed in order via the slow path.
    1728             :     bool found = false;
    1729         594 :     for (int i = 0; i < capacity; ++i) {
    1730         531 :       Object k = dictionary->KeyAt(i);
    1731         801 :       if (k == the_hole) continue;
    1732         531 :       if (k == undefined) continue;
    1733             : 
    1734             :       uint32_t index;
    1735         369 :       if (!k->ToArrayIndex(&index) || index < start_from || index >= length) {
    1736             :         continue;
    1737             :       }
    1738             : 
    1739         522 :       if (dictionary->DetailsAt(i).kind() == kAccessor) {
    1740             :         // Restart from beginning in slow path, otherwise we may observably
    1741             :         // access getters out of order
    1742         162 :         return false;
    1743          99 :       } else if (!found) {
    1744          99 :         Object element_k = dictionary->ValueAt(i);
    1745          99 :         if (value->SameValueZero(element_k)) found = true;
    1746             :       }
    1747             :     }
    1748             : 
    1749          63 :     *result = Just(found);
    1750          63 :     return true;
    1751             :   }
    1752             : 
    1753         279 :   static Maybe<bool> IncludesValueImpl(Isolate* isolate,
    1754             :                                        Handle<JSObject> receiver,
    1755             :                                        Handle<Object> value,
    1756             :                                        uint32_t start_from, uint32_t length) {
    1757             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver));
    1758         558 :     bool search_for_hole = value->IsUndefined(isolate);
    1759             : 
    1760         279 :     if (!search_for_hole) {
    1761         225 :       Maybe<bool> result = Nothing<bool>();
    1762         225 :       if (DictionaryElementsAccessor::IncludesValueFastPath(
    1763             :               isolate, receiver, value, start_from, length, &result)) {
    1764          63 :         return result;
    1765             :       }
    1766             :     }
    1767         216 :     ElementsKind original_elements_kind = receiver->GetElementsKind();
    1768             :     USE(original_elements_kind);
    1769             :     Handle<NumberDictionary> dictionary(
    1770         432 :         NumberDictionary::cast(receiver->elements()), isolate);
    1771             :     // Iterate through entire range, as accessing elements out of order is
    1772             :     // observable
    1773     9277830 :     for (uint32_t k = start_from; k < length; ++k) {
    1774             :       DCHECK_EQ(receiver->GetElementsKind(), original_elements_kind);
    1775     9277767 :       int entry = dictionary->FindEntry(isolate, k);
    1776     9277767 :       if (entry == NumberDictionary::kNotFound) {
    1777     9277461 :         if (search_for_hole) return Just(true);
    1778     9277506 :         continue;
    1779             :       }
    1780             : 
    1781         612 :       PropertyDetails details = GetDetailsImpl(*dictionary, entry);
    1782         306 :       switch (details.kind()) {
    1783             :         case kData: {
    1784         126 :           Object element_k = dictionary->ValueAt(entry);
    1785         126 :           if (value->SameValueZero(element_k)) return Just(true);
    1786          90 :           break;
    1787             :         }
    1788             :         case kAccessor: {
    1789             :           LookupIterator it(isolate, receiver, k,
    1790         180 :                             LookupIterator::OWN_SKIP_INTERCEPTOR);
    1791             :           DCHECK(it.IsFound());
    1792             :           DCHECK_EQ(it.state(), LookupIterator::ACCESSOR);
    1793             :           Handle<Object> element_k;
    1794             : 
    1795         459 :           ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k,
    1796             :                                            Object::GetPropertyWithAccessor(&it),
    1797             :                                            Nothing<bool>());
    1798             : 
    1799         171 :           if (value->SameValueZero(*element_k)) return Just(true);
    1800             : 
    1801             :           // Bailout to slow path if elements on prototype changed
    1802          81 :           if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) {
    1803             :             return IncludesValueSlowPath(isolate, receiver, value, k + 1,
    1804           0 :                                          length);
    1805             :           }
    1806             : 
    1807             :           // Continue if elements unchanged
    1808         225 :           if (*dictionary == receiver->elements()) continue;
    1809             : 
    1810             :           // Otherwise, bailout or update elements
    1811             : 
    1812             :           // If switched to initial elements, return true if searching for
    1813             :           // undefined, and false otherwise.
    1814          54 :           if (receiver->map()->GetInitialElements() == receiver->elements()) {
    1815             :             return Just(search_for_hole);
    1816             :           }
    1817             : 
    1818             :           // If switched to fast elements, continue with the correct accessor.
    1819          18 :           if (receiver->GetElementsKind() != DICTIONARY_ELEMENTS) {
    1820           0 :             ElementsAccessor* accessor = receiver->GetElementsAccessor();
    1821             :             return accessor->IncludesValue(isolate, receiver, value, k + 1,
    1822           0 :                                            length);
    1823             :           }
    1824             :           dictionary =
    1825          36 :               handle(NumberDictionary::cast(receiver->elements()), isolate);
    1826          18 :           break;
    1827             :         }
    1828             :       }
    1829             :     }
    1830             :     return Just(false);
    1831             :   }
    1832             : 
    1833         315 :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    1834             :                                          Handle<JSObject> receiver,
    1835             :                                          Handle<Object> value,
    1836             :                                          uint32_t start_from, uint32_t length) {
    1837             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver));
    1838             : 
    1839         315 :     ElementsKind original_elements_kind = receiver->GetElementsKind();
    1840             :     USE(original_elements_kind);
    1841             :     Handle<NumberDictionary> dictionary(
    1842         630 :         NumberDictionary::cast(receiver->elements()), isolate);
    1843             :     // Iterate through entire range, as accessing elements out of order is
    1844             :     // observable.
    1845     5868648 :     for (uint32_t k = start_from; k < length; ++k) {
    1846             :       DCHECK_EQ(receiver->GetElementsKind(), original_elements_kind);
    1847     5868495 :       int entry = dictionary->FindEntry(isolate, k);
    1848    11736288 :       if (entry == NumberDictionary::kNotFound) continue;
    1849             : 
    1850        1512 :       PropertyDetails details = GetDetailsImpl(*dictionary, entry);
    1851         756 :       switch (details.kind()) {
    1852             :         case kData: {
    1853         693 :           Object element_k = dictionary->ValueAt(entry);
    1854         693 :           if (value->StrictEquals(element_k)) {
    1855         153 :             return Just<int64_t>(k);
    1856             :           }
    1857         540 :           break;
    1858             :         }
    1859             :         case kAccessor: {
    1860             :           LookupIterator it(isolate, receiver, k,
    1861          63 :                             LookupIterator::OWN_SKIP_INTERCEPTOR);
    1862             :           DCHECK(it.IsFound());
    1863             :           DCHECK_EQ(it.state(), LookupIterator::ACCESSOR);
    1864             :           Handle<Object> element_k;
    1865             : 
    1866         135 :           ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k,
    1867             :                                            Object::GetPropertyWithAccessor(&it),
    1868             :                                            Nothing<int64_t>());
    1869             : 
    1870          54 :           if (value->StrictEquals(*element_k)) return Just<int64_t>(k);
    1871             : 
    1872             :           // Bailout to slow path if elements on prototype changed.
    1873          54 :           if (!JSObject::PrototypeHasNoElements(isolate, *receiver)) {
    1874             :             return IndexOfValueSlowPath(isolate, receiver, value, k + 1,
    1875           0 :                                         length);
    1876             :           }
    1877             : 
    1878             :           // Continue if elements unchanged.
    1879         162 :           if (*dictionary == receiver->elements()) continue;
    1880             : 
    1881             :           // Otherwise, bailout or update elements.
    1882           0 :           if (receiver->GetElementsKind() != DICTIONARY_ELEMENTS) {
    1883             :             // Otherwise, switch to slow path.
    1884             :             return IndexOfValueSlowPath(isolate, receiver, value, k + 1,
    1885           0 :                                         length);
    1886             :           }
    1887             :           dictionary =
    1888           0 :               handle(NumberDictionary::cast(receiver->elements()), isolate);
    1889           0 :           break;
    1890             :         }
    1891             :       }
    1892             :     }
    1893             :     return Just<int64_t>(-1);
    1894             :   }
    1895             : 
    1896             :   static void ValidateContents(JSObject holder, int length) {
    1897             :     DisallowHeapAllocation no_gc;
    1898             : #if DEBUG
    1899             :     DCHECK_EQ(holder->map()->elements_kind(), DICTIONARY_ELEMENTS);
    1900             :     if (!FLAG_enable_slow_asserts) return;
    1901             :     ReadOnlyRoots roots = holder->GetReadOnlyRoots();
    1902             :     NumberDictionary dictionary = NumberDictionary::cast(holder->elements());
    1903             :     // Validate the requires_slow_elements and max_number_key values.
    1904             :     int capacity = dictionary->Capacity();
    1905             :     bool requires_slow_elements = false;
    1906             :     int max_key = 0;
    1907             :     for (int i = 0; i < capacity; ++i) {
    1908             :       Object k;
    1909             :       if (!dictionary->ToKey(roots, i, &k)) continue;
    1910             :       DCHECK_LE(0.0, k->Number());
    1911             :       if (k->Number() > NumberDictionary::kRequiresSlowElementsLimit) {
    1912             :         requires_slow_elements = true;
    1913             :       } else {
    1914             :         max_key = Max(max_key, Smi::ToInt(k));
    1915             :       }
    1916             :     }
    1917             :     if (requires_slow_elements) {
    1918             :       DCHECK(dictionary->requires_slow_elements());
    1919             :     } else if (!dictionary->requires_slow_elements()) {
    1920             :       DCHECK_LE(max_key, dictionary->max_number_key());
    1921             :     }
    1922             : #endif
    1923             :   }
    1924             : };
    1925             : 
    1926             : 
    1927             : // Super class for all fast element arrays.
    1928             : template <typename Subclass, typename KindTraits>
    1929      350796 : class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
    1930             :  public:
    1931             :   explicit FastElementsAccessor(const char* name)
    1932      357498 :       : ElementsAccessorBase<Subclass, KindTraits>(name) {}
    1933             : 
    1934             :   typedef typename KindTraits::BackingStore BackingStore;
    1935             : 
    1936      293053 :   static Handle<NumberDictionary> NormalizeImpl(Handle<JSObject> object,
    1937             :                                                 Handle<FixedArrayBase> store) {
    1938             :     Isolate* isolate = object->GetIsolate();
    1939             :     ElementsKind kind = Subclass::kind();
    1940             : 
    1941             :     // Ensure that notifications fire if the array or object prototypes are
    1942             :     // normalizing.
    1943             :     if (IsSmiOrObjectElementsKind(kind) ||
    1944             :         kind == FAST_STRING_WRAPPER_ELEMENTS) {
    1945             :       isolate->UpdateNoElementsProtectorOnNormalizeElements(object);
    1946             :     }
    1947             : 
    1948      293053 :     int capacity = object->GetFastElementsUsage();
    1949             :     Handle<NumberDictionary> dictionary =
    1950      293053 :         NumberDictionary::New(isolate, capacity);
    1951             : 
    1952      293053 :     PropertyDetails details = PropertyDetails::Empty();
    1953             :     int j = 0;
    1954             :     int max_number_key = -1;
    1955    18358608 :     for (int i = 0; j < capacity; i++) {
    1956             :       if (IsHoleyElementsKind(kind)) {
    1957    33906150 :         if (BackingStore::cast(*store)->is_the_hole(isolate, i)) continue;
    1958             :       }
    1959             :       max_number_key = i;
    1960     4421242 :       Handle<Object> value = Subclass::GetImpl(isolate, *store, i);
    1961     2210621 :       dictionary =
    1962             :           NumberDictionary::Add(isolate, dictionary, i, value, details);
    1963     2210621 :       j++;
    1964             :     }
    1965             : 
    1966      293053 :     if (max_number_key > 0) {
    1967       26092 :       dictionary->UpdateMaxNumberKey(static_cast<uint32_t>(max_number_key),
    1968       78276 :                                      object);
    1969             :     }
    1970      293053 :     return dictionary;
    1971             :   }
    1972             : 
    1973       45000 :   static void DeleteAtEnd(Handle<JSObject> obj,
    1974             :                           Handle<BackingStore> backing_store, uint32_t entry) {
    1975       45000 :     uint32_t length = static_cast<uint32_t>(backing_store->length());
    1976             :     Isolate* isolate = obj->GetIsolate();
    1977      135027 :     for (; entry > 0; entry--) {
    1978      180018 :       if (!backing_store->is_the_hole(isolate, entry - 1)) break;
    1979             :     }
    1980       45000 :     if (entry == 0) {
    1981             :       FixedArray empty = ReadOnlyRoots(isolate).empty_fixed_array();
    1982             :       // Dynamically ask for the elements kind here since we manually redirect
    1983             :       // the operations for argument backing stores.
    1984          18 :       if (obj->GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
    1985           0 :         SloppyArgumentsElements::cast(obj->elements())->set_arguments(empty);
    1986             :       } else {
    1987          18 :         obj->set_elements(empty);
    1988             :       }
    1989       45000 :       return;
    1990             :     }
    1991             : 
    1992       89964 :     isolate->heap()->RightTrimFixedArray(*backing_store, length - entry);
    1993             :   }
    1994             : 
    1995       98694 :   static void DeleteCommon(Handle<JSObject> obj, uint32_t entry,
    1996             :                            Handle<FixedArrayBase> store) {
    1997             :     DCHECK(obj->HasSmiOrObjectElements() || obj->HasDoubleElements() ||
    1998             :            obj->HasFastArgumentsElements() ||
    1999             :            obj->HasFastStringWrapperElements());
    2000       98694 :     Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store);
    2001      288769 :     if (!obj->IsJSArray() &&
    2002             :         entry == static_cast<uint32_t>(store->length()) - 1) {
    2003       45000 :       DeleteAtEnd(obj, backing_store, entry);
    2004       45000 :       return;
    2005             :     }
    2006             : 
    2007         308 :     Isolate* isolate = obj->GetIsolate();
    2008      107022 :     backing_store->set_the_hole(isolate, entry);
    2009             : 
    2010             :     // TODO(verwaest): Move this out of elements.cc.
    2011             :     // If an old space backing store is larger than a certain size and
    2012             :     // has too few used values, normalize it.
    2013             :     const int kMinLengthForSparsenessCheck = 64;
    2014       53694 :     if (backing_store->length() < kMinLengthForSparsenessCheck) return;
    2015             :     // TODO(ulan): Check if it works with young large objects.
    2016       46122 :     if (ObjectInYoungGeneration(*backing_store)) return;
    2017         308 :     uint32_t length = 0;
    2018         616 :     if (obj->IsJSArray()) {
    2019         598 :       JSArray::cast(*obj)->length()->ToArrayLength(&length);
    2020             :     } else {
    2021           9 :       length = static_cast<uint32_t>(store->length());
    2022             :     }
    2023             : 
    2024             :     // To avoid doing the check on every delete, use a counter-based heuristic.
    2025             :     const int kLengthFraction = 16;
    2026             :     // The above constant must be large enough to ensure that we check for
    2027             :     // normalization frequently enough. At a minimum, it should be large
    2028             :     // enough to reliably hit the "window" of remaining elements count where
    2029             :     // normalization would be beneficial.
    2030             :     STATIC_ASSERT(kLengthFraction >=
    2031             :                   NumberDictionary::kEntrySize *
    2032             :                       NumberDictionary::kPreferFastElementsSizeFactor);
    2033             :     size_t current_counter = isolate->elements_deletion_counter();
    2034         308 :     if (current_counter < length / kLengthFraction) {
    2035         308 :       isolate->set_elements_deletion_counter(current_counter + 1);
    2036             :       return;
    2037             :     }
    2038             :     // Reset the counter whenever the full check is performed.
    2039             :     isolate->set_elements_deletion_counter(0);
    2040             : 
    2041           0 :     if (!obj->IsJSArray()) {
    2042             :       uint32_t i;
    2043           0 :       for (i = entry + 1; i < length; i++) {
    2044           0 :         if (!backing_store->is_the_hole(isolate, i)) break;
    2045             :       }
    2046           0 :       if (i == length) {
    2047           0 :         DeleteAtEnd(obj, backing_store, entry);
    2048           0 :         return;
    2049             :       }
    2050             :     }
    2051             :     int num_used = 0;
    2052           0 :     for (int i = 0; i < backing_store->length(); ++i) {
    2053           0 :       if (!backing_store->is_the_hole(isolate, i)) {
    2054           0 :         ++num_used;
    2055             :         // Bail out if a number dictionary wouldn't be able to save much space.
    2056           0 :         if (NumberDictionary::kPreferFastElementsSizeFactor *
    2057             :                 NumberDictionary::ComputeCapacity(num_used) *
    2058             :                 NumberDictionary::kEntrySize >
    2059             :             static_cast<uint32_t>(backing_store->length())) {
    2060             :           return;
    2061             :         }
    2062             :       }
    2063             :     }
    2064           0 :     JSObject::NormalizeElements(obj);
    2065             :   }
    2066             : 
    2067        9408 :   static void ReconfigureImpl(Handle<JSObject> object,
    2068             :                               Handle<FixedArrayBase> store, uint32_t entry,
    2069             :                               Handle<Object> value,
    2070             :                               PropertyAttributes attributes) {
    2071        9408 :     Handle<NumberDictionary> dictionary = JSObject::NormalizeElements(object);
    2072        9408 :     entry = dictionary->FindEntry(object->GetIsolate(), entry);
    2073        9408 :     DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, entry,
    2074        9408 :                                                 value, attributes);
    2075        9408 :   }
    2076             : 
    2077     5033453 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
    2078             :                       Handle<Object> value, PropertyAttributes attributes,
    2079             :                       uint32_t new_capacity) {
    2080             :     DCHECK_EQ(NONE, attributes);
    2081     5033453 :     ElementsKind from_kind = object->GetElementsKind();
    2082             :     ElementsKind to_kind = Subclass::kind();
    2083    20131219 :     if (IsDictionaryElementsKind(from_kind) ||
    2084             :         IsDoubleElementsKind(from_kind) != IsDoubleElementsKind(to_kind) ||
    2085    10064790 :         Subclass::GetCapacityImpl(*object, object->elements()) !=
    2086             :             new_capacity) {
    2087      283653 :       Subclass::GrowCapacityAndConvertImpl(object, new_capacity);
    2088             :     } else {
    2089     4749802 :       if (IsFastElementsKind(from_kind) && from_kind != to_kind) {
    2090       15274 :         JSObject::TransitionElementsKind(object, to_kind);
    2091             :       }
    2092     4749801 :       if (IsSmiOrObjectElementsKind(from_kind)) {
    2093             :         DCHECK(IsSmiOrObjectElementsKind(to_kind));
    2094     4664644 :         JSObject::EnsureWritableFastElements(object);
    2095             :       }
    2096             :     }
    2097     5033454 :     Subclass::SetImpl(object, index, *value);
    2098     5033454 :   }
    2099             : 
    2100       98694 :   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
    2101             :     ElementsKind kind = KindTraits::Kind;
    2102             :     if (IsFastPackedElementsKind(kind)) {
    2103         760 :       JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind));
    2104             :     }
    2105             :     if (IsSmiOrObjectElementsKind(KindTraits::Kind)) {
    2106       98328 :       JSObject::EnsureWritableFastElements(obj);
    2107             :     }
    2108      197388 :     DeleteCommon(obj, entry, handle(obj->elements(), obj->GetIsolate()));
    2109       98694 :   }
    2110             : 
    2111      368648 :   static bool HasEntryImpl(Isolate* isolate, FixedArrayBase backing_store,
    2112             :                            uint32_t entry) {
    2113      737296 :     return !BackingStore::cast(backing_store)->is_the_hole(isolate, entry);
    2114             :   }
    2115             : 
    2116          63 :   static uint32_t NumberOfElementsImpl(JSObject receiver,
    2117             :                                        FixedArrayBase backing_store) {
    2118        6489 :     uint32_t max_index = Subclass::GetMaxIndex(receiver, backing_store);
    2119             :     if (IsFastPackedElementsKind(Subclass::kind())) return max_index;
    2120             :     Isolate* isolate = receiver->GetIsolate();
    2121             :     uint32_t count = 0;
    2122      252548 :     for (uint32_t i = 0; i < max_index; i++) {
    2123      252485 :       if (Subclass::HasEntryImpl(isolate, backing_store, i)) count++;
    2124             :     }
    2125             :     return count;
    2126             :   }
    2127             : 
    2128         243 :   static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
    2129         243 :                                               KeyAccumulator* accumulator,
    2130             :                                               AddKeyConversion convert) {
    2131             :     Isolate* isolate = accumulator->isolate();
    2132         486 :     Handle<FixedArrayBase> elements(receiver->elements(), isolate);
    2133             :     uint32_t length = Subclass::GetMaxNumberOfEntries(*receiver, *elements);
    2134        1086 :     for (uint32_t i = 0; i < length; i++) {
    2135         843 :       if (IsFastPackedElementsKind(KindTraits::Kind) ||
    2136         843 :           HasEntryImpl(isolate, *elements, i)) {
    2137         711 :         accumulator->AddKey(Subclass::GetImpl(isolate, *elements, i), convert);
    2138             :       }
    2139             :     }
    2140         243 :   }
    2141             : 
    2142             :   static void ValidateContents(JSObject holder, int length) {
    2143             : #if DEBUG
    2144             :     Isolate* isolate = holder->GetIsolate();
    2145             :     Heap* heap = isolate->heap();
    2146             :     FixedArrayBase elements = holder->elements();
    2147             :     Map map = elements->map();
    2148             :     if (IsSmiOrObjectElementsKind(KindTraits::Kind)) {
    2149             :       DCHECK_NE(map, ReadOnlyRoots(heap).fixed_double_array_map());
    2150             :     } else if (IsDoubleElementsKind(KindTraits::Kind)) {
    2151             :       DCHECK_NE(map, ReadOnlyRoots(heap).fixed_cow_array_map());
    2152             :       if (map == ReadOnlyRoots(heap).fixed_array_map()) DCHECK_EQ(0, length);
    2153             :     } else {
    2154             :       UNREACHABLE();
    2155             :     }
    2156             :     if (length == 0) return;  // nothing to do!
    2157             : #if ENABLE_SLOW_DCHECKS
    2158             :     DisallowHeapAllocation no_gc;
    2159             :     BackingStore backing_store = BackingStore::cast(elements);
    2160             :     if (IsSmiElementsKind(KindTraits::Kind)) {
    2161             :       HandleScope scope(isolate);
    2162             :       for (int i = 0; i < length; i++) {
    2163             :         DCHECK(BackingStore::get(backing_store, i, isolate)->IsSmi() ||
    2164             :                (IsHoleyElementsKind(KindTraits::Kind) &&
    2165             :                 backing_store->is_the_hole(isolate, i)));
    2166             :       }
    2167             :     } else if (KindTraits::Kind == PACKED_ELEMENTS ||
    2168             :                KindTraits::Kind == PACKED_DOUBLE_ELEMENTS) {
    2169             :       for (int i = 0; i < length; i++) {
    2170             :         DCHECK(!backing_store->is_the_hole(isolate, i));
    2171             :       }
    2172             :     } else {
    2173             :       DCHECK(IsHoleyElementsKind(KindTraits::Kind));
    2174             :     }
    2175             : #endif
    2176             : #endif
    2177             :   }
    2178             : 
    2179             :   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
    2180       50719 :     return Subclass::RemoveElement(receiver, AT_END);
    2181             :   }
    2182             : 
    2183             :   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
    2184      183049 :     return Subclass::RemoveElement(receiver, AT_START);
    2185             :   }
    2186             : 
    2187     9373987 :   static uint32_t PushImpl(Handle<JSArray> receiver,
    2188             :                            Arguments* args, uint32_t push_size) {
    2189    18747992 :     Handle<FixedArrayBase> backing_store(receiver->elements(),
    2190     9374004 :                                          receiver->GetIsolate());
    2191             :     return Subclass::AddArguments(receiver, backing_store, args, push_size,
    2192     9373988 :                                   AT_END);
    2193             :   }
    2194             : 
    2195        5846 :   static uint32_t UnshiftImpl(Handle<JSArray> receiver,
    2196             :                               Arguments* args, uint32_t unshift_size) {
    2197       11692 :     Handle<FixedArrayBase> backing_store(receiver->elements(),
    2198        5846 :                                          receiver->GetIsolate());
    2199             :     return Subclass::AddArguments(receiver, backing_store, args, unshift_size,
    2200        5846 :                                   AT_START);
    2201             :   }
    2202             : 
    2203           0 :   static Handle<JSObject> SliceImpl(Handle<JSObject> receiver, uint32_t start,
    2204             :                                     uint32_t end) {
    2205             :     Isolate* isolate = receiver->GetIsolate();
    2206           0 :     Handle<FixedArrayBase> backing_store(receiver->elements(), isolate);
    2207           0 :     int result_len = end < start ? 0u : end - start;
    2208             :     Handle<JSArray> result_array = isolate->factory()->NewJSArray(
    2209           0 :         KindTraits::Kind, result_len, result_len);
    2210             :     DisallowHeapAllocation no_gc;
    2211           0 :     Subclass::CopyElementsImpl(isolate, *backing_store, start,
    2212           0 :                                result_array->elements(), KindTraits::Kind, 0,
    2213           0 :                                kPackedSizeNotKnown, result_len);
    2214           0 :     Subclass::TryTransitionResultArrayToPacked(result_array);
    2215           0 :     return result_array;
    2216             :   }
    2217             : 
    2218      183833 :   static void MoveElements(Isolate* isolate, Handle<JSArray> receiver,
    2219             :                            Handle<FixedArrayBase> backing_store, int dst_index,
    2220             :                            int src_index, int len, int hole_start,
    2221             :                            int hole_end) {
    2222      183833 :     Heap* heap = isolate->heap();
    2223      183833 :     Handle<BackingStore> dst_elms = Handle<BackingStore>::cast(backing_store);
    2224      365575 :     if (len > JSArray::kMaxCopyElements && dst_index == 0 &&
    2225             :         heap->CanMoveObjectStart(*dst_elms)) {
    2226             :       // Update all the copies of this backing_store handle.
    2227      181600 :       *dst_elms.location() =
    2228      363200 :           BackingStore::cast(heap->LeftTrimFixedArray(*dst_elms, src_index))
    2229             :               ->ptr();
    2230      363200 :       receiver->set_elements(*dst_elms);
    2231             :       // Adjust the hole offset as the array has been shrunk.
    2232      181600 :       hole_end -= src_index;
    2233             :       DCHECK_LE(hole_start, backing_store->length());
    2234             :       DCHECK_LE(hole_end, backing_store->length());
    2235        2233 :     } else if (len != 0) {
    2236             :       WriteBarrierMode mode = GetWriteBarrierMode(KindTraits::Kind);
    2237        2868 :       dst_elms->MoveElements(heap, dst_index, src_index, len, mode);
    2238             :     }
    2239      183833 :     if (hole_start != hole_end) {
    2240      363200 :       dst_elms->FillWithHoles(hole_start, hole_end);
    2241             :     }
    2242      183833 :   }
    2243             : 
    2244        6786 :   static Object FillImpl(Handle<JSObject> receiver, Handle<Object> obj_value,
    2245             :                          uint32_t start, uint32_t end) {
    2246             :     // Ensure indexes are within array bounds
    2247             :     DCHECK_LE(0, start);
    2248             :     DCHECK_LE(start, end);
    2249             : 
    2250             :     // Make sure COW arrays are copied.
    2251             :     if (IsSmiOrObjectElementsKind(Subclass::kind())) {
    2252        6633 :       JSObject::EnsureWritableFastElements(receiver);
    2253             :     }
    2254             : 
    2255             :     // Make sure we have enough space.
    2256             :     uint32_t capacity =
    2257       13572 :         Subclass::GetCapacityImpl(*receiver, receiver->elements());
    2258        6786 :     if (end > capacity) {
    2259           0 :       Subclass::GrowCapacityAndConvertImpl(receiver, end);
    2260           0 :       CHECK_EQ(Subclass::kind(), receiver->GetElementsKind());
    2261             :     }
    2262             :     DCHECK_LE(end, Subclass::GetCapacityImpl(*receiver, receiver->elements()));
    2263             : 
    2264     3771625 :     for (uint32_t index = start; index < end; ++index) {
    2265     3764839 :       Subclass::SetImpl(receiver, index, *obj_value);
    2266             :     }
    2267        6786 :     return *receiver;
    2268             :   }
    2269             : 
    2270       90535 :   static Maybe<bool> IncludesValueImpl(Isolate* isolate,
    2271             :                                        Handle<JSObject> receiver,
    2272             :                                        Handle<Object> search_value,
    2273             :                                        uint32_t start_from, uint32_t length) {
    2274             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver));
    2275             :     DisallowHeapAllocation no_gc;
    2276       90535 :     FixedArrayBase elements_base = receiver->elements();
    2277             :     Object the_hole = ReadOnlyRoots(isolate).the_hole_value();
    2278             :     Object undefined = ReadOnlyRoots(isolate).undefined_value();
    2279       90535 :     Object value = *search_value;
    2280             : 
    2281       90535 :     if (start_from >= length) return Just(false);
    2282             : 
    2283             :     // Elements beyond the capacity of the backing store treated as undefined.
    2284       90517 :     uint32_t elements_length = static_cast<uint32_t>(elements_base->length());
    2285       90517 :     if (value == undefined && elements_length < length) return Just(true);
    2286       90508 :     if (elements_length == 0) {
    2287             :       DCHECK_NE(value, undefined);
    2288             :       return Just(false);
    2289             :     }
    2290             : 
    2291       90490 :     length = std::min(elements_length, length);
    2292             : 
    2293       90490 :     if (!value->IsNumber()) {
    2294       90216 :       if (value == undefined) {
    2295             :         // Search for `undefined` or The Hole. Even in the case of
    2296             :         // PACKED_DOUBLE_ELEMENTS or PACKED_SMI_ELEMENTS, we might encounter The
    2297             :         // Hole here, since the {length} used here can be larger than
    2298             :         // JSArray::length.
    2299             :         if (IsSmiOrObjectElementsKind(Subclass::kind())) {
    2300         108 :           auto elements = FixedArray::cast(receiver->elements());
    2301             : 
    2302         234 :           for (uint32_t k = start_from; k < length; ++k) {
    2303         198 :             Object element_k = elements->get(k);
    2304             : 
    2305         198 :             if (element_k == the_hole || element_k == undefined) {
    2306             :               return Just(true);
    2307             :             }
    2308             :           }
    2309             :           return Just(false);
    2310             :         } else {
    2311             :           // Search for The Hole in HOLEY_DOUBLE_ELEMENTS or
    2312             :           // PACKED_DOUBLE_ELEMENTS.
    2313             :           DCHECK(IsDoubleElementsKind(Subclass::kind()));
    2314          36 :           auto elements = FixedDoubleArray::cast(receiver->elements());
    2315             : 
    2316          72 :           for (uint32_t k = start_from; k < length; ++k) {
    2317         108 :             if (elements->is_the_hole(k)) {
    2318             :               return Just(true);
    2319             :             }
    2320             :           }
    2321             :           return Just(false);
    2322             :         }
    2323             :       } else if (!IsObjectElementsKind(Subclass::kind())) {
    2324             :         // Search for non-number, non-Undefined value, with either
    2325             :         // PACKED_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS, HOLEY_SMI_ELEMENTS or
    2326             :         // HOLEY_DOUBLE_ELEMENTS. Guaranteed to return false, since these
    2327             :         // elements kinds can only contain Number values or undefined.
    2328             :         return Just(false);
    2329             :       } else {
    2330             :         // Search for non-number, non-Undefined value with either
    2331             :         // PACKED_ELEMENTS or HOLEY_ELEMENTS.
    2332             :         DCHECK(IsObjectElementsKind(Subclass::kind()));
    2333      180288 :         auto elements = FixedArray::cast(receiver->elements());
    2334             : 
    2335      450342 :         for (uint32_t k = start_from; k < length; ++k) {
    2336      360288 :           Object element_k = elements->get(k);
    2337      360288 :           if (element_k == the_hole) {
    2338             :             continue;
    2339             :           }
    2340             : 
    2341      270243 :           if (value->SameValueZero(element_k)) return Just(true);
    2342             :         }
    2343             :         return Just(false);
    2344             :       }
    2345             :     } else {
    2346         274 :       if (!value->IsNaN()) {
    2347         220 :         double search_value = value->Number();
    2348             :         if (IsDoubleElementsKind(Subclass::kind())) {
    2349             :           // Search for non-NaN Number in PACKED_DOUBLE_ELEMENTS or
    2350             :           // HOLEY_DOUBLE_ELEMENTS --- Skip TheHole, and trust UCOMISD or
    2351             :           // similar operation for result.
    2352          50 :           auto elements = FixedDoubleArray::cast(receiver->elements());
    2353             : 
    2354          47 :           for (uint32_t k = start_from; k < length; ++k) {
    2355          76 :             if (elements->is_the_hole(k)) {
    2356             :               continue;
    2357             :             }
    2358          29 :             if (elements->get_scalar(k) == search_value) return Just(true);
    2359             :           }
    2360             :           return Just(false);
    2361             :         } else {
    2362             :           // Search for non-NaN Number in PACKED_ELEMENTS, HOLEY_ELEMENTS,
    2363             :           // PACKED_SMI_ELEMENTS or HOLEY_SMI_ELEMENTS --- Skip non-Numbers,
    2364             :           // and trust UCOMISD or similar operation for result
    2365         390 :           auto elements = FixedArray::cast(receiver->elements());
    2366             : 
    2367         718 :           for (uint32_t k = start_from; k < length; ++k) {
    2368        1254 :             Object element_k = elements->get(k);
    2369         627 :             if (element_k->IsNumber() && element_k->Number() == search_value) {
    2370             :               return Just(true);
    2371             :             }
    2372             :           }
    2373             :           return Just(false);
    2374             :         }
    2375             :       } else {
    2376             :         // Search for NaN --- NaN cannot be represented with Smi elements, so
    2377             :         // abort if ElementsKind is PACKED_SMI_ELEMENTS or HOLEY_SMI_ELEMENTS
    2378             :         if (IsSmiElementsKind(Subclass::kind())) return Just(false);
    2379             : 
    2380             :         if (IsDoubleElementsKind(Subclass::kind())) {
    2381             :           // Search for NaN in PACKED_DOUBLE_ELEMENTS or
    2382             :           // HOLEY_DOUBLE_ELEMENTS --- Skip The Hole and trust
    2383             :           // std::isnan(elementK) for result
    2384           0 :           auto elements = FixedDoubleArray::cast(receiver->elements());
    2385             : 
    2386           0 :           for (uint32_t k = start_from; k < length; ++k) {
    2387           0 :             if (elements->is_the_hole(k)) {
    2388             :               continue;
    2389             :             }
    2390           0 :             if (std::isnan(elements->get_scalar(k))) return Just(true);
    2391             :           }
    2392             :           return Just(false);
    2393             :         } else {
    2394             :           // Search for NaN in PACKED_ELEMENTS, HOLEY_ELEMENTS,
    2395             :           // PACKED_SMI_ELEMENTS or HOLEY_SMI_ELEMENTS. Return true if
    2396             :           // elementK->IsHeapNumber() && std::isnan(elementK->Number())
    2397             :           DCHECK(IsSmiOrObjectElementsKind(Subclass::kind()));
    2398         108 :           auto elements = FixedArray::cast(receiver->elements());
    2399             : 
    2400         342 :           for (uint32_t k = start_from; k < length; ++k) {
    2401         918 :             if (elements->get(k)->IsNaN()) return Just(true);
    2402             :           }
    2403             :           return Just(false);
    2404             :         }
    2405             :       }
    2406             :     }
    2407             :   }
    2408             : 
    2409         116 :   static Handle<FixedArray> CreateListFromArrayLikeImpl(Isolate* isolate,
    2410             :                                                         Handle<JSObject> object,
    2411             :                                                         uint32_t length) {
    2412         116 :     Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
    2413         232 :     Handle<FixedArrayBase> elements(object->elements(), isolate);
    2414       90176 :     for (uint32_t i = 0; i < length; i++) {
    2415       90060 :       if (!Subclass::HasElementImpl(isolate, *object, i, *elements)) continue;
    2416             :       Handle<Object> value;
    2417        5012 :       value = Subclass::GetImpl(isolate, *elements, i);
    2418       10024 :       if (value->IsName()) {
    2419           0 :         value = isolate->factory()->InternalizeName(Handle<Name>::cast(value));
    2420             :       }
    2421       10024 :       result->set(i, *value);
    2422             :     }
    2423         116 :     return result;
    2424             :   }
    2425             : 
    2426      233768 :   static Handle<Object> RemoveElement(Handle<JSArray> receiver,
    2427             :                                       Where remove_position) {
    2428             :     Isolate* isolate = receiver->GetIsolate();
    2429             :     ElementsKind kind = KindTraits::Kind;
    2430             :     if (IsSmiOrObjectElementsKind(kind)) {
    2431             :       HandleScope scope(isolate);
    2432      201872 :       JSObject::EnsureWritableFastElements(receiver);
    2433             :     }
    2434      467536 :     Handle<FixedArrayBase> backing_store(receiver->elements(), isolate);
    2435      233768 :     uint32_t length = static_cast<uint32_t>(Smi::ToInt(receiver->length()));
    2436             :     DCHECK_GT(length, 0);
    2437      233768 :     int new_length = length - 1;
    2438      233768 :     int remove_index = remove_position == AT_START ? 0 : new_length;
    2439             :     Handle<Object> result =
    2440      467536 :         Subclass::GetImpl(isolate, *backing_store, remove_index);
    2441      233768 :     if (remove_position == AT_START) {
    2442      183049 :       Subclass::MoveElements(isolate, receiver, backing_store, 0, 1, new_length,
    2443             :                              0, 0);
    2444             :     }
    2445      233768 :     Subclass::SetLengthImpl(isolate, receiver, new_length, backing_store);
    2446             : 
    2447       18476 :     if (IsHoleyElementsKind(kind) && result->IsTheHole(isolate)) {
    2448        8742 :       return isolate->factory()->undefined_value();
    2449             :     }
    2450      225026 :     return result;
    2451             :   }
    2452             : 
    2453     9379823 :   static uint32_t AddArguments(Handle<JSArray> receiver,
    2454             :                                Handle<FixedArrayBase> backing_store,
    2455             :                                Arguments* args, uint32_t add_size,
    2456             :                                Where add_position) {
    2457     9379808 :     uint32_t length = Smi::ToInt(receiver->length());
    2458             :     DCHECK_LT(0, add_size);
    2459     9379909 :     uint32_t elms_len = backing_store->length();
    2460             :     // Check we do not overflow the new_length.
    2461             :     DCHECK(add_size <= static_cast<uint32_t>(Smi::kMaxValue - length));
    2462     9379909 :     uint32_t new_length = length + add_size;
    2463             : 
    2464     9379909 :     if (new_length > elms_len) {
    2465             :       // New backing storage is needed.
    2466             :       uint32_t capacity = JSObject::NewElementsCapacity(new_length);
    2467             :       // If we add arguments to the start we have to shift the existing objects.
    2468      144711 :       int copy_dst_index = add_position == AT_START ? add_size : 0;
    2469             :       // Copy over all objects to a new backing_store.
    2470      144711 :       backing_store = Subclass::ConvertElementsWithCapacity(
    2471             :           receiver, backing_store, KindTraits::Kind, capacity, 0,
    2472      289419 :           copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole);
    2473      144710 :       receiver->set_elements(*backing_store);
    2474     9235198 :     } else if (add_position == AT_START) {
    2475             :       // If the backing store has enough capacity and we add elements to the
    2476             :       // start we have to shift the existing objects.
    2477             :       Isolate* isolate = receiver->GetIsolate();
    2478         784 :       Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0,
    2479         784 :                              length, 0, 0);
    2480             :     }
    2481             : 
    2482     9379860 :     int insertion_index = add_position == AT_START ? 0 : length;
    2483             :     // Copy the arguments to the start.
    2484     9379860 :     Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index);
    2485             :     // Set the length.
    2486    28139720 :     receiver->set_length(Smi::FromInt(new_length));
    2487     9379905 :     return new_length;
    2488             :   }
    2489             : 
    2490     9379855 :   static void CopyArguments(Arguments* args, Handle<FixedArrayBase> dst_store,
    2491             :                             uint32_t copy_size, uint32_t src_index,
    2492             :                             uint32_t dst_index) {
    2493             :     // Add the provided values.
    2494             :     DisallowHeapAllocation no_gc;
    2495     9379863 :     FixedArrayBase raw_backing_store = *dst_store;
    2496             :     WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc);
    2497    18877348 :     for (uint32_t i = 0; i < copy_size; i++) {
    2498    18994854 :       Object argument = (*args)[src_index + i];
    2499             :       DCHECK(!argument->IsTheHole());
    2500     9497427 :       Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode);
    2501             :     }
    2502     9379921 :   }
    2503             : };
    2504             : 
    2505             : template <typename Subclass, typename KindTraits>
    2506      233864 : class FastSmiOrObjectElementsAccessor
    2507             :     : public FastElementsAccessor<Subclass, KindTraits> {
    2508             :  public:
    2509             :   explicit FastSmiOrObjectElementsAccessor(const char* name)
    2510      238332 :       : FastElementsAccessor<Subclass, KindTraits>(name) {}
    2511             : 
    2512     8335325 :   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
    2513             :                              Object value) {
    2514     8335325 :     SetImpl(holder->elements(), entry, value);
    2515     8335328 :   }
    2516             : 
    2517     8355470 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2518             :                              Object value) {
    2519    16710941 :     FixedArray::cast(backing_store)->set(entry, value);
    2520     8355471 :   }
    2521             : 
    2522     9497360 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2523             :                              Object value, WriteBarrierMode mode) {
    2524    18994737 :     FixedArray::cast(backing_store)->set(entry, value, mode);
    2525     9497373 :   }
    2526             : 
    2527             :   static Object GetRaw(FixedArray backing_store, uint32_t entry) {
    2528             :     uint32_t index = Subclass::GetIndexForEntryImpl(backing_store, entry);
    2529        1161 :     return backing_store->get(index);
    2530             :   }
    2531             : 
    2532             :   // NOTE: this method violates the handlified function signature convention:
    2533             :   // raw pointer parameters in the function that allocates.
    2534             :   // See ElementsAccessor::CopyElements() for details.
    2535             :   // This method could actually allocate if copying from double elements to
    2536             :   // object elements.
    2537     1441971 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
    2538             :                                uint32_t from_start, FixedArrayBase to,
    2539             :                                ElementsKind from_kind, uint32_t to_start,
    2540             :                                int packed_size, int copy_size) {
    2541             :     DisallowHeapAllocation no_gc;
    2542             :     ElementsKind to_kind = KindTraits::Kind;
    2543     1441971 :     switch (from_kind) {
    2544             :       case PACKED_SMI_ELEMENTS:
    2545             :       case HOLEY_SMI_ELEMENTS:
    2546             :       case PACKED_ELEMENTS:
    2547             :       case HOLEY_ELEMENTS:
    2548     1440121 :         CopyObjectToObjectElements(isolate, from, from_kind, from_start, to,
    2549     1440121 :                                    to_kind, to_start, copy_size);
    2550             :         break;
    2551             :       case PACKED_DOUBLE_ELEMENTS:
    2552             :       case HOLEY_DOUBLE_ELEMENTS: {
    2553             :         AllowHeapAllocation allow_allocation;
    2554             :         DCHECK(IsObjectElementsKind(to_kind));
    2555        1375 :         CopyDoubleToObjectElements(isolate, from, from_start, to, to_start,
    2556             :                                    copy_size);
    2557             :         break;
    2558             :       }
    2559             :       case DICTIONARY_ELEMENTS:
    2560         470 :         CopyDictionaryToObjectElements(isolate, from, from_start, to, to_kind,
    2561             :                                        to_start, copy_size);
    2562             :         break;
    2563             :       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    2564             :       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    2565             :       case FAST_STRING_WRAPPER_ELEMENTS:
    2566             :       case SLOW_STRING_WRAPPER_ELEMENTS:
    2567             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
    2568             :         TYPED_ARRAYS(TYPED_ARRAY_CASE)
    2569             : #undef TYPED_ARRAY_CASE
    2570             :       // This function is currently only used for JSArrays with non-zero
    2571             :       // length.
    2572           0 :       UNREACHABLE();
    2573             :       break;
    2574             :       case NO_ELEMENTS:
    2575             :         break;  // Nothing to do.
    2576             :     }
    2577     1441977 :   }
    2578             : 
    2579         450 :   static Maybe<bool> CollectValuesOrEntriesImpl(
    2580             :       Isolate* isolate, Handle<JSObject> object,
    2581             :       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
    2582             :       PropertyFilter filter) {
    2583             :     int count = 0;
    2584         450 :     if (get_entries) {
    2585             :       // Collecting entries needs to allocate, so this code must be handlified.
    2586         270 :       Handle<FixedArray> elements(FixedArray::cast(object->elements()),
    2587         270 :                                   isolate);
    2588         135 :       uint32_t length = elements->length();
    2589       82314 :       for (uint32_t index = 0; index < length; ++index) {
    2590      164313 :         if (!Subclass::HasEntryImpl(isolate, *elements, index)) continue;
    2591         315 :         Handle<Object> value = Subclass::GetImpl(isolate, *elements, index);
    2592         315 :         value = MakeEntryPair(isolate, index, value);
    2593         630 :         values_or_entries->set(count++, *value);
    2594             :       }
    2595             :     } else {
    2596             :       // No allocations here, so we can avoid handlification overhead.
    2597             :       DisallowHeapAllocation no_gc;
    2598         630 :       FixedArray elements = FixedArray::cast(object->elements());
    2599         315 :       uint32_t length = elements->length();
    2600       32382 :       for (uint32_t index = 0; index < length; ++index) {
    2601       63621 :         if (!Subclass::HasEntryImpl(isolate, elements, index)) continue;
    2602        1143 :         Object value = GetRaw(elements, index);
    2603        2286 :         values_or_entries->set(count++, value);
    2604             :       }
    2605             :     }
    2606         450 :     *nof_items = count;
    2607         450 :     return Just(true);
    2608             :   }
    2609             : 
    2610         375 :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    2611             :                                          Handle<JSObject> receiver,
    2612             :                                          Handle<Object> search_value,
    2613             :                                          uint32_t start_from, uint32_t length) {
    2614             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver));
    2615             :     DisallowHeapAllocation no_gc;
    2616         375 :     FixedArrayBase elements_base = receiver->elements();
    2617         375 :     Object value = *search_value;
    2618             : 
    2619         375 :     if (start_from >= length) return Just<int64_t>(-1);
    2620             : 
    2621         750 :     length = std::min(static_cast<uint32_t>(elements_base->length()), length);
    2622             : 
    2623             :     // Only FAST_{,HOLEY_}ELEMENTS can store non-numbers.
    2624          69 :     if (!value->IsNumber() && !IsObjectElementsKind(Subclass::kind())) {
    2625             :       return Just<int64_t>(-1);
    2626             :     }
    2627             :     // NaN can never be found by strict equality.
    2628         375 :     if (value->IsNaN()) return Just<int64_t>(-1);
    2629             : 
    2630             :     // k can be greater than receiver->length() below, but it is bounded by
    2631             :     // elements_base->length() so we never read out of bounds. This means that
    2632             :     // elements->get(k) can return the hole, for which the StrictEquals will
    2633             :     // always fail.
    2634         642 :     FixedArray elements = FixedArray::cast(receiver->elements());
    2635         874 :     for (uint32_t k = start_from; k < length; ++k) {
    2636        2028 :       if (value->StrictEquals(elements->get(k))) return Just<int64_t>(k);
    2637             :     }
    2638             :     return Just<int64_t>(-1);
    2639             :   }
    2640             : };
    2641             : 
    2642      116932 : class FastPackedSmiElementsAccessor
    2643             :     : public FastSmiOrObjectElementsAccessor<
    2644             :           FastPackedSmiElementsAccessor,
    2645             :           ElementsKindTraits<PACKED_SMI_ELEMENTS>> {
    2646             :  public:
    2647             :   explicit FastPackedSmiElementsAccessor(const char* name)
    2648             :       : FastSmiOrObjectElementsAccessor<
    2649             :             FastPackedSmiElementsAccessor,
    2650       59583 :             ElementsKindTraits<PACKED_SMI_ELEMENTS>>(name) {}
    2651             : };
    2652             : 
    2653      116932 : class FastHoleySmiElementsAccessor
    2654             :     : public FastSmiOrObjectElementsAccessor<
    2655             :           FastHoleySmiElementsAccessor,
    2656             :           ElementsKindTraits<HOLEY_SMI_ELEMENTS>> {
    2657             :  public:
    2658             :   explicit FastHoleySmiElementsAccessor(const char* name)
    2659             :       : FastSmiOrObjectElementsAccessor<FastHoleySmiElementsAccessor,
    2660             :                                         ElementsKindTraits<HOLEY_SMI_ELEMENTS>>(
    2661       59583 :             name) {}
    2662             : };
    2663             : 
    2664      116932 : class FastPackedObjectElementsAccessor
    2665             :     : public FastSmiOrObjectElementsAccessor<
    2666             :           FastPackedObjectElementsAccessor,
    2667             :           ElementsKindTraits<PACKED_ELEMENTS>> {
    2668             :  public:
    2669             :   explicit FastPackedObjectElementsAccessor(const char* name)
    2670             :       : FastSmiOrObjectElementsAccessor<FastPackedObjectElementsAccessor,
    2671             :                                         ElementsKindTraits<PACKED_ELEMENTS>>(
    2672       59583 :             name) {}
    2673             : };
    2674             : 
    2675      116932 : class FastHoleyObjectElementsAccessor
    2676             :     : public FastSmiOrObjectElementsAccessor<
    2677             :           FastHoleyObjectElementsAccessor, ElementsKindTraits<HOLEY_ELEMENTS>> {
    2678             :  public:
    2679             :   explicit FastHoleyObjectElementsAccessor(const char* name)
    2680             :       : FastSmiOrObjectElementsAccessor<FastHoleyObjectElementsAccessor,
    2681             :                                         ElementsKindTraits<HOLEY_ELEMENTS>>(
    2682       59583 :             name) {}
    2683             : };
    2684             : 
    2685             : template <typename Subclass, typename KindTraits>
    2686      116932 : class FastDoubleElementsAccessor
    2687             :     : public FastElementsAccessor<Subclass, KindTraits> {
    2688             :  public:
    2689             :   explicit FastDoubleElementsAccessor(const char* name)
    2690      119166 :       : FastElementsAccessor<Subclass, KindTraits>(name) {}
    2691             : 
    2692     1307471 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
    2693             :                                 uint32_t entry) {
    2694             :     return FixedDoubleArray::get(FixedDoubleArray::cast(backing_store), entry,
    2695     2614942 :                                  isolate);
    2696             :   }
    2697             : 
    2698      636805 :   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
    2699             :                              Object value) {
    2700      636805 :     SetImpl(holder->elements(), entry, value);
    2701      636805 :   }
    2702             : 
    2703      636805 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2704             :                              Object value) {
    2705     1273610 :     FixedDoubleArray::cast(backing_store)->set(entry, value->Number());
    2706      636805 :   }
    2707             : 
    2708          64 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2709             :                              Object value, WriteBarrierMode mode) {
    2710         128 :     FixedDoubleArray::cast(backing_store)->set(entry, value->Number());
    2711          64 :   }
    2712             : 
    2713      214104 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
    2714             :                                uint32_t from_start, FixedArrayBase to,
    2715             :                                ElementsKind from_kind, uint32_t to_start,
    2716             :                                int packed_size, int copy_size) {
    2717             :     DisallowHeapAllocation no_allocation;
    2718      214104 :     switch (from_kind) {
    2719             :       case PACKED_SMI_ELEMENTS:
    2720      208345 :         CopyPackedSmiToDoubleElements(from, from_start, to, to_start,
    2721             :                                       packed_size, copy_size);
    2722      208345 :         break;
    2723             :       case HOLEY_SMI_ELEMENTS:
    2724        1512 :         CopySmiToDoubleElements(from, from_start, to, to_start, copy_size);
    2725        1512 :         break;
    2726             :       case PACKED_DOUBLE_ELEMENTS:
    2727             :       case HOLEY_DOUBLE_ELEMENTS:
    2728         932 :         CopyDoubleToDoubleElements(from, from_start, to, to_start, copy_size);
    2729         932 :         break;
    2730             :       case PACKED_ELEMENTS:
    2731             :       case HOLEY_ELEMENTS:
    2732        3306 :         CopyObjectToDoubleElements(from, from_start, to, to_start, copy_size);
    2733        3306 :         break;
    2734             :       case DICTIONARY_ELEMENTS:
    2735           9 :         CopyDictionaryToDoubleElements(isolate, from, from_start, to, to_start,
    2736             :                                        copy_size);
    2737           9 :         break;
    2738             :       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    2739             :       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
    2740             :       case FAST_STRING_WRAPPER_ELEMENTS:
    2741             :       case SLOW_STRING_WRAPPER_ELEMENTS:
    2742             :       case NO_ELEMENTS:
    2743             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype) case TYPE##_ELEMENTS:
    2744             :         TYPED_ARRAYS(TYPED_ARRAY_CASE)
    2745             : #undef TYPED_ARRAY_CASE
    2746             :       // This function is currently only used for JSArrays with non-zero
    2747             :       // length.
    2748           0 :       UNREACHABLE();
    2749             :       break;
    2750             :     }
    2751      214104 :   }
    2752             : 
    2753          54 :   static Maybe<bool> CollectValuesOrEntriesImpl(
    2754             :       Isolate* isolate, Handle<JSObject> object,
    2755             :       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
    2756             :       PropertyFilter filter) {
    2757             :     Handle<FixedDoubleArray> elements(
    2758         108 :         FixedDoubleArray::cast(object->elements()), isolate);
    2759             :     int count = 0;
    2760          54 :     uint32_t length = elements->length();
    2761         162 :     for (uint32_t index = 0; index < length; ++index) {
    2762         216 :       if (!Subclass::HasEntryImpl(isolate, *elements, index)) continue;
    2763         108 :       Handle<Object> value = Subclass::GetImpl(isolate, *elements, index);
    2764         108 :       if (get_entries) {
    2765          72 :         value = MakeEntryPair(isolate, index, value);
    2766             :       }
    2767         216 :       values_or_entries->set(count++, *value);
    2768             :     }
    2769          54 :     *nof_items = count;
    2770          54 :     return Just(true);
    2771             :   }
    2772             : 
    2773          25 :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    2774             :                                          Handle<JSObject> receiver,
    2775             :                                          Handle<Object> search_value,
    2776             :                                          uint32_t start_from, uint32_t length) {
    2777             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver));
    2778             :     DisallowHeapAllocation no_gc;
    2779          25 :     FixedArrayBase elements_base = receiver->elements();
    2780          25 :     Object value = *search_value;
    2781             : 
    2782          50 :     length = std::min(static_cast<uint32_t>(elements_base->length()), length);
    2783             : 
    2784          25 :     if (start_from >= length) return Just<int64_t>(-1);
    2785             : 
    2786          16 :     if (!value->IsNumber()) {
    2787             :       return Just<int64_t>(-1);
    2788             :     }
    2789          16 :     if (value->IsNaN()) {
    2790             :       return Just<int64_t>(-1);
    2791             :     }
    2792          16 :     double numeric_search_value = value->Number();
    2793          32 :     FixedDoubleArray elements = FixedDoubleArray::cast(receiver->elements());
    2794             : 
    2795           4 :     for (uint32_t k = start_from; k < length; ++k) {
    2796          40 :       if (elements->is_the_hole(k)) {
    2797             :         continue;
    2798             :       }
    2799          20 :       if (elements->get_scalar(k) == numeric_search_value) {
    2800          16 :         return Just<int64_t>(k);
    2801             :       }
    2802             :     }
    2803             :     return Just<int64_t>(-1);
    2804             :   }
    2805             : };
    2806             : 
    2807      116932 : class FastPackedDoubleElementsAccessor
    2808             :     : public FastDoubleElementsAccessor<
    2809             :           FastPackedDoubleElementsAccessor,
    2810             :           ElementsKindTraits<PACKED_DOUBLE_ELEMENTS>> {
    2811             :  public:
    2812             :   explicit FastPackedDoubleElementsAccessor(const char* name)
    2813             :       : FastDoubleElementsAccessor<FastPackedDoubleElementsAccessor,
    2814             :                                    ElementsKindTraits<PACKED_DOUBLE_ELEMENTS>>(
    2815       59583 :             name) {}
    2816             : };
    2817             : 
    2818      116932 : class FastHoleyDoubleElementsAccessor
    2819             :     : public FastDoubleElementsAccessor<
    2820             :           FastHoleyDoubleElementsAccessor,
    2821             :           ElementsKindTraits<HOLEY_DOUBLE_ELEMENTS>> {
    2822             :  public:
    2823             :   explicit FastHoleyDoubleElementsAccessor(const char* name)
    2824             :       : FastDoubleElementsAccessor<FastHoleyDoubleElementsAccessor,
    2825             :                                    ElementsKindTraits<HOLEY_DOUBLE_ELEMENTS>>(
    2826       59583 :             name) {}
    2827             : };
    2828             : 
    2829             : 
    2830             : // Super class for all external element arrays.
    2831             : template <ElementsKind Kind, typename ctype>
    2832     1286252 : class TypedElementsAccessor
    2833             :     : public ElementsAccessorBase<TypedElementsAccessor<Kind, ctype>,
    2834             :                                   ElementsKindTraits<Kind>> {
    2835             :  public:
    2836             :   explicit TypedElementsAccessor(const char* name)
    2837             :       : ElementsAccessorBase<AccessorClass,
    2838      655413 :                              ElementsKindTraits<Kind> >(name) {}
    2839             : 
    2840             :   typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
    2841             :   typedef TypedElementsAccessor<Kind, ctype> AccessorClass;
    2842             : 
    2843      699969 :   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
    2844             :                              Object value) {
    2845      699969 :     SetImpl(holder->elements(), entry, value);
    2846      699969 :   }
    2847             : 
    2848      699969 :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2849             :                              Object value) {
    2850      699969 :     BackingStore::cast(backing_store)->SetValue(entry, value);
    2851      699969 :   }
    2852             : 
    2853             :   static inline void SetImpl(FixedArrayBase backing_store, uint32_t entry,
    2854             :                              Object value, WriteBarrierMode mode) {
    2855             :     BackingStore::cast(backing_store)->SetValue(entry, value);
    2856             :   }
    2857             : 
    2858      401341 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase backing_store,
    2859             :                                 uint32_t entry) {
    2860      802682 :     return BackingStore::get(isolate, BackingStore::cast(backing_store), entry);
    2861             :   }
    2862             : 
    2863             :   static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
    2864             :     return PropertyDetails(kData, DONT_DELETE, PropertyCellType::kNoCell);
    2865             :   }
    2866             : 
    2867             :   static PropertyDetails GetDetailsImpl(FixedArrayBase backing_store,
    2868             :                                         uint32_t entry) {
    2869             :     return PropertyDetails(kData, DONT_DELETE, PropertyCellType::kNoCell);
    2870             :   }
    2871             : 
    2872             :   static bool HasElementImpl(Isolate* isolate, JSObject holder, uint32_t index,
    2873             :                              FixedArrayBase backing_store,
    2874             :                              PropertyFilter filter) {
    2875       66438 :     return index < AccessorClass::GetCapacityImpl(holder, backing_store);
    2876             :   }
    2877             : 
    2878             :   static bool HasAccessorsImpl(JSObject holder, FixedArrayBase backing_store) {
    2879             :     return false;
    2880             :   }
    2881             : 
    2882           0 :   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
    2883             :                             uint32_t length,
    2884             :                             Handle<FixedArrayBase> backing_store) {
    2885             :     // External arrays do not support changing their length.
    2886           0 :     UNREACHABLE();
    2887             :   }
    2888             : 
    2889           0 :   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
    2890           0 :     UNREACHABLE();
    2891             :   }
    2892             : 
    2893             :   static uint32_t GetIndexForEntryImpl(FixedArrayBase backing_store,
    2894             :                                        uint32_t entry) {
    2895             :     return entry;
    2896             :   }
    2897             : 
    2898             :   static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject holder,
    2899             :                                        FixedArrayBase backing_store,
    2900             :                                        uint32_t index, PropertyFilter filter) {
    2901     1822355 :     return index < AccessorClass::GetCapacityImpl(holder, backing_store)
    2902             :                ? index
    2903     1822355 :                : kMaxUInt32;
    2904             :   }
    2905             : 
    2906     1911752 :   static bool WasDetached(JSObject holder) {
    2907     1911752 :     JSArrayBufferView view = JSArrayBufferView::cast(holder);
    2908     1911752 :     return view->WasDetached();
    2909             :   }
    2910             : 
    2911     1906379 :   static uint32_t GetCapacityImpl(JSObject holder,
    2912             :                                   FixedArrayBase backing_store) {
    2913     1906379 :     if (WasDetached(holder)) return 0;
    2914     1905105 :     return backing_store->length();
    2915             :   }
    2916             : 
    2917             :   static uint32_t NumberOfElementsImpl(JSObject receiver,
    2918             :                                        FixedArrayBase backing_store) {
    2919           0 :     return AccessorClass::GetCapacityImpl(receiver, backing_store);
    2920             :   }
    2921             : 
    2922           0 :   static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
    2923             :                                               KeyAccumulator* accumulator,
    2924             :                                               AddKeyConversion convert) {
    2925             :     Isolate* isolate = receiver->GetIsolate();
    2926           0 :     Handle<FixedArrayBase> elements(receiver->elements(), isolate);
    2927           0 :     uint32_t length = AccessorClass::GetCapacityImpl(*receiver, *elements);
    2928           0 :     for (uint32_t i = 0; i < length; i++) {
    2929           0 :       Handle<Object> value = AccessorClass::GetImpl(isolate, *elements, i);
    2930           0 :       accumulator->AddKey(value, convert);
    2931             :     }
    2932           0 :   }
    2933             : 
    2934           0 :   static Maybe<bool> CollectValuesOrEntriesImpl(
    2935             :       Isolate* isolate, Handle<JSObject> object,
    2936             :       Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items,
    2937             :       PropertyFilter filter) {
    2938             :     int count = 0;
    2939           0 :     if ((filter & ONLY_CONFIGURABLE) == 0) {
    2940           0 :       Handle<FixedArrayBase> elements(object->elements(), isolate);
    2941           0 :       uint32_t length = AccessorClass::GetCapacityImpl(*object, *elements);
    2942           0 :       for (uint32_t index = 0; index < length; ++index) {
    2943             :         Handle<Object> value =
    2944           0 :             AccessorClass::GetImpl(isolate, *elements, index);
    2945           0 :         if (get_entries) {
    2946           0 :           value = MakeEntryPair(isolate, index, value);
    2947             :         }
    2948           0 :         values_or_entries->set(count++, *value);
    2949             :       }
    2950             :     }
    2951           0 :     *nof_items = count;
    2952           0 :     return Just(true);
    2953             :   }
    2954             : 
    2955        3779 :   static Object FillImpl(Handle<JSObject> receiver, Handle<Object> obj_value,
    2956             :                          uint32_t start, uint32_t end) {
    2957        3779 :     Handle<JSTypedArray> array = Handle<JSTypedArray>::cast(receiver);
    2958             :     DCHECK(!array->WasDetached());
    2959             :     DCHECK(obj_value->IsNumeric());
    2960             : 
    2961        3779 :     ctype value = BackingStore::FromHandle(obj_value);
    2962             : 
    2963             :     // Ensure indexes are within array bounds
    2964             :     CHECK_LE(0, start);
    2965        3779 :     CHECK_LE(start, end);
    2966        3779 :     CHECK_LE(end, array->length_value());
    2967             : 
    2968             :     DisallowHeapAllocation no_gc;
    2969        7558 :     BackingStore elements = BackingStore::cast(receiver->elements());
    2970             :     ctype* data = static_cast<ctype*>(elements->DataPtr());
    2971        3779 :     std::fill(data + start, data + end, value);
    2972        3779 :     return *array;
    2973             :   }
    2974             : 
    2975        3033 :   static Maybe<bool> IncludesValueImpl(Isolate* isolate,
    2976             :                                        Handle<JSObject> receiver,
    2977             :                                        Handle<Object> value,
    2978             :                                        uint32_t start_from, uint32_t length) {
    2979             :     DisallowHeapAllocation no_gc;
    2980             : 
    2981             :     // TODO(caitp): return Just(false) here when implementing strict throwing on
    2982             :     // detached views.
    2983        3033 :     if (WasDetached(*receiver)) {
    2984          54 :       return Just(value->IsUndefined(isolate) && length > start_from);
    2985             :     }
    2986             : 
    2987        6030 :     BackingStore elements = BackingStore::cast(receiver->elements());
    2988        6102 :     if (value->IsUndefined(isolate) &&
    2989             :         length > static_cast<uint32_t>(elements->length())) {
    2990             :       return Just(true);
    2991             :     }
    2992             :     ctype typed_search_value;
    2993             :     // Prototype has no elements, and not searching for the hole --- limit
    2994             :     // search to backing store length.
    2995        3015 :     if (static_cast<uint32_t>(elements->length()) < length) {
    2996           9 :       length = elements->length();
    2997             :     }
    2998             : 
    2999             :     if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
    3000         576 :       if (!value->IsBigInt()) return Just(false);
    3001             :       bool lossless;
    3002         144 :       typed_search_value = BackingStore::FromHandle(value, &lossless);
    3003         144 :       if (!lossless) return Just(false);
    3004             :     } else {
    3005        5454 :       if (!value->IsNumber()) return Just(false);
    3006        2727 :       double search_value = value->Number();
    3007        2727 :       if (!std::isfinite(search_value)) {
    3008             :         // Integral types cannot represent +Inf or NaN.
    3009             :         if (Kind < FLOAT32_ELEMENTS || Kind > FLOAT64_ELEMENTS) {
    3010             :           return Just(false);
    3011             :         }
    3012         144 :         if (std::isnan(search_value)) {
    3013          36 :           for (uint32_t k = start_from; k < length; ++k) {
    3014         108 :             double element_k = elements->get_scalar(k);
    3015          72 :             if (std::isnan(element_k)) return Just(true);
    3016             :           }
    3017             :           return Just(false);
    3018             :         }
    3019        2583 :       } else if (search_value < std::numeric_limits<ctype>::lowest() ||
    3020             :                  search_value > std::numeric_limits<ctype>::max()) {
    3021             :         // Return false if value can't be represented in this space.
    3022             :         return Just(false);
    3023             :       }
    3024        2223 :       typed_search_value = static_cast<ctype>(search_value);
    3025        2565 :       if (static_cast<double>(typed_search_value) != search_value) {
    3026             :         return Just(false);  // Loss of precision.
    3027             :       }
    3028             :     }
    3029             : 
    3030        1719 :     for (uint32_t k = start_from; k < length; ++k) {
    3031        3483 :       ctype element_k = elements->get_scalar(k);
    3032        3483 :       if (element_k == typed_search_value) return Just(true);
    3033             :     }
    3034             :     return Just(false);
    3035             :   }
    3036             : 
    3037        2340 :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    3038             :                                          Handle<JSObject> receiver,
    3039             :                                          Handle<Object> value,
    3040             :                                          uint32_t start_from, uint32_t length) {
    3041             :     DisallowHeapAllocation no_gc;
    3042             : 
    3043        2340 :     if (WasDetached(*receiver)) return Just<int64_t>(-1);
    3044             : 
    3045        4662 :     BackingStore elements = BackingStore::cast(receiver->elements());
    3046             :     ctype typed_search_value;
    3047             : 
    3048             :     if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
    3049         576 :       if (!value->IsBigInt()) return Just<int64_t>(-1);
    3050             :       bool lossless;
    3051         144 :       typed_search_value = BackingStore::FromHandle(value, &lossless);
    3052         144 :       if (!lossless) return Just<int64_t>(-1);
    3053             :     } else {
    3054        4086 :       if (!value->IsNumber()) return Just<int64_t>(-1);
    3055        2034 :       double search_value = value->Number();
    3056        2034 :       if (!std::isfinite(search_value)) {
    3057             :         // Integral types cannot represent +Inf or NaN.
    3058             :         if (Kind < FLOAT32_ELEMENTS || Kind > FLOAT64_ELEMENTS) {
    3059             :           return Just<int64_t>(-1);
    3060             :         }
    3061         108 :         if (std::isnan(search_value)) {
    3062             :           return Just<int64_t>(-1);
    3063             :         }
    3064        1737 :       } else if (search_value < std::numeric_limits<ctype>::lowest() ||
    3065             :                  search_value > std::numeric_limits<ctype>::max()) {
    3066             :         // Return false if value can't be represented in this ElementsKind.
    3067             :         return Just<int64_t>(-1);
    3068             :       }
    3069        1476 :       typed_search_value = static_cast<ctype>(search_value);
    3070        1683 :       if (static_cast<double>(typed_search_value) != search_value) {
    3071             :         return Just<int64_t>(-1);  // Loss of precision.
    3072             :       }
    3073             :     }
    3074             : 
    3075             :     // Prototype has no elements, and not searching for the hole --- limit
    3076             :     // search to backing store length.
    3077        1755 :     if (static_cast<uint32_t>(elements->length()) < length) {
    3078           0 :       length = elements->length();
    3079             :     }
    3080             : 
    3081        2439 :     for (uint32_t k = start_from; k < length; ++k) {
    3082        3780 :       ctype element_k = elements->get_scalar(k);
    3083        3780 :       if (element_k == typed_search_value) return Just<int64_t>(k);
    3084             :     }
    3085             :     return Just<int64_t>(-1);
    3086             :   }
    3087             : 
    3088        1107 :   static Maybe<int64_t> LastIndexOfValueImpl(Handle<JSObject> receiver,
    3089             :                                              Handle<Object> value,
    3090             :                                              uint32_t start_from) {
    3091             :     DisallowHeapAllocation no_gc;
    3092             :     DCHECK(!WasDetached(*receiver));
    3093             : 
    3094        2214 :     BackingStore elements = BackingStore::cast(receiver->elements());
    3095             :     ctype typed_search_value;
    3096             : 
    3097             :     if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
    3098         576 :       if (!value->IsBigInt()) return Just<int64_t>(-1);
    3099             :       bool lossless;
    3100         144 :       typed_search_value = BackingStore::FromHandle(value, &lossless);
    3101         144 :       if (!lossless) return Just<int64_t>(-1);
    3102             :     } else {
    3103        1638 :       if (!value->IsNumber()) return Just<int64_t>(-1);
    3104         810 :       double search_value = value->Number();
    3105         810 :       if (!std::isfinite(search_value)) {
    3106             :         if (std::is_integral<ctype>::value) {
    3107             :           // Integral types cannot represent +Inf or NaN.
    3108             :           return Just<int64_t>(-1);
    3109          54 :         } else if (std::isnan(search_value)) {
    3110             :           // Strict Equality Comparison of NaN is always false.
    3111             :           return Just<int64_t>(-1);
    3112             :         }
    3113         567 :       } else if (search_value < std::numeric_limits<ctype>::lowest() ||
    3114             :                  search_value > std::numeric_limits<ctype>::max()) {
    3115             :         // Return -1 if value can't be represented in this ElementsKind.
    3116             :         return Just<int64_t>(-1);
    3117             :       }
    3118         522 :       typed_search_value = static_cast<ctype>(search_value);
    3119         603 :       if (static_cast<double>(typed_search_value) != search_value) {
    3120             :         return Just<int64_t>(-1);  // Loss of precision.
    3121             :       }
    3122             :     }
    3123             : 
    3124             :     DCHECK_LT(start_from, elements->length());
    3125             : 
    3126             :     uint32_t k = start_from;
    3127         891 :     do {
    3128        1566 :       ctype element_k = elements->get_scalar(k);
    3129        1566 :       if (element_k == typed_search_value) return Just<int64_t>(k);
    3130             :     } while (k-- != 0);
    3131             :     return Just<int64_t>(-1);
    3132             :   }
    3133             : 
    3134         234 :   static void ReverseImpl(JSObject receiver) {
    3135             :     DisallowHeapAllocation no_gc;
    3136             :     DCHECK(!WasDetached(receiver));
    3137             : 
    3138         468 :     BackingStore elements = BackingStore::cast(receiver->elements());
    3139             : 
    3140         234 :     uint32_t len = elements->length();
    3141         468 :     if (len == 0) return;
    3142             : 
    3143             :     ctype* data = static_cast<ctype*>(elements->DataPtr());
    3144         234 :     std::reverse(data, data + len);
    3145             :   }
    3146             : 
    3147         595 :   static Handle<FixedArray> CreateListFromArrayLikeImpl(Isolate* isolate,
    3148             :                                                         Handle<JSObject> object,
    3149             :                                                         uint32_t length) {
    3150             :     DCHECK(!WasDetached(*object));
    3151             :     DCHECK(object->IsJSTypedArray());
    3152         595 :     Handle<FixedArray> result = isolate->factory()->NewFixedArray(length);
    3153        1190 :     Handle<BackingStore> elements(BackingStore::cast(object->elements()),
    3154        1190 :                                   isolate);
    3155       12075 :     for (uint32_t i = 0; i < length; i++) {
    3156       11480 :       Handle<Object> value = AccessorClass::GetImpl(isolate, *elements, i);
    3157       22960 :       result->set(i, *value);
    3158             :     }
    3159         595 :     return result;
    3160             :   }
    3161             : 
    3162        2034 :   static void CopyTypedArrayElementsSliceImpl(JSTypedArray source,
    3163             :                                               JSTypedArray destination,
    3164             :                                               size_t start, size_t end) {
    3165             :     DisallowHeapAllocation no_gc;
    3166             :     DCHECK_EQ(destination->GetElementsKind(), AccessorClass::kind());
    3167        2034 :     CHECK(!source->WasDetached());
    3168        2034 :     CHECK(!destination->WasDetached());
    3169             :     DCHECK_LE(start, end);
    3170             :     DCHECK_LE(end, source->length_value());
    3171             : 
    3172        2034 :     size_t count = end - start;
    3173             :     DCHECK_LE(count, destination->length_value());
    3174             : 
    3175             :     FixedTypedArrayBase src_elements =
    3176        4068 :         FixedTypedArrayBase::cast(source->elements());
    3177        4068 :     BackingStore dest_elements = BackingStore::cast(destination->elements());
    3178             : 
    3179        2034 :     size_t element_size = source->element_size();
    3180             :     uint8_t* source_data =
    3181        2034 :         static_cast<uint8_t*>(src_elements->DataPtr()) + start * element_size;
    3182             : 
    3183             :     // Fast path for the same type result array
    3184        2034 :     if (source->type() == destination->type()) {
    3185             :       uint8_t* dest_data = static_cast<uint8_t*>(dest_elements->DataPtr());
    3186             : 
    3187             :       // The spec defines the copy-step iteratively, which means that we
    3188             :       // cannot use memcpy if the buffer is shared.
    3189          90 :       uint8_t* end_ptr = source_data + count * element_size;
    3190         999 :       while (source_data < end_ptr) {
    3191         819 :         *dest_data++ = *source_data++;
    3192             :       }
    3193        2034 :       return;
    3194             :     }
    3195             : 
    3196        1944 :     switch (source->GetElementsKind()) {
    3197             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)                           \
    3198             :   case TYPE##_ELEMENTS:                                                     \
    3199             :     CopyBetweenBackingStores<Type##ArrayTraits>(source_data, dest_elements, \
    3200             :                                                 count, 0);                  \
    3201             :     break;
    3202         216 :       TYPED_ARRAYS(TYPED_ARRAY_CASE)
    3203             : #undef TYPED_ARRAY_CASE
    3204             :       default:
    3205           0 :         UNREACHABLE();
    3206             :         break;
    3207             :     }
    3208             :   }
    3209             : 
    3210             :   static bool HasSimpleRepresentation(InstanceType type) {
    3211             :     return !(type == FIXED_FLOAT32_ARRAY_TYPE ||
    3212             :              type == FIXED_FLOAT64_ARRAY_TYPE ||
    3213        2947 :              type == FIXED_UINT8_CLAMPED_ARRAY_TYPE);
    3214             :   }
    3215             : 
    3216             :   template <typename SourceTraits>
    3217        2223 :   static void CopyBetweenBackingStores(void* source_data_ptr, BackingStore dest,
    3218             :                                        size_t length, uint32_t offset) {
    3219             :     DisallowHeapAllocation no_gc;
    3220       18072 :     for (uint32_t i = 0; i < length; i++) {
    3221             :       // We use scalar accessors to avoid boxing/unboxing, so there are no
    3222             :       // allocations.
    3223             :       typename SourceTraits::ElementType elem =
    3224             :           FixedTypedArray<SourceTraits>::get_scalar_from_data_ptr(
    3225       15849 :               source_data_ptr, i);
    3226       19701 :       dest->set(offset + i, dest->from(elem));
    3227             :     }
    3228        2223 :   }
    3229             : 
    3230        1604 :   static void CopyElementsFromTypedArray(JSTypedArray source,
    3231             :                                          JSTypedArray destination,
    3232             :                                          size_t length, uint32_t offset) {
    3233             :     // The source is a typed array, so we know we don't need to do ToNumber
    3234             :     // side-effects, as the source elements will always be a number.
    3235             :     DisallowHeapAllocation no_gc;
    3236             : 
    3237        1604 :     CHECK(!source->WasDetached());
    3238        1604 :     CHECK(!destination->WasDetached());
    3239             : 
    3240             :     FixedTypedArrayBase source_elements =
    3241        3208 :         FixedTypedArrayBase::cast(source->elements());
    3242             :     BackingStore destination_elements =
    3243        3208 :         BackingStore::cast(destination->elements());
    3244             : 
    3245             :     DCHECK_LE(offset, destination->length_value());
    3246             :     DCHECK_LE(length, destination->length_value() - offset);
    3247             :     DCHECK(source->length()->IsSmi());
    3248             :     DCHECK_LE(length, source->length_value());
    3249             : 
    3250             :     InstanceType source_type = source_elements->map()->instance_type();
    3251             :     InstanceType destination_type =
    3252             :         destination_elements->map()->instance_type();
    3253             : 
    3254             :     bool same_type = source_type == destination_type;
    3255        1604 :     bool same_size = source->element_size() == destination->element_size();
    3256             :     bool both_are_simple = HasSimpleRepresentation(source_type) &&
    3257        2947 :                            HasSimpleRepresentation(destination_type);
    3258             : 
    3259             :     uint8_t* source_data = static_cast<uint8_t*>(source_elements->DataPtr());
    3260             :     uint8_t* dest_data = static_cast<uint8_t*>(destination_elements->DataPtr());
    3261             :     size_t source_byte_length = source->byte_length();
    3262             :     size_t dest_byte_length = destination->byte_length();
    3263             : 
    3264             :     // We can simply copy the backing store if the types are the same, or if
    3265             :     // we are converting e.g. Uint8 <-> Int8, as the binary representation
    3266             :     // will be the same. This is not the case for floats or clamped Uint8,
    3267             :     // which have special conversion operations.
    3268        1604 :     if (same_type || (same_size && both_are_simple)) {
    3269         542 :       size_t element_size = source->element_size();
    3270         542 :       std::memmove(dest_data + offset * element_size, source_data,
    3271         542 :                    length * element_size);
    3272             :     } else {
    3273             :       std::unique_ptr<uint8_t[]> cloned_source_elements;
    3274             : 
    3275             :       // If the typedarrays are overlapped, clone the source.
    3276        2061 :       if (dest_data + dest_byte_length > source_data &&
    3277         999 :           source_data + source_byte_length > dest_data) {
    3278         288 :         cloned_source_elements.reset(new uint8_t[source_byte_length]);
    3279             :         std::memcpy(cloned_source_elements.get(), source_data,
    3280             :                     source_byte_length);
    3281             :         source_data = cloned_source_elements.get();
    3282             :       }
    3283             : 
    3284        1062 :       switch (source->GetElementsKind()) {
    3285             : #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype)           \
    3286             :   case TYPE##_ELEMENTS:                                     \
    3287             :     CopyBetweenBackingStores<Type##ArrayTraits>(            \
    3288             :         source_data, destination_elements, length, offset); \
    3289             :     break;
    3290         108 :         TYPED_ARRAYS(TYPED_ARRAY_CASE)
    3291             :         default:
    3292           0 :           UNREACHABLE();
    3293             :           break;
    3294             :       }
    3295             : #undef TYPED_ARRAY_CASE
    3296             :     }
    3297        1604 :   }
    3298             : 
    3299       29784 :   static bool HoleyPrototypeLookupRequired(Isolate* isolate, Context context,
    3300             :                                            JSArray source) {
    3301             :     DisallowHeapAllocation no_gc;
    3302       29784 :     DisallowJavascriptExecution no_js(isolate);
    3303             : 
    3304             : #ifdef V8_ENABLE_FORCE_SLOW_PATH
    3305             :     if (isolate->force_slow_path()) return true;
    3306             : #endif
    3307             : 
    3308       29784 :     Object source_proto = source->map()->prototype();
    3309             : 
    3310             :     // Null prototypes are OK - we don't need to do prototype chain lookups on
    3311             :     // them.
    3312       29784 :     if (source_proto->IsNull(isolate)) return false;
    3313       29784 :     if (source_proto->IsJSProxy()) return true;
    3314       29622 :     if (!context->native_context()->is_initial_array_prototype(
    3315       29622 :             JSObject::cast(source_proto))) {
    3316             :       return true;
    3317             :     }
    3318             : 
    3319       29451 :     return !isolate->IsNoElementsProtectorIntact(context);
    3320             :   }
    3321             : 
    3322       29784 :   static bool TryCopyElementsFastNumber(Context context, JSArray source,
    3323             :                                         JSTypedArray destination, size_t length,
    3324             :                                         uint32_t offset) {
    3325             :     if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) return false;
    3326             :     Isolate* isolate = source->GetIsolate();
    3327             :     DisallowHeapAllocation no_gc;
    3328       29784 :     DisallowJavascriptExecution no_js(isolate);
    3329             : 
    3330       29784 :     CHECK(!destination->WasDetached());
    3331             : 
    3332             :     size_t current_length;
    3333             :     DCHECK(source->length()->IsNumber() &&
    3334             :            TryNumberToSize(source->length(), &current_length) &&
    3335             :            length <= current_length);
    3336             :     USE(current_length);
    3337             : 
    3338             :     size_t dest_length = destination->length_value();
    3339             :     DCHECK(length + offset <= dest_length);
    3340             :     USE(dest_length);
    3341             : 
    3342       29784 :     ElementsKind kind = source->GetElementsKind();
    3343       59568 :     BackingStore dest = BackingStore::cast(destination->elements());
    3344             : 
    3345             :     // When we find the hole, we normally have to look up the element on the
    3346             :     // prototype chain, which is not handled here and we return false instead.
    3347             :     // When the array has the original array prototype, and that prototype has
    3348             :     // not been changed in a way that would affect lookups, we can just convert
    3349             :     // the hole into undefined.
    3350       29784 :     if (HoleyPrototypeLookupRequired(isolate, context, source)) return false;
    3351             : 
    3352       27449 :     Object undefined = ReadOnlyRoots(isolate).undefined_value();
    3353             : 
    3354             :     // Fastpath for packed Smi kind.
    3355       27449 :     if (kind == PACKED_SMI_ELEMENTS) {
    3356       36890 :       FixedArray source_store = FixedArray::cast(source->elements());
    3357             : 
    3358      781995 :       for (uint32_t i = 0; i < length; i++) {
    3359     1527100 :         Object elem = source_store->get(i);
    3360             :         DCHECK(elem->IsSmi());
    3361      763550 :         int int_value = Smi::ToInt(elem);
    3362      763550 :         dest->set(offset + i, dest->from(int_value));
    3363             :       }
    3364             :       return true;
    3365        9004 :     } else if (kind == HOLEY_SMI_ELEMENTS) {
    3366        6528 :       FixedArray source_store = FixedArray::cast(source->elements());
    3367     1511111 :       for (uint32_t i = 0; i < length; i++) {
    3368     1507847 :         if (source_store->is_the_hole(isolate, i)) {
    3369       14669 :           dest->SetValue(offset + i, undefined);
    3370             :         } else {
    3371     1493178 :           Object elem = source_store->get(i);
    3372             :           DCHECK(elem->IsSmi());
    3373     1493178 :           int int_value = Smi::ToInt(elem);
    3374     1493178 :           dest->set(offset + i, dest->from(int_value));
    3375             :         }
    3376             :       }
    3377             :       return true;
    3378        5740 :     } else if (kind == PACKED_DOUBLE_ELEMENTS) {
    3379             :       // Fastpath for packed double kind. We avoid boxing and then immediately
    3380             :       // unboxing the double here by using get_scalar.
    3381             :       FixedDoubleArray source_store =
    3382        4346 :           FixedDoubleArray::cast(source->elements());
    3383             : 
    3384       18182 :       for (uint32_t i = 0; i < length; i++) {
    3385             :         // Use the from_double conversion for this specific TypedArray type,
    3386             :         // rather than relying on C++ to convert elem.
    3387       16009 :         double elem = source_store->get_scalar(i);
    3388       16009 :         dest->set(offset + i, dest->from(elem));
    3389             :       }
    3390             :       return true;
    3391        3567 :     } else if (kind == HOLEY_DOUBLE_ELEMENTS) {
    3392             :       FixedDoubleArray source_store =
    3393         242 :           FixedDoubleArray::cast(source->elements());
    3394      100379 :       for (uint32_t i = 0; i < length; i++) {
    3395      200516 :         if (source_store->is_the_hole(i)) {
    3396          81 :           dest->SetValue(offset + i, undefined);
    3397             :         } else {
    3398             :           double elem = source_store->get_scalar(i);
    3399      100177 :           dest->set(offset + i, dest->from(elem));
    3400             :         }
    3401             :       }
    3402             :       return true;
    3403             :     }
    3404       29784 :     return false;
    3405             :   }
    3406             : 
    3407        8058 :   static Object CopyElementsHandleSlow(Handle<Object> source,
    3408             :                                        Handle<JSTypedArray> destination,
    3409             :                                        size_t length, uint32_t offset) {
    3410             :     Isolate* isolate = destination->GetIsolate();
    3411             :     Handle<BackingStore> destination_elements(
    3412       16116 :         BackingStore::cast(destination->elements()), isolate);
    3413     1955001 :     for (uint32_t i = 0; i < length; i++) {
    3414     1947528 :       LookupIterator it(isolate, source, i);
    3415             :       Handle<Object> elem;
    3416     3895056 :       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
    3417             :                                          Object::GetProperty(&it));
    3418             :       if (Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS) {
    3419        2664 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
    3420             :                                            BigInt::FromObject(isolate, elem));
    3421             :       } else {
    3422     3892968 :         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, elem,
    3423             :                                            Object::ToNumber(isolate, elem));
    3424             :       }
    3425             : 
    3426     1946952 :       if (V8_UNLIKELY(destination->WasDetached())) {
    3427             :         const char* op = "set";
    3428             :         const MessageTemplate message = MessageTemplate::kDetachedOperation;
    3429             :         Handle<String> operation =
    3430           9 :             isolate->factory()->NewStringFromAsciiChecked(op);
    3431          18 :         THROW_NEW_ERROR_RETURN_FAILURE(isolate,
    3432             :                                        NewTypeError(message, operation));
    3433             :       }
    3434             :       // The spec says we store the length, then get each element, so we don't
    3435             :       // need to check changes to length.
    3436     3893886 :       destination_elements->SetValue(offset + i, *elem);
    3437             :     }
    3438        7473 :     return *isolate->factory()->undefined_value();
    3439             :   }
    3440             : 
    3441             :   // This doesn't guarantee that the destination array will be completely
    3442             :   // filled. The caller must do this by passing a source with equal length, if
    3443             :   // that is required.
    3444       30411 :   static Object CopyElementsHandleImpl(Handle<Object> source,
    3445             :                                        Handle<JSObject> destination,
    3446             :                                        size_t length, uint32_t offset) {
    3447             :     Isolate* isolate = destination->GetIsolate();
    3448             :     Handle<JSTypedArray> destination_ta =
    3449       30411 :         Handle<JSTypedArray>::cast(destination);
    3450             :     DCHECK_LE(offset + length, destination_ta->length_value());
    3451       30411 :     CHECK(!destination_ta->WasDetached());
    3452             : 
    3453       31356 :     if (length == 0) return *isolate->factory()->undefined_value();
    3454             : 
    3455             :     // All conversions from TypedArrays can be done without allocation.
    3456       58932 :     if (source->IsJSTypedArray()) {
    3457        1198 :       Handle<JSTypedArray> source_ta = Handle<JSTypedArray>::cast(source);
    3458        1198 :       ElementsKind source_kind = source_ta->GetElementsKind();
    3459             :       bool source_is_bigint =
    3460        1198 :           source_kind == BIGINT64_ELEMENTS || source_kind == BIGUINT64_ELEMENTS;
    3461             :       bool target_is_bigint =
    3462             :           Kind == BIGINT64_ELEMENTS || Kind == BIGUINT64_ELEMENTS;
    3463             :       if (target_is_bigint) {
    3464         252 :         if (V8_UNLIKELY(!source_is_bigint)) {
    3465             :           Handle<Object> first =
    3466          72 :               JSReceiver::GetElement(isolate, source_ta, 0).ToHandleChecked();
    3467          72 :           THROW_NEW_ERROR_RETURN_FAILURE(
    3468             :               isolate, NewTypeError(MessageTemplate::kBigIntFromObject, first));
    3469             :         }
    3470             :       } else {
    3471         946 :         if (V8_UNLIKELY(source_is_bigint)) {
    3472          72 :           THROW_NEW_ERROR_RETURN_FAILURE(
    3473             :               isolate, NewTypeError(MessageTemplate::kBigIntToNumber));
    3474             :         }
    3475             :       }
    3476             :       // If we have to copy more elements than we have in the source, we need to
    3477             :       // do special handling and conversion; that happens in the slow case.
    3478        2162 :       if (!source_ta->WasDetached() &&
    3479             :           length + offset <= source_ta->length_value()) {
    3480         955 :         CopyElementsFromTypedArray(*source_ta, *destination_ta, length, offset);
    3481         955 :         return *isolate->factory()->undefined_value();
    3482             :       }
    3483             :     }
    3484             : 
    3485             :     // Fast cases for packed numbers kinds where we don't need to allocate.
    3486       56878 :     if (source->IsJSArray()) {
    3487       26765 :       Handle<JSArray> source_js_array = Handle<JSArray>::cast(source);
    3488             :       size_t current_length;
    3489       80295 :       if (source_js_array->length()->IsNumber() &&
    3490       26765 :           TryNumberToSize(source_js_array->length(), &current_length)) {
    3491       26765 :         if (length <= current_length) {
    3492       26756 :           Handle<JSArray> source_array = Handle<JSArray>::cast(source);
    3493       26162 :           if (TryCopyElementsFastNumber(isolate->context(), *source_array,
    3494             :                                         *destination_ta, length, offset)) {
    3495       20381 :             return *isolate->factory()->undefined_value();
    3496             :           }
    3497             :         }
    3498             :       }
    3499             :     }
    3500             :     // Final generic case that handles prototype chain lookups, getters, proxies
    3501             :     // and observable side effects via valueOf, etc.
    3502        8058 :     return CopyElementsHandleSlow(source, destination_ta, length, offset);
    3503             :   }
    3504             : };
    3505             : 
    3506             : #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype) \
    3507             :   typedef TypedElementsAccessor<TYPE##_ELEMENTS, ctype>  \
    3508             :       Fixed##Type##ElementsAccessor;
    3509             : 
    3510             : TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
    3511             : #undef FIXED_ELEMENTS_ACCESSOR
    3512             : 
    3513             : template <typename Subclass, typename ArgumentsAccessor, typename KindTraits>
    3514      116932 : class SloppyArgumentsElementsAccessor
    3515             :     : public ElementsAccessorBase<Subclass, KindTraits> {
    3516             :  public:
    3517             :   explicit SloppyArgumentsElementsAccessor(const char* name)
    3518      119166 :       : ElementsAccessorBase<Subclass, KindTraits>(name) {
    3519             :     USE(KindTraits::Kind);
    3520             :   }
    3521             : 
    3522             :   static void ConvertArgumentsStoreResult(
    3523             :       Handle<SloppyArgumentsElements> elements, Handle<Object> result) {
    3524             :     UNREACHABLE();
    3525             :   }
    3526             : 
    3527       29546 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase parameters,
    3528             :                                 uint32_t entry) {
    3529             :     Handle<SloppyArgumentsElements> elements(
    3530             :         SloppyArgumentsElements::cast(parameters), isolate);
    3531             :     uint32_t length = elements->parameter_map_length();
    3532       29546 :     if (entry < length) {
    3533             :       // Read context mapped entry.
    3534             :       DisallowHeapAllocation no_gc;
    3535       27110 :       Object probe = elements->get_mapped_entry(entry);
    3536             :       DCHECK(!probe->IsTheHole(isolate));
    3537       27110 :       Context context = elements->context();
    3538       27110 :       int context_entry = Smi::ToInt(probe);
    3539             :       DCHECK(!context->get(context_entry)->IsTheHole(isolate));
    3540             :       return handle(context->get(context_entry), isolate);
    3541             :     } else {
    3542             :       // Entry is not context mapped, defer to the arguments.
    3543             :       Handle<Object> result = ArgumentsAccessor::GetImpl(
    3544        4872 :           isolate, elements->arguments(), entry - length);
    3545        1473 :       return Subclass::ConvertArgumentsStoreResult(isolate, elements, result);
    3546             :     }
    3547             :   }
    3548             : 
    3549           0 :   static void TransitionElementsKindImpl(Handle<JSObject> object,
    3550             :                                          Handle<Map> map) {
    3551           0 :     UNREACHABLE();
    3552             :   }
    3553             : 
    3554           0 :   static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
    3555             :                                          uint32_t capacity) {
    3556           0 :     UNREACHABLE();
    3557             :   }
    3558             : 
    3559       21055 :   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
    3560             :                              Object value) {
    3561       21055 :     SetImpl(holder->elements(), entry, value);
    3562       21055 :   }
    3563             : 
    3564       21055 :   static inline void SetImpl(FixedArrayBase store, uint32_t entry,
    3565             :                              Object value) {
    3566       21055 :     SloppyArgumentsElements elements = SloppyArgumentsElements::cast(store);
    3567             :     uint32_t length = elements->parameter_map_length();
    3568       21055 :     if (entry < length) {
    3569             :       // Store context mapped entry.
    3570             :       DisallowHeapAllocation no_gc;
    3571       20787 :       Object probe = elements->get_mapped_entry(entry);
    3572             :       DCHECK(!probe->IsTheHole());
    3573       20787 :       Context context = elements->context();
    3574       20787 :       int context_entry = Smi::ToInt(probe);
    3575             :       DCHECK(!context->get(context_entry)->IsTheHole());
    3576             :       context->set(context_entry, value);
    3577             :     } else {
    3578             :       //  Entry is not context mapped defer to arguments.
    3579         268 :       FixedArray arguments = elements->arguments();
    3580         286 :       Object current = ArgumentsAccessor::GetRaw(arguments, entry - length);
    3581         268 :       if (current->IsAliasedArgumentsEntry()) {
    3582             :         AliasedArgumentsEntry alias = AliasedArgumentsEntry::cast(current);
    3583          62 :         Context context = elements->context();
    3584             :         int context_entry = alias->aliased_context_slot();
    3585             :         DCHECK(!context->get(context_entry)->IsTheHole());
    3586             :         context->set(context_entry, value);
    3587             :       } else {
    3588         206 :         ArgumentsAccessor::SetImpl(arguments, entry - length, value);
    3589             :       }
    3590             :     }
    3591       21055 :   }
    3592             : 
    3593           0 :   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
    3594             :                             uint32_t length,
    3595             :                             Handle<FixedArrayBase> parameter_map) {
    3596             :     // Sloppy arguments objects are not arrays.
    3597           0 :     UNREACHABLE();
    3598             :   }
    3599             : 
    3600         497 :   static uint32_t GetCapacityImpl(JSObject holder, FixedArrayBase store) {
    3601         497 :     SloppyArgumentsElements elements = SloppyArgumentsElements::cast(store);
    3602         497 :     FixedArray arguments = elements->arguments();
    3603             :     return elements->parameter_map_length() +
    3604         497 :            ArgumentsAccessor::GetCapacityImpl(holder, arguments);
    3605             :   }
    3606             : 
    3607         206 :   static uint32_t GetMaxNumberOfEntries(JSObject holder,
    3608             :                                         FixedArrayBase backing_store) {
    3609             :     SloppyArgumentsElements elements =
    3610         206 :         SloppyArgumentsElements::cast(backing_store);
    3611         206 :     FixedArrayBase arguments = elements->arguments();
    3612             :     return elements->parameter_map_length() +
    3613         206 :            ArgumentsAccessor::GetMaxNumberOfEntries(holder, arguments);
    3614             :   }
    3615             : 
    3616           0 :   static uint32_t NumberOfElementsImpl(JSObject receiver,
    3617             :                                        FixedArrayBase backing_store) {
    3618             :     Isolate* isolate = receiver->GetIsolate();
    3619             :     SloppyArgumentsElements elements =
    3620           0 :         SloppyArgumentsElements::cast(backing_store);
    3621           0 :     FixedArrayBase arguments = elements->arguments();
    3622             :     uint32_t nof_elements = 0;
    3623             :     uint32_t length = elements->parameter_map_length();
    3624           0 :     for (uint32_t entry = 0; entry < length; entry++) {
    3625           0 :       if (HasParameterMapArg(isolate, elements, entry)) nof_elements++;
    3626             :     }
    3627             :     return nof_elements +
    3628           0 :            ArgumentsAccessor::NumberOfElementsImpl(receiver, arguments);
    3629             :   }
    3630             : 
    3631          66 :   static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
    3632          66 :                                               KeyAccumulator* accumulator,
    3633             :                                               AddKeyConversion convert) {
    3634             :     Isolate* isolate = accumulator->isolate();
    3635         132 :     Handle<FixedArrayBase> elements(receiver->elements(), isolate);
    3636          66 :     uint32_t length = GetCapacityImpl(*receiver, *elements);
    3637         462 :     for (uint32_t entry = 0; entry < length; entry++) {
    3638         528 :       if (!HasEntryImpl(isolate, *elements, entry)) continue;
    3639         264 :       Handle<Object> value = GetImpl(isolate, *elements, entry);
    3640         264 :       accumulator->AddKey(value, convert);
    3641             :     }
    3642          66 :   }
    3643             : 
    3644         468 :   static bool HasEntryImpl(Isolate* isolate, FixedArrayBase parameters,
    3645             :                            uint32_t entry) {
    3646             :     SloppyArgumentsElements elements =
    3647         468 :         SloppyArgumentsElements::cast(parameters);
    3648             :     uint32_t length = elements->parameter_map_length();
    3649         468 :     if (entry < length) {
    3650         156 :       return HasParameterMapArg(isolate, elements, entry);
    3651             :     }
    3652         312 :     FixedArrayBase arguments = elements->arguments();
    3653         312 :     return ArgumentsAccessor::HasEntryImpl(isolate, arguments, entry - length);
    3654             :   }
    3655             : 
    3656          45 :   static bool HasAccessorsImpl(JSObject holder, FixedArrayBase backing_store) {
    3657             :     SloppyArgumentsElements elements =
    3658          45 :         SloppyArgumentsElements::cast(backing_store);
    3659          45 :     FixedArray arguments = elements->arguments();
    3660          45 :     return ArgumentsAccessor::HasAccessorsImpl(holder, arguments);
    3661             :   }
    3662             : 
    3663             :   static uint32_t GetIndexForEntryImpl(FixedArrayBase parameters,
    3664             :                                        uint32_t entry) {
    3665             :     SloppyArgumentsElements elements =
    3666             :         SloppyArgumentsElements::cast(parameters);
    3667             :     uint32_t length = elements->parameter_map_length();
    3668             :     if (entry < length) return entry;
    3669             :     FixedArray arguments = elements->arguments();
    3670             :     return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length);
    3671             :   }
    3672             : 
    3673      443476 :   static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject holder,
    3674             :                                        FixedArrayBase parameters,
    3675             :                                        uint32_t index, PropertyFilter filter) {
    3676             :     SloppyArgumentsElements elements =
    3677      443476 :         SloppyArgumentsElements::cast(parameters);
    3678      443476 :     if (HasParameterMapArg(isolate, elements, index)) return index;
    3679      394284 :     FixedArray arguments = elements->arguments();
    3680             :     uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(
    3681      394284 :         isolate, holder, arguments, index, filter);
    3682      394284 :     if (entry == kMaxUInt32) return kMaxUInt32;
    3683             :     // Arguments entries could overlap with the dictionary entries, hence offset
    3684             :     // them by the number of context mapped entries.
    3685        3213 :     return elements->parameter_map_length() + entry;
    3686             :   }
    3687             : 
    3688       51964 :   static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
    3689             :     SloppyArgumentsElements elements =
    3690      103928 :         SloppyArgumentsElements::cast(holder->elements());
    3691             :     uint32_t length = elements->parameter_map_length();
    3692       51964 :     if (entry < length) {
    3693       49039 :       return PropertyDetails(kData, NONE, PropertyCellType::kNoCell);
    3694             :     }
    3695        2925 :     FixedArray arguments = elements->arguments();
    3696        1946 :     return ArgumentsAccessor::GetDetailsImpl(arguments, entry - length);
    3697             :   }
    3698             : 
    3699      443632 :   static bool HasParameterMapArg(Isolate* isolate,
    3700             :                                  SloppyArgumentsElements elements,
    3701             :                                  uint32_t index) {
    3702             :     uint32_t length = elements->parameter_map_length();
    3703      443632 :     if (index >= length) return false;
    3704      102432 :     return !elements->get_mapped_entry(index)->IsTheHole(isolate);
    3705             :   }
    3706             : 
    3707         666 :   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
    3708             :     Handle<SloppyArgumentsElements> elements(
    3709        1332 :         SloppyArgumentsElements::cast(obj->elements()), obj->GetIsolate());
    3710             :     uint32_t length = elements->parameter_map_length();
    3711             :     uint32_t delete_or_entry = entry;
    3712         666 :     if (entry < length) {
    3713             :       delete_or_entry = kMaxUInt32;
    3714             :     }
    3715         666 :     Subclass::SloppyDeleteImpl(obj, elements, delete_or_entry);
    3716             :     // SloppyDeleteImpl allocates a new dictionary elements store. For making
    3717             :     // heap verification happy we postpone clearing out the mapped entry.
    3718         666 :     if (entry < length) {
    3719             :       elements->set_mapped_entry(entry,
    3720        1296 :                                  obj->GetReadOnlyRoots().the_hole_value());
    3721             :     }
    3722         666 :   }
    3723             : 
    3724             :   static void SloppyDeleteImpl(Handle<JSObject> obj,
    3725             :                                Handle<SloppyArgumentsElements> elements,
    3726             :                                uint32_t entry) {
    3727             :     // Implemented in subclasses.
    3728             :     UNREACHABLE();
    3729             :   }
    3730             : 
    3731         329 :   static void CollectElementIndicesImpl(Handle<JSObject> object,
    3732             :                                         Handle<FixedArrayBase> backing_store,
    3733         329 :                                         KeyAccumulator* keys) {
    3734             :     Isolate* isolate = keys->isolate();
    3735         329 :     uint32_t nof_indices = 0;
    3736             :     Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
    3737         329 :         GetCapacityImpl(*object, *backing_store));
    3738         329 :     DirectCollectElementIndicesImpl(isolate, object, backing_store,
    3739             :                                     GetKeysConversion::kKeepNumbers,
    3740             :                                     ENUMERABLE_STRINGS, indices, &nof_indices);
    3741         329 :     SortIndices(isolate, indices, nof_indices);
    3742        1309 :     for (uint32_t i = 0; i < nof_indices; i++) {
    3743        1960 :       keys->AddKey(indices->get(i));
    3744             :     }
    3745         329 :   }
    3746             : 
    3747         535 :   static Handle<FixedArray> DirectCollectElementIndicesImpl(
    3748             :       Isolate* isolate, Handle<JSObject> object,
    3749             :       Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
    3750             :       PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
    3751             :       uint32_t insertion_index = 0) {
    3752             :     Handle<SloppyArgumentsElements> elements =
    3753         535 :         Handle<SloppyArgumentsElements>::cast(backing_store);
    3754             :     uint32_t length = elements->parameter_map_length();
    3755             : 
    3756        1314 :     for (uint32_t i = 0; i < length; ++i) {
    3757        2628 :       if (elements->get_mapped_entry(i)->IsTheHole(isolate)) continue;
    3758         873 :       if (convert == GetKeysConversion::kConvertToString) {
    3759           0 :         Handle<String> index_string = isolate->factory()->Uint32ToString(i);
    3760           0 :         list->set(insertion_index, *index_string);
    3761             :       } else {
    3762        1746 :         list->set(insertion_index, Smi::FromInt(i));
    3763             :       }
    3764         873 :       insertion_index++;
    3765             :     }
    3766             : 
    3767        1070 :     Handle<FixedArray> store(elements->arguments(), isolate);
    3768             :     return ArgumentsAccessor::DirectCollectElementIndicesImpl(
    3769             :         isolate, object, store, convert, filter, list, nof_indices,
    3770         535 :         insertion_index);
    3771             :   }
    3772             : 
    3773          90 :   static Maybe<bool> IncludesValueImpl(Isolate* isolate,
    3774             :                                        Handle<JSObject> object,
    3775             :                                        Handle<Object> value,
    3776             :                                        uint32_t start_from, uint32_t length) {
    3777             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *object));
    3778             :     Handle<Map> original_map(object->map(), isolate);
    3779             :     Handle<SloppyArgumentsElements> elements(
    3780         180 :         SloppyArgumentsElements::cast(object->elements()), isolate);
    3781         180 :     bool search_for_hole = value->IsUndefined(isolate);
    3782             : 
    3783         225 :     for (uint32_t k = start_from; k < length; ++k) {
    3784             :       DCHECK_EQ(object->map(), *original_map);
    3785             :       uint32_t entry =
    3786         360 :           GetEntryForIndexImpl(isolate, *object, *elements, k, ALL_PROPERTIES);
    3787         180 :       if (entry == kMaxUInt32) {
    3788           0 :         if (search_for_hole) return Just(true);
    3789             :         continue;
    3790             :       }
    3791             : 
    3792         180 :       Handle<Object> element_k = Subclass::GetImpl(isolate, *elements, entry);
    3793             : 
    3794         360 :       if (element_k->IsAccessorPair()) {
    3795          36 :         LookupIterator it(isolate, object, k, LookupIterator::OWN);
    3796             :         DCHECK(it.IsFound());
    3797             :         DCHECK_EQ(it.state(), LookupIterator::ACCESSOR);
    3798          81 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k,
    3799             :                                          Object::GetPropertyWithAccessor(&it),
    3800             :                                          Nothing<bool>());
    3801             : 
    3802          36 :         if (value->SameValueZero(*element_k)) return Just(true);
    3803             : 
    3804          27 :         if (object->map() != *original_map) {
    3805             :           // Some mutation occurred in accessor. Abort "fast" path
    3806           0 :           return IncludesValueSlowPath(isolate, object, value, k + 1, length);
    3807             :         }
    3808         144 :       } else if (value->SameValueZero(*element_k)) {
    3809             :         return Just(true);
    3810             :       }
    3811             :     }
    3812             :     return Just(false);
    3813             :   }
    3814             : 
    3815          90 :   static Maybe<int64_t> IndexOfValueImpl(Isolate* isolate,
    3816             :                                          Handle<JSObject> object,
    3817             :                                          Handle<Object> value,
    3818             :                                          uint32_t start_from, uint32_t length) {
    3819             :     DCHECK(JSObject::PrototypeHasNoElements(isolate, *object));
    3820             :     Handle<Map> original_map(object->map(), isolate);
    3821             :     Handle<SloppyArgumentsElements> elements(
    3822         180 :         SloppyArgumentsElements::cast(object->elements()), isolate);
    3823             : 
    3824         270 :     for (uint32_t k = start_from; k < length; ++k) {
    3825             :       DCHECK_EQ(object->map(), *original_map);
    3826             :       uint32_t entry =
    3827         414 :           GetEntryForIndexImpl(isolate, *object, *elements, k, ALL_PROPERTIES);
    3828         207 :       if (entry == kMaxUInt32) {
    3829             :         continue;
    3830             :       }
    3831             : 
    3832         207 :       Handle<Object> element_k = Subclass::GetImpl(isolate, *elements, entry);
    3833             : 
    3834         414 :       if (element_k->IsAccessorPair()) {
    3835          45 :         LookupIterator it(isolate, object, k, LookupIterator::OWN);
    3836             :         DCHECK(it.IsFound());
    3837             :         DCHECK_EQ(it.state(), LookupIterator::ACCESSOR);
    3838          99 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_k,
    3839             :                                          Object::GetPropertyWithAccessor(&it),
    3840             :                                          Nothing<int64_t>());
    3841             : 
    3842          45 :         if (value->StrictEquals(*element_k)) {
    3843           9 :           return Just<int64_t>(k);
    3844             :         }
    3845             : 
    3846          36 :         if (object->map() != *original_map) {
    3847             :           // Some mutation occurred in accessor. Abort "fast" path.
    3848           0 :           return IndexOfValueSlowPath(isolate, object, value, k + 1, length);
    3849             :         }
    3850         162 :       } else if (value->StrictEquals(*element_k)) {
    3851          18 :         return Just<int64_t>(k);
    3852             :       }
    3853             :     }
    3854             :     return Just<int64_t>(-1);
    3855             :   }
    3856             : 
    3857           0 :   static Handle<JSObject> SliceImpl(Handle<JSObject> receiver, uint32_t start,
    3858             :                                     uint32_t end) {
    3859             :     Isolate* isolate = receiver->GetIsolate();
    3860           0 :     uint32_t result_len = end < start ? 0u : end - start;
    3861             :     Handle<JSArray> result_array =
    3862           0 :         isolate->factory()->NewJSArray(HOLEY_ELEMENTS, result_len, result_len);
    3863             :     DisallowHeapAllocation no_gc;
    3864           0 :     FixedArray elements = FixedArray::cast(result_array->elements());
    3865           0 :     FixedArray parameters = FixedArray::cast(receiver->elements());
    3866             :     uint32_t insertion_index = 0;
    3867           0 :     for (uint32_t i = start; i < end; i++) {
    3868             :       uint32_t entry = GetEntryForIndexImpl(isolate, *receiver, parameters, i,
    3869           0 :                                             ALL_PROPERTIES);
    3870           0 :       if (entry != kMaxUInt32 && HasEntryImpl(isolate, parameters, entry)) {
    3871           0 :         elements->set(insertion_index, *GetImpl(isolate, parameters, entry));
    3872             :       } else {
    3873           0 :         elements->set_the_hole(isolate, insertion_index);
    3874             :       }
    3875           0 :       insertion_index++;
    3876             :     }
    3877           0 :     return result_array;
    3878             :   }
    3879             : };
    3880             : 
    3881             : 
    3882      116932 : class SlowSloppyArgumentsElementsAccessor
    3883             :     : public SloppyArgumentsElementsAccessor<
    3884             :           SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
    3885             :           ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > {
    3886             :  public:
    3887             :   explicit SlowSloppyArgumentsElementsAccessor(const char* name)
    3888             :       : SloppyArgumentsElementsAccessor<
    3889             :             SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
    3890       59583 :             ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
    3891             : 
    3892        1473 :   static Handle<Object> ConvertArgumentsStoreResult(
    3893             :       Isolate* isolate, Handle<SloppyArgumentsElements> elements,
    3894             :       Handle<Object> result) {
    3895             :     // Elements of the arguments object in slow mode might be slow aliases.
    3896        2946 :     if (result->IsAliasedArgumentsEntry()) {
    3897             :       DisallowHeapAllocation no_gc;
    3898             :       AliasedArgumentsEntry alias = AliasedArgumentsEntry::cast(*result);
    3899          26 :       Context context = elements->context();
    3900             :       int context_entry = alias->aliased_context_slot();
    3901             :       DCHECK(!context->get(context_entry)->IsTheHole(isolate));
    3902             :       return handle(context->get(context_entry), isolate);
    3903             :     }
    3904        1447 :     return result;
    3905             :   }
    3906         666 :   static void SloppyDeleteImpl(Handle<JSObject> obj,
    3907             :                                Handle<SloppyArgumentsElements> elements,
    3908             :                                uint32_t entry) {
    3909             :     // No need to delete a context mapped entry from the arguments elements.
    3910        1332 :     if (entry == kMaxUInt32) return;
    3911             :     Isolate* isolate = obj->GetIsolate();
    3912         468 :     Handle<NumberDictionary> dict(NumberDictionary::cast(elements->arguments()),
    3913         468 :                                   isolate);
    3914             :     int length = elements->parameter_map_length();
    3915         234 :     dict = NumberDictionary::DeleteEntry(isolate, dict, entry - length);
    3916         468 :     elements->set_arguments(*dict);
    3917             :   }
    3918       99587 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
    3919             :                       Handle<Object> value, PropertyAttributes attributes,
    3920             :                       uint32_t new_capacity) {
    3921             :     Isolate* isolate = object->GetIsolate();
    3922             :     Handle<SloppyArgumentsElements> elements(
    3923      199174 :         SloppyArgumentsElements::cast(object->elements()), isolate);
    3924             :     Handle<FixedArrayBase> old_arguments(
    3925      199174 :         FixedArrayBase::cast(elements->arguments()), isolate);
    3926             :     Handle<NumberDictionary> dictionary =
    3927      199174 :         old_arguments->IsNumberDictionary()
    3928             :             ? Handle<NumberDictionary>::cast(old_arguments)
    3929       99587 :             : JSObject::NormalizeElements(object);
    3930             :     PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
    3931             :     Handle<NumberDictionary> new_dictionary =
    3932       99587 :         NumberDictionary::Add(isolate, dictionary, index, value, details);
    3933       99677 :     if (attributes != NONE) object->RequireSlowElements(*new_dictionary);
    3934       99587 :     if (*dictionary != *new_dictionary) {
    3935         576 :       elements->set_arguments(*new_dictionary);
    3936             :     }
    3937       99587 :   }
    3938             : 
    3939         196 :   static void ReconfigureImpl(Handle<JSObject> object,
    3940             :                               Handle<FixedArrayBase> store, uint32_t entry,
    3941             :                               Handle<Object> value,
    3942             :                               PropertyAttributes attributes) {
    3943             :     Isolate* isolate = object->GetIsolate();
    3944             :     Handle<SloppyArgumentsElements> elements =
    3945         196 :         Handle<SloppyArgumentsElements>::cast(store);
    3946             :     uint32_t length = elements->parameter_map_length();
    3947         196 :     if (entry < length) {
    3948         161 :       Object probe = elements->get_mapped_entry(entry);
    3949             :       DCHECK(!probe->IsTheHole(isolate));
    3950         161 :       Context context = elements->context();
    3951         161 :       int context_entry = Smi::ToInt(probe);
    3952             :       DCHECK(!context->get(context_entry)->IsTheHole(isolate));
    3953             :       context->set(context_entry, *value);
    3954             : 
    3955             :       // Redefining attributes of an aliased element destroys fast aliasing.
    3956             :       elements->set_mapped_entry(entry,
    3957         322 :                                  ReadOnlyRoots(isolate).the_hole_value());
    3958             :       // For elements that are still writable we re-establish slow aliasing.
    3959         161 :       if ((attributes & READ_ONLY) == 0) {
    3960          53 :         value = isolate->factory()->NewAliasedArgumentsEntry(context_entry);
    3961             :       }
    3962             : 
    3963             :       PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
    3964             :       Handle<NumberDictionary> arguments(
    3965         322 :           NumberDictionary::cast(elements->arguments()), isolate);
    3966             :       arguments =
    3967         161 :           NumberDictionary::Add(isolate, arguments, entry, value, details);
    3968             :       // If the attributes were NONE, we would have called set rather than
    3969             :       // reconfigure.
    3970             :       DCHECK_NE(NONE, attributes);
    3971         161 :       object->RequireSlowElements(*arguments);
    3972         322 :       elements->set_arguments(*arguments);
    3973             :     } else {
    3974          70 :       Handle<FixedArrayBase> arguments(elements->arguments(), isolate);
    3975             :       DictionaryElementsAccessor::ReconfigureImpl(
    3976          35 :           object, arguments, entry - length, value, attributes);
    3977             :     }
    3978         196 :   }
    3979             : };
    3980             : 
    3981             : 
    3982      116932 : class FastSloppyArgumentsElementsAccessor
    3983             :     : public SloppyArgumentsElementsAccessor<
    3984             :           FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
    3985             :           ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > {
    3986             :  public:
    3987             :   explicit FastSloppyArgumentsElementsAccessor(const char* name)
    3988             :       : SloppyArgumentsElementsAccessor<
    3989             :             FastSloppyArgumentsElementsAccessor,
    3990             :             FastHoleyObjectElementsAccessor,
    3991       59583 :             ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
    3992             : 
    3993             :   static Handle<Object> ConvertArgumentsStoreResult(
    3994             :       Isolate* isolate, Handle<SloppyArgumentsElements> paramtere_map,
    3995             :       Handle<Object> result) {
    3996             :     DCHECK(!result->IsAliasedArgumentsEntry());
    3997             :     return result;
    3998             :   }
    3999             : 
    4000         739 :   static Handle<FixedArray> GetArguments(Isolate* isolate,
    4001             :                                          FixedArrayBase store) {
    4002         739 :     SloppyArgumentsElements elements = SloppyArgumentsElements::cast(store);
    4003        1478 :     return Handle<FixedArray>(elements->arguments(), isolate);
    4004             :   }
    4005             : 
    4006         739 :   static Handle<NumberDictionary> NormalizeImpl(
    4007             :       Handle<JSObject> object, Handle<FixedArrayBase> elements) {
    4008             :     Handle<FixedArray> arguments =
    4009         739 :         GetArguments(object->GetIsolate(), *elements);
    4010         739 :     return FastHoleyObjectElementsAccessor::NormalizeImpl(object, arguments);
    4011             :   }
    4012             : 
    4013         513 :   static Handle<NumberDictionary> NormalizeArgumentsElements(
    4014             :       Handle<JSObject> object, Handle<SloppyArgumentsElements> elements,
    4015             :       uint32_t* entry) {
    4016         513 :     Handle<NumberDictionary> dictionary = JSObject::NormalizeElements(object);
    4017        1026 :     elements->set_arguments(*dictionary);
    4018             :     // kMaxUInt32 indicates that a context mapped element got deleted. In this
    4019             :     // case we only normalize the elements (aka. migrate to SLOW_SLOPPY).
    4020         513 :     if (*entry == kMaxUInt32) return dictionary;
    4021             :     uint32_t length = elements->parameter_map_length();
    4022         135 :     if (*entry >= length) {
    4023             :       *entry =
    4024         180 :           dictionary->FindEntry(object->GetIsolate(), *entry - length) + length;
    4025             :     }
    4026         135 :     return dictionary;
    4027             :   }
    4028             : 
    4029         468 :   static void SloppyDeleteImpl(Handle<JSObject> obj,
    4030             :                                Handle<SloppyArgumentsElements> elements,
    4031             :                                uint32_t entry) {
    4032             :     // Always normalize element on deleting an entry.
    4033         468 :     NormalizeArgumentsElements(obj, elements, &entry);
    4034         468 :     SlowSloppyArgumentsElementsAccessor::SloppyDeleteImpl(obj, elements, entry);
    4035         468 :   }
    4036             : 
    4037       19981 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
    4038             :                       Handle<Object> value, PropertyAttributes attributes,
    4039             :                       uint32_t new_capacity) {
    4040             :     DCHECK_EQ(NONE, attributes);
    4041             :     Isolate* isolate = object->GetIsolate();
    4042             :     Handle<SloppyArgumentsElements> elements(
    4043       39962 :         SloppyArgumentsElements::cast(object->elements()), isolate);
    4044       39962 :     Handle<FixedArray> old_arguments(elements->arguments(), isolate);
    4045       59943 :     if (old_arguments->IsNumberDictionary() ||
    4046       19981 :         static_cast<uint32_t>(old_arguments->length()) < new_capacity) {
    4047       19945 :       GrowCapacityAndConvertImpl(object, new_capacity);
    4048             :     }
    4049       19981 :     FixedArray arguments = elements->arguments();
    4050             :     // For fast holey objects, the entry equals the index. The code above made
    4051             :     // sure that there's enough space to store the value. We cannot convert
    4052             :     // index to entry explicitly since the slot still contains the hole, so the
    4053             :     // current EntryForIndex would indicate that it is "absent" by returning
    4054             :     // kMaxUInt32.
    4055       19981 :     FastHoleyObjectElementsAccessor::SetImpl(arguments, index, *value);
    4056       19981 :   }
    4057             : 
    4058          45 :   static void ReconfigureImpl(Handle<JSObject> object,
    4059             :                               Handle<FixedArrayBase> store, uint32_t entry,
    4060             :                               Handle<Object> value,
    4061             :                               PropertyAttributes attributes) {
    4062             :     DCHECK_EQ(object->elements(), *store);
    4063             :     Handle<SloppyArgumentsElements> elements(
    4064             :         SloppyArgumentsElements::cast(*store), object->GetIsolate());
    4065          45 :     NormalizeArgumentsElements(object, elements, &entry);
    4066             :     SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(object, store, entry,
    4067          45 :                                                          value, attributes);
    4068          45 :   }
    4069             : 
    4070       19945 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
    4071             :                                uint32_t from_start, FixedArrayBase to,
    4072             :                                ElementsKind from_kind, uint32_t to_start,
    4073             :                                int packed_size, int copy_size) {
    4074             :     DCHECK(!to->IsDictionary());
    4075       19945 :     if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
    4076             :       CopyDictionaryToObjectElements(isolate, from, from_start, to,
    4077           0 :                                      HOLEY_ELEMENTS, to_start, copy_size);
    4078             :     } else {
    4079             :       DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, from_kind);
    4080             :       CopyObjectToObjectElements(isolate, from, HOLEY_ELEMENTS, from_start, to,
    4081       19945 :                                  HOLEY_ELEMENTS, to_start, copy_size);
    4082             :     }
    4083       19945 :   }
    4084             : 
    4085       19945 :   static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
    4086             :                                          uint32_t capacity) {
    4087             :     Isolate* isolate = object->GetIsolate();
    4088             :     Handle<SloppyArgumentsElements> elements(
    4089       39890 :         SloppyArgumentsElements::cast(object->elements()), isolate);
    4090       39890 :     Handle<FixedArray> old_arguments(FixedArray::cast(elements->arguments()),
    4091       39890 :                                      isolate);
    4092       19945 :     ElementsKind from_kind = object->GetElementsKind();
    4093             :     // This method should only be called if there's a reason to update the
    4094             :     // elements.
    4095             :     DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS ||
    4096             :            static_cast<uint32_t>(old_arguments->length()) < capacity);
    4097             :     Handle<FixedArrayBase> arguments =
    4098             :         ConvertElementsWithCapacity(object, old_arguments, from_kind, capacity);
    4099             :     Handle<Map> new_map = JSObject::GetElementsTransitionMap(
    4100       19945 :         object, FAST_SLOPPY_ARGUMENTS_ELEMENTS);
    4101       19945 :     JSObject::MigrateToMap(object, new_map);
    4102       39890 :     elements->set_arguments(FixedArray::cast(*arguments));
    4103       19945 :     JSObject::ValidateElements(*object);
    4104       19945 :   }
    4105             : };
    4106             : 
    4107             : template <typename Subclass, typename BackingStoreAccessor, typename KindTraits>
    4108      116932 : class StringWrapperElementsAccessor
    4109             :     : public ElementsAccessorBase<Subclass, KindTraits> {
    4110             :  public:
    4111             :   explicit StringWrapperElementsAccessor(const char* name)
    4112      119166 :       : ElementsAccessorBase<Subclass, KindTraits>(name) {
    4113             :     USE(KindTraits::Kind);
    4114             :   }
    4115             : 
    4116             :   static Handle<Object> GetInternalImpl(Handle<JSObject> holder,
    4117             :                                         uint32_t entry) {
    4118       21160 :     return GetImpl(holder, entry);
    4119             :   }
    4120             : 
    4121       21160 :   static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
    4122             :     Isolate* isolate = holder->GetIsolate();
    4123       21160 :     Handle<String> string(GetString(*holder), isolate);
    4124       21160 :     uint32_t length = static_cast<uint32_t>(string->length());
    4125       21160 :     if (entry < length) {
    4126             :       return isolate->factory()->LookupSingleCharacterStringFromCode(
    4127       55767 :           String::Flatten(isolate, string)->Get(entry));
    4128             :     }
    4129             :     return BackingStoreAccessor::GetImpl(isolate, holder->elements(),
    4130        5142 :                                          entry - length);
    4131             :   }
    4132             : 
    4133           0 :   static Handle<Object> GetImpl(Isolate* isolate, FixedArrayBase elements,
    4134             :                                 uint32_t entry) {
    4135           0 :     UNREACHABLE();
    4136             :   }
    4137             : 
    4138      111591 :   static PropertyDetails GetDetailsImpl(JSObject holder, uint32_t entry) {
    4139      223182 :     uint32_t length = static_cast<uint32_t>(GetString(holder)->length());
    4140      111591 :     if (entry < length) {
    4141             :       PropertyAttributes attributes =
    4142             :           static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
    4143       19470 :       return PropertyDetails(kData, attributes, PropertyCellType::kNoCell);
    4144             :     }
    4145        1219 :     return BackingStoreAccessor::GetDetailsImpl(holder, entry - length);
    4146             :   }
    4147             : 
    4148      293538 :   static uint32_t GetEntryForIndexImpl(Isolate* isolate, JSObject holder,
    4149             :                                        FixedArrayBase backing_store,
    4150             :                                        uint32_t index, PropertyFilter filter) {
    4151      587076 :     uint32_t length = static_cast<uint32_t>(GetString(holder)->length());
    4152      293538 :     if (index < length) return index;
    4153             :     uint32_t backing_store_entry = BackingStoreAccessor::GetEntryForIndexImpl(
    4154      274068 :         isolate, holder, backing_store, index, filter);
    4155      274068 :     if (backing_store_entry == kMaxUInt32) return kMaxUInt32;
    4156             :     DCHECK(backing_store_entry < kMaxUInt32 - length);
    4157       92121 :     return backing_store_entry + length;
    4158             :   }
    4159             : 
    4160       90063 :   static void DeleteImpl(Handle<JSObject> holder, uint32_t entry) {
    4161      180126 :     uint32_t length = static_cast<uint32_t>(GetString(*holder)->length());
    4162       90063 :     if (entry < length) {
    4163       90063 :       return;  // String contents can't be deleted.
    4164             :     }
    4165       90063 :     BackingStoreAccessor::DeleteImpl(holder, entry - length);
    4166             :   }
    4167             : 
    4168         153 :   static void SetImpl(Handle<JSObject> holder, uint32_t entry, Object value) {
    4169         306 :     uint32_t length = static_cast<uint32_t>(GetString(*holder)->length());
    4170         153 :     if (entry < length) {
    4171         153 :       return;  // String contents are read-only.
    4172             :     }
    4173         306 :     BackingStoreAccessor::SetImpl(holder->elements(), entry - length, value);
    4174             :   }
    4175             : 
    4176       84034 :   static void AddImpl(Handle<JSObject> object, uint32_t index,
    4177             :                       Handle<Object> value, PropertyAttributes attributes,
    4178             :                       uint32_t new_capacity) {
    4179             :     DCHECK(index >= static_cast<uint32_t>(GetString(*object)->length()));
    4180             :     // Explicitly grow fast backing stores if needed. Dictionaries know how to
    4181             :     // extend their capacity themselves.
    4182      252093 :     if (KindTraits::Kind == FAST_STRING_WRAPPER_ELEMENTS &&
    4183      168068 :         (object->GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS ||
    4184      168059 :          BackingStoreAccessor::GetCapacityImpl(*object, object->elements()) !=
    4185             :              new_capacity)) {
    4186         280 :       GrowCapacityAndConvertImpl(object, new_capacity);
    4187             :     }
    4188       90307 :     BackingStoreAccessor::AddImpl(object, index, value, attributes,
    4189             :                                   new_capacity);
    4190       84034 :   }
    4191             : 
    4192           9 :   static void ReconfigureImpl(Handle<JSObject> object,
    4193             :                               Handle<FixedArrayBase> store, uint32_t entry,
    4194             :                               Handle<Object> value,
    4195             :                               PropertyAttributes attributes) {
    4196          18 :     uint32_t length = static_cast<uint32_t>(GetString(*object)->length());
    4197           9 :     if (entry < length) {
    4198           9 :       return;  // String contents can't be reconfigured.
    4199             :     }
    4200           9 :     BackingStoreAccessor::ReconfigureImpl(object, store, entry - length, value,
    4201           9 :                                           attributes);
    4202             :   }
    4203             : 
    4204           0 :   static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
    4205             :                                               KeyAccumulator* accumulator,
    4206             :                                               AddKeyConversion convert) {
    4207             :     Isolate* isolate = receiver->GetIsolate();
    4208           0 :     Handle<String> string(GetString(*receiver), isolate);
    4209           0 :     string = String::Flatten(isolate, string);
    4210           0 :     uint32_t length = static_cast<uint32_t>(string->length());
    4211           0 :     for (uint32_t i = 0; i < length; i++) {
    4212           0 :       accumulator->AddKey(
    4213             :           isolate->factory()->LookupSingleCharacterStringFromCode(
    4214           0 :               string->Get(i)),
    4215           0 :           convert);
    4216             :     }
    4217           0 :     BackingStoreAccessor::AddElementsToKeyAccumulatorImpl(receiver, accumulator,
    4218             :                                                           convert);
    4219           0 :   }
    4220             : 
    4221        2114 :   static void CollectElementIndicesImpl(Handle<JSObject> object,
    4222             :                                         Handle<FixedArrayBase> backing_store,
    4223        2114 :                                         KeyAccumulator* keys) {
    4224        4228 :     uint32_t length = GetString(*object)->length();
    4225             :     Factory* factory = keys->isolate()->factory();
    4226        8316 :     for (uint32_t i = 0; i < length; i++) {
    4227        6202 :       keys->AddKey(factory->NewNumberFromUint(i));
    4228             :     }
    4229        2114 :     BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store,
    4230             :                                                     keys);
    4231        2114 :   }
    4232             : 
    4233         280 :   static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
    4234             :                                          uint32_t capacity) {
    4235             :     Handle<FixedArrayBase> old_elements(object->elements(),
    4236         560 :                                         object->GetIsolate());
    4237         280 :     ElementsKind from_kind = object->GetElementsKind();
    4238         280 :     if (from_kind == FAST_STRING_WRAPPER_ELEMENTS) {
    4239             :       // The optimizing compiler relies on the prototype lookups of String
    4240             :       // objects always returning undefined. If there's a store to the
    4241             :       // initial String.prototype object, make sure all the optimizations
    4242             :       // are invalidated.
    4243             :       object->GetIsolate()->UpdateNoElementsProtectorOnSetLength(object);
    4244             :     }
    4245             :     // This method should only be called if there's a reason to update the
    4246             :     // elements.
    4247             :     DCHECK(from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
    4248             :            static_cast<uint32_t>(old_elements->length()) < capacity);
    4249         280 :     Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
    4250             :                                               FAST_STRING_WRAPPER_ELEMENTS,
    4251         280 :                                               capacity);
    4252         280 :   }
    4253             : 
    4254         280 :   static void CopyElementsImpl(Isolate* isolate, FixedArrayBase from,
    4255             :                                uint32_t from_start, FixedArrayBase to,
    4256             :                                ElementsKind from_kind, uint32_t to_start,
    4257             :                                int packed_size, int copy_size) {
    4258             :     DCHECK(!to->IsDictionary());
    4259         280 :     if (from_kind == SLOW_STRING_WRAPPER_ELEMENTS) {
    4260           9 :       CopyDictionaryToObjectElements(isolate, from, from_start, to,
    4261             :                                      HOLEY_ELEMENTS, to_start, copy_size);
    4262             :     } else {
    4263             :       DCHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, from_kind);
    4264         271 :       CopyObjectToObjectElements(isolate, from, HOLEY_ELEMENTS, from_start, to,
    4265             :                                  HOLEY_ELEMENTS, to_start, copy_size);
    4266             :     }
    4267         280 :   }
    4268             : 
    4269           0 :   static uint32_t NumberOfElementsImpl(JSObject object,
    4270             :                                        FixedArrayBase backing_store) {
    4271           0 :     uint32_t length = GetString(object)->length();
    4272             :     return length +
    4273           0 :            BackingStoreAccessor::NumberOfElementsImpl(object, backing_store);
    4274             :   }
    4275             : 
    4276             :  private:
    4277      518628 :   static String GetString(JSObject holder) {
    4278             :     DCHECK(holder->IsJSValue());
    4279             :     JSValue js_value = JSValue::cast(holder);
    4280             :     DCHECK(js_value->value()->IsString());
    4281      518628 :     return String::cast(js_value->value());
    4282             :   }
    4283             : };
    4284             : 
    4285      116932 : class FastStringWrapperElementsAccessor
    4286             :     : public StringWrapperElementsAccessor<
    4287             :           FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
    4288             :           ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>> {
    4289             :  public:
    4290             :   explicit FastStringWrapperElementsAccessor(const char* name)
    4291             :       : StringWrapperElementsAccessor<
    4292             :             FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
    4293       59583 :             ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>>(name) {}
    4294             : 
    4295             :   static Handle<NumberDictionary> NormalizeImpl(
    4296             :       Handle<JSObject> object, Handle<FixedArrayBase> elements) {
    4297         139 :     return FastHoleyObjectElementsAccessor::NormalizeImpl(object, elements);
    4298             :   }
    4299             : };
    4300             : 
    4301      116932 : class SlowStringWrapperElementsAccessor
    4302             :     : public StringWrapperElementsAccessor<
    4303             :           SlowStringWrapperElementsAccessor, DictionaryElementsAccessor,
    4304             :           ElementsKindTraits<SLOW_STRING_WRAPPER_ELEMENTS>> {
    4305             :  public:
    4306             :   explicit SlowStringWrapperElementsAccessor(const char* name)
    4307             :       : StringWrapperElementsAccessor<
    4308             :             SlowStringWrapperElementsAccessor, DictionaryElementsAccessor,
    4309       59583 :             ElementsKindTraits<SLOW_STRING_WRAPPER_ELEMENTS>>(name) {}
    4310             : 
    4311             :   static bool HasAccessorsImpl(JSObject holder, FixedArrayBase backing_store) {
    4312           0 :     return DictionaryElementsAccessor::HasAccessorsImpl(holder, backing_store);
    4313             :   }
    4314             : };
    4315             : 
    4316             : }  // namespace
    4317             : 
    4318             : 
    4319           0 : void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index,
    4320             :                      bool allow_appending) {
    4321             :   DisallowHeapAllocation no_allocation;
    4322           0 :   Object raw_length;
    4323             :   const char* elements_type = "array";
    4324           0 :   if (obj->IsJSArray()) {
    4325             :     JSArray array = JSArray::cast(*obj);
    4326           0 :     raw_length = array->length();
    4327             :   } else {
    4328           0 :     raw_length = Smi::FromInt(obj->elements()->length());
    4329             :     elements_type = "object";
    4330             :   }
    4331             : 
    4332           0 :   if (raw_length->IsNumber()) {
    4333           0 :     double n = raw_length->Number();
    4334           0 :     if (FastI2D(FastD2UI(n)) == n) {
    4335           0 :       int32_t int32_length = DoubleToInt32(n);
    4336           0 :       uint32_t compare_length = static_cast<uint32_t>(int32_length);
    4337           0 :       if (allow_appending) compare_length++;
    4338           0 :       if (index >= compare_length) {
    4339             :         PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ",
    4340             :                elements_type, op, elements_type, static_cast<int>(int32_length),
    4341           0 :                static_cast<int>(index));
    4342           0 :         TraceTopFrame(obj->GetIsolate());
    4343           0 :         PrintF("]\n");
    4344             :       }
    4345             :     } else {
    4346           0 :       PrintF("[%s elements length not integer value in ", elements_type);
    4347           0 :       TraceTopFrame(obj->GetIsolate());
    4348           0 :       PrintF("]\n");
    4349             :     }
    4350             :   } else {
    4351           0 :     PrintF("[%s elements length not a number in ", elements_type);
    4352           0 :     TraceTopFrame(obj->GetIsolate());
    4353           0 :     PrintF("]\n");
    4354             :   }
    4355           0 : }
    4356             : 
    4357             : 
    4358      572602 : MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array,
    4359     1003074 :                                                      Arguments* args) {
    4360      572602 :   if (args->length() == 0) {
    4361             :     // Optimize the case where there are no parameters passed.
    4362      138564 :     JSArray::Initialize(array, JSArray::kPreallocatedArrayElements);
    4363      138574 :     return array;
    4364             : 
    4365      443106 :   } else if (args->length() == 1 && args->at(0)->IsNumber()) {
    4366             :     uint32_t length;
    4367        7132 :     if (!args->at(0)->ToArrayLength(&length)) {
    4368         108 :       return ThrowArrayLengthRangeError(array->GetIsolate());
    4369             :     }
    4370             : 
    4371             :     // Optimize the case where there is one argument and the argument is a small
    4372             :     // smi.
    4373        3458 :     if (length > 0 && length < JSArray::kInitialMaxFastElementArray) {
    4374         303 :       ElementsKind elements_kind = array->GetElementsKind();
    4375         303 :       JSArray::Initialize(array, length, length);
    4376             : 
    4377         303 :       if (!IsHoleyElementsKind(elements_kind)) {
    4378             :         elements_kind = GetHoleyElementsKind(elements_kind);
    4379          40 :         JSObject::TransitionElementsKind(array, elements_kind);
    4380             :       }
    4381        3155 :     } else if (length == 0) {
    4382         630 :       JSArray::Initialize(array, JSArray::kPreallocatedArrayElements);
    4383             :     } else {
    4384             :       // Take the argument as the length.
    4385        2525 :       JSArray::Initialize(array, 0);
    4386        2525 :       JSArray::SetLength(array, length);
    4387             :     }
    4388        3458 :     return array;
    4389             :   }
    4390             : 
    4391             :   Factory* factory = array->GetIsolate()->factory();
    4392             : 
    4393             :   // Set length and elements on the array.
    4394             :   int number_of_elements = args->length();
    4395             :   JSObject::EnsureCanContainElements(
    4396      860944 :       array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS);
    4397             : 
    4398             :   // Allocate an appropriately typed elements array.
    4399      430472 :   ElementsKind elements_kind = array->GetElementsKind();
    4400             :   Handle<FixedArrayBase> elms;
    4401      430472 :   if (IsDoubleElementsKind(elements_kind)) {
    4402             :     elms = Handle<FixedArrayBase>::cast(
    4403      302249 :         factory->NewFixedDoubleArray(number_of_elements));
    4404             :   } else {
    4405             :     elms = Handle<FixedArrayBase>::cast(
    4406      128223 :         factory->NewFixedArrayWithHoles(number_of_elements));
    4407             :   }
    4408             : 
    4409             :   // Fill in the content
    4410             :   switch (elements_kind) {
    4411             :     case HOLEY_SMI_ELEMENTS:
    4412             :     case PACKED_SMI_ELEMENTS: {
    4413      126734 :       Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms);
    4414     7613826 :       for (int entry = 0; entry < number_of_elements; entry++) {
    4415     7487092 :         smi_elms->set(entry, (*args)[entry], SKIP_WRITE_BARRIER);
    4416             :       }
    4417             :       break;
    4418             :     }
    4419             :     case HOLEY_ELEMENTS:
    4420             :     case PACKED_ELEMENTS: {
    4421             :       DisallowHeapAllocation no_gc;
    4422        2978 :       WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
    4423        1489 :       Handle<FixedArray> object_elms = Handle<FixedArray>::cast(elms);
    4424     3263779 :       for (int entry = 0; entry < number_of_elements; entry++) {
    4425     3262290 :         object_elms->set(entry, (*args)[entry], mode);
    4426             :       }
    4427             :       break;
    4428             :     }
    4429             :     case HOLEY_DOUBLE_ELEMENTS:
    4430             :     case PACKED_DOUBLE_ELEMENTS: {
    4431             :       Handle<FixedDoubleArray> double_elms =
    4432      302249 :           Handle<FixedDoubleArray>::cast(elms);
    4433     2031964 :       for (int entry = 0; entry < number_of_elements; entry++) {
    4434     3459430 :         double_elms->set(entry, (*args)[entry]->Number());
    4435             :       }
    4436             :       break;
    4437             :     }
    4438             :     default:
    4439           0 :       UNREACHABLE();
    4440             :       break;
    4441             :   }
    4442             : 
    4443      430472 :   array->set_elements(*elms);
    4444      860944 :   array->set_length(Smi::FromInt(number_of_elements));
    4445      430472 :   return array;
    4446             : }
    4447             : 
    4448        3622 : void CopyFastNumberJSArrayElementsToTypedArray(Address raw_context,
    4449             :                                                Address raw_source,
    4450             :                                                Address raw_destination,
    4451             :                                                uintptr_t length,
    4452             :                                                uintptr_t offset) {
    4453        3622 :   Context context = Context::cast(Object(raw_context));
    4454        3622 :   JSArray source = JSArray::cast(Object(raw_source));
    4455        3622 :   JSTypedArray destination = JSTypedArray::cast(Object(raw_destination));
    4456             : 
    4457        3622 :   switch (destination->GetElementsKind()) {
    4458             : #define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype)                             \
    4459             :   case TYPE##_ELEMENTS:                                                        \
    4460             :     CHECK(Fixed##Type##ElementsAccessor::TryCopyElementsFastNumber(            \
    4461             :         context, source, destination, length, static_cast<uint32_t>(offset))); \
    4462             :     break;
    4463        3001 :     TYPED_ARRAYS(TYPED_ARRAYS_CASE)
    4464             : #undef TYPED_ARRAYS_CASE
    4465             :     default:
    4466           0 :       UNREACHABLE();
    4467             :   }
    4468        3622 : }
    4469             : 
    4470         649 : void CopyTypedArrayElementsToTypedArray(Address raw_source,
    4471             :                                         Address raw_destination,
    4472             :                                         uintptr_t length, uintptr_t offset) {
    4473         649 :   JSTypedArray source = JSTypedArray::cast(Object(raw_source));
    4474         649 :   JSTypedArray destination = JSTypedArray::cast(Object(raw_destination));
    4475             : 
    4476         649 :   switch (destination->GetElementsKind()) {
    4477             : #define TYPED_ARRAYS_CASE(Type, type, TYPE, ctype)                   \
    4478             :   case TYPE##_ELEMENTS:                                              \
    4479             :     Fixed##Type##ElementsAccessor::CopyElementsFromTypedArray(       \
    4480             :         source, destination, length, static_cast<uint32_t>(offset)); \
    4481             :     break;
    4482          27 :     TYPED_ARRAYS(TYPED_ARRAYS_CASE)
    4483             : #undef TYPED_ARRAYS_CASE
    4484             :     default:
    4485           0 :       UNREACHABLE();
    4486             :   }
    4487         649 : }
    4488             : 
    4489        2034 : void CopyTypedArrayElementsSlice(Address raw_source, Address raw_destination,
    4490             :                                  uintptr_t start, uintptr_t end) {
    4491        2034 :   JSTypedArray source = JSTypedArray::cast(Object(raw_source));
    4492        2034 :   JSTypedArray destination = JSTypedArray::cast(Object(raw_destination));
    4493             : 
    4494        2034 :   destination->GetElementsAccessor()->CopyTypedArrayElementsSlice(
    4495        2034 :       source, destination, start, end);
    4496        2034 : }
    4497             : 
    4498       59583 : void ElementsAccessor::InitializeOncePerProcess() {
    4499             :   static ElementsAccessor* accessor_array[] = {
    4500             : #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind),
    4501             :       ELEMENTS_LIST(ACCESSOR_ARRAY)
    4502             : #undef ACCESSOR_ARRAY
    4503     1370409 :   };
    4504             : 
    4505             :   STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
    4506             :                 kElementsKindCount);
    4507             : 
    4508       59583 :   elements_accessors_ = accessor_array;
    4509       59583 : }
    4510             : 
    4511             : 
    4512       58516 : void ElementsAccessor::TearDown() {
    4513      117032 :   if (elements_accessors_ == nullptr) return;
    4514             : #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind];
    4515       58466 :   ELEMENTS_LIST(ACCESSOR_DELETE)
    4516             : #undef ACCESSOR_DELETE
    4517       58466 :   elements_accessors_ = nullptr;
    4518             : }
    4519             : 
    4520      284551 : Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args,
    4521             :                                          uint32_t concat_size,
    4522             :                                          uint32_t result_len) {
    4523             :   ElementsKind result_elements_kind = GetInitialFastElementsKind();
    4524             :   bool has_raw_doubles = false;
    4525             :   {
    4526             :     DisallowHeapAllocation no_gc;
    4527             :     bool is_holey = false;
    4528      854056 :     for (uint32_t i = 0; i < concat_size; i++) {
    4529      569505 :       Object arg = (*args)[i];
    4530      569505 :       ElementsKind arg_kind = JSArray::cast(arg)->GetElementsKind();
    4531     1138946 :       has_raw_doubles = has_raw_doubles || IsDoubleElementsKind(arg_kind);
    4532      865689 :       is_holey = is_holey || IsHoleyElementsKind(arg_kind);
    4533             :       result_elements_kind =
    4534             :           GetMoreGeneralElementsKind(result_elements_kind, arg_kind);
    4535             :     }
    4536      284551 :     if (is_holey) {
    4537             :       result_elements_kind = GetHoleyElementsKind(result_elements_kind);
    4538             :     }
    4539             :   }
    4540             : 
    4541             :   // If a double array is concatted into a fast elements array, the fast
    4542             :   // elements array needs to be initialized to contain proper holes, since
    4543             :   // boxing doubles may cause incremental marking.
    4544             :   bool requires_double_boxing =
    4545      284652 :       has_raw_doubles && !IsDoubleElementsKind(result_elements_kind);
    4546             :   ArrayStorageAllocationMode mode = requires_double_boxing
    4547             :                                         ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE
    4548      284551 :                                         : DONT_INITIALIZE_ARRAY_ELEMENTS;
    4549             :   Handle<JSArray> result_array = isolate->factory()->NewJSArray(
    4550      284551 :       result_elements_kind, result_len, result_len, mode);
    4551      284551 :   if (result_len == 0) return result_array;
    4552             : 
    4553             :   uint32_t insertion_index = 0;
    4554      569102 :   Handle<FixedArrayBase> storage(result_array->elements(), isolate);
    4555             :   ElementsAccessor* accessor = ElementsAccessor::ForKind(result_elements_kind);
    4556      854056 :   for (uint32_t i = 0; i < concat_size; i++) {
    4557             :     // It is crucial to keep |array| in a raw pointer form to avoid
    4558             :     // performance degradation.
    4559     1139010 :     JSArray array = JSArray::cast((*args)[i]);
    4560      569505 :     uint32_t len = 0;
    4561     1139010 :     array->length()->ToArrayLength(&len);
    4562      570732 :     if (len == 0) continue;
    4563      568278 :     ElementsKind from_kind = array->GetElementsKind();
    4564      568278 :     accessor->CopyElements(array, 0, from_kind, storage, insertion_index, len);
    4565      568278 :     insertion_index += len;
    4566             :   }
    4567             : 
    4568             :   DCHECK_EQ(insertion_index, result_len);
    4569      284551 :   return result_array;
    4570             : }
    4571             : 
    4572             : ElementsAccessor** ElementsAccessor::elements_accessors_ = nullptr;
    4573             : 
    4574             : #undef ELEMENTS_LIST
    4575             : }  // namespace internal
    4576      178779 : }  // namespace v8

Generated by: LCOV version 1.10