Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/elements.cc b/src/elements.cc
index 288c60e..6c257ac 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -140,14 +140,11 @@
   if (copy_size == 0) return;
   FixedArray* from = FixedArray::cast(from_base);
   FixedArray* to = FixedArray::cast(to_base);
-  DCHECK(IsFastSmiOrObjectElementsKind(from_kind) ||
-         from_kind == FAST_STRING_WRAPPER_ELEMENTS);
+  DCHECK(IsFastSmiOrObjectElementsKind(from_kind));
   DCHECK(IsFastSmiOrObjectElementsKind(to_kind));
 
   WriteBarrierMode write_barrier_mode =
-      ((IsFastObjectElementsKind(from_kind) &&
-        IsFastObjectElementsKind(to_kind)) ||
-       from_kind == FAST_STRING_WRAPPER_ELEMENTS)
+      (IsFastObjectElementsKind(from_kind) && IsFastObjectElementsKind(to_kind))
           ? UPDATE_WRITE_BARRIER
           : SKIP_WRITE_BARRIER;
   for (int i = 0; i < copy_size; i++) {
@@ -466,8 +463,7 @@
 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
 // CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
 // specialization of SomeElementsAccessor methods).
-template <typename ElementsAccessorSubclass,
-          typename ElementsTraitsParam>
+template <typename Subclass, typename ElementsTraitsParam>
 class ElementsAccessorBase : public ElementsAccessor {
  public:
   explicit ElementsAccessorBase(const char* name)
@@ -495,12 +491,12 @@
     } else {
       length = fixed_array_base->length();
     }
-    ElementsAccessorSubclass::ValidateContents(holder, length);
+    Subclass::ValidateContents(holder, length);
   }
 
   void Validate(Handle<JSObject> holder) final {
     DisallowHeapAllocation no_gc;
-    ElementsAccessorSubclass::ValidateImpl(holder);
+    Subclass::ValidateImpl(holder);
   }
 
   static bool IsPackedImpl(Handle<JSObject> holder,
@@ -508,8 +504,7 @@
                            uint32_t end) {
     if (IsFastPackedElementsKind(kind())) return true;
     for (uint32_t i = start; i < end; i++) {
-      if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store,
-                                                    ALL_PROPERTIES)) {
+      if (!Subclass::HasElementImpl(holder, i, backing_store, ALL_PROPERTIES)) {
         return false;
       }
     }
@@ -520,8 +515,7 @@
     if (!IsHoleyElementsKind(kind())) return;
     int length = Smi::cast(array->length())->value();
     Handle<FixedArrayBase> backing_store(array->elements());
-    if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0,
-                                                length)) {
+    if (!Subclass::IsPackedImpl(array, backing_store, 0, length)) {
       return;
     }
     ElementsKind packed_kind = GetPackedElementsKind(kind());
@@ -537,20 +531,18 @@
   bool HasElement(Handle<JSObject> holder, uint32_t index,
                   Handle<FixedArrayBase> backing_store,
                   PropertyFilter filter) final {
-    return ElementsAccessorSubclass::HasElementImpl(holder, index,
-                                                    backing_store, filter);
+    return Subclass::HasElementImpl(holder, index, backing_store, filter);
   }
 
   static bool HasElementImpl(Handle<JSObject> holder, uint32_t index,
                              Handle<FixedArrayBase> backing_store,
                              PropertyFilter filter) {
-    return ElementsAccessorSubclass::GetEntryForIndexImpl(
-               *holder, *backing_store, index, filter) != kMaxUInt32;
+    return Subclass::GetEntryForIndexImpl(*holder, *backing_store, index,
+                                          filter) != kMaxUInt32;
   }
 
   bool HasAccessors(JSObject* holder) final {
-    return ElementsAccessorSubclass::HasAccessorsImpl(holder,
-                                                      holder->elements());
+    return Subclass::HasAccessorsImpl(holder, holder->elements());
   }
 
   static bool HasAccessorsImpl(JSObject* holder,
@@ -559,11 +551,11 @@
   }
 
   Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) final {
-    return ElementsAccessorSubclass::GetImpl(holder, entry);
+    return Subclass::GetImpl(holder, entry);
   }
 
   static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
-    return ElementsAccessorSubclass::GetImpl(holder->elements(), entry);
+    return Subclass::GetImpl(holder->elements(), entry);
   }
 
   static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
