LCOV - code coverage report
Current view: top level - src - elements.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1203 1470 81.8 %
Date: 2019-04-17 Functions: 864 1950 44.3 %

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

Generated by: LCOV version 1.10