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

Generated by: LCOV version 1.10