@@ -573,14 +565,13 @@
   }
 
   void Set(Handle<JSObject> holder, uint32_t entry, Object* value) final {
-    ElementsAccessorSubclass::SetImpl(holder, entry, value);
+    Subclass::SetImpl(holder, entry, value);
   }
 
   void Reconfigure(Handle<JSObject> object, Handle<FixedArrayBase> store,
                    uint32_t entry, Handle<Object> value,
                    PropertyAttributes attributes) final {
-    ElementsAccessorSubclass::ReconfigureImpl(object, store, entry, value,
-                                              attributes);
+    Subclass::ReconfigureImpl(object, store, entry, value, attributes);
   }
 
   static void ReconfigureImpl(Handle<JSObject> object,
@@ -592,8 +583,7 @@
 
   void Add(Handle<JSObject> object, uint32_t index, Handle<Object> value,
            PropertyAttributes attributes, uint32_t new_capacity) final {
-    ElementsAccessorSubclass::AddImpl(object, index, value, attributes,
-                                      new_capacity);
+    Subclass::AddImpl(object, index, value, attributes, new_capacity);
   }
 
   static void AddImpl(Handle<JSObject> object, uint32_t index,
@@ -604,7 +594,7 @@
 
   uint32_t Push(Handle<JSArray> receiver, Arguments* args,
                 uint32_t push_size) final {
-    return ElementsAccessorSubclass::PushImpl(receiver, args, push_size);
+    return Subclass::PushImpl(receiver, args, push_size);
   }
 
   static uint32_t PushImpl(Handle<JSArray> receiver, Arguments* args,
@@ -615,7 +605,7 @@
 
   uint32_t Unshift(Handle<JSArray> receiver, Arguments* args,
                    uint32_t unshift_size) final {
-    return ElementsAccessorSubclass::UnshiftImpl(receiver, args, unshift_size);
+    return Subclass::UnshiftImpl(receiver, args, unshift_size);
   }
 
   static uint32_t UnshiftImpl(Handle<JSArray> receiver, Arguments* args,
@@ -626,7 +616,7 @@
 
   Handle<JSArray> Slice(Handle<JSObject> receiver, uint32_t start,
                         uint32_t end) final {
-    return ElementsAccessorSubclass::SliceImpl(receiver, start, end);
+    return Subclass::SliceImpl(receiver, start, end);
   }
 
   static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
@@ -638,8 +628,7 @@
   Handle<JSArray> Splice(Handle<JSArray> receiver, uint32_t start,
                          uint32_t delete_count, Arguments* args,
                          uint32_t add_count) final {
-    return ElementsAccessorSubclass::SpliceImpl(receiver, start, delete_count,
-                                                args, add_count);
+    return Subclass::SpliceImpl(receiver, start, delete_count, args, add_count);
   }
 
   static Handle<JSArray> SpliceImpl(Handle<JSArray> receiver,
@@ -650,7 +639,7 @@
   }
 
   Handle<Object> Pop(Handle<JSArray> receiver) final {
-    return ElementsAccessorSubclass::PopImpl(receiver);
+    return Subclass::PopImpl(receiver);
   }
 
   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
@@ -659,7 +648,7 @@
   }
 
   Handle<Object> Shift(Handle<JSArray> receiver) final {
-    return ElementsAccessorSubclass::ShiftImpl(receiver);
+    return Subclass::ShiftImpl(receiver);
   }
 
   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
@@ -668,8 +657,8 @@
   }
 
   void SetLength(Handle<JSArray> array, uint32_t length) final {
-    ElementsAccessorSubclass::SetLengthImpl(array->GetIsolate(), array, length,
-                                            handle(array->elements()));
+    Subclass::SetLengthImpl(array->GetIsolate(), array, length,
+                            handle(array->elements()));
   }
 
   static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
@@ -713,7 +702,7 @@
     } else {
       // Check whether the backing store should be expanded.
       capacity = Max(length, JSObject::NewElementsCapacity(capacity));
-      ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity);
+      Subclass::GrowCapacityAndConvertImpl(array, capacity);
     }
 
     array->set_length(Smi::FromInt(length));
@@ -727,7 +716,7 @@
       return static_cast<uint32_t>(
           Smi::cast(JSArray::cast(receiver)->length())->value());
     }
-    return ElementsAccessorSubclass::GetCapacityImpl(receiver, elements);
+    return Subclass::GetCapacityImpl(receiver, elements);
   }
 
   static Handle<FixedArrayBase> ConvertElementsWithCapacity(
@@ -762,9 +751,8 @@
       packed_size = Smi::cast(JSArray::cast(*object)->length())->value();
     }
 
-    ElementsAccessorSubclass::CopyElementsImpl(
-        *old_elements, src_index, *new_elements, from_kind, dst_index,
-        packed_size, copy_size);
+    Subclass::CopyElementsImpl(*old_elements, src_index, *new_elements,
+                               from_kind, dst_index, packed_size, copy_size);
 
     return new_elements;
   }
@@ -784,12 +772,17 @@
     DCHECK(IsFastDoubleElementsKind(from_kind) !=
                IsFastDoubleElementsKind(kind()) ||
            IsDictionaryElementsKind(from_kind) ||
-           from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
            static_cast<uint32_t>(old_elements->length()) < capacity);
+    Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
+                                              kind(), capacity);
+  }
+
+  static void BasicGrowCapacityAndConvertImpl(
+      Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
+      ElementsKind from_kind, ElementsKind to_kind, uint32_t capacity) {
     Handle<FixedArrayBase> elements =
         ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
 
-    ElementsKind to_kind = kind();
     if (IsHoleyElementsKind(from_kind)) to_kind = GetHoleyElementsKind(to_kind);
     Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, to_kind);
     JSObject::SetMapAndElements(object, new_map, elements);
@@ -805,11 +798,11 @@
 
   void GrowCapacityAndConvert(Handle<JSObject> object,
                               uint32_t capacity) final {
-    ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity);
+    Subclass::GrowCapacityAndConvertImpl(object, capacity);
   }
 
   void Delete(Handle<JSObject> obj, uint32_t entry) final {
-    ElementsAccessorSubclass::DeleteImpl(obj, entry);
+    Subclass::DeleteImpl(obj, entry);
   }
 
   static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
@@ -833,7 +826,7 @@
       }
     }
     FixedArrayBase* from = from_holder->elements();
-    // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods
+    // NOTE: the Subclass::CopyElementsImpl() methods
     // violate the handlified function signature convention:
     // raw pointer parameters in the function that allocates. This is done
     // intentionally to avoid ArrayConcat() builtin performance degradation.
@@ -842,13 +835,12 @@
     // copying from object with fast double elements to object with object
     // elements. In all the other cases there are no allocations performed and
     // handle creation causes noticeable performance degradation of the builtin.
