elements.cc revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
15d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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
34592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
35592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// Each concrete ElementsAccessor can handle exactly one ElementsKind,
36592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// several abstract ElementsAccessor classes are used to allow sharing
37592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// common code.
38592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//
39592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// Inheritance hierarchy:
40592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// - ElementsAccessorBase                        (abstract)
41592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//   - FastElementsAccessor                      (abstract)
42592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - FastObjectElementsAccessor
43592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - FastDoubleElementsAccessor
44592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//   - ExternalElementsAccessor                  (abstract)
45592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalByteElementsAccessor
46592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalUnsignedByteElementsAccessor
47592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalShortElementsAccessor
48592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalUnsignedShortElementsAccessor
49592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalIntElementsAccessor
50592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalUnsignedIntElementsAccessor
51592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalFloatElementsAccessor
52592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - ExternalDoubleElementsAccessor
53592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//     - PixelElementsAccessor
54592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//   - DictionaryElementsAccessor
55592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch//   - NonStrictArgumentsElementsAccessor
56592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
57592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
5869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace v8 {
5969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochnamespace internal {
6069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
6169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// First argument in list is the accessor class, the second argument is the
635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// accessor ElementsKind, and the third is the backing store class.  Use the
645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// fast element handler for smi-only arrays.  The implementation is currently
655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// identical.  Note that the order must match that of the ElementsKind enum for
665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// the |accessor_array[]| below to work.
675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#define ELEMENTS_LIST(V)                                                \
685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray)     \
695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray)              \
705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \
715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS,                    \
725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    SeededNumberDictionary)                                             \
735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS,  \
745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FixedArray)                                                         \
755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS,               \
765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ExternalByteArray)                                                  \
775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalUnsignedByteElementsAccessor,                               \
785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray)         \
795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS,             \
805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ExternalShortArray)                                                 \
815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalUnsignedShortElementsAccessor,                              \
825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray)       \
835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS,                 \
845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ExternalIntArray)                                                   \
855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalUnsignedIntElementsAccessor,                                \
865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray)           \
875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalFloatElementsAccessor,                                      \
885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray)                        \
895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(ExternalDoubleElementsAccessor,                                     \
905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray)                      \
915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate<ElementsKind Kind> class ElementsKindTraits {
955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef FixedArrayBase BackingStore;
975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch};
985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#define ELEMENTS_TRAITS(Class, KindParam, Store)               \
1005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate<> class ElementsKindTraits<KindParam> {               \
1015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  public:                                                      \
1025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static const ElementsKind Kind = KindParam;                  \
1035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef Store BackingStore;                                  \
1045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch};
1055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochELEMENTS_LIST(ELEMENTS_TRAITS)
1065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#undef ELEMENTS_TRAITS
1075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
10969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochElementsAccessor** ElementsAccessor::elements_accessors_;
11069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
112592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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
126592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic Failure* ThrowArrayLengthRangeError(Heap* heap) {
127592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  HandleScope scope(heap->isolate());
128592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return heap->isolate()->Throw(
129592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      *heap->isolate()->factory()->NewRangeError("invalid_array_length",
130592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          HandleVector<Object>(NULL, 0)));
131592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
132592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
133592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid CopyObjectToObjectElements(FixedArray* from,
1355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                ElementsKind from_kind,
1365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                uint32_t from_start,
1375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                FixedArray* to,
1385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                ElementsKind to_kind,
1395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                uint32_t to_start,
1405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                int raw_copy_size) {
1415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(to->map() != HEAP->fixed_cow_array_map());
1425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS);
1435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
1445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
1455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (raw_copy_size < 0) {
1465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
1475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
1485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = Min(from->length() - from_start,
1495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    to->length() - to_start);
1505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#ifdef DEBUG
1515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
1525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // marked with the hole.
1535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
1545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
1555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(to->get(i)->IsTheHole());
1565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
1575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
1585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#endif
1595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
1605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
1615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
1625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return;
1635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Address to_address = to->address() + FixedArray::kHeaderSize;
1645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Address from_address = from->address() + FixedArray::kHeaderSize;
1655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
1665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            reinterpret_cast<Object**>(from_address) + from_start,
1675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            copy_size);
1685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) {
1695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Heap* heap = from->GetHeap();
1705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!heap->InNewSpace(to)) {
1715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      heap->RecordWrites(to->address(),
1725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         to->OffsetOfElementAt(to_start),
1735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         copy_size);
1745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
1755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    heap->incremental_marking()->RecordWrites(to);
1765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
1775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
1785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
1815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           uint32_t from_start,
1825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           FixedArray* to,
1835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           ElementsKind to_kind,
1845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           uint32_t to_start,
1855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           int raw_copy_size) {
1865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
1875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Heap* heap = from->GetHeap();
1885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (raw_copy_size < 0) {
1895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
1905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
1915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = from->max_number_key() + 1 - from_start;
1925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#ifdef DEBUG
1935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
1945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // marked with the hole.
1955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
1965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
1975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(to->get(i)->IsTheHole());
1985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
1995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#endif
2015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length());
2035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(to != from);
2045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
2055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return;
2065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < copy_size; i++) {
2075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int entry = from->FindEntry(i + from_start);
2085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
2095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Object* value = from->ValueAt(entry);
2105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(!value->IsTheHole());
2115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set(i + to_start, value, SKIP_WRITE_BARRIER);
2125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
2135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set_the_hole(i + to_start);
2145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (to_kind == FAST_ELEMENTS) {
2175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (!heap->InNewSpace(to)) {
2185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      heap->RecordWrites(to->address(),
2195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         to->OffsetOfElementAt(to_start),
2205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                         copy_size);
2215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    heap->incremental_marking()->RecordWrites(to);
2235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
2255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochMUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
2285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FixedDoubleArray* from,
2295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t from_start,
2305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FixedArray* to,
2315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ElementsKind to_kind,
2325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t to_start,
2335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int raw_copy_size) {
2345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
2355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
2365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (raw_copy_size < 0) {
2375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
2385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
2395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = Min(from->length() - from_start,
2405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    to->length() - to_start);
2415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#ifdef DEBUG
2425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
2435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    // marked with the hole.
2445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
2455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
2465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(to->get(i)->IsTheHole());
2475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
2485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#endif
2505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
2525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
2535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return from;
2545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < copy_size; ++i) {
2555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (to_kind == FAST_SMI_ONLY_ELEMENTS) {
2565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      UNIMPLEMENTED();
2575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return Failure::Exception();
2585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
2595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      MaybeObject* maybe_value = from->get(i + from_start);
2605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Object* value;
2615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ASSERT(to_kind == FAST_ELEMENTS);
2625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects
2635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // iteratively, the allocate must succeed within a single GC cycle,
2645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // otherwise the retry after the GC will also fail. In order to ensure
2655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // that no GC is triggered, allocate HeapNumbers from old space if they
2665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // can't be taken from new space.
2675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (!maybe_value->ToObject(&value)) {
2685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory());
2695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Heap* heap = from->GetHeap();
2705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        MaybeObject* maybe_value_object =
2715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            heap->AllocateHeapNumber(from->get_scalar(i + from_start),
2725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                     TENURED);
2735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
2745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
2755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set(i + to_start, value, UPDATE_WRITE_BARRIER);
2765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  return to;
2795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
2805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
2825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void CopyDoubleToDoubleElements(FixedDoubleArray* from,
2835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
2845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedDoubleArray* to,
2855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
2865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int raw_copy_size) {
2875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
2885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (raw_copy_size < 0) {
2895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
2905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
2915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = Min(from->length() - from_start,
2925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                    to->length() - to_start);
2935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
2945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
2955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        to->set_the_hole(i);
2965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
2975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
2985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
2995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
3005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
3015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return;
3025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Address to_address = to->address() + FixedDoubleArray::kHeaderSize;
3035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  Address from_address = from->address() + FixedDoubleArray::kHeaderSize;
3045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  to_address += kDoubleSize * to_start;
3055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  from_address += kDoubleSize * from_start;
3065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int words_per_double = (kDoubleSize / kPointerSize);
3075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  CopyWords(reinterpret_cast<Object**>(to_address),
3085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            reinterpret_cast<Object**>(from_address),
3095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            words_per_double * copy_size);
3105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
3115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void CopyObjectToDoubleElements(FixedArray* from,
3145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
3155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedDoubleArray* to,
3165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
3175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int raw_copy_size) {
3185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
3195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (raw_copy_size < 0) {
3205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
3215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
3225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = from->length() - from_start;
3235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
3245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
3255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        to->set_the_hole(i);
3265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
3275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
3305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         (copy_size + static_cast<int>(from_start)) <= from->length());
3315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return;
3325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < copy_size; i++) {
3335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Object* hole_or_object = from->get(i + from_start);
3345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (hole_or_object->IsTheHole()) {
3355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set_the_hole(i + to_start);
3365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
3375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set(i + to_start, hole_or_object->Number());
3385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
3415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic void CopyDictionaryToDoubleElements(SeededNumberDictionary* from,
3445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           uint32_t from_start,
3455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           FixedDoubleArray* to,
3465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           uint32_t to_start,
3475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                           int raw_copy_size) {
3485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  int copy_size = raw_copy_size;
3495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size < 0) {
3505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ASSERT(copy_size == ElementsAccessor::kCopyToEnd ||
3515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch           copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
3525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    copy_size = from->max_number_key() + 1 - from_start;
3535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
3545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      for (int i = to_start + copy_size; i < to->length(); ++i) {
3555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        to->set_the_hole(i);
3565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
3575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  ASSERT(copy_size + static_cast<int>(to_start) <= to->length());
3605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  if (copy_size == 0) return;
3615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  for (int i = 0; i < copy_size; i++) {
3625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    int entry = from->FindEntry(i + from_start);
3635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
3645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set(i + to_start, from->ValueAt(entry)->Number());
3655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    } else {
3665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      to->set_the_hole(i + to_start);
3675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
3685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
3695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch}
3705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
37269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Base class for element handler implementations. Contains the
37369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// the common logic for objects with different ElementsKinds.
37469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Subclasses must specialize method for which the element
37569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// implementation differs from the base class implementation.
37669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
37769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// This class is intended to be used in the following way:
37869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
37969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//   class SomeElementsAccessor :
38069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//       public ElementsAccessorBase<SomeElementsAccessor,
38169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//                                   BackingStoreClass> {
38269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//     ...
38369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//   }
38469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch//
38569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// This is an example of the Curiously Recurring Template Pattern (see
38669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern).  We use
38769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// CRTP to guarantee aggressive compile time optimizations (i.e.  inlining and
38869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// specialization of SomeElementsAccessor methods).
3895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate <typename ElementsAccessorSubclass,
3905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          typename ElementsTraitsParam>
39169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ElementsAccessorBase : public ElementsAccessor {
39269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
3935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ElementsAccessorBase(const char* name)
3945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ElementsAccessor(name) { }
3955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef ElementsTraitsParam ElementsTraits;
3975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef typename ElementsTraitsParam::BackingStore BackingStore;
3985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
3995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual ElementsKind kind() const { return ElementsTraits::Kind; }
4005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static bool HasElementImpl(Object* receiver,
4025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             JSObject* holder,
4035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             uint32_t key,
4045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             BackingStore* backing_store) {
4055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    MaybeObject* element =
4065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store);
4075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return !element->IsTheHole();
4085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual bool HasElement(Object* receiver,
4115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          JSObject* holder,
4125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          uint32_t key,
4135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                          FixedArrayBase* backing_store) {
4145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (backing_store == NULL) {
4155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      backing_store = holder->elements();
4165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
4175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return ElementsAccessorSubclass::HasElementImpl(
4185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        receiver, holder, key, BackingStore::cast(backing_store));
4195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual MaybeObject* Get(Object* receiver,
4225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           JSObject* holder,
42369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                           uint32_t key,
4245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                           FixedArrayBase* backing_store) {
4255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (backing_store == NULL) {
4265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      backing_store = holder->elements();
4275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
428592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return ElementsAccessorSubclass::GetImpl(
4295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        receiver, holder, key, BackingStore::cast(backing_store));
43069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
43169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
4325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
433592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              JSObject* obj,
4345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              uint32_t key,
4355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              BackingStore* backing_store) {
436592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store))
437592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           ? backing_store->get(key)
438592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           : backing_store->GetHeap()->the_hole_value();
43969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
44069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
4415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual MaybeObject* SetLength(JSArray* array,
442592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                 Object* length) {
443592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return ElementsAccessorSubclass::SetLengthImpl(
4445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        array, length, BackingStore::cast(array->elements()));
445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
446592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
4475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
4485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    Object* length,
4495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    BackingStore* backing_store);
450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  virtual MaybeObject* SetCapacityAndLength(JSArray* array,
452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                            int capacity,
453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                            int length) {
454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        array,
456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        capacity,
457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        length);
458c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
460c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                       int capacity,
462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                       int length) {
463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    UNIMPLEMENTED();
464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    return obj;
465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
46769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
46869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
46969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) = 0;
47069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
4715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
4725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
4735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedArrayBase* to,
4745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       ElementsKind to_kind,
4755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
4765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int copy_size) {
4775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    UNREACHABLE();
4785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return NULL;
4795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual MaybeObject* CopyElements(JSObject* from_holder,
4825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    uint32_t from_start,
4835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    FixedArrayBase* to,
4845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKind to_kind,
4855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    uint32_t to_start,
4865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    int copy_size,
4875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    FixedArrayBase* from) {
4885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (from == NULL) {
4895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      from = from_holder->elements();
4905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
4915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (from->length() == 0) {
4925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return from;
4935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
4945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return ElementsAccessorSubclass::CopyElementsImpl(
4955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        from, from_start, to, to_kind, to_start, copy_size);
4965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
4975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
4985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  virtual MaybeObject* AddElementsToFixedArray(Object* receiver,
49969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                               JSObject* holder,
5005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               FixedArray* to,
5015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                               FixedArrayBase* from) {
50269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int len0 = to->length();
50369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#ifdef DEBUG
50469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (FLAG_enable_slow_asserts) {
50569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      for (int i = 0; i < len0; i++) {
50669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!to->get(i)->IsTheHole());
50769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
50869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
50969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch#endif
5105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (from == NULL) {
5115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      from = holder->elements();
5125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
5135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    BackingStore* backing_store = BackingStore::cast(from);
514592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store);
51569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
51669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Optimize if 'other' is empty.
51769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // We cannot optimize if 'this' is empty, as other may have holes.
51869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (len1 == 0) return to;
51969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
52069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Compute how many elements are not in other.
5215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t extra = 0;
52269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for (uint32_t y = 0; y < len1; y++) {
5235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      uint32_t key =
5245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
5255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (ElementsAccessorSubclass::HasElementImpl(
5265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              receiver, holder, key, backing_store)) {
52769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_value =
5285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            ElementsAccessorSubclass::GetImpl(receiver, holder,
5295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                              key, backing_store);
53069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* value;
53169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_value->ToObject(&value)) return maybe_value;
53269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(!value->IsTheHole());
53369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!HasKey(to, value)) {
53469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          extra++;
53569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
53669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
53769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
53869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
53969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (extra == 0) return to;
54069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
54169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Allocate the result
54269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* result;
54369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    MaybeObject* maybe_obj =
54469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        backing_store->GetHeap()->AllocateFixedArray(len0 + extra);
54569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!maybe_obj->To<FixedArray>(&result)) return maybe_obj;
54669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
54769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Fill in the content
54869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    {
54969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      AssertNoAllocation no_gc;
55069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
55169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      for (int i = 0; i < len0; i++) {
55269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* e = to->get(i);
55369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ASSERT(e->IsString() || e->IsNumber());
55469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        result->set(i, e, mode);
55569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
55669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
55769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // Fill in the extra values.
5585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t index = 0;
55969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    for (uint32_t y = 0; y < len1; y++) {
5605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      uint32_t key =
5615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, y);
5625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (ElementsAccessorSubclass::HasElementImpl(
5635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch              receiver, holder, key, backing_store)) {
56469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_value =
5655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            ElementsAccessorSubclass::GetImpl(receiver, holder,
5665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                              key, backing_store);
56769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Object* value;
56869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_value->ToObject(&value)) return maybe_value;
56969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!value->IsTheHole() && !HasKey(to, value)) {
57069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          result->set(len0 + index, value);
57169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          index++;
57269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
57369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
57469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
57569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    ASSERT(extra == index);
57669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return result;
57769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
57869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
57969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
5805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static uint32_t GetCapacityImpl(BackingStore* backing_store) {
58169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return backing_store->length();
58269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
58369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
58469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return ElementsAccessorSubclass::GetCapacityImpl(
5865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        BackingStore::cast(backing_store));
58769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
58869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
5895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
590592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     uint32_t index) {
59169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return index;
59269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
59369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
59469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
5955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  uint32_t index) {
596592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return ElementsAccessorSubclass::GetKeyForIndexImpl(
5975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        BackingStore::cast(backing_store), index);
59869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
59969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
60069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private:
60169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase);
60269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
60369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
60469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// Super class for all fast element arrays.
606592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochtemplate<typename FastElementsAccessorSubclass,
6075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         typename KindTraits,
608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch         int ElementSize>
60969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass FastElementsAccessor
6105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
6115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
6125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit FastElementsAccessor(const char* name)
6135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ElementsAccessorBase<FastElementsAccessorSubclass,
6145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             KindTraits>(name) {}
615592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch protected:
6165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
6175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
6185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef typename KindTraits::BackingStore BackingStore;
619592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
620592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Adjusts the length of the fast backing store or returns the new length or
621592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // undefined in case conversion to a slow backing store should be performed.
622592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static MaybeObject* SetLengthWithoutNormalize(BackingStore* backing_store,
623592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                JSArray* array,
624592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Object* length_object,
625592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                uint32_t length) {
626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    uint32_t old_capacity = backing_store->length();
627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
628592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check whether the backing store should be shrunk.
629592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (length <= old_capacity) {
630592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (array->HasFastTypeElements()) {
631592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        MaybeObject* maybe_obj = array->EnsureWritableFastElements();
632592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (!maybe_obj->To(&backing_store)) return maybe_obj;
633592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
634592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (2 * length <= old_capacity) {
635592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // If more than half the elements won't be used, trim the array.
636592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (length == 0) {
637592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          array->initialize_elements();
638592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        } else {
639592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          backing_store->set_length(length);
640592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          Address filler_start = backing_store->address() +
641592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              BackingStore::OffsetOfElementAt(length);
642592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          int filler_size = (old_capacity - length) * ElementSize;
643592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          array->GetHeap()->CreateFillerObjectAt(filler_start, filler_size);
644592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
645592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      } else {
646592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Otherwise, fill the unused tail with holes.
647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        int old_length = FastD2I(array->length()->Number());
648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        for (int i = length; i < old_length; i++) {
649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          backing_store->set_the_hole(i);
650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
651592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return length_object;
653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
654592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
655592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Check whether the backing store should be expanded.
656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    uint32_t min = JSObject::NewElementsCapacity(old_capacity);
657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    uint32_t new_capacity = length > min ? length : min;
658592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (!array->ShouldConvertToSlowElements(new_capacity)) {
659592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MaybeObject* result = FastElementsAccessorSubclass::
660592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          SetFastElementsCapacityAndLength(array, new_capacity, length);
661592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (result->IsFailure()) return result;
662592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return length_object;
663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // Request conversion to slow elements.
666592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return array->GetHeap()->undefined_value();
667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
668592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch};
669592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
670592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
671592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochclass FastObjectElementsAccessor
672592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    : public FastElementsAccessor<FastObjectElementsAccessor,
6735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  ElementsKindTraits<FAST_ELEMENTS>,
674592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  kPointerSize> {
67569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
6765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit FastObjectElementsAccessor(const char* name)
6775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : FastElementsAccessor<FastObjectElementsAccessor,
6785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             ElementsKindTraits<FAST_ELEMENTS>,
6795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             kPointerSize>(name) {}
6805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
68169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static MaybeObject* DeleteCommon(JSObject* obj,
68269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   uint32_t key) {
683592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ASSERT(obj->HasFastElements() ||
684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           obj->HasFastSmiOnlyElements() ||
685592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch           obj->HasFastArgumentsElements());
68669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Heap* heap = obj->GetHeap();
68769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* backing_store = FixedArray::cast(obj->elements());
68869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
68969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(backing_store->get(1));
69069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
69169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* writable;
69269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      MaybeObject* maybe = obj->EnsureWritableFastElements();
69369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (!maybe->ToObject(&writable)) return maybe;
69469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(writable);
69569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
69669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    uint32_t length = static_cast<uint32_t>(
69769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        obj->IsJSArray()
69869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? Smi::cast(JSArray::cast(obj)->length())->value()
69969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : backing_store->length());
70069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (key < length) {
70169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store->set_the_hole(key);
70269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // If an old space backing store is larger than a certain size and
70369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // has too few used values, normalize it.
70469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // To avoid doing the check on every delete we require at least
70569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // one adjacent hole to the value being deleted.
70669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* hole = heap->the_hole_value();
70769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      const int kMinLengthForSparsenessCheck = 64;
70869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (backing_store->length() >= kMinLengthForSparsenessCheck &&
70969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          !heap->InNewSpace(backing_store) &&
71069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          ((key > 0 && backing_store->get(key - 1) == hole) ||
71169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch           (key + 1 < length && backing_store->get(key + 1) == hole))) {
71269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        int num_used = 0;
71369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        for (int i = 0; i < backing_store->length(); ++i) {
71469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (backing_store->get(i) != hole) ++num_used;
71569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          // Bail out early if more than 1/4 is used.
71669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (4 * num_used > backing_store->length()) break;
71769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
71869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (4 * num_used <= backing_store->length()) {
71969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          MaybeObject* result = obj->NormalizeElements();
72069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          if (result->IsFailure()) return result;
72169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
72269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
72369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
72469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return heap->true_value();
72569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
72669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
7275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
7285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
7295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedArrayBase* to,
7305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       ElementsKind to_kind,
7315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
7325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int copy_size) {
7335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    switch (to_kind) {
7345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
7355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_ELEMENTS: {
7365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        CopyObjectToObjectElements(
7375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedArray::cast(from), ElementsTraits::Kind, from_start,
7385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedArray::cast(to), to_kind, to_start, copy_size);
7395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return from;
7405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
7415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_DOUBLE_ELEMENTS:
7425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        CopyObjectToDoubleElements(
7435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedArray::cast(from), from_start,
7445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedDoubleArray::cast(to), to_start, copy_size);
7455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return from;
7465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      default:
7475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        UNREACHABLE();
7485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
7495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return to->GetHeap()->undefined_value();
7505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
7515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
7525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                       uint32_t capacity,
755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                       uint32_t length) {
756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    JSObject::SetFastElementsCapacityMode set_capacity_mode =
757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        obj->HasFastSmiOnlyElements()
758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            ? JSObject::kAllowSmiOnlyElements
759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            : JSObject::kDontAllowSmiOnlyElements;
760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return obj->SetFastElementsCapacityAndLength(capacity,
761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                 length,
762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                 set_capacity_mode);
763592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
765c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch protected:
766c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  friend class FastElementsAccessor<FastObjectElementsAccessor,
7675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKindTraits<FAST_ELEMENTS>,
768c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                    kPointerSize>;
769c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
77069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
77169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
77269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
77369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return DeleteCommon(obj, key);
77469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
77569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
77669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
77769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
77869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass FastDoubleElementsAccessor
779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    : public FastElementsAccessor<FastDoubleElementsAccessor,
7805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                  kDoubleSize> {
7825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
7835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit FastDoubleElementsAccessor(const char* name)
7845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : FastElementsAccessor<FastDoubleElementsAccessor,
7855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
7865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             kDoubleSize>(name) {}
7875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
788c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
789c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                       uint32_t capacity,
790c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch                                                       uint32_t length) {
791c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    return obj->SetFastDoubleElementsCapacityAndLength(capacity, length);
792c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  }
793c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch
79469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
79569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<FastDoubleElementsAccessor,
7965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
797592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  friend class FastElementsAccessor<FastDoubleElementsAccessor,
7985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
799592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                    kDoubleSize>;
800592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
8015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
8025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
8035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedArrayBase* to,
8045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       ElementsKind to_kind,
8055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
8065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int copy_size) {
8075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    switch (to_kind) {
8085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
8095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_ELEMENTS:
8105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return CopyDoubleToObjectElements(
8115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
8125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            to_kind, to_start, copy_size);
8135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_DOUBLE_ELEMENTS:
8145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
8155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                   FixedDoubleArray::cast(to),
8165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                   to_start, copy_size);
8175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return from;
8185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      default:
8195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        UNREACHABLE();
8205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
8215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return to->GetHeap()->undefined_value();
8225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
8235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
82769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int length = obj->IsJSArray()
82869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? Smi::cast(JSArray::cast(obj)->length())->value()
82969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : FixedDoubleArray::cast(obj->elements())->length();
83069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (key < static_cast<uint32_t>(length)) {
83169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
83269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
83369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
83469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
83569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static bool HasElementImpl(Object* receiver,
8375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             JSObject* holder,
8385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             uint32_t key,
8395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             FixedDoubleArray* backing_store) {
8405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return key < static_cast<uint32_t>(backing_store->length()) &&
8415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        !backing_store->is_the_hole(key);
84269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
84369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
84469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
84569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
84669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Super class for all external element arrays.
84769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochtemplate<typename ExternalElementsAccessorSubclass,
8485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch         ElementsKind Kind>
84969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalElementsAccessor
85069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
8515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  ElementsKindTraits<Kind> > {
8525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
8535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalElementsAccessor(const char* name)
8545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ElementsAccessorBase<ExternalElementsAccessorSubclass,
8555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             ElementsKindTraits<Kind> >(name) {}
8565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
85769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
8585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
8595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
86069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
8615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKindTraits<Kind> >;
86269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
8635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
864592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              JSObject* obj,
8655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              uint32_t key,
8665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              BackingStore* backing_store) {
867592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return
868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        ? backing_store->get(key)
870592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        : backing_store->GetHeap()->undefined_value();
871592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
872592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
8735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
8745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    Object* length,
8755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    BackingStore* backing_store) {
876592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // External arrays do not support changing their length.
877592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    UNREACHABLE();
878592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return obj;
87969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
88069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
88169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
88269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
88369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
88469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    // External arrays always ignore deletes.
88569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
88669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
8875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
8885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static bool HasElementImpl(Object* receiver,
8895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             JSObject* holder,
8905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             uint32_t key,
8915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             BackingStore* backing_store) {
8925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t capacity =
8935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
8945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return key < capacity;
8955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
89669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
89769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
89869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
89969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalByteElementsAccessor
90069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalByteElementsAccessor,
9015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_BYTE_ELEMENTS> {
9025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalByteElementsAccessor(const char* name)
9045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalByteElementsAccessor,
9055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_BYTE_ELEMENTS>(name) {}
90669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
90769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
90869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
90969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedByteElementsAccessor
91069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
9115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
9125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalUnsignedByteElementsAccessor(const char* name)
9145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
9155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
91669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
91769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
91869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
91969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalShortElementsAccessor
92069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalShortElementsAccessor,
9215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_SHORT_ELEMENTS> {
9225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalShortElementsAccessor(const char* name)
9245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalShortElementsAccessor,
9255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_SHORT_ELEMENTS>(name) {}
92669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
92769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
92969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedShortElementsAccessor
93069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
9315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
9325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalUnsignedShortElementsAccessor(const char* name)
9345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
9355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
93669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
93769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
93869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
93969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalIntElementsAccessor
94069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalIntElementsAccessor,
9415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_INT_ELEMENTS> {
9425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalIntElementsAccessor(const char* name)
9445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalIntElementsAccessor,
9455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_INT_ELEMENTS>(name) {}
94669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
94769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
94969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalUnsignedIntElementsAccessor
95069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
9515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_UNSIGNED_INT_ELEMENTS> {
9525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalUnsignedIntElementsAccessor(const char* name)
9545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
9555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
95669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
95769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
95969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalFloatElementsAccessor
96069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
9615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_FLOAT_ELEMENTS> {
9625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalFloatElementsAccessor(const char* name)
9645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalFloatElementsAccessor,
9655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_FLOAT_ELEMENTS>(name) {}
96669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
96769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
96869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
96969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass ExternalDoubleElementsAccessor
97069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
9715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_DOUBLE_ELEMENTS> {
9725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit ExternalDoubleElementsAccessor(const char* name)
9745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<ExternalDoubleElementsAccessor,
9755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_DOUBLE_ELEMENTS>(name) {}
97669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
97769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
97869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
97969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass PixelElementsAccessor
98069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ExternalElementsAccessor<PixelElementsAccessor,
9815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                      EXTERNAL_PIXEL_ELEMENTS> {
9825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
9835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit PixelElementsAccessor(const char* name)
9845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ExternalElementsAccessor<PixelElementsAccessor,
9855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                 EXTERNAL_PIXEL_ELEMENTS>(name) {}
98669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
98769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
98869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
98969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochclass DictionaryElementsAccessor
99069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    : public ElementsAccessorBase<DictionaryElementsAccessor,
9915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  ElementsKindTraits<DICTIONARY_ELEMENTS> > {
99269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch public:
9935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit DictionaryElementsAccessor(const char* name)
9945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ElementsAccessorBase<DictionaryElementsAccessor,
9955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
9965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Adjusts the length of the dictionary backing store and returns the new
998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // length according to ES5 section 15.4.5.2 behavior.
999c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  static MaybeObject* SetLengthWithoutNormalize(SeededNumberDictionary* dict,
1000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                JSArray* array,
1001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                Object* length_object,
1002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                                uint32_t length) {
1003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (length == 0) {
1004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // If the length of a slow array is reset to zero, we clear
1005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // the array and flush backing storage. This has the added
1006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      // benefit that the array returns to fast mode.
1007592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Object* obj;
1008592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MaybeObject* maybe_obj = array->ResetElements();
1009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!maybe_obj->ToObject(&obj)) return maybe_obj;
1010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
1011592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      uint32_t new_length = length;
1012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      uint32_t old_length = static_cast<uint32_t>(array->length()->Number());
1013592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (new_length < old_length) {
1014592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Find last non-deletable element in range of elements to be
1015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // deleted and adjust range accordingly.
1016592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Heap* heap = array->GetHeap();
1017592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        int capacity = dict->Capacity();
1018592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        for (int i = 0; i < capacity; i++) {
1019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          Object* key = dict->KeyAt(i);
1020592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          if (key->IsNumber()) {
1021592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            uint32_t number = static_cast<uint32_t>(key->Number());
1022592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            if (new_length <= number && number < old_length) {
1023592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              PropertyDetails details = dict->DetailsAt(i);
1024592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              if (details.IsDontDelete()) new_length = number + 1;
1025592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            }
1026592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          }
1027592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
1028592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        if (new_length != length) {
1029592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          MaybeObject* maybe_object = heap->NumberFromUint32(new_length);
1030592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          if (!maybe_object->To(&length_object)) return maybe_object;
1031592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
1032592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1033592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Remove elements that should be deleted.
1034592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        int removed_entries = 0;
1035592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        Object* the_hole_value = heap->the_hole_value();
1036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        for (int i = 0; i < capacity; i++) {
1037592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          Object* key = dict->KeyAt(i);
1038592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          if (key->IsNumber()) {
1039592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            uint32_t number = static_cast<uint32_t>(key->Number());
1040592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            if (new_length <= number && number < old_length) {
1041592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              dict->SetEntry(i, the_hole_value, the_hole_value);
1042592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch              removed_entries++;
1043592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch            }
1044592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          }
1045592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        }
1046592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1047592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        // Update the number of elements.
1048592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        dict->ElementsRemoved(removed_entries);
1049592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
1050592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1051592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return length_object;
1052592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1053592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
105469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static MaybeObject* DeleteCommon(JSObject* obj,
105569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   uint32_t key,
105669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                   JSReceiver::DeleteMode mode) {
105769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Isolate* isolate = obj->GetIsolate();
105869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Heap* heap = isolate->heap();
105969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* backing_store = FixedArray::cast(obj->elements());
106069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    bool is_arguments =
1061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        (obj->GetElementsKind() == NON_STRICT_ARGUMENTS_ELEMENTS);
106269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (is_arguments) {
106369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      backing_store = FixedArray::cast(backing_store->get(1));
106469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
1065c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    SeededNumberDictionary* dictionary =
1066c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch        SeededNumberDictionary::cast(backing_store);
106769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int entry = dictionary->FindEntry(key);
1068c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
106969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* result = dictionary->DeleteProperty(entry, mode);
107069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (result == heap->true_value()) {
107169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        MaybeObject* maybe_elements = dictionary->Shrink(key);
107269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        FixedArray* new_elements = NULL;
107369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (!maybe_elements->To(&new_elements)) {
107469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          return maybe_elements;
107569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
107669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        if (is_arguments) {
107769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          FixedArray::cast(obj->elements())->set(1, new_elements);
107869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        } else {
107969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          obj->set_elements(new_elements);
108069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        }
108169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
108269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (mode == JSObject::STRICT_DELETION &&
108369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch          result == heap->false_value()) {
108469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // In strict mode, attempting to delete a non-configurable property
108569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        // throws an exception.
108669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        HandleScope scope(isolate);
108769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> holder(obj);
108869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> name = isolate->factory()->NewNumberFromUint(key);
108969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> args[2] = { name, holder };
109069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        Handle<Object> error =
109169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch            isolate->factory()->NewTypeError("strict_delete_property",
109269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                             HandleVector(args, 2));
109369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return isolate->Throw(*error);
109469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
109569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
109669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return heap->true_value();
109769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
109869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
10995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
11005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
11015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedArrayBase* to,
11025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       ElementsKind to_kind,
11035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
11045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int copy_size) {
11055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    switch (to_kind) {
11065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_SMI_ONLY_ELEMENTS:
11075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_ELEMENTS:
11085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        CopyDictionaryToObjectElements(
11095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            SeededNumberDictionary::cast(from), from_start,
11105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedArray::cast(to), to_kind, to_start, copy_size);
11115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return from;
11125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      case FAST_DOUBLE_ELEMENTS:
11135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        CopyDictionaryToDoubleElements(
11145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            SeededNumberDictionary::cast(from), from_start,
11155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch            FixedDoubleArray::cast(to), to_start, copy_size);
11165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return from;
11175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      default:
11185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        UNREACHABLE();
11195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    }
11205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return to->GetHeap()->undefined_value();
11215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
11225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
11235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
112469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
112569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  friend class ElementsAccessorBase<DictionaryElementsAccessor,
11265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    ElementsKindTraits<DICTIONARY_ELEMENTS> >;
112769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
112869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
112969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              uint32_t key,
113069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
113169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return DeleteCommon(obj, key, mode);
113269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
113369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
1135592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              JSObject* obj,
11365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              uint32_t key,
11375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              SeededNumberDictionary* backing_store) {
113869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    int entry = backing_store->FindEntry(key);
1139c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch    if (entry != SeededNumberDictionary::kNotFound) {
114069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Object* element = backing_store->ValueAt(entry);
114169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      PropertyDetails details = backing_store->DetailsAt(entry);
114269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (details.type() == CALLBACKS) {
114369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return obj->GetElementWithCallback(receiver,
114469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           element,
114569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           key,
114669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                           obj);
114769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
114869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return element;
114969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
115069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
115169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->the_hole_value();
115269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
115369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static bool HasElementImpl(Object* receiver,
11555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             JSObject* holder,
11565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             uint32_t key,
11575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             SeededNumberDictionary* backing_store) {
11585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return backing_store->FindEntry(key) !=
11595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        SeededNumberDictionary::kNotFound;
11605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
11615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1162c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch  static uint32_t GetKeyForIndexImpl(SeededNumberDictionary* dict,
1163592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     uint32_t index) {
116469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    Object* key = dict->KeyAt(index);
116569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Smi::cast(key)->value();
116669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
116769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
116869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
116969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochclass NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
11715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    NonStrictArgumentsElementsAccessor,
11725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
11735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch public:
11745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  explicit NonStrictArgumentsElementsAccessor(const char* name)
11755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      : ElementsAccessorBase<
11765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          NonStrictArgumentsElementsAccessor,
11775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {}
117869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch protected:
11795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  friend class ElementsAccessorBase<
11805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      NonStrictArgumentsElementsAccessor,
11815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >;
118269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
11835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* GetImpl(Object* receiver,
1184592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              JSObject* obj,
11855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              uint32_t key,
11865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                              FixedArray* parameter_map) {
11875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Object* probe = GetParameterMapArg(obj, parameter_map, key);
118869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
118969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      Context* context = Context::cast(parameter_map->get(0));
119069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      int context_index = Smi::cast(probe)->value();
119169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ASSERT(!context->get(context_index)->IsTheHole());
119269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return context->get(context_index);
119369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
119469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // Object is not mapped, defer to the arguments.
119569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
11965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      MaybeObject* maybe_result = ElementsAccessor::ForArray(arguments)->Get(
11975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch          receiver, obj, key, arguments);
11985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      Object* result;
11995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (!maybe_result->ToObject(&result)) return maybe_result;
12005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      // Elements of the arguments object in slow mode might be slow aliases.
12015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      if (result->IsAliasedArgumentsEntry()) {
12025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(result);
12035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        Context* context = Context::cast(parameter_map->get(0));
12045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        int context_index = entry->aliased_context_slot();
12055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ASSERT(!context->get(context_index)->IsTheHole());
12065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return context->get(context_index);
12075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      } else {
12085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        return result;
12095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      }
121069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
121169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
121269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* SetLengthImpl(JSObject* obj,
12145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    Object* length,
12155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    FixedArray* parameter_map) {
1216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // TODO(mstarzinger): This was never implemented but will be used once we
1217592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    // correctly implement [[DefineOwnProperty]] on arrays.
1218592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    UNIMPLEMENTED();
1219592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    return obj;
1220592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1221592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
122269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  virtual MaybeObject* Delete(JSObject* obj,
1223592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                              uint32_t key,
122469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                              JSReceiver::DeleteMode mode) {
122569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArray* parameter_map = FixedArray::cast(obj->elements());
12265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Object* probe = GetParameterMapArg(obj, parameter_map, key);
122769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
122869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // TODO(kmillikin): We could check if this was the last aliased
122969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // parameter, and revert to normal elements in that case.  That
123069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      // would enable GC of the context.
123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      parameter_map->set_the_hole(key + 2);
123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
123369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
123469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (arguments->IsDictionary()) {
123569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
123669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
1237592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        return FastObjectElementsAccessor::DeleteCommon(obj, key);
123869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
123969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
124069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return obj->GetHeap()->true_value();
124169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
124269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
12445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t from_start,
12455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       FixedArrayBase* to,
12465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       ElementsKind to_kind,
12475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       uint32_t to_start,
12485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                       int copy_size) {
12495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FixedArray* parameter_map = FixedArray::cast(from);
12505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
12515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
12525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    return accessor->CopyElements(NULL, from_start, to, to_kind,
12535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  to_start, copy_size, arguments);
12545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
12555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch
1256592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
125769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
125869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return Max(static_cast<uint32_t>(parameter_map->length() - 2),
125969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch               ForArray(arguments)->GetCapacity(arguments));
126069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
126169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  static uint32_t GetKeyForIndexImpl(FixedArray* dict,
1263592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                                     uint32_t index) {
126469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return index;
126569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
126669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
12675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static bool HasElementImpl(Object* receiver,
12685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             JSObject* holder,
12695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             uint32_t key,
12705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                             FixedArray* parameter_map) {
12715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    Object* probe = GetParameterMapArg(holder, parameter_map, key);
127269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    if (!probe->IsTheHole()) {
127369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return true;
127469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    } else {
127569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
127669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
12775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch      return !accessor->Get(receiver, holder, key, arguments)->IsTheHole();
127869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    }
127969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
128069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
128169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch private:
12825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  static Object* GetParameterMapArg(JSObject* holder,
12835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                    FixedArray* parameter_map,
128469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch                                    uint32_t key) {
12855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    uint32_t length = holder->IsJSArray()
12865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        ? Smi::cast(JSArray::cast(holder)->length())->value()
12875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch        : parameter_map->length();
128869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    return key < (length - 2 )
128969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        ? parameter_map->get(key + 2)
129069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch        : parameter_map->GetHeap()->the_hole_value();
129169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
129269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch};
129369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
129469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
129569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
129669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  switch (array->map()->instance_type()) {
129769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case FIXED_ARRAY_TYPE:
129869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      if (array->IsDictionary()) {
1299589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return elements_accessors_[DICTIONARY_ELEMENTS];
130069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      } else {
1301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch        return elements_accessors_[FAST_ELEMENTS];
130269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      }
130369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_BYTE_ARRAY_TYPE:
1304589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
130569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_BYTE_ARRAY_TYPE:
1306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_BYTE_ELEMENTS];
130769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_SHORT_ARRAY_TYPE:
1308589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_SHORT_ELEMENTS];
130969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_SHORT_ARRAY_TYPE:
1310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_SHORT_ELEMENTS];
131169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_INT_ARRAY_TYPE:
1312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_INT_ELEMENTS];
131369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_UNSIGNED_INT_ARRAY_TYPE:
1314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_UNSIGNED_INT_ELEMENTS];
131569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_FLOAT_ARRAY_TYPE:
1316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_FLOAT_ELEMENTS];
131769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_DOUBLE_ARRAY_TYPE:
1318589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_DOUBLE_ELEMENTS];
131969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    case EXTERNAL_PIXEL_ARRAY_TYPE:
1320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch      return elements_accessors_[EXTERNAL_PIXEL_ELEMENTS];
132169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch    default:
132269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      UNREACHABLE();
132369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch      return NULL;
132469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  }
132569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
132669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
132769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
132869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid ElementsAccessor::InitializeOncePerProcess() {
132969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static struct ConcreteElementsAccessors {
13305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#define ACCESSOR_STRUCT(Class, Kind, Store) Class* Kind##_handler;
1331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ELEMENTS_LIST(ACCESSOR_STRUCT)
1332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#undef ACCESSOR_STRUCT
1333592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  } element_accessors = {
13345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#define ACCESSOR_INIT(Class, Kind, Store) new Class(#Kind),
1335592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ELEMENTS_LIST(ACCESSOR_INIT)
1336592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#undef ACCESSOR_INIT
1337592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  };
133869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
133969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  static ElementsAccessor* accessor_array[] = {
13405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch#define ACCESSOR_ARRAY(Class, Kind, Store) element_accessors.Kind##_handler,
1341592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    ELEMENTS_LIST(ACCESSOR_ARRAY)
1342592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#undef ACCESSOR_ARRAY
134369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  };
134469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1345592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
1346592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch                kElementsKindCount);
1347592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
134869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  elements_accessors_ = accessor_array;
134969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
135069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
135169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
13525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate <typename ElementsAccessorSubclass, typename ElementsKindTraits>
13535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochMaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
13545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                                  ElementsKindTraits>::
13555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    SetLengthImpl(JSObject* obj,
13565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                  Object* length,
13575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch                  typename ElementsKindTraits::BackingStore* backing_store) {
1358592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  JSArray* array = JSArray::cast(obj);
1359592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1360592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Fast case: The new length fits into a Smi.
1361592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  MaybeObject* maybe_smi_length = length->ToSmi();
1362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  Object* smi_length = Smi::FromInt(0);
1363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) {
1364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    const int value = Smi::cast(smi_length)->value();
1365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (value >= 0) {
1366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Object* new_length;
1367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MaybeObject* result = ElementsAccessorSubclass::
1368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          SetLengthWithoutNormalize(backing_store, array, smi_length, value);
1369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!result->ToObject(&new_length)) return result;
1370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT(new_length->IsSmi() || new_length->IsUndefined());
1371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (new_length->IsSmi()) {
1372592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        array->set_length(Smi::cast(new_length));
1373592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch        return array;
1374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      }
1375592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
1376592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return ThrowArrayLengthRangeError(array->GetHeap());
1377592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1378592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1379592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1380592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Slow case: The new length does not fit into a Smi or conversion
1381592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // to slow elements is needed for other reasons.
1382592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (length->IsNumber()) {
1383592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    uint32_t value;
1384592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    if (length->ToArrayIndex(&value)) {
1385c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      SeededNumberDictionary* dictionary;
1386592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MaybeObject* maybe_object = array->NormalizeElements();
1387592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!maybe_object->To(&dictionary)) return maybe_object;
1388592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      Object* new_length;
1389592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      MaybeObject* result = DictionaryElementsAccessor::
1390592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch          SetLengthWithoutNormalize(dictionary, array, length, value);
1391592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      if (!result->ToObject(&new_length)) return result;
1392592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      ASSERT(new_length->IsNumber());
1393592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      array->set_length(new_length);
1394592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return array;
1395592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    } else {
1396592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch      return ThrowArrayLengthRangeError(array->GetHeap());
1397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch    }
1398592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  }
1399592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1400592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // Fall-back case: The new length is not a number so make the array
1401592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  // size one and set only element to length.
1402592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  FixedArray* new_backing_store;
1403592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  MaybeObject* maybe_obj = array->GetHeap()->AllocateFixedArray(1);
1404592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  if (!maybe_obj->To(&new_backing_store)) return maybe_obj;
1405592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  new_backing_store->set(0, length);
14065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  { MaybeObject* result = array->SetContent(new_backing_store);
14075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch    if (result->IsFailure()) return result;
14085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch  }
1409592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch  return array;
1410592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch}
1411592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
1412592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch
141369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} }  // namespace v8::internal
1414