| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index e1be677072bc67e58c368b1d275c8e333993005a..5a9f4f4b75106c35e603f73cee348bf6b6c7ffc6 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -59,6 +59,53 @@ namespace v8 {
|
| namespace internal {
|
|
|
|
|
| +// First argument in list is the accessor class, the second argument is the
|
| +// accessor ElementsKind, and the third is the backing store class. Use the
|
| +// fast element handler for smi-only arrays. The implementation is currently
|
| +// 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(DictionaryElementsAccessor, DICTIONARY_ELEMENTS, \
|
| + SeededNumberDictionary) \
|
| + V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS, \
|
| + FixedArray) \
|
| + V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS, \
|
| + ExternalByteArray) \
|
| + V(ExternalUnsignedByteElementsAccessor, \
|
| + EXTERNAL_UNSIGNED_BYTE_ELEMENTS, ExternalUnsignedByteArray) \
|
| + V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS, \
|
| + ExternalShortArray) \
|
| + V(ExternalUnsignedShortElementsAccessor, \
|
| + EXTERNAL_UNSIGNED_SHORT_ELEMENTS, ExternalUnsignedShortArray) \
|
| + V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS, \
|
| + ExternalIntArray) \
|
| + V(ExternalUnsignedIntElementsAccessor, \
|
| + EXTERNAL_UNSIGNED_INT_ELEMENTS, ExternalUnsignedIntArray) \
|
| + V(ExternalFloatElementsAccessor, \
|
| + EXTERNAL_FLOAT_ELEMENTS, ExternalFloatArray) \
|
| + V(ExternalDoubleElementsAccessor, \
|
| + EXTERNAL_DOUBLE_ELEMENTS, ExternalDoubleArray) \
|
| + V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS, ExternalPixelArray)
|
| +
|
| +
|
| +template<ElementsKind Kind> class ElementsKindTraits {
|
| + public:
|
| + typedef FixedArrayBase BackingStore;
|
| +};
|
| +
|
| +#define ELEMENTS_TRAITS(Class, KindParam, Store) \
|
| +template<> class ElementsKindTraits<KindParam> { \
|
| + public: \
|
| + static const ElementsKind Kind = KindParam; \
|
| + typedef Store BackingStore; \
|
| +};
|
| +ELEMENTS_LIST(ELEMENTS_TRAITS)
|
| +#undef ELEMENTS_TRAITS
|
| +
|
| +
|
| ElementsAccessor** ElementsAccessor::elements_accessors_;
|
|
|
|
|
| @@ -84,6 +131,140 @@ static Failure* ThrowArrayLengthRangeError(Heap* heap) {
|
| }
|
|
|
|
|
| +void CopyObjectToObjectElements(AssertNoAllocation* no_gc,
|
| + FixedArray* from_obj,
|
| + ElementsKind from_kind,
|
| + uint32_t from_start,
|
| + FixedArray* to_obj,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + ASSERT(to_obj->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);
|
| + if (copy_size == -1) {
|
| + copy_size = Min(from_obj->length() - from_start,
|
| + to_obj->length() - to_start);
|
| + }
|
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() &&
|
| + (copy_size + static_cast<int>(from_start)) <= from_obj->length()));
|
| + if (copy_size == 0) return;
|
| + Address to = to_obj->address() + FixedArray::kHeaderSize;
|
| + Address from = from_obj->address() + FixedArray::kHeaderSize;
|
| + CopyWords(reinterpret_cast<Object**>(to) + to_start,
|
| + reinterpret_cast<Object**>(from) + from_start,
|
| + copy_size);
|
| + if (from_kind == FAST_ELEMENTS && to_kind == FAST_ELEMENTS) {
|
| + Heap* heap = from_obj->GetHeap();
|
| + WriteBarrierMode mode = to_obj->GetWriteBarrierMode(*no_gc);
|
| + if (mode == UPDATE_WRITE_BARRIER) {
|
| + heap->RecordWrites(to_obj->address(),
|
| + to_obj->OffsetOfElementAt(to_start),
|
| + copy_size);
|
| + }
|
| + heap->incremental_marking()->RecordWrites(to_obj);
|
| + }
|
| +}
|
| +
|
| +
|
| +
|
| +
|
| +static void CopyDictionaryToObjectElements(SeededNumberDictionary* from,
|
| + uint32_t from_start,
|
| + FixedArray* to,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + ASSERT(to != from);
|
| + ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
|
| + ASSERT(copy_size == -1 ||
|
| + (copy_size + static_cast<int>(to_start)) <= to->length());
|
| + WriteBarrierMode mode = to_kind == FAST_ELEMENTS
|
| + ? UPDATE_WRITE_BARRIER
|
| + : SKIP_WRITE_BARRIER;
|
| + uint32_t copy_limit = (copy_size == -1)
|
| + ? to->length()
|
| + : Min(to_start + copy_size, static_cast<uint32_t>(to->length()));
|
| + for (int i = 0; i < from->Capacity(); ++i) {
|
| + Object* key = from->KeyAt(i);
|
| + if (key->IsNumber()) {
|
| + uint32_t entry = static_cast<uint32_t>(key->Number());
|
| + if (entry >= to_start && entry < copy_limit) {
|
| + Object* value = from->ValueAt(i);
|
| + ASSERT(to_kind == FAST_ELEMENTS || value->IsSmi());
|
| + to->set(entry, value, mode);
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| +MUST_USE_RESULT static MaybeObject* CopyDoubleToObjectElements(
|
| + FixedDoubleArray* from_obj,
|
| + uint32_t from_start,
|
| + FixedArray* to_obj,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + ASSERT(to_kind == FAST_ELEMENTS || to_kind == FAST_SMI_ONLY_ELEMENTS);
|
| + if (copy_size == -1) {
|
| + copy_size = Min(from_obj->length() - from_start,
|
| + to_obj->length() - to_start);
|
| + }
|
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() &&
|
| + (copy_size + static_cast<int>(from_start)) <= from_obj->length()));
|
| + if (copy_size == 0) return from_obj;
|
| + for (int i = 0; i < copy_size; ++i) {
|
| + if (to_kind == FAST_SMI_ONLY_ELEMENTS) {
|
| + UNIMPLEMENTED();
|
| + return Failure::Exception();
|
| + } else {
|
| + MaybeObject* maybe_value = from_obj->get(i + from_start);
|
| + Object* value;
|
| + ASSERT(to_kind == FAST_ELEMENTS);
|
| + // Because FAST_DOUBLE_ELEMENTS -> FAST_ELEMENT 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
|
| + // can't be taken from new space.
|
| + if (!maybe_value->ToObject(&value)) {
|
| + ASSERT(maybe_value->IsRetryAfterGC() || maybe_value->IsOutOfMemory());
|
| + Heap* heap = from_obj->GetHeap();
|
| + MaybeObject* maybe_value_object =
|
| + heap->AllocateHeapNumber(from_obj->get_scalar(i + from_start),
|
| + TENURED);
|
| + if (!maybe_value_object->ToObject(&value)) return maybe_value_object;
|
| + }
|
| + to_obj->set(i + to_start, value, UPDATE_WRITE_BARRIER);
|
| + }
|
| + }
|
| + return to_obj;
|
| +}
|
| +
|
| +
|
| +static void CopyDoubleToDoubleElements(FixedDoubleArray* from_obj,
|
| + uint32_t from_start,
|
| + FixedDoubleArray* to_obj,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + if (copy_size == -1) {
|
| + copy_size = Min(from_obj->length() - from_start,
|
| + to_obj->length() - to_start);
|
| + }
|
| + ASSERT(((copy_size + static_cast<int>(to_start)) <= to_obj->length() &&
|
| + (copy_size + static_cast<int>(from_start)) <= from_obj->length()));
|
| + if (copy_size == 0) return;
|
| + Address to = to_obj->address() + FixedDoubleArray::kHeaderSize;
|
| + Address from = from_obj->address() + FixedDoubleArray::kHeaderSize;
|
| + to += kDoubleSize * to_start;
|
| + from += kDoubleSize * from_start;
|
| + int words_per_double = (kDoubleSize / kPointerSize);
|
| + CopyWords(reinterpret_cast<Object**>(to),
|
| + reinterpret_cast<Object**>(from),
|
| + words_per_double * copy_size);
|
| +}
|
| +
|
| +
|
| // Base class for element handler implementations. Contains the
|
| // the common logic for objects with different ElementsKinds.
|
| // Subclasses must specialize method for which the element
|
| @@ -101,15 +282,22 @@ static Failure* ThrowArrayLengthRangeError(Heap* heap) {
|
| // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use
|
| // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and
|
| // specialization of SomeElementsAccessor methods).
|
| -template <typename ElementsAccessorSubclass, typename BackingStoreClass>
|
| +template <typename ElementsAccessorSubclass,
|
| + typename ElementsTraitsParam>
|
| class ElementsAccessorBase : public ElementsAccessor {
|
| protected:
|
| - explicit ElementsAccessorBase(const char* name) : ElementsAccessor(name) { }
|
| + explicit ElementsAccessorBase(const char* name)
|
| + : ElementsAccessor(name) { }
|
| +
|
| + typedef ElementsTraitsParam ElementsTraits;
|
| + typedef typename ElementsTraitsParam::BackingStore BackingStore;
|
| +
|
| + virtual ElementsKind kind() const { return ElementsTraits::Kind; }
|
|
|
| static bool HasElementImpl(Object* receiver,
|
| JSObject* holder,
|
| uint32_t key,
|
| - BackingStoreClass* backing_store) {
|
| + BackingStore* backing_store) {
|
| MaybeObject* element =
|
| ElementsAccessorSubclass::GetImpl(receiver, holder, key, backing_store);
|
| return !element->IsTheHole();
|
| @@ -123,7 +311,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| backing_store = holder->elements();
|
| }
|
| return ElementsAccessorSubclass::HasElementImpl(
|
| - receiver, holder, key, BackingStoreClass::cast(backing_store));
|
| + receiver, holder, key, BackingStore::cast(backing_store));
|
| }
|
|
|
| virtual MaybeObject* Get(Object* receiver,
|
| @@ -134,13 +322,13 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| backing_store = holder->elements();
|
| }
|
| return ElementsAccessorSubclass::GetImpl(
|
| - receiver, holder, key, BackingStoreClass::cast(backing_store));
|
| + receiver, holder, key, BackingStore::cast(backing_store));
|
| }
|
|
|
| static MaybeObject* GetImpl(Object* receiver,
|
| JSObject* obj,
|
| uint32_t key,
|
| - BackingStoreClass* backing_store) {
|
| + BackingStore* backing_store) {
|
| return (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store))
|
| ? backing_store->get(key)
|
| : backing_store->GetHeap()->the_hole_value();
|
| @@ -149,12 +337,12 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| virtual MaybeObject* SetLength(JSArray* array,
|
| Object* length) {
|
| return ElementsAccessorSubclass::SetLengthImpl(
|
| - array, length, BackingStoreClass::cast(array->elements()));
|
| + array, length, BackingStore::cast(array->elements()));
|
| }
|
|
|
| static MaybeObject* SetLengthImpl(JSObject* obj,
|
| Object* length,
|
| - BackingStoreClass* backing_store);
|
| + BackingStore* backing_store);
|
|
|
| virtual MaybeObject* SetCapacityAndLength(JSArray* array,
|
| int capacity,
|
| @@ -176,6 +364,30 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| uint32_t key,
|
| JSReceiver::DeleteMode mode) = 0;
|
|
|
| + static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
|
| + uint32_t from_start,
|
| + FixedArrayBase* to,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + UNREACHABLE();
|
| + return NULL;
|
| + }
|
| +
|
| + virtual MaybeObject* CopyElements(JSObject* from_holder,
|
| + uint32_t from_start,
|
| + FixedArrayBase* to,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size,
|
| + FixedArrayBase* from) {
|
| + if (from == NULL) {
|
| + from = from_holder->elements();
|
| + }
|
| + return ElementsAccessorSubclass::CopyElementsImpl(
|
| + from, from_start, to, to_kind, to_start, copy_size);
|
| + }
|
| +
|
| virtual MaybeObject* AddElementsToFixedArray(Object* receiver,
|
| JSObject* holder,
|
| FixedArray* to,
|
| @@ -191,7 +403,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| if (from == NULL) {
|
| from = holder->elements();
|
| }
|
| - BackingStoreClass* backing_store = BackingStoreClass::cast(from);
|
| + BackingStore* backing_store = BackingStore::cast(from);
|
| uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(backing_store);
|
|
|
| // Optimize if 'other' is empty.
|
| @@ -258,16 +470,16 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| }
|
|
|
| protected:
|
| - static uint32_t GetCapacityImpl(BackingStoreClass* backing_store) {
|
| + static uint32_t GetCapacityImpl(BackingStore* backing_store) {
|
| return backing_store->length();
|
| }
|
|
|
| virtual uint32_t GetCapacity(FixedArrayBase* backing_store) {
|
| return ElementsAccessorSubclass::GetCapacityImpl(
|
| - BackingStoreClass::cast(backing_store));
|
| + BackingStore::cast(backing_store));
|
| }
|
|
|
| - static uint32_t GetKeyForIndexImpl(BackingStoreClass* backing_store,
|
| + static uint32_t GetKeyForIndexImpl(BackingStore* backing_store,
|
| uint32_t index) {
|
| return index;
|
| }
|
| @@ -275,7 +487,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store,
|
| uint32_t index) {
|
| return ElementsAccessorSubclass::GetKeyForIndexImpl(
|
| - BackingStoreClass::cast(backing_store), index);
|
| + BackingStore::cast(backing_store), index);
|
| }
|
|
|
| private:
|
| @@ -285,16 +497,18 @@ class ElementsAccessorBase : public ElementsAccessor {
|
|
|
| // Super class for all fast element arrays.
|
| template<typename FastElementsAccessorSubclass,
|
| - typename BackingStore,
|
| + typename KindTraits,
|
| int ElementSize>
|
| class FastElementsAccessor
|
| - : public ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore> {
|
| + : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> {
|
| public:
|
| explicit FastElementsAccessor(const char* name)
|
| : ElementsAccessorBase<FastElementsAccessorSubclass,
|
| - BackingStore>(name) {}
|
| + KindTraits>(name) {}
|
| protected:
|
| - friend class ElementsAccessorBase<FastElementsAccessorSubclass, BackingStore>;
|
| + friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
| +
|
| + typedef typename KindTraits::BackingStore BackingStore;
|
|
|
| // Adjusts the length of the fast backing store or returns the new length or
|
| // undefined in case conversion to a slow backing store should be performed.
|
| @@ -349,12 +563,12 @@ class FastElementsAccessor
|
|
|
| class FastObjectElementsAccessor
|
| : public FastElementsAccessor<FastObjectElementsAccessor,
|
| - FixedArray,
|
| + ElementsKindTraits<FAST_ELEMENTS>,
|
| kPointerSize> {
|
| public:
|
| explicit FastObjectElementsAccessor(const char* name)
|
| : FastElementsAccessor<FastObjectElementsAccessor,
|
| - FixedArray,
|
| + ElementsKindTraits<FAST_ELEMENTS>,
|
| kPointerSize>(name) {}
|
|
|
| static MaybeObject* DeleteCommon(JSObject* obj,
|
| @@ -403,6 +617,28 @@ class FastObjectElementsAccessor
|
| return heap->true_value();
|
| }
|
|
|
| + 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: {
|
| + AssertNoAllocation no_gc;
|
| + CopyObjectToObjectElements(
|
| + &no_gc, FixedArray::cast(from), ElementsTraits::Kind, from_start,
|
| + FixedArray::cast(to), to_kind, to_start, copy_size);
|
| + return from;
|
| + }
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + return to->GetHeap()->undefined_value();
|
| + }
|
| +
|
| +
|
| static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
|
| uint32_t capacity,
|
| uint32_t length) {
|
| @@ -417,7 +653,7 @@ class FastObjectElementsAccessor
|
|
|
| protected:
|
| friend class FastElementsAccessor<FastObjectElementsAccessor,
|
| - FixedArray,
|
| + ElementsKindTraits<FAST_ELEMENTS>,
|
| kPointerSize>;
|
|
|
| virtual MaybeObject* Delete(JSObject* obj,
|
| @@ -430,12 +666,12 @@ class FastObjectElementsAccessor
|
|
|
| class FastDoubleElementsAccessor
|
| : public FastElementsAccessor<FastDoubleElementsAccessor,
|
| - FixedDoubleArray,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| kDoubleSize> {
|
| public:
|
| explicit FastDoubleElementsAccessor(const char* name)
|
| : FastElementsAccessor<FastDoubleElementsAccessor,
|
| - FixedDoubleArray,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| kDoubleSize>(name) {}
|
|
|
| static MaybeObject* SetFastElementsCapacityAndLength(JSObject* obj,
|
| @@ -446,11 +682,34 @@ class FastDoubleElementsAccessor
|
|
|
| protected:
|
| friend class ElementsAccessorBase<FastDoubleElementsAccessor,
|
| - FixedDoubleArray>;
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >;
|
| friend class FastElementsAccessor<FastDoubleElementsAccessor,
|
| - FixedDoubleArray,
|
| + ElementsKindTraits<FAST_DOUBLE_ELEMENTS>,
|
| kDoubleSize>;
|
|
|
| + 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:
|
| + return CopyDoubleToObjectElements(
|
| + FixedDoubleArray::cast(from), from_start, FixedArray::cast(to),
|
| + to_kind, to_start, copy_size);
|
| + case FAST_DOUBLE_ELEMENTS:
|
| + CopyDoubleToDoubleElements(FixedDoubleArray::cast(from), from_start,
|
| + FixedDoubleArray::cast(to),
|
| + to_start, copy_size);
|
| + return from;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + return to->GetHeap()->undefined_value();
|
| + }
|
| +
|
| virtual MaybeObject* Delete(JSObject* obj,
|
| uint32_t key,
|
| JSReceiver::DeleteMode mode) {
|
| @@ -474,23 +733,25 @@ class FastDoubleElementsAccessor
|
|
|
| // Super class for all external element arrays.
|
| template<typename ExternalElementsAccessorSubclass,
|
| - typename ExternalArray>
|
| + ElementsKind Kind>
|
| class ExternalElementsAccessor
|
| : public ElementsAccessorBase<ExternalElementsAccessorSubclass,
|
| - ExternalArray> {
|
| + ElementsKindTraits<Kind> > {
|
| public:
|
| explicit ExternalElementsAccessor(const char* name)
|
| : ElementsAccessorBase<ExternalElementsAccessorSubclass,
|
| - ExternalArray>(name) {}
|
| + ElementsKindTraits<Kind> >(name) {}
|
|
|
| protected:
|
| + typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
|
| +
|
| friend class ElementsAccessorBase<ExternalElementsAccessorSubclass,
|
| - ExternalArray>;
|
| + ElementsKindTraits<Kind> >;
|
|
|
| static MaybeObject* GetImpl(Object* receiver,
|
| JSObject* obj,
|
| uint32_t key,
|
| - ExternalArray* backing_store) {
|
| + BackingStore* backing_store) {
|
| return
|
| key < ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store)
|
| ? backing_store->get(key)
|
| @@ -499,7 +760,7 @@ class ExternalElementsAccessor
|
|
|
| static MaybeObject* SetLengthImpl(JSObject* obj,
|
| Object* length,
|
| - ExternalArray* backing_store) {
|
| + BackingStore* backing_store) {
|
| // External arrays do not support changing their length.
|
| UNREACHABLE();
|
| return obj;
|
| @@ -515,7 +776,7 @@ class ExternalElementsAccessor
|
| static bool HasElementImpl(Object* receiver,
|
| JSObject* holder,
|
| uint32_t key,
|
| - ExternalArray* backing_store) {
|
| + BackingStore* backing_store) {
|
| uint32_t capacity =
|
| ExternalElementsAccessorSubclass::GetCapacityImpl(backing_store);
|
| return key < capacity;
|
| @@ -525,101 +786,101 @@ class ExternalElementsAccessor
|
|
|
| class ExternalByteElementsAccessor
|
| : public ExternalElementsAccessor<ExternalByteElementsAccessor,
|
| - ExternalByteArray> {
|
| + EXTERNAL_BYTE_ELEMENTS> {
|
| public:
|
| explicit ExternalByteElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalByteElementsAccessor,
|
| - ExternalByteArray>(name) {}
|
| + EXTERNAL_BYTE_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalUnsignedByteElementsAccessor
|
| : public ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
|
| - ExternalUnsignedByteArray> {
|
| + EXTERNAL_UNSIGNED_BYTE_ELEMENTS> {
|
| public:
|
| explicit ExternalUnsignedByteElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalUnsignedByteElementsAccessor,
|
| - ExternalUnsignedByteArray>(name) {}
|
| + EXTERNAL_UNSIGNED_BYTE_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalShortElementsAccessor
|
| : public ExternalElementsAccessor<ExternalShortElementsAccessor,
|
| - ExternalShortArray> {
|
| + EXTERNAL_SHORT_ELEMENTS> {
|
| public:
|
| explicit ExternalShortElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalShortElementsAccessor,
|
| - ExternalShortArray>(name) {}
|
| + EXTERNAL_SHORT_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalUnsignedShortElementsAccessor
|
| : public ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
|
| - ExternalUnsignedShortArray> {
|
| + EXTERNAL_UNSIGNED_SHORT_ELEMENTS> {
|
| public:
|
| explicit ExternalUnsignedShortElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalUnsignedShortElementsAccessor,
|
| - ExternalUnsignedShortArray>(name) {}
|
| + EXTERNAL_UNSIGNED_SHORT_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalIntElementsAccessor
|
| : public ExternalElementsAccessor<ExternalIntElementsAccessor,
|
| - ExternalIntArray> {
|
| + EXTERNAL_INT_ELEMENTS> {
|
| public:
|
| explicit ExternalIntElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalIntElementsAccessor,
|
| - ExternalIntArray>(name) {}
|
| + EXTERNAL_INT_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalUnsignedIntElementsAccessor
|
| : public ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
|
| - ExternalUnsignedIntArray> {
|
| + EXTERNAL_UNSIGNED_INT_ELEMENTS> {
|
| public:
|
| explicit ExternalUnsignedIntElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalUnsignedIntElementsAccessor,
|
| - ExternalUnsignedIntArray>(name) {}
|
| + EXTERNAL_UNSIGNED_INT_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalFloatElementsAccessor
|
| : public ExternalElementsAccessor<ExternalFloatElementsAccessor,
|
| - ExternalFloatArray> {
|
| + EXTERNAL_FLOAT_ELEMENTS> {
|
| public:
|
| explicit ExternalFloatElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalFloatElementsAccessor,
|
| - ExternalFloatArray>(name) {}
|
| + EXTERNAL_FLOAT_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class ExternalDoubleElementsAccessor
|
| : public ExternalElementsAccessor<ExternalDoubleElementsAccessor,
|
| - ExternalDoubleArray> {
|
| + EXTERNAL_DOUBLE_ELEMENTS> {
|
| public:
|
| explicit ExternalDoubleElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<ExternalDoubleElementsAccessor,
|
| - ExternalDoubleArray>(name) {}
|
| + EXTERNAL_DOUBLE_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class PixelElementsAccessor
|
| : public ExternalElementsAccessor<PixelElementsAccessor,
|
| - ExternalPixelArray> {
|
| + EXTERNAL_PIXEL_ELEMENTS> {
|
| public:
|
| explicit PixelElementsAccessor(const char* name)
|
| : ExternalElementsAccessor<PixelElementsAccessor,
|
| - ExternalPixelArray>(name) {}
|
| + EXTERNAL_PIXEL_ELEMENTS>(name) {}
|
| };
|
|
|
|
|
| class DictionaryElementsAccessor
|
| : public ElementsAccessorBase<DictionaryElementsAccessor,
|
| - SeededNumberDictionary> {
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> > {
|
| public:
|
| explicit DictionaryElementsAccessor(const char* name)
|
| : ElementsAccessorBase<DictionaryElementsAccessor,
|
| - SeededNumberDictionary>(name) {}
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {}
|
|
|
| // Adjusts the length of the dictionary backing store and returns the new
|
| // length according to ES5 section 15.4.5.2 behavior.
|
| @@ -723,9 +984,29 @@ class DictionaryElementsAccessor
|
| return heap->true_value();
|
| }
|
|
|
| + 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:
|
| + CopyDictionaryToObjectElements(
|
| + SeededNumberDictionary::cast(from), from_start,
|
| + FixedArray::cast(to), to_kind, to_start, copy_size);
|
| + return from;
|
| + default:
|
| + UNREACHABLE();
|
| + }
|
| + return to->GetHeap()->undefined_value();
|
| + }
|
| +
|
| +
|
| protected:
|
| friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
| - SeededNumberDictionary>;
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
|
|
| virtual MaybeObject* Delete(JSObject* obj,
|
| uint32_t key,
|
| @@ -769,16 +1050,18 @@ class DictionaryElementsAccessor
|
| };
|
|
|
|
|
| -class NonStrictArgumentsElementsAccessor
|
| - : public ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
|
| - FixedArray> {
|
| +class NonStrictArgumentsElementsAccessor : public ElementsAccessorBase<
|
| + NonStrictArgumentsElementsAccessor,
|
| + ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> > {
|
| public:
|
| explicit NonStrictArgumentsElementsAccessor(const char* name)
|
| - : ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
|
| - FixedArray>(name) {}
|
| + : ElementsAccessorBase<
|
| + NonStrictArgumentsElementsAccessor,
|
| + ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >(name) {}
|
| protected:
|
| - friend class ElementsAccessorBase<NonStrictArgumentsElementsAccessor,
|
| - FixedArray>;
|
| + friend class ElementsAccessorBase<
|
| + NonStrictArgumentsElementsAccessor,
|
| + ElementsKindTraits<NON_STRICT_ARGUMENTS_ELEMENTS> >;
|
|
|
| static MaybeObject* GetImpl(Object* receiver,
|
| JSObject* obj,
|
| @@ -840,6 +1123,19 @@ class NonStrictArgumentsElementsAccessor
|
| return obj->GetHeap()->true_value();
|
| }
|
|
|
| + static MaybeObject* CopyElementsImpl(FixedArrayBase* from,
|
| + uint32_t from_start,
|
| + FixedArrayBase* to,
|
| + ElementsKind to_kind,
|
| + uint32_t to_start,
|
| + int copy_size) {
|
| + FixedArray* parameter_map = FixedArray::cast(from);
|
| + FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| + ElementsAccessor* accessor = ElementsAccessor::ForArray(arguments);
|
| + return accessor->CopyElements(NULL, from_start, to, to_kind,
|
| + to_start, copy_size, arguments);
|
| + }
|
| +
|
| static uint32_t GetCapacityImpl(FixedArray* parameter_map) {
|
| FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
| return Max(static_cast<uint32_t>(parameter_map->length() - 2),
|
| @@ -913,45 +1209,22 @@ ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
|
|
|
|
|
| void ElementsAccessor::InitializeOncePerProcess() {
|
| - // First argument in list is the accessor class, the second argument is can
|
| - // be any arbitrary unique identifier, in this case chosen to be the
|
| - // corresponding enum. Use the fast element handler for smi-only arrays.
|
| - // The implementation is currently 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) \
|
| - V(FastObjectElementsAccessor, FAST_ELEMENTS) \
|
| - V(FastDoubleElementsAccessor, FAST_DOUBLE_ELEMENTS) \
|
| - V(DictionaryElementsAccessor, DICTIONARY_ELEMENTS) \
|
| - V(NonStrictArgumentsElementsAccessor, NON_STRICT_ARGUMENTS_ELEMENTS) \
|
| - V(ExternalByteElementsAccessor, EXTERNAL_BYTE_ELEMENTS) \
|
| - V(ExternalUnsignedByteElementsAccessor, EXTERNAL_UNSIGNED_BYTE_ELEMENTS) \
|
| - V(ExternalShortElementsAccessor, EXTERNAL_SHORT_ELEMENTS) \
|
| - V(ExternalUnsignedShortElementsAccessor, EXTERNAL_UNSIGNED_SHORT_ELEMENTS) \
|
| - V(ExternalIntElementsAccessor, EXTERNAL_INT_ELEMENTS) \
|
| - V(ExternalUnsignedIntElementsAccessor, EXTERNAL_UNSIGNED_INT_ELEMENTS) \
|
| - V(ExternalFloatElementsAccessor, EXTERNAL_FLOAT_ELEMENTS) \
|
| - V(ExternalDoubleElementsAccessor, EXTERNAL_DOUBLE_ELEMENTS) \
|
| - V(PixelElementsAccessor, EXTERNAL_PIXEL_ELEMENTS)
|
| -
|
| static struct ConcreteElementsAccessors {
|
| -#define ACCESSOR_STRUCT(Class, Name) Class* Name##_handler;
|
| +#define ACCESSOR_STRUCT(Class, Kind, Store) Class* Kind##_handler;
|
| ELEMENTS_LIST(ACCESSOR_STRUCT)
|
| #undef ACCESSOR_STRUCT
|
| } element_accessors = {
|
| -#define ACCESSOR_INIT(Class, Name) new Class(#Name),
|
| +#define ACCESSOR_INIT(Class, Kind, Store) new Class(#Kind),
|
| ELEMENTS_LIST(ACCESSOR_INIT)
|
| #undef ACCESSOR_INIT
|
| };
|
|
|
| static ElementsAccessor* accessor_array[] = {
|
| -#define ACCESSOR_ARRAY(Class, Name) element_accessors.Name##_handler,
|
| +#define ACCESSOR_ARRAY(Class, Kind, Store) element_accessors.Kind##_handler,
|
| ELEMENTS_LIST(ACCESSOR_ARRAY)
|
| #undef ACCESSOR_ARRAY
|
| };
|
|
|
| -#undef ELEMENTS_LIST
|
| -
|
| STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) ==
|
| kElementsKindCount);
|
|
|
| @@ -959,11 +1232,12 @@ void ElementsAccessor::InitializeOncePerProcess() {
|
| }
|
|
|
|
|
| -template <typename ElementsAccessorSubclass, typename BackingStoreClass>
|
| -MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass, BackingStoreClass>::
|
| +template <typename ElementsAccessorSubclass, typename ElementsKindTraits>
|
| +MaybeObject* ElementsAccessorBase<ElementsAccessorSubclass,
|
| + ElementsKindTraits>::
|
| SetLengthImpl(JSObject* obj,
|
| Object* length,
|
| - BackingStoreClass* backing_store) {
|
| + typename ElementsKindTraits::BackingStore* backing_store) {
|
| JSArray* array = JSArray::cast(obj);
|
|
|
| // Fast case: The new length fits into a Smi.
|
|
|