-    ElementsAccessorSubclass::CopyElementsImpl(
-        from, from_start, *to, from_kind, to_start, packed_size, copy_size);
+    Subclass::CopyElementsImpl(from, from_start, *to, from_kind, to_start,
+                               packed_size, copy_size);
   }
 
   Handle<SeededNumberDictionary> Normalize(Handle<JSObject> object) final {
-    return ElementsAccessorSubclass::NormalizeImpl(object,
-                                                   handle(object->elements()));
+    return Subclass::NormalizeImpl(object, handle(object->elements()));
   }
 
   static Handle<SeededNumberDictionary> NormalizeImpl(
@@ -861,7 +853,7 @@
                                      Handle<FixedArray> values_or_entries,
                                      bool get_entries, int* nof_items,
                                      PropertyFilter filter) {
-    return ElementsAccessorSubclass::CollectValuesOrEntriesImpl(
+    return Subclass::CollectValuesOrEntriesImpl(
         isolate, object, values_or_entries, get_entries, nof_items, filter);
   }
 
@@ -872,9 +864,8 @@
     int count = 0;
     KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES);
     accumulator.NextPrototype();
-    ElementsAccessorSubclass::CollectElementIndicesImpl(
-        object, handle(object->elements(), isolate), &accumulator, kMaxUInt32,
-        ALL_PROPERTIES, 0);
+    Subclass::CollectElementIndicesImpl(
+        object, handle(object->elements(), isolate), &accumulator);
     Handle<FixedArray> keys = accumulator.GetKeys();
 
     for (int i = 0; i < keys->length(); ++i) {
@@ -883,15 +874,14 @@
       uint32_t index;
       if (!key->ToUint32(&index)) continue;
 
-      uint32_t entry = ElementsAccessorSubclass::GetEntryForIndexImpl(
+      uint32_t entry = Subclass::GetEntryForIndexImpl(
           *object, object->elements(), index, filter);
       if (entry == kMaxUInt32) continue;
 
-      PropertyDetails details =
-          ElementsAccessorSubclass::GetDetailsImpl(*object, entry);
+      PropertyDetails details = Subclass::GetDetailsImpl(*object, entry);
 
       if (details.kind() == kData) {
-        value = ElementsAccessorSubclass::GetImpl(object, entry);
+        value = Subclass::GetImpl(object, entry);
       } else {
         LookupIterator it(isolate, object, index, LookupIterator::OWN);
         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
@@ -909,25 +899,20 @@
 
   void CollectElementIndices(Handle<JSObject> object,
                              Handle<FixedArrayBase> backing_store,
-                             KeyAccumulator* keys, uint32_t range,
-                             PropertyFilter filter, uint32_t offset) final {
-    if (filter & ONLY_ALL_CAN_READ) return;
-    ElementsAccessorSubclass::CollectElementIndicesImpl(
-        object, backing_store, keys, range, filter, offset);
+                             KeyAccumulator* keys) final {
+    if (keys->filter() & ONLY_ALL_CAN_READ) return;
+    Subclass::CollectElementIndicesImpl(object, backing_store, keys);
   }
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
+                                        KeyAccumulator* keys) {
     DCHECK_NE(DICTIONARY_ELEMENTS, kind());
     // Non-dictionary elements can't have all-can-read accessors.
     uint32_t length = GetIterationLength(*object, *backing_store);
-    if (range < length) length = range;
-    for (uint32_t i = offset; i < length; i++) {
-      if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
-                                                   filter)) {
+    PropertyFilter filter = keys->filter();
+    for (uint32_t i = 0; i < length; i++) {
+      if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
         keys->AddKey(i);
       }
     }
@@ -938,11 +923,9 @@
       Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
       PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices,
       uint32_t insertion_index = 0) {
-    uint32_t length =
-        ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
+    uint32_t length = Subclass::GetIterationLength(*object, *backing_store);
     for (uint32_t i = 0; i < length; i++) {
-      if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
-                                                   filter)) {
+      if (Subclass::HasElementImpl(object, i, backing_store, filter)) {
         if (convert == CONVERT_TO_STRING) {
           Handle<String> index_string = isolate->factory()->Uint32ToString(i);
           list->set(insertion_index, *index_string);
@@ -961,8 +944,8 @@
                                            Handle<FixedArray> keys,
                                            GetKeysConversion convert,
                                            PropertyFilter filter) final {
-    return ElementsAccessorSubclass::PrependElementIndicesImpl(
-        object, backing_store, keys, convert, filter);
+    return Subclass::PrependElementIndicesImpl(object, backing_store, keys,
+                                               convert, filter);
   }
 
   static Handle<FixedArray> PrependElementIndicesImpl(
@@ -972,14 +955,14 @@
     Isolate* isolate = object->GetIsolate();
     uint32_t nof_property_keys = keys->length();
     uint32_t initial_list_length =
-        ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store);
+        Subclass::GetCapacityImpl(*object, *backing_store);
     initial_list_length += nof_property_keys;
 
     // Collect the element indices into a new list.
     uint32_t nof_indices = 0;
     Handle<FixedArray> combined_keys =
         isolate->factory()->NewFixedArray(initial_list_length);
-    combined_keys = ElementsAccessorSubclass::DirectCollectElementIndicesImpl(
+    combined_keys = Subclass::DirectCollectElementIndicesImpl(
         isolate, object, backing_store, convert, filter, combined_keys,
         &nof_indices);
 
@@ -1011,13 +994,10 @@
                        &array_length) &&
                    array_length <= Smi::kMaxValue)) {
         // Since we use std::sort above, the GC will no longer know where the
-        // HeapNumbers are, hence we have to write them again.
-        // For Arrays with valid Smi length, we are sure to have no HeapNumber
-        // indices and thus we can skip this step.
-        for (uint32_t i = 0; i < nof_indices; i++) {
-          Object* index = combined_keys->get(i);
-          combined_keys->set(i, index);
-        }
+        // HeapNumbers are.  For Arrays with valid Smi length, we are sure to
+        // have no HeapNumber indices and thus we can skip this step.
+        FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(isolate->heap(), *combined_keys, 0,
+                                           nof_indices);
       }
     }
 
