13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Redistribution and use in source and binary forms, with or without
369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// modification, are permitted provided that the following conditions are
469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// met:
569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Redistributions of source code must retain the above copyright
769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       notice, this list of conditions and the following disclaimer.
869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Redistributions in binary form must reproduce the above
969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       copyright notice, this list of conditions and the following
1069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       disclaimer in the documentation and/or other materials provided
1169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       with the distribution.
1269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     * Neither the name of Google Inc. nor the names of its
1369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       contributors may be used to endorse or promote products derived
1469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       from this software without specific prior written permission.
1569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
1669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
2869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "v8.h"
2969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
3069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "objects.h"
3169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "elements.h"
3269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#include "utils.h"
3369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Each concrete ElementsAccessor can handle exactly one ElementsKind,
363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// several abstract ElementsAccessor classes are used to allow sharing
373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// common code.
383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//
393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Inheritance hierarchy:
403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// - ElementsAccessorBase                        (abstract)
413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   - FastElementsAccessor                      (abstract)
423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - FastObjectElementsAccessor
433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - FastDoubleElementsAccessor
443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   - ExternalElementsAccessor                  (abstract)
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalByteElementsAccessor
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalUnsignedByteElementsAccessor
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalShortElementsAccessor
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalUnsignedShortElementsAccessor
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalIntElementsAccessor
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalUnsignedIntElementsAccessor
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalFloatElementsAccessor
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - ExternalDoubleElementsAccessor
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//     - PixelElementsAccessor
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   - DictionaryElementsAccessor
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch//   - NonStrictArgumentsElementsAccessor
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace v8 {
5969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace internal {
6069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// First argument in list is the accessor class, the second argument is the
633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// accessor ElementsKind, and the third is the backing store class.  Use the
643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// fast element handler for smi-only arrays.  The implementation is currently
653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// identical.  Note that the order must match that of the ElementsKind enum for
663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// the |accessor_array[]| below to work.
673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define ELEMENTS_LIST(V)                                                \
683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray)     \
693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray)              \
703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \
713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS,                    \
723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SeededNumberDictionary)                                             \
733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS,  \
743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FixedArray)                                                         \
753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS,               \
763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalByteArray)                                                  \
773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalUnsignedByteElementsAccessor,                               \
783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray)         \
793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS,             \
803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalShortArray)                                                 \
813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalUnsignedShortElementsAccessor,                              \
823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray)       \
833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS,                 \
843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ExternalIntArray)                                                   \
853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalUnsignedIntElementsAccessor,                                \
863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray)           \
873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalFloatElementsAccessor,                                      \
883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray)                        \
893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(ExternalDoubleElementsAccessor,                                     \
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray)                      \
913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate<ElementsKind Kind> class ElementsKindTraits {
953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef FixedArrayBase BackingStore;
973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define ELEMENTS_TRAITS(Class, KindParam, Store)               \
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate<> class ElementsKindTraits<KindParam> {               \
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  public:                                                      \
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const ElementsKind Kind = KindParam;                  \
1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef Store BackingStore;                                  \
1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochELEMENTS_LIST(ELEMENTS_TRAITS)
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef ELEMENTS_TRAITS
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochElementsAccessor** ElementsAccessor::elements_accessors_;
11069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool HasKey(FixedArray* array, Object* key) {
11369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  int len0 = array->length();
11469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  for (int i = 0; i < len0; i++) {
11569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Object* element = array->get(i);
11669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (element->IsSmi() && element == key) return true;
11769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (element->IsString() &&
11869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        key->IsString() && String::cast(element)->Equals(String::cast(key))) {
11969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return true;
12069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
12169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
12269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  return false;
12369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
12469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Failure* ThrowArrayLengthRangeError(Heap* heap) {
1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HandleScope scope(heap->isolate());
1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return heap->isolate()->Throw(
1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      *heap->isolate()->factory()->NewRangeError("invalid_array_length",
1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          HandleVector<Object>(NULL, 0)));
1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CopyObjectToObjectElements(FixedArray* from,
1353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                ElementsKind from_kind,
1363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                uint32_t from_start,
1373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                FixedArray* to,
1383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                ElementsKind to_kind,
1393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                uint32_t to_start,
1403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                int raw_copy_size) {
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(to->map() != HEAP->fixed_cow_array_map());
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS);
1433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
1443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_copy_size < 0) {
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
1483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = Min(from->length() - from_start,
1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    to->length() - to_start);
1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // marked with the hole.
1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
1553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(to->get(i)->IsTheHole());
1563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
1623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return;
1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address to_address = to->address() + FixedArray::kHeaderSize;
1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address from_address = from->address() + FixedArray::kHeaderSize;
1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            reinterpret_cast<Object**>(from_address) + from_start,
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            copy_size);
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) {
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Heap* heap = from->GetHeap();
1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!heap->InNewSpace(to)) {
1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      heap->RecordWrites(to->address(),
1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         to->OffsetOfElementAt(to_start),
1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         copy_size);
1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    heap->incremental_marking()->RecordWrites(to);
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           uint32_t from_start,
1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           FixedArray* to,
1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           ElementsKind to_kind,
1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           uint32_t to_start,
1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int raw_copy_size) {
1863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Heap* heap = from->GetHeap();
1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_copy_size < 0) {
1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
1913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = from->max_number_key() + 1 - from_start;
1923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // marked with the hole.
1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
1973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(to->get(i)->IsTheHole());
1983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
1993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(to != from);
2033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
2043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return;
2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t to_length = to->length();
2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (to_start + copy_size > to_length) {
2073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = to_length - to_start;
2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < copy_size; i++) {
2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int entry = from->FindEntry(i + from_start);
2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* value = from->ValueAt(entry);
2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!value->IsTheHole());
2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set(i + to_start, value, SKIP_WRITE_BARRIER);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set_the_hole(i + to_start);
2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (to_kind == FAST_ELEMENTS) {
2203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!heap->InNewSpace(to)) {
2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      heap->RecordWrites(to->address(),
2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         to->OffsetOfElementAt(to_start),
2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         copy_size);
2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    heap->incremental_marking()->RecordWrites(to);
2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2303ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FixedDoubleArray* from,
2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t from_start,
2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FixedArray* to,
2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKind to_kind,
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t to_start,
2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int raw_copy_size) {
2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_copy_size < 0) {
2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
2413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
2423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = Min(from->length() - from_start,
2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    to->length() - to_start);
2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // marked with the hole.
2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(to->get(i)->IsTheHole());
2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return from;
2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < copy_size; ++i) {
2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (to_kind == FAST_SMI_ONLY_ELEMENTS) {
2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      UNIMPLEMENTED();
2603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return Failure::Exception();
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
2623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* maybe_value = from->get(i + from_start);
2633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* value;
2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(to_kind == FAST_ELEMENTS);
2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects
2663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // iteratively, the allocate must succeed within a single GC cycle,
2673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // otherwise the retry after the GC will also fail. In order to ensure
2683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // that no GC is triggered, allocate HeapNumbers from old space if they
2693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // can't be taken from new space.
2703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!maybe_value->ToObject(&value)) {
2713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory());
2723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap* heap = from->GetHeap();
2733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MaybeObject* maybe_value_object =
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            heap->AllocateHeapNumber(from->get_scalar(i + from_start),
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     TENURED);
2763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
2783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set(i + to_start, value, UPDATE_WRITE_BARRIER);
2793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
2803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
2813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return to;
2823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
2833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
2853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CopyDoubleToDoubleElements(FixedDoubleArray* from,
2863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
2873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedDoubleArray* to,
2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int raw_copy_size) {
2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_copy_size < 0) {
2923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
2933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
2943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = Min(from->length() - from_start,
2953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                    to->length() - to_start);
2963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
2973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
2983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        to->set_the_hole(i);
2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
3033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
3043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return;
3053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
3063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
3073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  to_address += kDoubleSize * to_start;
3083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  from_address += kDoubleSize * from_start;
3093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int words_per_double = (kDoubleSize / kPointerSize);
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  CopyWords(reinterpret_cast<Object**>(to_address),
3113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            reinterpret_cast<Object**>(from_address),
3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            words_per_double * copy_size);
3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CopyObjectToDoubleElements(FixedArray* from,
3173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
3183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedDoubleArray* to,
3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int raw_copy_size) {
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (raw_copy_size < 0) {
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = from->length() - from_start;
3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        to->set_the_hole(i);
3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return;
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < copy_size; i++) {
3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* hole_or_object = from->get(i + from_start);
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (hole_or_object->IsTheHole()) {
3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set_the_hole(i + to_start);
3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set(i + to_start, hole_or_object->Number());
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CopyDictionaryToDoubleElements(SeededNumberDictionary* from,
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           uint32_t from_start,
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           FixedDoubleArray* to,
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           uint32_t to_start,
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                           int raw_copy_size) {
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int copy_size = raw_copy_size;
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size < 0) {
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(copy_size == ElementsAccessor::kCopyToEnd ||
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = from->max_number_key() + 1 - from_start;
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        to->set_the_hole(i);
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (copy_size == 0) return;
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t to_length = to->length();
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (to_start + copy_size > to_length) {
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    copy_size = to_length - to_start;
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < copy_size; i++) {
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int entry = from->FindEntry(i + from_start);
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set(i + to_start, from->ValueAt(entry)->Number());
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      to->set_the_hole(i + to_start);
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
37869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Base class for element handler implementations. Contains the
37969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// the common logic for objects with different ElementsKinds.
38069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Subclasses must specialize method for which the element
38169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// implementation differs from the base class implementation.
38269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
38369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// This class is intended to be used in the following way:
38469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
38569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//   class SomeElementsAccessor :
38669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       public ElementsAccessorBase<SomeElementsAccessor,
38769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//                                   BackingStoreClass> {
38869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     ...
38969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//   }
39069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
39169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// This is an example of the Curiously Recurring Template Pattern (see
39269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
39369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
39469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// specialization of SomeElementsAccessor methods).
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename ElementsAccessorSubclass,
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          typename ElementsTraitsParam>
39769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ElementsAccessorBase : public ElementsAccessor {
39869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ElementsAccessorBase(const char* name)
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ElementsAccessor(name) { }
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef ElementsTraitsParam ElementsTraits;
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename ElementsTraitsParam::BackingStore BackingStore;
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual ElementsKind kind() const { return ElementsTraits::Kind; }
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool HasElementImpl(Object* receiver,
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSObject* holder,
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             uint32_t key,
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             BackingStore* backing_store) {
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    MaybeObject* element =
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return !element->IsTheHole();
4145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual bool HasElement(Object* receiver,
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          JSObject* holder,
4185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          uint32_t key,
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                          FixedArrayBase* backing_store) {
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (backing_store == NULL) {
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      backing_store = holder->elements();
4225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::HasElementImpl(
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        receiver, holder, key, BackingStore::cast(backing_store));
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual MaybeObject* Get(Object* receiver,
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           JSObject* holder,
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           uint32_t key,
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           FixedArrayBase* backing_store) {
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (backing_store == NULL) {
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      backing_store = holder->elements();
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::GetImpl(
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        receiver, holder, key, BackingStore::cast(backing_store));
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              JSObject* obj,
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              uint32_t key,
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              BackingStore* backing_store) {
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store))
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           ? backing_store->get(key)
4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           : backing_store->GetHeap()->the_hole_value();
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual MaybeObject* SetLength(JSArray* array,
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 Object* length) {
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::SetLengthImpl(
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        array, length, BackingStore::cast(array->elements()));
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Object* length,
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    BackingStore* backing_store);
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual MaybeObject* SetCapacityAndLength(JSArray* array,
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int capacity,
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                            int length) {
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        array,
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        capacity,
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        length);
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       int capacity,
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       int length) {
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNIMPLEMENTED();
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return obj;
471c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
472c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
47369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
47469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
47569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) = 0;
47669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedArrayBase* to,
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       ElementsKind to_kind,
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int copy_size) {
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return NULL;
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual MaybeObject* CopyElements(JSObject* from_holder,
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    uint32_t from_start,
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    FixedArrayBase* to,
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKind to_kind,
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    uint32_t to_start,
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    int copy_size,
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    FixedArrayBase* from) {
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (from == NULL) {
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      from = from_holder->elements();
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (from->length() == 0) {
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return from;
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::CopyElementsImpl(
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        from, from_start, to, to_kind, to_start, copy_size);
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  virtual MaybeObject* AddElementsToFixedArray(Object* receiver,
50585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch                                               JSObject* holder,
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FixedArray* to,
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                               FixedArrayBase* from) {
50869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int len0 = to->length();
50969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#ifdef DEBUG
51069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (FLAG_enable_slow_asserts) {
51169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      for (int i = 0; i < len0; i++) {
51269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!to->get(i)->IsTheHole());
51369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
51469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
51569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#endif
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (from == NULL) {
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      from = holder->elements();
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    BackingStore* backing_store = BackingStore::cast(from);
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store);
52169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
52269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Optimize if 'other' is empty.
52369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // We cannot optimize if 'this' is empty, as other may have holes.
52469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (len1 == 0) return to;
52569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
52669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Compute how many elements are not in other.
5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t extra = 0;
52869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for (uint32_t y = 0; y < len1; y++) {
5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      uint32_t key =
5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (ElementsAccessorSubclass::HasElementImpl(
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              receiver, holder, key, backing_store)) {
53369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_value =
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ElementsAccessorSubclass::GetImpl(receiver, holder,
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              key, backing_store);
53669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* value;
53769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_value->ToObject(&value)) return maybe_value;
53869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!value->IsTheHole());
53969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!HasKey(to, value)) {
54069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          extra++;
54169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
54269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
54369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
54469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
54569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (extra == 0) return to;
54669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
54769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Allocate the result
54869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* result;
54969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    MaybeObject* maybe_obj =
55069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        backing_store->GetHeap()->AllocateFixedArray(len0 + extra);
55169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
55269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
55369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Fill in the content
55469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    {
55569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      AssertNoAllocation no_gc;
55669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
55769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      for (int i = 0; i < len0; i++) {
55869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* e = to->get(i);
55969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(e->IsString() || e->IsNumber());
56069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        result->set(i, e, mode);
56169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
56269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
56369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Fill in the extra values.
5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t index = 0;
56569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for (uint32_t y = 0; y < len1; y++) {
5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      uint32_t key =
5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (ElementsAccessorSubclass::HasElementImpl(
5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              receiver, holder, key, backing_store)) {
57069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_value =
5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ElementsAccessorSubclass::GetImpl(receiver, holder,
5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              key, backing_store);
57369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* value;
57469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_value->ToObject(&value)) return maybe_value;
57569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!value->IsTheHole() && !HasKey(to, value)) {
57669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          result->set(len0 + index, value);
57769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          index++;
57869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
57969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
58069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
58169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ASSERT(extra == index);
58269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return result;
58369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
58469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
58569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static uint32_t GetCapacityImpl(BackingStore* backing_store) {
58769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return backing_store->length();
58869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
58969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
59069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::GetCapacityImpl(
5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        BackingStore::cast(backing_store));
59369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
59469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
5963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     uint32_t index) {
59769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return index;
59869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
59969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
60069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
6013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  uint32_t index) {
6023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return ElementsAccessorSubclass::GetKeyForIndexImpl(
6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        BackingStore::cast(backing_store), index);
60469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
60569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
60669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private:
60769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
60869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
60969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
61069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Super class for all fast element arrays.
6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate<typename FastElementsAccessorSubclass,
6133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         typename KindTraits,
6143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         int ElementSize>
61569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass FastElementsAccessor
6163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
6175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
6183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit FastElementsAccessor(const char* name)
6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ElementsAccessorBase<FastElementsAccessorSubclass,
6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             KindTraits>(name) {}
6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch protected:
6223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
6233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename KindTraits::BackingStore BackingStore;
6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Adjusts the length of the fast backing store or returns the new length or
6273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // undefined in case conversion to a slow backing store should be performed.
6283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store,
6293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                JSArray* array,
6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Object* length_object,
6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                uint32_t length) {
6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t old_capacity = backing_store->length();
6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check whether the backing store should be shrunk.
6353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (length <= old_capacity) {
6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (array->HasFastTypeElements()) {
6373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        MaybeObject* maybe_obj = array->EnsureWritableFastElements();
6383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (!maybe_obj->To(&backing_store)) return maybe_obj;
6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (2 * length <= old_capacity) {
6413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // If more than half the elements won't be used, trim the array.
6423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (length == 0) {
6433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          array->initialize_elements();
6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        } else {
6453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          backing_store->set_length(length);
6463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Address filler_start = backing_store->address() +
6473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              BackingStore::OffsetOfElementAt(length);
6483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          int filler_size = (old_capacity - length) * ElementSize;
6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
6523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Otherwise, fill the unused tail with holes.
6533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int old_length = FastD2I(array->length()->Number());
6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = length; i < old_length; i++) {
6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          backing_store->set_the_hole(i);
6563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
6583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return length_object;
6593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Check whether the backing store should be expanded.
6623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t min = JSObject::NewElementsCapacity(old_capacity);
6633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t new_capacity = length > min ? length : min;
6643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (!array->ShouldConvertToSlowElements(new_capacity)) {
6653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* result = FastElementsAccessorSubclass::
6663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SetFastElementsCapacityAndLength(array, new_capacity, length);
6673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (result->IsFailure()) return result;
6683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return length_object;
6693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Request conversion to slow elements.
6723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return array->GetHeap()->undefined_value();
6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch};
6753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass FastObjectElementsAccessor
6783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : public FastElementsAccessor<FastObjectElementsAccessor,
6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ElementsKindTraits<FAST_ELEMENTS>,
6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kPointerSize> {
6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit FastObjectElementsAccessor(const char* name)
6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : FastElementsAccessor<FastObjectElementsAccessor,
6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ElementsKindTraits<FAST_ELEMENTS>,
6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             kPointerSize>(name) {}
6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
68769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static MaybeObject* DeleteCommon(JSObject* obj,
68869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   uint32_t key) {
6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(obj->HasFastElements() ||
6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           obj->HasFastSmiOnlyElements() ||
6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           obj->HasFastArgumentsElements());
69269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Heap* heap = obj->GetHeap();
69369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* backing_store = FixedArray::cast(obj->elements());
69469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
69569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(backing_store->get(1));
69669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
69769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* writable;
69869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      MaybeObject* maybe = obj->EnsureWritableFastElements();
69969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (!maybe->ToObject(&writable)) return maybe;
70069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(writable);
70169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
70269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t length = static_cast<uint32_t>(
70369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        obj->IsJSArray()
70469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? Smi::cast(JSArray::cast(obj)->length())->value()
70569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : backing_store->length());
70669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (key < length) {
70769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store->set_the_hole(key);
70869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // If an old space backing store is larger than a certain size and
70969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // has too few used values, normalize it.
71069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // To avoid doing the check on every delete we require at least
71169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // one adjacent hole to the value being deleted.
71269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* hole = heap->the_hole_value();
71369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      const int kMinLengthForSparsenessCheck = 64;
71469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (backing_store->length() >= kMinLengthForSparsenessCheck &&
71569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          !heap->InNewSpace(backing_store) &&
71669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ((key > 0 && backing_store->get(key - 1) == hole) ||
71769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           (key + 1 < length && backing_store->get(key + 1) == hole))) {
71869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        int num_used = 0;
71969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        for (int i = 0; i < backing_store->length(); ++i) {
72069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (backing_store->get(i) != hole) ++num_used;
72169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          // Bail out early if more than 1/4 is used.
72269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (4 * num_used > backing_store->length()) break;
72369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
72469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (4 * num_used <= backing_store->length()) {
72569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          MaybeObject* result = obj->NormalizeElements();
72669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (result->IsFailure()) return result;
72769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
72869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
72969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
73069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return heap->true_value();
73169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
73269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
7343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedArrayBase* to,
7363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       ElementsKind to_kind,
7373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int copy_size) {
7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (to_kind) {
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS: {
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CopyObjectToObjectElements(
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedArray::cast(from), ElementsTraits::Kind, from_start,
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedArray::cast(to), to_kind, to_start, copy_size);
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return from;
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CopyObjectToDoubleElements(
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedArray::cast(from), from_start,
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedDoubleArray::cast(to), to_start, copy_size);
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return from;
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return to->GetHeap()->undefined_value();
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       uint32_t capacity,
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       uint32_t length) {
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    JSObject::SetFastElementsCapacityMode set_capacity_mode =
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        obj->HasFastSmiOnlyElements()
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            ? JSObject::kAllowSmiOnlyElements
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            : JSObject::kDontAllowSmiOnlyElements;
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return obj->SetFastElementsCapacityAndLength(capacity,
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 length,
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 set_capacity_mode);
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
771c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch protected:
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class FastElementsAccessor<FastObjectElementsAccessor,
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKindTraits<FAST_ELEMENTS>,
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    kPointerSize>;
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
77669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
77769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
77869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
77969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return DeleteCommon(obj, key);
78069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
78169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
78269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
78369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
78469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass FastDoubleElementsAccessor
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : public FastElementsAccessor<FastDoubleElementsAccessor,
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  kDoubleSize> {
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit FastDoubleElementsAccessor(const char* name)
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : FastElementsAccessor<FastDoubleElementsAccessor,
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             kDoubleSize>(name) {}
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       uint32_t capacity,
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                       uint32_t length) {
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return obj->SetFastDoubleElementsCapacityAndLength(capacity, length);
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
80069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
80169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<FastDoubleElementsAccessor,
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class FastElementsAccessor<FastDoubleElementsAccessor,
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    kDoubleSize>;
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedArrayBase* to,
8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       ElementsKind to_kind,
8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int copy_size) {
8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (to_kind) {
8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
8163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return CopyDoubleToObjectElements(
8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
8183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            to_kind, to_start, copy_size);
8193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
8203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
8213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   FixedDoubleArray::cast(to),
8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   to_start, copy_size);
8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return from;
8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return to->GetHeap()->undefined_value();
8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
83069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
83169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
83269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int length = obj->IsJSArray()
83469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? Smi::cast(JSArray::cast(obj)->length())->value()
83569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : FixedDoubleArray::cast(obj->elements())->length();
83669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (key < static_cast<uint32_t>(length)) {
83769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
83869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
83969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
84069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
84169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool HasElementImpl(Object* receiver,
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSObject* holder,
8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             uint32_t key,
8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FixedDoubleArray* backing_store) {
8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return key < static_cast<uint32_t>(backing_store->length()) &&
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        !backing_store->is_the_hole(key);
84869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
85169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
85269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Super class for all external element arrays.
85369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochtemplate<typename ExternalElementsAccessorSubclass,
8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         ElementsKind Kind>
85569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalElementsAccessor
85669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ElementsKindTraits<Kind> > {
8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalElementsAccessor(const char* name)
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ElementsAccessorBase<ExternalElementsAccessorSubclass,
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ElementsKindTraits<Kind> >(name) {}
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
86369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
8653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
86669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
8673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKindTraits<Kind> >;
868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
8693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
8703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              JSObject* obj,
8713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              uint32_t key,
8723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              BackingStore* backing_store) {
8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return
8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? backing_store->get(key)
8763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : backing_store->GetHeap()->undefined_value();
8773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Object* length,
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    BackingStore* backing_store) {
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // External arrays do not support changing their length.
8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNREACHABLE();
8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return obj;
88569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
88669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
88769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
88869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
88969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
89069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // External arrays always ignore deletes.
89169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
89269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
8933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool HasElementImpl(Object* receiver,
8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSObject* holder,
8963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             uint32_t key,
8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             BackingStore* backing_store) {
8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t capacity =
8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return key < capacity;
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
90269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
90369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
90469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
90569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalByteElementsAccessor
90669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalByteElementsAccessor,
9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_BYTE_ELEMENTS> {
9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalByteElementsAccessor(const char* name)
9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalByteElementsAccessor,
9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_BYTE_ELEMENTS>(name) {}
91269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
91369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
91469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
91569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedByteElementsAccessor
91669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalUnsignedByteElementsAccessor(const char* name)
9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
92269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
92369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalShortElementsAccessor
92669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalShortElementsAccessor,
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_SHORT_ELEMENTS> {
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalShortElementsAccessor(const char* name)
9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalShortElementsAccessor,
9313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_SHORT_ELEMENTS>(name) {}
93269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
93369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
93469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
93569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedShortElementsAccessor
93669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalUnsignedShortElementsAccessor(const char* name)
9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
94269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
94369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalIntElementsAccessor
94669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalIntElementsAccessor,
9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_INT_ELEMENTS> {
9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalIntElementsAccessor(const char* name)
9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalIntElementsAccessor,
9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_INT_ELEMENTS>(name) {}
95269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
95369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedIntElementsAccessor
95669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_UNSIGNED_INT_ELEMENTS> {
9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalUnsignedIntElementsAccessor(const char* name)
9603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
9613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
96269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
96369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
96469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
96569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalFloatElementsAccessor
96669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
9673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_FLOAT_ELEMENTS> {
9683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalFloatElementsAccessor(const char* name)
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalFloatElementsAccessor,
9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_FLOAT_ELEMENTS>(name) {}
97269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
97369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
97469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
97569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalDoubleElementsAccessor
97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_DOUBLE_ELEMENTS> {
9783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit ExternalDoubleElementsAccessor(const char* name)
9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<ExternalDoubleElementsAccessor,
9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_DOUBLE_ELEMENTS>(name) {}
98269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
98369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
98469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
98569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass PixelElementsAccessor
98669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<PixelElementsAccessor,
9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                      EXTERNAL_PIXEL_ELEMENTS> {
9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
9893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit PixelElementsAccessor(const char* name)
9903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ExternalElementsAccessor<PixelElementsAccessor,
9913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                 EXTERNAL_PIXEL_ELEMENTS>(name) {}
99269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
99369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
99469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
99569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass DictionaryElementsAccessor
99669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ElementsAccessorBase<DictionaryElementsAccessor,
9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ElementsKindTraits<DICTIONARY_ELEMENTS> > {
99869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
9993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit DictionaryElementsAccessor(const char* name)
10003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ElementsAccessorBase<DictionaryElementsAccessor,
10013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Adjusts the length of the dictionary backing store and returns the new
10043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // length according to ES5 section 15.4.5.2 behavior.
10053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict,
10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                JSArray* array,
10073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Object* length_object,
10083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                uint32_t length) {
10093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (length == 0) {
10103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // If the length of a slow array is reset to zero, we clear
10113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // the array and flush backing storage. This has the added
10123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // benefit that the array returns to fast mode.
10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* obj;
10143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* maybe_obj = array->ResetElements();
10153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
10163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
10173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      uint32_t new_length = length;
10183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
10193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (new_length < old_length) {
10203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Find last non-deletable element in range of elements to be
10213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // deleted and adjust range accordingly.
10223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Heap* heap = array->GetHeap();
10233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int capacity = dict->Capacity();
10243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < capacity; i++) {
10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Object* key = dict->KeyAt(i);
10263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (key->IsNumber()) {
10273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            uint32_t number = static_cast<uint32_t>(key->Number());
10283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (new_length <= number && number < old_length) {
10293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              PropertyDetails details = dict->DetailsAt(i);
10303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              if (details.IsDontDelete()) new_length = number + 1;
10313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
10323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
10333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (new_length != length) {
10353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
10363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (!maybe_object->To(&length_object)) return maybe_object;
10373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Remove elements that should be deleted.
10403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int removed_entries = 0;
10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Object* the_hole_value = heap->the_hole_value();
10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < capacity; i++) {
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Object* key = dict->KeyAt(i);
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (key->IsNumber()) {
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            uint32_t number = static_cast<uint32_t>(key->Number());
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (new_length <= number && number < old_length) {
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              dict->SetEntry(i, the_hole_value, the_hole_value);
10483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              removed_entries++;
10493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
10503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // Update the number of elements.
10543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        dict->ElementsRemoved(removed_entries);
10553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
10563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
10573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return length_object;
10583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
106069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static MaybeObject* DeleteCommon(JSObject* obj,
106169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   uint32_t key,
106269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   JSReceiver::DeleteMode mode) {
106369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Isolate* isolate = obj->GetIsolate();
106469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Heap* heap = isolate->heap();
106569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* backing_store = FixedArray::cast(obj->elements());
106669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    bool is_arguments =
1067589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS);
106869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (is_arguments) {
106969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(backing_store->get(1));
107069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
1071c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SeededNumberDictionary* dictionary =
1072c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        SeededNumberDictionary::cast(backing_store);
107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int entry = dictionary->FindEntry(key);
1074c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
107569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* result = dictionary->DeleteProperty(entry, mode);
107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (result == heap->true_value()) {
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_elements = dictionary->Shrink(key);
107869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        FixedArray* new_elements = NULL;
107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_elements->To(&new_elements)) {
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          return maybe_elements;
108169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
108269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (is_arguments) {
108369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          FixedArray::cast(obj->elements())->set(1, new_elements);
108469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        } else {
108569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          obj->set_elements(new_elements);
108669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
108769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (mode == JSObject::STRICT_DELETION &&
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          result == heap->false_value()) {
109069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // In strict mode, attempting to delete a non-configurable property
109169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // throws an exception.
109269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        HandleScope scope(isolate);
109369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> holder(obj);
109469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> args[2] = { name, holder };
109669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> error =
109769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            isolate->factory()->NewTypeError("strict_delete_property",
109869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                             HandleVector(args, 2));
109969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return isolate->Throw(*error);
110069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
110169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
110269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return heap->true_value();
110369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
110469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
11073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedArrayBase* to,
11083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       ElementsKind to_kind,
11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int copy_size) {
11113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    switch (to_kind) {
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_ELEMENTS:
11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CopyDictionaryToObjectElements(
11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            SeededNumberDictionary::cast(from), from_start,
11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedArray::cast(to), to_kind, to_start, copy_size);
11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return from;
11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      case FAST_DOUBLE_ELEMENTS:
11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        CopyDictionaryToDoubleElements(
11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            SeededNumberDictionary::cast(from), from_start,
11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            FixedDoubleArray::cast(to), to_start, copy_size);
11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return from;
11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      default:
11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        UNREACHABLE();
11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return to->GetHeap()->undefined_value();
11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
113069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
113169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<DictionaryElementsAccessor,
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    ElementsKindTraits<DICTIONARY_ELEMENTS> >;
113369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
113469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
113569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
113669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
113769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return DeleteCommon(obj, key, mode);
113869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
113969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              JSObject* obj,
11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              uint32_t key,
11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              SeededNumberDictionary* backing_store) {
114469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int entry = backing_store->FindEntry(key);
1145c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* element = backing_store->ValueAt(entry);
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      PropertyDetails details = backing_store->DetailsAt(entry);
114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (details.type() == CALLBACKS) {
114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return obj->GetElementWithCallback(receiver,
115069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           element,
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           key,
115269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           obj);
115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
115469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return element;
115569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
115669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
115769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->the_hole_value();
115869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
115969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool HasElementImpl(Object* receiver,
11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSObject* holder,
11623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             uint32_t key,
11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             SeededNumberDictionary* backing_store) {
11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return backing_store->FindEntry(key) !=
11653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        SeededNumberDictionary::kNotFound;
11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict,
11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     uint32_t index) {
117069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Object* key = dict->KeyAt(index);
117169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Smi::cast(key)->value();
117269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
117369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
117469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
117569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochclass NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    NonStrictArgumentsElementsAccessor,
11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
11793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch public:
11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  explicit NonStrictArgumentsElementsAccessor(const char* name)
11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : ElementsAccessorBase<
11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          NonStrictArgumentsElementsAccessor,
11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {}
118469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  friend class ElementsAccessorBase<
11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      NonStrictArgumentsElementsAccessor,
11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >;
118869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              JSObject* obj,
11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              uint32_t key,
11923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              FixedArray* parameter_map) {
11933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* probe = GetParameterMapArg(obj, parameter_map, key);
119469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
119569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Context* context = Context::cast(parameter_map->get(0));
119669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      int context_index = Smi::cast(probe)->value();
119769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ASSERT(!context->get(context_index)->IsTheHole());
119869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return context->get(context_index);
119969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
120069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Object is not mapped, defer to the arguments.
120169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
12023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get(
12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          receiver, obj, key, arguments);
12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* result;
12053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!maybe_result->ToObject(&result)) return maybe_result;
12063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // Elements of the arguments object in slow mode might be slow aliases.
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (result->IsAliasedArgumentsEntry()) {
12083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(result);
12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Context* context = Context::cast(parameter_map->get(0));
12103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int context_index = entry->aliased_context_slot();
12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ASSERT(!context->get(context_index)->IsTheHole());
12123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return context->get(context_index);
12133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
12143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return result;
12153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
121769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
121869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
12203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    Object* length,
12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    FixedArray* parameter_map) {
12223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // TODO(mstarzinger): This was never implemented but will be used once we
12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // correctly implement [[DefineOwnProperty]] on arrays.
12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    UNIMPLEMENTED();
12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return obj;
12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
122869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              uint32_t key,
123069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* parameter_map = FixedArray::cast(obj->elements());
12323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* probe = GetParameterMapArg(obj, parameter_map, key);
123369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
123469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // TODO(kmillikin): We could check if this was the last aliased
123569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // parameter, and revert to normal elements in that case.  That
123669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // would enable GC of the context.
123769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parameter_map->set_the_hole(key + 2);
123869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
123969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
124069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (arguments->IsDictionary()) {
124169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
124269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return FastObjectElementsAccessor::DeleteCommon(obj, key);
124469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
124569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
124669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
124769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
124869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
12503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t from_start,
12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       FixedArrayBase* to,
12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       ElementsKind to_kind,
12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       uint32_t to_start,
12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                       int copy_size) {
12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FixedArray* parameter_map = FixedArray::cast(from);
12563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
12573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
12583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return accessor->CopyElements(NULL, from_start, to, to_kind,
12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  to_start, copy_size, arguments);
12603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
126369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Max(static_cast<uint32_t>(parameter_map->length() - 2),
126569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               ForArray(arguments)->GetCapacity(arguments));
126669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
126769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static uint32_t GetKeyForIndexImpl(FixedArray* dict,
12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                     uint32_t index) {
127069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return index;
127169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
127269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static bool HasElementImpl(Object* receiver,
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             JSObject* holder,
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             uint32_t key,
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                             FixedArray* parameter_map) {
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Object* probe = GetParameterMapArg(holder, parameter_map, key);
127869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
127969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return true;
128069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
128169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
128269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return !accessor->Get(receiver, holder, key, arguments)->IsTheHole();
128469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
128569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
128669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
128769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private:
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static Object* GetParameterMapArg(JSObject* holder,
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                    FixedArray* parameter_map,
129069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                    uint32_t key) {
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t length = holder->IsJSArray()
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ? Smi::cast(JSArray::cast(holder)->length())->value()
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        : parameter_map->length();
129469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return key < (length - 2 )
129569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? parameter_map->get(key + 2)
129669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : parameter_map->GetHeap()->the_hole_value();
129769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
129869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
129969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
130069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
130169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
130269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  switch (array->map()->instance_type()) {
130369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case FIXED_ARRAY_TYPE:
130469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (array->IsDictionary()) {
1305589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return elements_accessors_[DICTIONARY_ELEMENTS];
130669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
1307589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return elements_accessors_[FAST_ELEMENTS];
130869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
130969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_BYTE_ARRAY_TYPE:
1310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
131169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
131369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_SHORT_ARRAY_TYPE:
1314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_SHORT_ELEMENTS];
131569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
131769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_INT_ARRAY_TYPE:
1318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_INT_ELEMENTS];
131969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS];
132169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_FLOAT_ARRAY_TYPE:
1322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS];
132369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_DOUBLE_ARRAY_TYPE:
1324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS];
132569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_PIXEL_ARRAY_TYPE:
1326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS];
132769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    default:
132869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      UNREACHABLE();
132969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return NULL;
133069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
133169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
133269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
133369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
133469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid ElementsAccessor::InitializeOncePerProcess() {
133569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static struct ConcreteElementsAccessors {
13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define ACCESSOR_STRUCT(Class, Kind, Store) Class* Kind##_handler;
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ELEMENTS_LIST(ACCESSOR_STRUCT)
13383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef ACCESSOR_STRUCT
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } element_accessors = {
13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define ACCESSOR_INIT(Class, Kind, Store) new Class(#Kind),
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ELEMENTS_LIST(ACCESSOR_INIT)
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef ACCESSOR_INIT
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  };
134469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
134569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static ElementsAccessor* accessor_array[] = {
13463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#define ACCESSOR_ARRAY(Class, Kind, Store) element_accessors.Kind##_handler,
13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ELEMENTS_LIST(ACCESSOR_ARRAY)
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#undef ACCESSOR_ARRAY
134969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  };
135069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
13523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                kElementsKindCount);
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
135469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  elements_accessors_ = accessor_array;
135569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
135669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
135769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
13583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <typename ElementsAccessorSubclass, typename ElementsKindTraits>
13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochMaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                  ElementsKindTraits>::
13613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    SetLengthImpl(JSObject* obj,
13623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  Object* length,
13633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  typename ElementsKindTraits::BackingStore* backing_store) {
13643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JSArray* array = JSArray::cast(obj);
13653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fast case: The new length fits into a Smi.
13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MaybeObject* maybe_smi_length = length->ToSmi();
13683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Object* smi_length = Smi::FromInt(0);
13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    const int value = Smi::cast(smi_length)->value();
13713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (value >= 0) {
13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* new_length;
13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* result = ElementsAccessorSubclass::
13743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SetLengthWithoutNormalize(backing_store, array, smi_length, value);
13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!result->ToObject(&new_length)) return result;
13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(new_length->IsSmi() || new_length->IsUndefined());
13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (new_length->IsSmi()) {
13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        array->set_length(Smi::cast(new_length));
13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return array;
13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ThrowArrayLengthRangeError(array->GetHeap());
13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Slow case: The new length does not fit into a Smi or conversion
13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // to slow elements is needed for other reasons.
13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (length->IsNumber()) {
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    uint32_t value;
13903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (length->ToArrayIndex(&value)) {
13913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      SeededNumberDictionary* dictionary;
13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* maybe_object = array->NormalizeElements();
13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!maybe_object->To(&dictionary)) return maybe_object;
13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* new_length;
13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      MaybeObject* result = DictionaryElementsAccessor::
13963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          SetLengthWithoutNormalize(dictionary, array, length, value);
13973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (!result->ToObject(&new_length)) return result;
13983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(new_length->IsNumber());
13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      array->set_length(new_length);
14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return array;
14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else {
14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      return ThrowArrayLengthRangeError(array->GetHeap());
14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Fall-back case: The new length is not a number so make the array
14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // size one and set only element to length.
14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FixedArray* new_backing_store;
14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1);
14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (!maybe_obj->To(&new_backing_store)) return maybe_obj;
14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  new_backing_store->set(0, length);
14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  { MaybeObject* result = array->SetContent(new_backing_store);
14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (result->IsFailure()) return result;
14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return array;
14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
141969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} }  // namespace v8::internal
1420