LCOV - code coverage report
Current view: top level - src - elements.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1138 1318 86.3 %
Date: 2017-04-26 Functions: 752 1632 46.1 %

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

Generated by: LCOV version 1.10