@@ -1038,8 +1018,7 @@
   void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
                                    KeyAccumulator* accumulator,
                                    AddKeyConversion convert) final {
-    ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl(
-        receiver, accumulator, convert);
+    Subclass::AddElementsToKeyAccumulatorImpl(receiver, accumulator, convert);
   }
 
   static uint32_t GetCapacityImpl(JSObject* holder,
@@ -1048,7 +1027,7 @@
   }
 
   uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final {
-    return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store);
+    return Subclass::GetCapacityImpl(holder, backing_store);
   }
 
   static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store,
@@ -1060,8 +1039,7 @@
                                        FixedArrayBase* backing_store,
                                        uint32_t index, PropertyFilter filter) {
     if (IsHoleyElementsKind(kind())) {
-      return index < ElementsAccessorSubclass::GetCapacityImpl(holder,
-                                                               backing_store) &&
+      return index < Subclass::GetCapacityImpl(holder, backing_store) &&
                      !BackingStore::cast(backing_store)->is_the_hole(index)
                  ? index
                  : kMaxUInt32;
@@ -1073,8 +1051,8 @@
 
   uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store,
                             uint32_t index) final {
-    return ElementsAccessorSubclass::GetEntryForIndexImpl(
-        holder, backing_store, index, ALL_PROPERTIES);
+    return Subclass::GetEntryForIndexImpl(holder, backing_store, index,
+                                          ALL_PROPERTIES);
   }
 
   static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
@@ -1087,7 +1065,7 @@
   }
 
   PropertyDetails GetDetails(JSObject* holder, uint32_t entry) final {
-    return ElementsAccessorSubclass::GetDetailsImpl(holder, entry);
+    return Subclass::GetDetailsImpl(holder, entry);
   }
 
  private:
@@ -1333,16 +1311,15 @@
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
-    if (filter & SKIP_STRINGS) return;
+                                        KeyAccumulator* keys) {
+    if (keys->filter() & SKIP_STRINGS) return;
     Isolate* isolate = keys->isolate();
     Handle<Object> undefined = isolate->factory()->undefined_value();
     Handle<Object> the_hole = isolate->factory()->the_hole_value();
     Handle<SeededNumberDictionary> dictionary =
         Handle<SeededNumberDictionary>::cast(backing_store);
     int capacity = dictionary->Capacity();
+    PropertyFilter filter = keys->filter();
     for (int i = 0; i < capacity; i++) {
       uint32_t key =
           GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole);
@@ -1403,21 +1380,18 @@
 
 
 // Super class for all fast element arrays.
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
-class FastElementsAccessor
-    : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
+template <typename Subclass, typename KindTraits>
+class FastElementsAccessor : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit FastElementsAccessor(const char* name)
-      : ElementsAccessorBase<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {}
 
   typedef typename KindTraits::BackingStore BackingStore;
 
   static Handle<SeededNumberDictionary> NormalizeImpl(
       Handle<JSObject> object, Handle<FixedArrayBase> store) {
     Isolate* isolate = store->GetIsolate();
-    ElementsKind kind = FastElementsAccessorSubclass::kind();
+    ElementsKind kind = Subclass::kind();
 
     // Ensure that notifications fire if the array or object prototypes are
     // normalizing.
@@ -1436,7 +1410,7 @@
       if (IsHoleyElementsKind(kind)) {
         if (BackingStore::cast(*store)->is_the_hole(i)) continue;
       }
-      Handle<Object> value = FastElementsAccessorSubclass::GetImpl(*store, i);
+      Handle<Object> value = Subclass::GetImpl(*store, i);
       dictionary = SeededNumberDictionary::AddNumberEntry(
           dictionary, i, value, details, used_as_prototype);
       j++;
@@ -1453,7 +1427,9 @@
     }
     if (entry == 0) {
       FixedArray* empty = heap->empty_fixed_array();
-      if (obj->HasFastArgumentsElements()) {
+      // Dynamically ask for the elements kind here since we manually redirect
+      // the operations for argument backing stores.
+      if (obj->GetElementsKind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
         FixedArray::cast(obj->elements())->set(1, empty);
       } else {
         obj->set_elements(empty);
@@ -1538,14 +1514,13 @@
                       uint32_t new_capacity) {
     DCHECK_EQ(NONE, attributes);
     ElementsKind from_kind = object->GetElementsKind();
-    ElementsKind to_kind = FastElementsAccessorSubclass::kind();
+    ElementsKind to_kind = Subclass::kind();
     if (IsDictionaryElementsKind(from_kind) ||
         IsFastDoubleElementsKind(from_kind) !=
             IsFastDoubleElementsKind(to_kind) ||
-        FastElementsAccessorSubclass::GetCapacityImpl(
-            *object, object->elements()) != new_capacity) {
-      FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object,
-                                                               new_capacity);
+        Subclass::GetCapacityImpl(*object, object->elements()) !=
+            new_capacity) {
+      Subclass::GrowCapacityAndConvertImpl(object, new_capacity);
     } else {
       if (IsFastElementsKind(from_kind) && from_kind != to_kind) {
         JSObject::TransitionElementsKind(object, to_kind);
@@ -1555,7 +1530,7 @@
         JSObject::EnsureWritableFastElements(object);
       }
     }
-    FastElementsAccessorSubclass::SetImpl(object, index, *value);
+    Subclass::SetImpl(object, index, *value);
   }
 
   static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
@@ -1578,13 +1553,11 @@
                                               AddKeyConversion convert) {
     Handle<FixedArrayBase> elements(receiver->elements(),
                                     receiver->GetIsolate());
-    uint32_t length =
-        FastElementsAccessorSubclass::GetIterationLength(*receiver, *elements);
+    uint32_t length = Subclass::GetIterationLength(*receiver, *elements);
     for (uint32_t i = 0; i < length; i++) {
       if (IsFastPackedElementsKind(KindTraits::Kind) ||
           HasEntryImpl(*elements, i)) {
-        accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i),
-                            convert);
+        accumulator->AddKey(Subclass::GetImpl(*elements, i), convert);
       }
     }
   }
