| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index d367af85cec392b4fcb2bfcae28434c1049e899c..2692cb53841c354a2c49d2714007746a19bb3f77 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -39,8 +39,14 @@
|
| // Inheritance hierarchy:
|
| // - ElementsAccessorBase (abstract)
|
| // - FastElementsAccessor (abstract)
|
| -// - FastObjectElementsAccessor
|
| +// - FastSmiOrObjectElementsAccessor
|
| +// - FastPackedSmiElementsAccessor
|
| +// - FastHoleySmiElementsAccessor
|
| +// - FastPackedObjectElementsAccessor
|
| +// - FastHoleyObjectElementsAccessor
|
| // - FastDoubleElementsAccessor
|
| +// - FastPackedDoubleElementsAccessor
|
| +// - FastHoleyDoubleElementsAccessor
|
| // - ExternalElementsAccessor (abstract)
|
| // - ExternalByteElementsAccessor
|
| // - ExternalUnsignedByteElementsAccessor
|
| @@ -65,9 +71,15 @@ namespace internal {
|
| // identical. Note that the order must match that of the ElementsKind enum for
|
| // the |accessor_array[]| below to work.
|
| #define ELEMENTS_LIST(V) \
|
| - V(FastObjectElementsAccessor, FAST_SMI_ONLY_ELEMENTS, FixedArray) \
|
| - V(FastObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
|
| - V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, FixedDoubleArray) \
|
| + V(FastPackedSmiElementsAccessor, FAST_SMI_ELEMENTS, FixedArray) \
|
| + V(FastHoleySmiElementsAccessor, FAST_HOLEY_SMI_ELEMENTS, \
|
| + FixedArray) \
|
| + V(FastPackedObjectElementsAccessor, FAST_ELEMENTS, FixedArray) \
|
| + V(FastHoleyObjectElementsAccessor, FAST_HOLEY_ELEMENTS, FixedArray) \
|
| + V(FastPackedDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS, \
|
| + FixedDoubleArray) \
|
| + V(FastHoleyDoubleElementsAccessor, FAST_HOLEY_DOUBLE_ELEMENTS, \
|
| + FixedDoubleArray) \
|
| V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
|
| SeededNumberDictionary) \
|
| V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \
|
| @@ -139,8 +151,6 @@ void CopyObjectToObjectElements(FixedArray* from,
|
| uint32_t to_start,
|
| int raw_copy_size) {
|
| ASSERT(to->map() != HEAP->fixed_cow_array_map());
|
| - ASSERT(from_kind == FAST_ELEMENTS || from_kind == FAST_SMI_ONLY_ELEMENTS);
|
| - ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
|
| int copy_size = raw_copy_size;
|
| if (raw_copy_size < 0) {
|
| ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
|
| @@ -148,7 +158,7 @@ void CopyObjectToObjectElements(FixedArray* from,
|
| copy_size = Min(from->length() - from_start,
|
| to->length() - to_start);
|
| #ifdef DEBUG
|
| - // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
|
| + // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
|
| // marked with the hole.
|
| if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
|
| for (int i = to_start + copy_size; i < to->length(); ++i) {
|
| @@ -160,12 +170,15 @@ void CopyObjectToObjectElements(FixedArray* from,
|
| ASSERT((copy_size + static_cast<int>(to_start)) <= to->length() &&
|
| (copy_size + static_cast<int>(from_start)) <= from->length());
|
| if (copy_size == 0) return;
|
| + ASSERT(IsFastSmiOrObjectElementsKind(from_kind));
|
| + ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
|
| Address to_address = to->address() + FixedArray::kHeaderSize;
|
| Address from_address = from->address() + FixedArray::kHeaderSize;
|
| CopyWords(reinterpret_cast<Object**>(to_address) + to_start,
|
| reinterpret_cast<Object**>(from_address) + from_start,
|
| copy_size);
|
| - if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) {
|
| + if (IsFastObjectElementsKind(from_kind) &&
|
| + IsFastObjectElementsKind(to_kind)) {
|
| Heap* heap = from->GetHeap();
|
| if (!heap->InNewSpace(to)) {
|
| heap->RecordWrites(to->address(),
|
| @@ -190,7 +203,7 @@ static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
|
| raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole);
|
| copy_size = from->max_number_key() + 1 - from_start;
|
| #ifdef DEBUG
|
| - // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
|
| + // Fast object arrays cannot be uninitialized. Ensure they are already
|
| // marked with the hole.
|
| if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
|
| for (int i = to_start + copy_size; i < to->length(); ++i) {
|
| @@ -200,7 +213,7 @@ static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
|
| #endif
|
| }
|
| ASSERT(to != from);
|
| - ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
|
| + ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
|
| if (copy_size == 0) return;
|
| uint32_t to_length = to->length();
|
| if (to_start + copy_size > to_length) {
|
| @@ -216,7 +229,7 @@ static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
|
| to->set_the_hole(i + to_start);
|
| }
|
| }
|
| - if (to_kind == FAST_ELEMENTS) {
|
| + if (IsFastObjectElementsKind(to_kind)) {
|
| if (!heap->InNewSpace(to)) {
|
| heap->RecordWrites(to->address(),
|
| to->OffsetOfElementAt(to_start),
|
| @@ -234,7 +247,7 @@ MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
|
| ElementsKind to_kind,
|
| uint32_t to_start,
|
| int raw_copy_size) {
|
| - ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
|
| + ASSERT(IsFastSmiOrObjectElementsKind(to_kind));
|
| int copy_size = raw_copy_size;
|
| if (raw_copy_size < 0) {
|
| ASSERT(raw_copy_size == ElementsAccessor::kCopyToEnd ||
|
| @@ -242,7 +255,7 @@ MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
|
| copy_size = Min(from->length() - from_start,
|
| to->length() - to_start);
|
| #ifdef DEBUG
|
| - // FAST_ELEMENT arrays cannot be uninitialized. Ensure they are already
|
| + // FAST_*_ELEMENTS arrays cannot be uninitialized. Ensure they are already
|
| // marked with the hole.
|
| if (raw_copy_size == ElementsAccessor::kCopyToEndAndInitializeToHole) {
|
| for (int i = to_start + copy_size; i < to->length(); ++i) {
|
| @@ -255,14 +268,14 @@ MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
|
| (copy_size + static_cast<int>(from_start)) <= from->length());
|
| if (copy_size == 0) return from;
|
| for (int i = 0; i < copy_size; ++i) {
|
| - if (to_kind == FAST_SMI_ONLY_ELEMENTS) {
|
| + if (IsFastSmiElementsKind(to_kind)) {
|
| UNIMPLEMENTED();
|
| return Failure::Exception();
|
| } else {
|
| MaybeObject* maybe_value = from->get(i + from_start);
|
| Object* value;
|
| - ASSERT(to_kind == FAST_ELEMENTS);
|
| - // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT allocate HeapObjects
|
| + ASSERT(IsFastObjectElementsKind(to_kind));
|
| + // Because Double -> Object elements transitions allocate HeapObjects
|
| // iteratively, the allocate must succeed within a single GC cycle,
|
| // otherwise the retry after the GC will also fail. In order to ensure
|
| // that no GC is triggered, allocate HeapNumbers from old space if they
|
| @@ -404,6 +417,38 @@ class ElementsAccessorBase : public ElementsAccessor {
|
|
|
| virtual ElementsKind kind() const { return ElementsTraits::Kind; }
|
|
|
| + static void ValidateContents(JSObject* holder, int length) {
|
| + }
|
| +
|
| + static void ValidateImpl(JSObject* holder) {
|
| + FixedArrayBase* fixed_array_base = holder->elements();
|
| + // When objects are first allocated, its elements are Failures.
|
| + if (fixed_array_base->IsFailure()) return;
|
| + if (!fixed_array_base->IsHeapObject()) return;
|
| + Map* map = fixed_array_base->map();
|
| + // Arrays that have been shifted in place can't be verified.
|
| + Heap* heap = holder->GetHeap();
|
| + if (map == heap->raw_unchecked_one_pointer_filler_map() ||
|
| + map == heap->raw_unchecked_two_pointer_filler_map() ||
|
| + map == heap->free_space_map()) {
|
| + return;
|
| + }
|
| + int length = 0;
|
| + if (holder->IsJSArray()) {
|
| + Object* length_obj = JSArray::cast(holder)->length();
|
| + if (length_obj->IsSmi()) {
|
| + length = Smi::cast(length_obj)->value();
|
| + }
|
| + } else {
|
| + length = fixed_array_base->length();
|
| + }
|
| + ElementsAccessorSubclass::ValidateContents(holder, length);
|
| + }
|
| +
|
| + virtual void Validate(JSObject* holder) {
|
| + ElementsAccessorSubclass::ValidateImpl(holder);
|
| + }
|
| +
|
| static bool HasElementImpl(Object* receiver,
|
| JSObject* holder,
|
| uint32_t key,
|
| @@ -455,9 +500,10 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| Object* length,
|
| BackingStore* backing_store);
|
|
|
| - MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(JSArray* array,
|
| - int capacity,
|
| - int length) {
|
| + MUST_USE_RESULT virtual MaybeObject* SetCapacityAndLength(
|
| + JSArray* array,
|
| + int capacity,
|
| + int length) {
|
| return ElementsAccessorSubclass::SetFastElementsCapacityAndLength(
|
| array,
|
| capacity,
|
| @@ -623,6 +669,7 @@ class FastElementsAccessor
|
| KindTraits>(name) {}
|
| protected:
|
| friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
| + friend class NonStrictArgumentsElementsAccessor;
|
|
|
| typedef typename KindTraits::BackingStore BackingStore;
|
|
|
| @@ -633,10 +680,21 @@ class FastElementsAccessor
|
| Object* length_object,
|
| uint32_t length) {
|
| uint32_t old_capacity = backing_store->length();
|
| + Object* old_length = array->length();
|
| + bool same_size = old_length->IsSmi() &&
|
| + static_cast<uint32_t>(Smi::cast(old_length)->value()) == length;
|
| + ElementsKind kind = array->GetElementsKind();
|
| +
|
| + if (!same_size && IsFastElementsKind(kind) &&
|
| + !IsFastHoleyElementsKind(kind)) {
|
| + kind = GetHoleyElementsKind(kind);
|
| + MaybeObject* maybe_obj = array->TransitionElementsKind(kind);
|
| + if (maybe_obj->IsFailure()) return maybe_obj;
|
| + }
|
|
|
| // Check whether the backing store should be shrunk.
|
| if (length <= old_capacity) {
|
| - if (array->HasFastTypeElements()) {
|
| + if (array->HasFastSmiOrObjectElements()) {
|
| MaybeObject* maybe_obj = array->EnsureWritableFastElements();
|
| if (!maybe_obj->To(&backing_store)) return maybe_obj;
|
| }
|
| @@ -668,39 +726,40 @@ class FastElementsAccessor
|
| MaybeObject* result = FastElementsAccessorSubclass::
|
| SetFastElementsCapacityAndLength(array, new_capacity, length);
|
| if (result->IsFailure()) return result;
|
| + array->ValidateElements();
|
| return length_object;
|
| }
|
|
|
| // Request conversion to slow elements.
|
| return array->GetHeap()->undefined_value();
|
| }
|
| -};
|
| -
|
| -
|
| -class FastObjectElementsAccessor
|
| - : public FastElementsAccessor<FastObjectElementsAccessor,
|
| - ElementsKindTraits<FAST_ELEMENTS>,
|
| - kPointerSize> {
|
| - public:
|
| - explicit FastObjectElementsAccessor(const char* name)
|
| - : FastElementsAccessor<FastObjectElementsAccessor,
|
| - ElementsKindTraits<FAST_ELEMENTS>,
|
| - kPointerSize>(name) {}
|
|
|
| static MaybeObject* DeleteCommon(JSObject* obj,
|
| - uint32_t key) {
|
| - ASSERT(obj->HasFastElements() ||
|
| - obj->HasFastSmiOnlyElements() ||
|
| + uint32_t key,
|
| + JSReceiver::DeleteMode mode) {
|
| + ASSERT(obj->HasFastSmiOrObjectElements() ||
|
| + obj->HasFastDoubleElements() ||
|
| obj->HasFastArgumentsElements());
|
| + typename KindTraits::BackingStore* backing_store =
|
| + KindTraits::BackingStore::cast(obj->elements());
|
| Heap* heap = obj->GetHeap();
|
| - FixedArray* backing_store = FixedArray::cast(obj->elements());
|
| if (backing_store->map() == heap->non_strict_arguments_elements_map()) {
|
| - backing_store = FixedArray::cast(backing_store->get(1));
|
| + backing_store =
|
| + KindTraits::BackingStore::cast(
|
| + FixedArray::cast(backing_store)->get(1));
|
| } else {
|
| - Object* writable;
|
| - MaybeObject* maybe = obj->EnsureWritableFastElements();
|
| - if (!maybe->ToObject(&writable)) return maybe;
|
| - backing_store = FixedArray::cast(writable);
|
| + ElementsKind kind = KindTraits::Kind;
|
| + if (IsFastPackedElementsKind(kind)) {
|
| + MaybeObject* transitioned =
|
| + obj->TransitionElementsKind(GetHoleyElementsKind(kind));
|
| + if (transitioned->IsFailure()) return transitioned;
|
| + }
|
| + if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) {
|
| + Object* writable;
|
| + MaybeObject* maybe = obj->EnsureWritableFastElements();
|
| + if (!maybe->ToObject(&writable)) return maybe;
|
| + backing_store = KindTraits::BackingStore::cast(writable);
|
| + }
|
| }
|
| uint32_t length = static_cast<uint32_t>(
|
| obj->IsJSArray()
|
| @@ -712,15 +771,14 @@ class FastObjectElementsAccessor
|
| // has too few used values, normalize it.
|
| // To avoid doing the check on every delete we require at least
|
| // one adjacent hole to the value being deleted.
|
| - Object* hole = heap->the_hole_value();
|
| const int kMinLengthForSparsenessCheck = 64;
|
| if (backing_store->length() >= kMinLengthForSparsenessCheck &&
|
| !heap->InNewSpace(backing_store) &&
|
| - ((key > 0 && backing_store->get(key - 1) == hole) ||
|
| - (key + 1 < length && backing_store->get(key + 1) == hole))) {
|
| + ((key > 0 && backing_store->is_the_hole(key - 1)) ||
|
| + (key + 1 < length && backing_store->is_the_hole(key + 1)))) {
|
| int num_used = 0;
|
| for (int i = 0; i < backing_store->length(); ++i) {
|
| - if (backing_store->get(i) != hole) ++num_used;
|
| + if (!backing_store->is_the_hole(i)) ++num_used;
|
| // Bail out early if more than 1/4 is used.
|
| if (4 * num_used > backing_store->length()) break;
|
| }
|
| @@ -733,27 +791,75 @@ class FastObjectElementsAccessor
|
| return heap->true_value();
|
| }
|
|
|
| + virtual MaybeObject* Delete(JSObject* obj,
|
| + uint32_t key,
|
| + JSReceiver::DeleteMode mode) {
|
| + return DeleteCommon(obj, key, mode);
|
| + }
|
| +
|
| + static bool HasElementImpl(
|
| + Object* receiver,
|
| + JSObject* holder,
|
| + uint32_t key,
|
| + typename KindTraits::BackingStore* backing_store) {
|
| + if (key >= static_cast<uint32_t>(backing_store->length())) {
|
| + return false;
|
| + }
|
| + return !backing_store->is_the_hole(key);
|
| + }
|
| +
|
| + static void ValidateContents(JSObject* holder, int length) {
|
| +#if DEBUG
|
| + FixedArrayBase* elements = holder->elements();
|
| + Heap* heap = elements->GetHeap();
|
| + Map* map = elements->map();
|
| + ASSERT((IsFastSmiOrObjectElementsKind(KindTraits::Kind) &&
|
| + (map == heap->fixed_array_map() ||
|
| + map == heap->fixed_cow_array_map())) ||
|
| + (IsFastDoubleElementsKind(KindTraits::Kind) ==
|
| + ((map == heap->fixed_array_map() && length == 0) ||
|
| + map == heap->fixed_double_array_map())));
|
| + for (int i = 0; i < length; i++) {
|
| + typename KindTraits::BackingStore* backing_store =
|
| + KindTraits::BackingStore::cast(elements);
|
| + ASSERT((!IsFastSmiElementsKind(KindTraits::Kind) ||
|
| + static_cast<Object*>(backing_store->get(i))->IsSmi()) ||
|
| + (IsFastHoleyElementsKind(KindTraits::Kind) ==
|
| + backing_store->is_the_hole(i)));
|
| + }
|
| +#endif
|
| + }
|
| +};
|
| +
|
| +
|
| +template<typename FastElementsAccessorSubclass,
|
| + typename KindTraits>
|
| +class FastSmiOrObjectElementsAccessor
|
| + : public FastElementsAccessor<FastElementsAccessorSubclass,
|
| + KindTraits,
|
| + kPointerSize> {
|
| + public:
|
| + explicit FastSmiOrObjectElementsAccessor(const char* name)
|
| + : FastElementsAccessor<FastElementsAccessorSubclass,
|
| + KindTraits,
|
| + kPointerSize>(name) {}
|
| +
|
| static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
|
| uint32_t from_start,
|
| FixedArrayBase* to,
|
| ElementsKind to_kind,
|
| uint32_t to_start,
|
| int copy_size) {
|
| - switch (to_kind) {
|
| - case FAST_SMI_ONLY_ELEMENTS:
|
| - case FAST_ELEMENTS: {
|
| - CopyObjectToObjectElements(
|
| - FixedArray::cast(from), ElementsTraits::Kind, from_start,
|
| - FixedArray::cast(to), to_kind, to_start, copy_size);
|
| - return from;
|
| - }
|
| - case FAST_DOUBLE_ELEMENTS:
|
| - CopyObjectToDoubleElements(
|
| - FixedArray::cast(from), from_start,
|
| - FixedDoubleArray::cast(to), to_start, copy_size);
|
| - return from;
|
| - default:
|
| - UNREACHABLE();
|
| + if (IsFastSmiOrObjectElementsKind(to_kind)) {
|
| + CopyObjectToObjectElements(
|
| + FixedArray::cast(from), KindTraits::Kind, from_start,
|
| + FixedArray::cast(to), to_kind, to_start, copy_size);
|
| + } else if (IsFastDoubleElementsKind(to_kind)) {
|
| + CopyObjectToDoubleElements(
|
| + FixedArray::cast(from), from_start,
|
| + FixedDoubleArray::cast(to), to_start, copy_size);
|
| + } else {
|
| + UNREACHABLE();
|
| }
|
| return to->GetHeap()->undefined_value();
|
| }
|
| @@ -762,51 +868,85 @@ class FastObjectElementsAccessor
|
| static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
|
| uint32_t capacity,
|
| uint32_t length) {
|
| - JSObject::SetFastElementsCapacityMode set_capacity_mode =
|
| - obj->HasFastSmiOnlyElements()
|
| - ? JSObject::kAllowSmiOnlyElements
|
| - : JSObject::kDontAllowSmiOnlyElements;
|
| + JSObject::SetFastElementsCapacitySmiMode set_capacity_mode =
|
| + obj->HasFastSmiElements()
|
| + ? JSObject::kAllowSmiElements
|
| + : JSObject::kDontAllowSmiElements;
|
| return obj->SetFastElementsCapacityAndLength(capacity,
|
| length,
|
| set_capacity_mode);
|
| }
|
| +};
|
|
|
| - protected:
|
| - friend class FastElementsAccessor<FastObjectElementsAccessor,
|
| - ElementsKindTraits<FAST_ELEMENTS>,
|
| - kPointerSize>;
|
|
|
| - virtual MaybeObject* Delete(JSObject* obj,
|
| - uint32_t key,
|
| - JSReceiver::DeleteMode mode) {
|
| - return DeleteCommon(obj, key);
|
| - }
|
| +class FastPackedSmiElementsAccessor
|
| + : public FastSmiOrObjectElementsAccessor<
|
| + FastPackedSmiElementsAccessor,
|
| + ElementsKindTraits<FAST_SMI_ELEMENTS> > {
|
| + public:
|
| + explicit FastPackedSmiElementsAccessor(const char* name)
|
| + : FastSmiOrObjectElementsAccessor<
|
| + FastPackedSmiElementsAccessor,
|
| + ElementsKindTraits<FAST_SMI_ELEMENTS> >(name) {}
|
| +};
|
| +
|
| +
|
| +class FastHoleySmiElementsAccessor
|
| + : public FastSmiOrObjectElementsAccessor<
|
| + FastHoleySmiElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> > {
|
| + public:
|
| + explicit FastHoleySmiElementsAccessor(const char* name)
|
| + : FastSmiOrObjectElementsAccessor<
|
| + FastHoleySmiElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_SMI_ELEMENTS> >(name) {}
|
| +};
|
| +
|
| +
|
| +class FastPackedObjectElementsAccessor
|
| + : public FastSmiOrObjectElementsAccessor<
|
| + FastPackedObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_ELEMENTS> > {
|
| + public:
|
| + explicit FastPackedObjectElementsAccessor(const char* name)
|
| + : FastSmiOrObjectElementsAccessor<
|
| + FastPackedObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_ELEMENTS> >(name) {}
|
| +};
|
| +
|
| +
|
| +class FastHoleyObjectElementsAccessor
|
| + : public FastSmiOrObjectElementsAccessor<
|
| + FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_ELEMENTS> > {
|
| + public:
|
| + explicit FastHoleyObjectElementsAccessor(const char* name)
|
| + : FastSmiOrObjectElementsAccessor<
|
| + FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_ELEMENTS> >(name) {}
|
| };
|
|
|
|
|
| +template<typename FastElementsAccessorSubclass,
|
| + typename KindTraits>
|
| class FastDoubleElementsAccessor
|
| - : public FastElementsAccessor<FastDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| + : public FastElementsAccessor<FastElementsAccessorSubclass,
|
| + KindTraits,
|
| kDoubleSize> {
|
| public:
|
| explicit FastDoubleElementsAccessor(const char* name)
|
| - : FastElementsAccessor<FastDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| + : FastElementsAccessor<FastElementsAccessorSubclass,
|
| + KindTraits,
|
| kDoubleSize>(name) {}
|
|
|
| static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
|
| uint32_t capacity,
|
| uint32_t length) {
|
| - return obj->SetFastDoubleElementsCapacityAndLength(capacity, length);
|
| + return obj->SetFastDoubleElementsCapacityAndLength(capacity,
|
| + length);
|
| }
|
|
|
| protected:
|
| - friend class ElementsAccessorBase<FastDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
|
| - friend class FastElementsAccessor<FastDoubleElementsAccessor,
|
| - ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| - kDoubleSize>;
|
| -
|
| static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
|
| uint32_t from_start,
|
| FixedArrayBase* to,
|
| @@ -814,12 +954,15 @@ class FastDoubleElementsAccessor
|
| uint32_t to_start,
|
| int copy_size) {
|
| switch (to_kind) {
|
| - case FAST_SMI_ONLY_ELEMENTS:
|
| + case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| + case FAST_HOLEY_SMI_ELEMENTS:
|
| + case FAST_HOLEY_ELEMENTS:
|
| return CopyDoubleToObjectElements(
|
| FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
|
| to_kind, to_start, copy_size);
|
| case FAST_DOUBLE_ELEMENTS:
|
| + case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
|
| FixedDoubleArray::cast(to),
|
| to_start, copy_size);
|
| @@ -829,26 +972,35 @@ class FastDoubleElementsAccessor
|
| }
|
| return to->GetHeap()->undefined_value();
|
| }
|
| +};
|
|
|
| - virtual MaybeObject* Delete(JSObject* obj,
|
| - uint32_t key,
|
| - JSReceiver::DeleteMode mode) {
|
| - int length = obj->IsJSArray()
|
| - ? Smi::cast(JSArray::cast(obj)->length())->value()
|
| - : FixedDoubleArray::cast(obj->elements())->length();
|
| - if (key < static_cast<uint32_t>(length)) {
|
| - FixedDoubleArray::cast(obj->elements())->set_the_hole(key);
|
| - }
|
| - return obj->GetHeap()->true_value();
|
| - }
|
|
|
| - static bool HasElementImpl(Object* receiver,
|
| - JSObject* holder,
|
| - uint32_t key,
|
| - FixedDoubleArray* backing_store) {
|
| - return key < static_cast<uint32_t>(backing_store->length()) &&
|
| - !backing_store->is_the_hole(key);
|
| - }
|
| +class FastPackedDoubleElementsAccessor
|
| + : public FastDoubleElementsAccessor<
|
| + FastPackedDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > {
|
| + public:
|
| + friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
|
| + explicit FastPackedDoubleElementsAccessor(const char* name)
|
| + : FastDoubleElementsAccessor<
|
| + FastPackedDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {}
|
| +};
|
| +
|
| +
|
| +class FastHoleyDoubleElementsAccessor
|
| + : public FastDoubleElementsAccessor<
|
| + FastHoleyDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > {
|
| + public:
|
| + friend class ElementsAccessorBase<
|
| + FastHoleyDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >;
|
| + explicit FastHoleyDoubleElementsAccessor(const char* name)
|
| + : FastDoubleElementsAccessor<
|
| + FastHoleyDoubleElementsAccessor,
|
| + ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {}
|
| };
|
|
|
|
|
| @@ -1115,13 +1267,16 @@ class DictionaryElementsAccessor
|
| uint32_t to_start,
|
| int copy_size) {
|
| switch (to_kind) {
|
| - case FAST_SMI_ONLY_ELEMENTS:
|
| + case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| + case FAST_HOLEY_SMI_ELEMENTS:
|
| + case FAST_HOLEY_ELEMENTS:
|
| CopyDictionaryToObjectElements(
|
| SeededNumberDictionary::cast(from), from_start,
|
| FixedArray::cast(to), to_kind, to_start, copy_size);
|
| return from;
|
| case FAST_DOUBLE_ELEMENTS:
|
| + case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| CopyDictionaryToDoubleElements(
|
| SeededNumberDictionary::cast(from), from_start,
|
| FixedDoubleArray::cast(to), to_start, copy_size);
|
| @@ -1248,7 +1403,10 @@ class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
|
| if (arguments->IsDictionary()) {
|
| return DictionaryElementsAccessor::DeleteCommon(obj, key, mode);
|
| } else {
|
| - return FastObjectElementsAccessor::DeleteCommon(obj, key);
|
| + // It's difficult to access the version of DeleteCommon that is declared
|
| + // in the templatized super class, call the concrete implementation in
|
| + // the class for the most generalized ElementsKind subclass.
|
| + return FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, mode);
|
| }
|
| }
|
| return obj->GetHeap()->true_value();
|
| @@ -1312,7 +1470,7 @@ ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
|
| if (array->IsDictionary()) {
|
| return elements_accessors_[DICTIONARY_ELEMENTS];
|
| } else {
|
| - return elements_accessors_[FAST_ELEMENTS];
|
| + return elements_accessors_[FAST_HOLEY_ELEMENTS];
|
| }
|
| case EXTERNAL_BYTE_ARRAY_TYPE:
|
| return elements_accessors_[EXTERNAL_BYTE_ELEMENTS];
|
|
|