LCOV - code coverage report
Current view: top level - src - elements.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1142 1342 85.1 %
Date: 2017-10-20 Functions: 823 1727 47.7 %

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

Generated by: LCOV version 1.10