@@ -1592,16 +1565,20 @@
   static void ValidateContents(Handle<JSObject> holder, int length) {
 #if DEBUG
     Isolate* isolate = holder->GetIsolate();
+    Heap* heap = isolate->heap();
     HandleScope scope(isolate);
     Handle<FixedArrayBase> elements(holder->elements(), isolate);
     Map* map = elements->map();
-    DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
-            (map == isolate->heap()->fixed_array_map() ||
-             map == isolate->heap()->fixed_cow_array_map())) ||
-           (IsFastDoubleElementsKind(KindTraits::Kind) ==
-            ((map == isolate->heap()->fixed_array_map() && length == 0) ||
-             map == isolate->heap()->fixed_double_array_map())));
+    if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
+      DCHECK_NE(map, heap->fixed_double_array_map());
+    } else if (IsFastDoubleElementsKind(KindTraits::Kind)) {
+      DCHECK_NE(map, heap->fixed_cow_array_map());
+      if (map == heap->fixed_array_map()) DCHECK_EQ(0, length);
+    } else {
+      UNREACHABLE();
+    }
     if (length == 0) return;  // nothing to do!
+#if ENABLE_SLOW_DCHECKS
     DisallowHeapAllocation no_gc;
     Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
     if (IsFastSmiElementsKind(KindTraits::Kind)) {
@@ -1610,30 +1587,38 @@
                (IsFastHoleyElementsKind(KindTraits::Kind) &&
                 backing_store->is_the_hole(i)));
       }
+    } else if (KindTraits::Kind == FAST_ELEMENTS ||
+               KindTraits::Kind == FAST_DOUBLE_ELEMENTS) {
+      for (int i = 0; i < length; i++) {
+        DCHECK(!backing_store->is_the_hole(i));
+      }
+    } else {
+      DCHECK(IsFastHoleyElementsKind(KindTraits::Kind));
     }
 #endif
+#endif
   }
 
   static Handle<Object> PopImpl(Handle<JSArray> receiver) {
-    return FastElementsAccessorSubclass::RemoveElement(receiver, AT_END);
+    return Subclass::RemoveElement(receiver, AT_END);
   }
 
   static Handle<Object> ShiftImpl(Handle<JSArray> receiver) {
-    return FastElementsAccessorSubclass::RemoveElement(receiver, AT_START);
+    return Subclass::RemoveElement(receiver, AT_START);
   }
 
   static uint32_t PushImpl(Handle<JSArray> receiver,
                            Arguments* args, uint32_t push_size) {
     Handle<FixedArrayBase> backing_store(receiver->elements());
-    return FastElementsAccessorSubclass::AddArguments(receiver, backing_store,
-                                                      args, push_size, AT_END);
+    return Subclass::AddArguments(receiver, backing_store, args, push_size,
+                                  AT_END);
   }
 
   static uint32_t UnshiftImpl(Handle<JSArray> receiver,
                               Arguments* args, uint32_t unshift_size) {
     Handle<FixedArrayBase> backing_store(receiver->elements());
-    return FastElementsAccessorSubclass::AddArguments(
-        receiver, backing_store, args, unshift_size, AT_START);
+    return Subclass::AddArguments(receiver, backing_store, args, unshift_size,
+                                  AT_START);
   }
 
   static Handle<JSArray> SliceImpl(Handle<JSObject> receiver,
@@ -1644,11 +1629,10 @@
     Handle<JSArray> result_array = isolate->factory()->NewJSArray(
         KindTraits::Kind, result_len, result_len);
     DisallowHeapAllocation no_gc;
-    FastElementsAccessorSubclass::CopyElementsImpl(
-        *backing_store, start, result_array->elements(), KindTraits::Kind, 0,
-        kPackedSizeNotKnown, result_len);
-    FastElementsAccessorSubclass::TryTransitionResultArrayToPacked(
-        result_array);
+    Subclass::CopyElementsImpl(*backing_store, start, result_array->elements(),
+                               KindTraits::Kind, 0, kPackedSizeNotKnown,
+                               result_len);
+    Subclass::TryTransitionResultArrayToPacked(result_array);
     return result_array;
   }
 
@@ -1681,29 +1665,26 @@
         KindTraits::Kind, delete_count, delete_count);
     if (delete_count > 0) {
       DisallowHeapAllocation no_gc;
-      FastElementsAccessorSubclass::CopyElementsImpl(
-          *backing_store, start, deleted_elements->elements(), KindTraits::Kind,
-          0, kPackedSizeNotKnown, delete_count);
+      Subclass::CopyElementsImpl(*backing_store, start,
+                                 deleted_elements->elements(), KindTraits::Kind,
+                                 0, kPackedSizeNotKnown, delete_count);
     }
 
     // Delete and move elements to make space for add_count new elements.
     if (add_count < delete_count) {
-      FastElementsAccessorSubclass::SpliceShrinkStep(
-          isolate, receiver, backing_store, start, delete_count, add_count,
-          length, new_length);
+      Subclass::SpliceShrinkStep(isolate, receiver, backing_store, start,
+                                 delete_count, add_count, length, new_length);
     } else if (add_count > delete_count) {
-      backing_store = FastElementsAccessorSubclass::SpliceGrowStep(
-          isolate, receiver, backing_store, start, delete_count, add_count,
-          length, new_length);
+      backing_store =
+          Subclass::SpliceGrowStep(isolate, receiver, backing_store, start,
+                                   delete_count, add_count, length, new_length);
     }
 
     // Copy over the arguments.
-    FastElementsAccessorSubclass::CopyArguments(args, backing_store, add_count,
-                                                3, start);
+    Subclass::CopyArguments(args, backing_store, add_count, 3, start);
 
     receiver->set_length(Smi::FromInt(new_length));
-    FastElementsAccessorSubclass::TryTransitionResultArrayToPacked(
-        deleted_elements);
+    Subclass::TryTransitionResultArrayToPacked(deleted_elements);
     return deleted_elements;
   }
 
@@ -1715,8 +1696,7 @@
     uint32_t length = object->elements()->length();
     for (uint32_t index = 0; index < length; ++index) {
       if (!HasEntryImpl(object->elements(), index)) continue;
-      Handle<Object> value =
-          FastElementsAccessorSubclass::GetImpl(object->elements(), index);
+      Handle<Object> value = Subclass::GetImpl(object->elements(), index);
       if (get_entries) {
         value = MakeEntryPair(isolate, index, value);
       }
@@ -1765,9 +1745,9 @@
                                uint32_t new_length) {
     const int move_left_count = len - delete_count - start;
     const int move_left_dst_index = start + add_count;
-    FastElementsAccessorSubclass::MoveElements(
-        isolate, receiver, backing_store, move_left_dst_index,
-        start + delete_count, move_left_count, new_length, len);
+    Subclass::MoveElements(isolate, receiver, backing_store,
+                           move_left_dst_index, start + delete_count,
+                           move_left_count, new_length, len);
   }
 
   // SpliceGrowStep might modify the backing_store.
@@ -1780,23 +1760,22 @@
     DCHECK((add_count - delete_count) <= (Smi::kMaxValue - length));
     // Check if backing_store is big enough.
     if (new_length <= static_cast<uint32_t>(backing_store->length())) {
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, start + add_count,
-          start + delete_count, (length - delete_count - start), 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store,
+                             start + add_count, start + delete_count,
+                             (length - delete_count - start), 0, 0);
       // MoveElements updates the backing_store in-place.
       return backing_store;
     }
     // New backing storage is needed.
     int capacity = JSObject::NewElementsCapacity(new_length);
     // Partially copy all elements up to start.
-    Handle<FixedArrayBase> new_elms =
-        FastElementsAccessorSubclass::ConvertElementsWithCapacity(
-            receiver, backing_store, KindTraits::Kind, capacity, start);
+    Handle<FixedArrayBase> new_elms = Subclass::ConvertElementsWithCapacity(
+        receiver, backing_store, KindTraits::Kind, capacity, start);
     // Copy the trailing elements after start + delete_count
-    FastElementsAccessorSubclass::CopyElementsImpl(
-        *backing_store, start + delete_count, *new_elms, KindTraits::Kind,
-        start + add_count, kPackedSizeNotKnown,
-        ElementsAccessor::kCopyToEndAndInitializeToHole);
+    Subclass::CopyElementsImpl(*backing_store, start + delete_count, *new_elms,
+                               KindTraits::Kind, start + add_count,
+                               kPackedSizeNotKnown,
+                               ElementsAccessor::kCopyToEndAndInitializeToHole);
     receiver->set_elements(*new_elms);
     return new_elms;
   }
@@ -1815,14 +1794,12 @@
     DCHECK(length > 0);
     int new_length = length - 1;
     int remove_index = remove_position == AT_START ? 0 : new_length;
-    Handle<Object> result =
-        FastElementsAccessorSubclass::GetImpl(*backing_store, remove_index);
+    Handle<Object> result = Subclass::GetImpl(*backing_store, remove_index);
     if (remove_position == AT_START) {
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, 0, 1, new_length, 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store, 0, 1, new_length,
+                             0, 0);
     }
-    FastElementsAccessorSubclass::SetLengthImpl(isolate, receiver, new_length,
-                                                backing_store);
+    Subclass::SetLengthImpl(isolate, receiver, new_length, backing_store);
 
     if (IsHoleyElementsKind(kind) && result->IsTheHole()) {
       return isolate->factory()->undefined_value();
@@ -1833,7 +1810,7 @@
   static uint32_t AddArguments(Handle<JSArray> receiver,
                                Handle<FixedArrayBase> backing_store,
                                Arguments* args, uint32_t add_size,
-                               Where remove_position) {
+                               Where add_position) {
     uint32_t length = Smi::cast(receiver->length())->value();
     DCHECK(0 < add_size);
     uint32_t elms_len = backing_store->length();
@@ -1845,24 +1822,23 @@
       // New backing storage is needed.
       uint32_t capacity = JSObject::NewElementsCapacity(new_length);
       // If we add arguments to the start we have to shift the existing objects.
-      int copy_dst_index = remove_position == AT_START ? add_size : 0;
+      int copy_dst_index = add_position == AT_START ? add_size : 0;
       // Copy over all objects to a new backing_store.
-      backing_store = FastElementsAccessorSubclass::ConvertElementsWithCapacity(
+      backing_store = Subclass::ConvertElementsWithCapacity(
           receiver, backing_store, KindTraits::Kind, capacity, 0,
           copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole);
       receiver->set_elements(*backing_store);
-    } else if (remove_position == AT_START) {
+    } else if (add_position == AT_START) {
       // If the backing store has enough capacity and we add elements to the
       // start we have to shift the existing objects.
       Isolate* isolate = receiver->GetIsolate();
-      FastElementsAccessorSubclass::MoveElements(
-          isolate, receiver, backing_store, add_size, 0, length, 0, 0);
+      Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0,
+                             length, 0, 0);
     }
 
-    int insertion_index = remove_position == AT_START ? 0 : length;
+    int insertion_index = add_position == AT_START ? 0 : length;
     // Copy the arguments to the start.
-    FastElementsAccessorSubclass::CopyArguments(args, backing_store, add_size,
-                                                1, insertion_index);
+    Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index);
     // Set the length.
     receiver->set_length(Smi::FromInt(new_length));
     return new_length;
@@ -1876,22 +1852,19 @@
     FixedArrayBase* raw_backing_store = *dst_store;
     WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc);
     for (uint32_t i = 0; i < copy_size; i++) {
-      Object* argument = (*args)[i + src_index];
-      FastElementsAccessorSubclass::SetImpl(raw_backing_store, i + dst_index,
-                                            argument, mode);
+      Object* argument = (*args)[src_index + i];
+      DCHECK(!argument->IsTheHole());
+      Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode);
     }
   }
 };
 
-
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
+template <typename Subclass, typename KindTraits>
 class FastSmiOrObjectElementsAccessor
-    : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
+    : public FastElementsAccessor<Subclass, KindTraits> {
  public:
   explicit FastSmiOrObjectElementsAccessor(const char* name)
-      : FastElementsAccessor<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : FastElementsAccessor<Subclass, KindTraits>(name) {}
 
   static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
                              Object* value) {
@@ -1909,8 +1882,7 @@
   }
 
   static Object* GetRaw(FixedArray* backing_store, uint32_t entry) {
-    uint32_t index = FastElementsAccessorSubclass::GetIndexForEntryImpl(
-        backing_store, entry);
+    uint32_t index = Subclass::GetIndexForEntryImpl(backing_store, entry);
     return backing_store->get(index);
   }
 
@@ -1931,7 +1903,6 @@
       case FAST_HOLEY_SMI_ELEMENTS:
       case FAST_ELEMENTS:
       case FAST_HOLEY_ELEMENTS:
-      case FAST_STRING_WRAPPER_ELEMENTS:
         CopyObjectToObjectElements(from, from_kind, from_start, to, to_kind,
                                    to_start, copy_size);
         break;
@@ -1943,12 +1914,13 @@
         break;
       }
       case DICTIONARY_ELEMENTS:
-      case SLOW_STRING_WRAPPER_ELEMENTS:
         CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
                                        copy_size);
         break;
       case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
       case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
+      case FAST_STRING_WRAPPER_ELEMENTS:
+      case SLOW_STRING_WRAPPER_ELEMENTS:
 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
       TYPED_ARRAYS(TYPED_ARRAY_CASE)
 #undef TYPED_ARRAY_CASE
@@ -2010,15 +1982,12 @@
           ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {}
 };
 
-
-template<typename FastElementsAccessorSubclass,
-         typename KindTraits>
+template <typename Subclass, typename KindTraits>
 class FastDoubleElementsAccessor
-    : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> {
+    : public FastElementsAccessor<Subclass, KindTraits> {
  public:
   explicit FastDoubleElementsAccessor(const char* name)
-      : FastElementsAccessor<FastElementsAccessorSubclass,
-                             KindTraits>(name) {}
+      : FastElementsAccessor<Subclass, KindTraits>(name) {}
 
   static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
     return GetImpl(holder->elements(), entry);
@@ -2239,16 +2208,12 @@
 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
 #undef FIXED_ELEMENTS_ACCESSOR
 
-
-template <typename SloppyArgumentsElementsAccessorSubclass,
-          typename ArgumentsAccessor, typename KindTraits>
+template <typename Subclass, typename ArgumentsAccessor, typename KindTraits>
 class SloppyArgumentsElementsAccessor
-    : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
-                                  KindTraits> {
+    : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit SloppyArgumentsElementsAccessor(const char* name)
-      : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
-                             KindTraits>(name) {
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {
     USE(KindTraits::Kind);
   }
 
@@ -2384,7 +2349,7 @@
     FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
     uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments,
                                                              index, filter);
-    if (entry == kMaxUInt32) return entry;
+    if (entry == kMaxUInt32) return kMaxUInt32;
     return (parameter_map->length() - 2) + entry;
   }
 
@@ -2414,31 +2379,24 @@
       // would enable GC of the context.
       parameter_map->set_the_hole(entry + 2);
     } else {
-      SloppyArgumentsElementsAccessorSubclass::DeleteFromArguments(
-          obj, entry - length);
+      Subclass::DeleteFromArguments(obj, entry - length);
     }
   }
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
+                                        KeyAccumulator* keys) {
     FixedArray* parameter_map = FixedArray::cast(*backing_store);
     uint32_t length = parameter_map->length() - 2;
-    if (range < length) length = range;
-
-    for (uint32_t i = offset; i < length; ++i) {
+    for (uint32_t i = 0; i < length; ++i) {
       if (!parameter_map->get(i + 2)->IsTheHole()) {
         keys->AddKey(i);
       }
     }
 
     Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1)));
-    ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys, range,
-                                                 filter, offset);
-    if (SloppyArgumentsElementsAccessorSubclass::kind() ==
-        FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
+    ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys);
+    if (Subclass::kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
       keys->SortCurrentElementsList();
     }
   }
@@ -2568,16 +2526,45 @@
             FastHoleyObjectElementsAccessor,
             ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
 
+  static Handle<FixedArray> GetArguments(Isolate* isolate,
+                                         FixedArrayBase* backing_store) {
+    FixedArray* parameter_map = FixedArray::cast(backing_store);
+    return Handle<FixedArray>(FixedArray::cast(parameter_map->get(1)), isolate);
+  }
+
+  static Handle<JSArray> SliceImpl(Handle<JSObject> receiver, uint32_t start,
+                                   uint32_t end) {
+    Isolate* isolate = receiver->GetIsolate();
+    uint32_t result_len = end < start ? 0u : end - start;
+    Handle<JSArray> result_array = isolate->factory()->NewJSArray(
+        FAST_HOLEY_ELEMENTS, result_len, result_len);
+    DisallowHeapAllocation no_gc;
+    FixedArray* elements = FixedArray::cast(result_array->elements());
+    FixedArray* parameters = FixedArray::cast(receiver->elements());
+    uint32_t insertion_index = 0;
+    for (uint32_t i = start; i < end; i++) {
+      uint32_t entry =
+          GetEntryForIndexImpl(*receiver, parameters, i, ALL_PROPERTIES);
+      if (entry != kMaxUInt32 && HasEntryImpl(parameters, entry)) {
+        elements->set(insertion_index, *GetImpl(parameters, entry));
+      } else {
+        elements->set_the_hole(insertion_index);
+      }
+      insertion_index++;
+    }
+    return result_array;
+  }
+
   static Handle<SeededNumberDictionary> NormalizeImpl(
       Handle<JSObject> object, Handle<FixedArrayBase> elements) {
-    FixedArray* parameter_map = FixedArray::cast(*elements);
-    Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+    Handle<FixedArray> arguments =
+        GetArguments(elements->GetIsolate(), *elements);
     return FastHoleyObjectElementsAccessor::NormalizeImpl(object, arguments);
   }
 
   static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) {
-    FixedArray* parameter_map = FixedArray::cast(obj->elements());
-    Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
+    Handle<FixedArray> arguments =
+        GetArguments(obj->GetIsolate(), obj->elements());
     FastHoleyObjectElementsAccessor::DeleteCommon(obj, entry, arguments);
   }
 
@@ -2650,15 +2637,12 @@
   }
 };
 
-template <typename StringWrapperElementsAccessorSubclass,
-          typename BackingStoreAccessor, typename KindTraits>
+template <typename Subclass, typename BackingStoreAccessor, typename KindTraits>
 class StringWrapperElementsAccessor
-    : public ElementsAccessorBase<StringWrapperElementsAccessorSubclass,
-                                  KindTraits> {
+    : public ElementsAccessorBase<Subclass, KindTraits> {
  public:
   explicit StringWrapperElementsAccessor(const char* name)
-      : ElementsAccessorBase<StringWrapperElementsAccessorSubclass, KindTraits>(
-            name) {
+      : ElementsAccessorBase<Subclass, KindTraits>(name) {
     USE(KindTraits::Kind);
   }
 
@@ -2722,8 +2706,7 @@
         (object->GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS ||
          BackingStoreAccessor::GetCapacityImpl(*object, object->elements()) !=
              new_capacity)) {
-      StringWrapperElementsAccessorSubclass::GrowCapacityAndConvertImpl(
-          object, new_capacity);
+      GrowCapacityAndConvertImpl(object, new_capacity);
     }
     BackingStoreAccessor::AddImpl(object, index, value, attributes,
                                   new_capacity);
@@ -2760,23 +2743,41 @@
 
   static void CollectElementIndicesImpl(Handle<JSObject> object,
                                         Handle<FixedArrayBase> backing_store,
-                                        KeyAccumulator* keys, uint32_t range,
-                                        PropertyFilter filter,
-                                        uint32_t offset) {
+                                        KeyAccumulator* keys) {
     uint32_t length = GetString(*object)->length();
     for (uint32_t i = 0; i < length; i++) {
       keys->AddKey(i);
     }
-    BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store, keys,
-                                                    range, filter, offset);
+    BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store,
+                                                    keys);
+  }
+
+  static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
+                                         uint32_t capacity) {
+    Handle<FixedArrayBase> old_elements(object->elements());
+    ElementsKind from_kind = object->GetElementsKind();
+    // This method should only be called if there's a reason to update the
+    // elements.
+    DCHECK(from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
+           static_cast<uint32_t>(old_elements->length()) < capacity);
+    Subclass::BasicGrowCapacityAndConvertImpl(object, old_elements, from_kind,
+                                              FAST_STRING_WRAPPER_ELEMENTS,
+                                              capacity);
   }
 
   static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
                                FixedArrayBase* to, ElementsKind from_kind,
                                uint32_t to_start, int packed_size,
                                int copy_size) {
-    BackingStoreAccessor::CopyElementsImpl(from, from_start, to, from_kind,
-                                           to_start, packed_size, copy_size);
+    DCHECK(!to->IsDictionary());
+    if (from_kind == SLOW_STRING_WRAPPER_ELEMENTS) {
+      CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
+                                     to_start, copy_size);
+    } else {
+      DCHECK_EQ(FAST_STRING_WRAPPER_ELEMENTS, from_kind);
+      CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to,
+                                 FAST_HOLEY_ELEMENTS, to_start, copy_size);
+    }
   }
 
  private:
@@ -2914,7 +2915,7 @@
   }
 
   // Fill in the content
-  switch (array->GetElementsKind()) {
+  switch (elements_kind) {
     case FAST_HOLEY_SMI_ELEMENTS:
     case FAST_SMI_ELEMENTS: {
       Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms);
@@ -2975,31 +2976,17 @@
   elements_accessors_ = NULL;
 }
 
-
 Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args,
-                                         uint32_t concat_size) {
-  const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
-  STATIC_ASSERT(FixedDoubleArray::kMaxLength < kHalfOfMaxInt);
-  USE(kHalfOfMaxInt);
-  uint32_t result_len = 0;
-  bool has_raw_doubles = false;
+                                         uint32_t concat_size,
+                                         uint32_t result_len) {
   ElementsKind result_elements_kind = GetInitialFastElementsKind();
+  bool has_raw_doubles = false;
   {
     DisallowHeapAllocation no_gc;
     bool is_holey = false;
-    // Iterate through all the arguments performing checks
-    // and calculating total length.
     for (uint32_t i = 0; i < concat_size; i++) {
-      JSArray* array = JSArray::cast((*args)[i]);
-      uint32_t len = 0;
-      array->length()->ToArrayLength(&len);
-
-      // We shouldn't overflow when adding another len.
-      result_len += len;
-      DCHECK(0 <= result_len);
-      DCHECK(result_len <= FixedDoubleArray::kMaxLength);
-
-      ElementsKind arg_kind = array->GetElementsKind();
+      Object* arg = (*args)[i];
+      ElementsKind arg_kind = JSArray::cast(arg)->GetElementsKind();
       has_raw_doubles = has_raw_doubles || IsFastDoubleElementsKind(arg_kind);
       is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
       result_elements_kind =