| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 16e8b067cf9273b15fc0dd291b4ad0471d47a721..45556d42c10152693be3a38d4e82ce58c4439d4f 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -40,7 +40,9 @@
|
| // - SloppyArgumentsElementsAccessor
|
| // - FastSloppyArgumentsElementsAccessor
|
| // - SlowSloppyArgumentsElementsAccessor
|
| -
|
| +// - StringWrapperElementsAccessor
|
| +// - FastStringWrapperElementsAccessor
|
| +// - SlowStringWrapperElementsAccessor
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -72,6 +74,10 @@ enum Where { AT_START, AT_END };
|
| FixedArray) \
|
| V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS, \
|
| FixedArray) \
|
| + V(FastStringWrapperElementsAccessor, FAST_STRING_WRAPPER_ELEMENTS, \
|
| + FixedArray) \
|
| + V(SlowStringWrapperElementsAccessor, SLOW_STRING_WRAPPER_ELEMENTS, \
|
| + FixedArray) \
|
| V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
|
| V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
|
| V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
|
| @@ -83,7 +89,6 @@ enum Where { AT_START, AT_END };
|
| V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
|
| FixedUint8ClampedArray)
|
|
|
| -
|
| template<ElementsKind Kind> class ElementsKindTraits {
|
| public:
|
| typedef FixedArrayBase BackingStore;
|
| @@ -230,15 +235,16 @@ static void CopyDoubleToObjectElements(FixedArrayBase* from_base,
|
| Handle<FixedDoubleArray> from(FixedDoubleArray::cast(from_base), isolate);
|
| Handle<FixedArray> to(FixedArray::cast(to_base), isolate);
|
|
|
| - // create an outer loop to not waste too much time on creating HandleScopes
|
| - // on the other hand we might overflow a single handle scope depending on
|
| - // the copy_size
|
| + // Use an outer loop to not waste too much time on creating HandleScopes.
|
| + // On the other hand we might overflow a single handle scope depending on
|
| + // the copy_size.
|
| int offset = 0;
|
| while (offset < copy_size) {
|
| HandleScope scope(isolate);
|
| offset += 100;
|
| for (int i = offset - 100; i < offset && i < copy_size; ++i) {
|
| - Handle<Object> value = FixedDoubleArray::get(from, i + from_start);
|
| + Handle<Object> value =
|
| + FixedDoubleArray::get(*from, i + from_start, isolate);
|
| to->set(i + to_start, *value, UPDATE_WRITE_BARRIER);
|
| }
|
| }
|
| @@ -545,30 +551,22 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| *holder, *backing_store, index, filter) != kMaxUInt32;
|
| }
|
|
|
| - Handle<Object> Get(Handle<FixedArrayBase> backing_store,
|
| - uint32_t entry) final {
|
| - return ElementsAccessorSubclass::GetImpl(backing_store, entry);
|
| + Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) final {
|
| + return ElementsAccessorSubclass::GetImpl(holder, entry);
|
| }
|
|
|
| - static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store,
|
| - uint32_t entry) {
|
| - uint32_t index = GetIndexForEntryImpl(*backing_store, entry);
|
| - return BackingStore::get(Handle<BackingStore>::cast(backing_store), index);
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + return ElementsAccessorSubclass::GetImpl(holder->elements(), entry);
|
| }
|
|
|
| - void Set(FixedArrayBase* backing_store, uint32_t entry, Object* value) final {
|
| - ElementsAccessorSubclass::SetImpl(backing_store, entry, value);
|
| + static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
|
| + Isolate* isolate = backing_store->GetIsolate();
|
| + uint32_t index = GetIndexForEntryImpl(backing_store, entry);
|
| + return handle(BackingStore::cast(backing_store)->get(index), isolate);
|
| }
|
|
|
| - static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| - Object* value) {
|
| - UNREACHABLE();
|
| - }
|
| -
|
| -
|
| - static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| - Object* value, WriteBarrierMode mode) {
|
| - UNREACHABLE();
|
| + void Set(Handle<JSObject> holder, uint32_t entry, Object* value) final {
|
| + ElementsAccessorSubclass::SetImpl(holder, entry, value);
|
| }
|
|
|
| void Reconfigure(Handle<JSObject> object, Handle<FixedArrayBase> store,
|
| @@ -780,6 +778,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| DCHECK(IsFastDoubleElementsKind(from_kind) !=
|
| IsFastDoubleElementsKind(kind()) ||
|
| IsDictionaryElementsKind(from_kind) ||
|
| + from_kind == SLOW_STRING_WRAPPER_ELEMENTS ||
|
| static_cast<uint32_t>(old_elements->length()) < capacity);
|
| Handle<FixedArrayBase> elements =
|
| ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
| @@ -814,21 +813,6 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| UNREACHABLE();
|
| }
|
|
|
| - void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start,
|
| - ElementsKind from_kind, Handle<FixedArrayBase> to,
|
| - uint32_t to_start, int copy_size) final {
|
| - DCHECK(!from.is_null());
|
| - // NOTE: the ElementsAccessorSubclass::CopyElementsImpl() methods
|
| - // violate the handlified function signature convention:
|
| - // raw pointer parameters in the function that allocates. This is done
|
| - // intentionally to avoid ArrayConcat() builtin performance degradation.
|
| - // See the comment in another ElementsAccessorBase::CopyElements() for
|
| - // details.
|
| - ElementsAccessorSubclass::CopyElementsImpl(*from, from_start, *to,
|
| - from_kind, to_start,
|
| - kPackedSizeNotKnown, copy_size);
|
| - }
|
| -
|
| void CopyElements(JSObject* from_holder, uint32_t from_start,
|
| ElementsKind from_kind, Handle<FixedArrayBase> to,
|
| uint32_t to_start, int copy_size) final {
|
| @@ -861,6 +845,7 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| KeyAccumulator* keys, uint32_t range,
|
| PropertyFilter filter,
|
| uint32_t offset) {
|
| + DCHECK_NE(DICTIONARY_ELEMENTS, kind());
|
| if (filter & ONLY_ALL_CAN_READ) {
|
| // Non-dictionary elements can't have all-can-read accessors.
|
| return;
|
| @@ -875,8 +860,9 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| if (range < length) length = range;
|
| for (uint32_t i = offset; i < length; i++) {
|
| if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
|
| - filter))
|
| + filter)) {
|
| continue;
|
| + }
|
| keys->AddKey(i);
|
| }
|
| }
|
| @@ -892,19 +878,8 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
|
| KeyAccumulator* accumulator,
|
| AddKeyConversion convert) final {
|
| - Handle<FixedArrayBase> from(receiver->elements());
|
| - uint32_t add_length =
|
| - ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from);
|
| - if (add_length == 0) return;
|
| -
|
| - for (uint32_t i = 0; i < add_length; i++) {
|
| - if (!ElementsAccessorSubclass::HasEntryImpl(*from, i)) continue;
|
| - Handle<Object> value = ElementsAccessorSubclass::GetImpl(from, i);
|
| - DCHECK(!value->IsTheHole());
|
| - DCHECK(!value->IsAccessorPair());
|
| - DCHECK(!value->IsAccessorInfo());
|
| - accumulator->AddKey(value, convert);
|
| - }
|
| + ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl(
|
| + receiver, accumulator, convert);
|
| }
|
|
|
| static uint32_t GetCapacityImpl(JSObject* holder,
|
| @@ -916,10 +891,6 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store);
|
| }
|
|
|
| - static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) {
|
| - return true;
|
| - }
|
| -
|
| static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store,
|
| uint32_t entry) {
|
| return entry;
|
| @@ -956,9 +927,12 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
|
| }
|
|
|
| - PropertyDetails GetDetails(FixedArrayBase* backing_store,
|
| - uint32_t entry) final {
|
| - return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry);
|
| + static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
| + return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
|
| + }
|
| +
|
| + PropertyDetails GetDetails(JSObject* holder, uint32_t entry) final {
|
| + return ElementsAccessorSubclass::GetDetailsImpl(holder, entry);
|
| }
|
|
|
| private:
|
| @@ -1053,15 +1027,22 @@ class DictionaryElementsAccessor
|
| return backing_store->ValueAt(entry);
|
| }
|
|
|
| - static Handle<Object> GetImpl(Handle<FixedArrayBase> store, uint32_t entry) {
|
| - Isolate* isolate = store->GetIsolate();
|
| - return handle(GetRaw(*store, entry), isolate);
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + return GetImpl(holder->elements(), entry);
|
| }
|
|
|
| - static inline void SetImpl(FixedArrayBase* store, uint32_t entry,
|
| + static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
|
| + return handle(GetRaw(backing_store, entry), backing_store->GetIsolate());
|
| + }
|
| +
|
| + static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
|
| Object* value) {
|
| - SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store);
|
| - dictionary->ValueAtPut(entry, value);
|
| + SetImpl(holder->elements(), entry, value);
|
| + }
|
| +
|
| + static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| + Object* value) {
|
| + SeededNumberDictionary::cast(backing_store)->ValueAtPut(entry, value);
|
| }
|
|
|
| static void ReconfigureImpl(Handle<JSObject> object,
|
| @@ -1082,7 +1063,7 @@ class DictionaryElementsAccessor
|
| uint32_t new_capacity) {
|
| PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| Handle<SeededNumberDictionary> dictionary =
|
| - object->HasFastElements()
|
| + object->HasFastElements() || object->HasFastStringWrapperElements()
|
| ? JSObject::NormalizeElements(object)
|
| : handle(SeededNumberDictionary::cast(object->elements()));
|
| Handle<SeededNumberDictionary> new_dictionary =
|
| @@ -1123,6 +1104,10 @@ class DictionaryElementsAccessor
|
| return static_cast<uint32_t>(entry);
|
| }
|
|
|
| + static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
| + return GetDetailsImpl(holder->elements(), entry);
|
| + }
|
| +
|
| static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
|
| uint32_t entry) {
|
| return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry);
|
| @@ -1159,6 +1144,24 @@ class DictionaryElementsAccessor
|
|
|
| keys->SortCurrentElementsList();
|
| }
|
| +
|
| + static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| + KeyAccumulator* accumulator,
|
| + AddKeyConversion convert) {
|
| + SeededNumberDictionary* dictionary =
|
| + SeededNumberDictionary::cast(receiver->elements());
|
| + int capacity = dictionary->Capacity();
|
| + for (int i = 0; i < capacity; i++) {
|
| + Object* k = dictionary->KeyAt(i);
|
| + if (!dictionary->IsKey(k)) continue;
|
| + if (dictionary->IsDeleted(i)) continue;
|
| + Object* value = dictionary->ValueAt(i);
|
| + DCHECK(!value->IsTheHole());
|
| + DCHECK(!value->IsAccessorPair());
|
| + DCHECK(!value->IsAccessorInfo());
|
| + accumulator->AddKey(value, convert);
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -1197,9 +1200,9 @@ class FastElementsAccessor
|
|
|
| static void DeleteCommon(Handle<JSObject> obj, uint32_t entry,
|
| Handle<FixedArrayBase> store) {
|
| - DCHECK(obj->HasFastSmiOrObjectElements() ||
|
| - obj->HasFastDoubleElements() ||
|
| - obj->HasFastArgumentsElements());
|
| + DCHECK(obj->HasFastSmiOrObjectElements() || obj->HasFastDoubleElements() ||
|
| + obj->HasFastArgumentsElements() ||
|
| + obj->HasFastStringWrapperElements());
|
| Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store);
|
| if (!obj->IsJSArray() &&
|
| entry == static_cast<uint32_t>(store->length()) - 1) {
|
| @@ -1277,7 +1280,7 @@ class FastElementsAccessor
|
| FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object,
|
| new_capacity);
|
| } else {
|
| - if (from_kind != to_kind) {
|
| + if (IsFastElementsKind(from_kind) && from_kind != to_kind) {
|
| JSObject::TransitionElementsKind(object, to_kind);
|
| }
|
| if (IsFastSmiOrObjectElementsKind(from_kind)) {
|
| @@ -1285,7 +1288,7 @@ class FastElementsAccessor
|
| JSObject::EnsureWritableFastElements(object);
|
| }
|
| }
|
| - FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value);
|
| + FastElementsAccessorSubclass::SetImpl(object, index, *value);
|
| }
|
|
|
| static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) {
|
| @@ -1303,6 +1306,27 @@ class FastElementsAccessor
|
| return !BackingStore::cast(backing_store)->is_the_hole(entry);
|
| }
|
|
|
| + static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| + KeyAccumulator* accumulator,
|
| + AddKeyConversion convert) {
|
| + uint32_t length = 0;
|
| + Handle<FixedArrayBase> elements(receiver->elements(),
|
| + receiver->GetIsolate());
|
| + if (receiver->IsJSArray()) {
|
| + length = Smi::cast(JSArray::cast(*receiver)->length())->value();
|
| + } else {
|
| + length =
|
| + FastElementsAccessorSubclass::GetCapacityImpl(*receiver, *elements);
|
| + }
|
| + for (uint32_t i = 0; i < length; i++) {
|
| + if (IsFastPackedElementsKind(KindTraits::Kind) ||
|
| + HasEntryImpl(*elements, i)) {
|
| + accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i),
|
| + convert);
|
| + }
|
| + }
|
| + }
|
| +
|
| static void ValidateContents(Handle<JSObject> holder, int length) {
|
| #if DEBUG
|
| Isolate* isolate = holder->GetIsolate();
|
| @@ -1320,7 +1344,7 @@ class FastElementsAccessor
|
| Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements);
|
| if (IsFastSmiElementsKind(KindTraits::Kind)) {
|
| for (int i = 0; i < length; i++) {
|
| - DCHECK(BackingStore::get(backing_store, i)->IsSmi() ||
|
| + DCHECK(BackingStore::get(*backing_store, i, isolate)->IsSmi() ||
|
| (IsFastHoleyElementsKind(KindTraits::Kind) &&
|
| backing_store->is_the_hole(i)));
|
| }
|
| @@ -1480,7 +1504,7 @@ class FastElementsAccessor
|
| int new_length = length - 1;
|
| int remove_index = remove_position == AT_START ? 0 : new_length;
|
| Handle<Object> result =
|
| - FastElementsAccessorSubclass::GetImpl(backing_store, remove_index);
|
| + FastElementsAccessorSubclass::GetImpl(*backing_store, remove_index);
|
| if (remove_position == AT_START) {
|
| FastElementsAccessorSubclass::MoveElements(
|
| isolate, receiver, backing_store, 0, 1, new_length, 0, 0);
|
| @@ -1557,6 +1581,11 @@ class FastSmiOrObjectElementsAccessor
|
| : FastElementsAccessor<FastElementsAccessorSubclass,
|
| KindTraits>(name) {}
|
|
|
| + static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
|
| + Object* value) {
|
| + SetImpl(holder->elements(), entry, value);
|
| + }
|
| +
|
| static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| Object* value) {
|
| FixedArray::cast(backing_store)->set(entry, value);
|
| @@ -1613,6 +1642,7 @@ class FastSmiOrObjectElementsAccessor
|
| case FAST_HOLEY_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| case FAST_HOLEY_ELEMENTS:
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| CopyObjectToObjectElements(from, from_kind, from_start, to, to_kind,
|
| to_start, copy_size);
|
| break;
|
| @@ -1624,17 +1654,21 @@ class FastSmiOrObjectElementsAccessor
|
| break;
|
| }
|
| case DICTIONARY_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS:
|
| CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
|
| copy_size);
|
| break;
|
| case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| - UNREACHABLE();
|
| -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| - case TYPE##_ELEMENTS: \
|
| - UNREACHABLE();
|
| +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
|
| TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| #undef TYPED_ARRAY_CASE
|
| + // This function is currently only used for JSArrays with non-zero
|
| + // length.
|
| + UNREACHABLE();
|
| + break;
|
| + case NO_ELEMENTS:
|
| + break; // Nothing to do.
|
| }
|
| }
|
| };
|
| @@ -1697,6 +1731,21 @@ class FastDoubleElementsAccessor
|
| : FastElementsAccessor<FastElementsAccessorSubclass,
|
| KindTraits>(name) {}
|
|
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + return GetImpl(holder->elements(), entry);
|
| + }
|
| +
|
| + static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
|
| + Isolate* isolate = backing_store->GetIsolate();
|
| + return FixedDoubleArray::get(FixedDoubleArray::cast(backing_store), entry,
|
| + isolate);
|
| + }
|
| +
|
| + static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
|
| + Object* value) {
|
| + SetImpl(holder->elements(), entry, value);
|
| + }
|
| +
|
| static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| Object* value) {
|
| FixedDoubleArray::cast(backing_store)->set(entry, value->Number());
|
| @@ -1759,13 +1808,16 @@ class FastDoubleElementsAccessor
|
| break;
|
| case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| - UNREACHABLE();
|
| -
|
| -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| - case TYPE##_ELEMENTS: \
|
| - UNREACHABLE();
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS:
|
| + case NO_ELEMENTS:
|
| +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
|
| TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| #undef TYPED_ARRAY_CASE
|
| + // This function is currently only used for JSArrays with non-zero
|
| + // length.
|
| + UNREACHABLE();
|
| + break;
|
| }
|
| }
|
| };
|
| @@ -1808,6 +1860,11 @@ class TypedElementsAccessor
|
| typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore;
|
| typedef TypedElementsAccessor<Kind> AccessorClass;
|
|
|
| + static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
|
| + Object* value) {
|
| + SetImpl(holder->elements(), entry, value);
|
| + }
|
| +
|
| static inline void SetImpl(FixedArrayBase* backing_store, uint32_t entry,
|
| Object* value) {
|
| BackingStore::cast(backing_store)->SetValue(entry, value);
|
| @@ -1818,10 +1875,16 @@ class TypedElementsAccessor
|
| BackingStore::cast(backing_store)->SetValue(entry, value);
|
| }
|
|
|
| - static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store,
|
| - uint32_t entry) {
|
| - uint32_t index = GetIndexForEntryImpl(*backing_store, entry);
|
| - return BackingStore::get(Handle<BackingStore>::cast(backing_store), index);
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + return GetImpl(holder->elements(), entry);
|
| + }
|
| +
|
| + static Handle<Object> GetImpl(FixedArrayBase* backing_store, uint32_t entry) {
|
| + return BackingStore::get(BackingStore::cast(backing_store), entry);
|
| + }
|
| +
|
| + static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
| + return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell);
|
| }
|
|
|
| static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store,
|
| @@ -1829,6 +1892,12 @@ class TypedElementsAccessor
|
| return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell);
|
| }
|
|
|
| + static bool HasElementImpl(Handle<JSObject> holder, uint32_t index,
|
| + Handle<FixedArrayBase> backing_store,
|
| + PropertyFilter filter) {
|
| + return index < AccessorClass::GetCapacityImpl(*holder, *backing_store);
|
| + }
|
| +
|
| static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array,
|
| uint32_t length,
|
| Handle<FixedArrayBase> backing_store) {
|
| @@ -1859,6 +1928,18 @@ class TypedElementsAccessor
|
| if (view->WasNeutered()) return 0;
|
| return backing_store->length();
|
| }
|
| +
|
| + static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| + KeyAccumulator* accumulator,
|
| + AddKeyConversion convert) {
|
| + Handle<FixedArrayBase> elements(receiver->elements(),
|
| + receiver->GetIsolate());
|
| + uint32_t length = AccessorClass::GetCapacityImpl(*receiver, *elements);
|
| + for (uint32_t i = 0; i < length; i++) {
|
| + Handle<Object> value = AccessorClass::GetImpl(*elements, i);
|
| + accumulator->AddKey(value, convert);
|
| + }
|
| + }
|
| };
|
|
|
|
|
| @@ -1883,10 +1964,13 @@ class SloppyArgumentsElementsAccessor
|
| USE(KindTraits::Kind);
|
| }
|
|
|
| - static Handle<Object> GetImpl(Handle<FixedArrayBase> parameters,
|
| - uint32_t entry) {
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + return GetImpl(holder->elements(), entry);
|
| + }
|
| +
|
| + static Handle<Object> GetImpl(FixedArrayBase* parameters, uint32_t entry) {
|
| Isolate* isolate = parameters->GetIsolate();
|
| - Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(parameters), isolate);
|
| uint32_t length = parameter_map->length() - 2;
|
| if (entry < length) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -1897,10 +1981,8 @@ class SloppyArgumentsElementsAccessor
|
| return handle(context->get(context_entry), isolate);
|
| } else {
|
| // Object is not mapped, defer to the arguments.
|
| - Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
|
| - isolate);
|
| - Handle<Object> result =
|
| - ArgumentsAccessor::GetImpl(arguments, entry - length);
|
| + Handle<Object> result = ArgumentsAccessor::GetImpl(
|
| + FixedArray::cast(parameter_map->get(1)), entry - length);
|
| // Elements of the arguments object in slow mode might be slow aliases.
|
| if (result->IsAliasedArgumentsEntry()) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -1919,6 +2001,11 @@ class SloppyArgumentsElementsAccessor
|
| UNREACHABLE();
|
| }
|
|
|
| + static inline void SetImpl(Handle<JSObject> holder, uint32_t entry,
|
| + Object* value) {
|
| + SetImpl(holder->elements(), entry, value);
|
| + }
|
| +
|
| static inline void SetImpl(FixedArrayBase* store, uint32_t entry,
|
| Object* value) {
|
| FixedArray* parameter_map = FixedArray::cast(store);
|
| @@ -1959,6 +2046,18 @@ class SloppyArgumentsElementsAccessor
|
| ArgumentsAccessor::GetCapacityImpl(holder, arguments);
|
| }
|
|
|
| + static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| + KeyAccumulator* accumulator,
|
| + AddKeyConversion convert) {
|
| + FixedArrayBase* elements = receiver->elements();
|
| + uint32_t length = GetCapacityImpl(*receiver, elements);
|
| + for (uint32_t entry = 0; entry < length; entry++) {
|
| + if (!HasEntryImpl(elements, entry)) continue;
|
| + Handle<Object> value = GetImpl(elements, entry);
|
| + accumulator->AddKey(value, convert);
|
| + }
|
| + }
|
| +
|
| static bool HasEntryImpl(FixedArrayBase* parameters, uint32_t entry) {
|
| FixedArray* parameter_map = FixedArray::cast(parameters);
|
| uint32_t length = parameter_map->length() - 2;
|
| @@ -1994,9 +2093,8 @@ class SloppyArgumentsElementsAccessor
|
| return (parameter_map->length() - 2) + entry;
|
| }
|
|
|
| - static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters,
|
| - uint32_t entry) {
|
| - FixedArray* parameter_map = FixedArray::cast(parameters);
|
| + static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
| + FixedArray* parameter_map = FixedArray::cast(holder->elements());
|
| uint32_t length = parameter_map->length() - 2;
|
| if (entry < length) {
|
| return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell);
|
| @@ -2201,6 +2299,165 @@ class FastSloppyArgumentsElementsAccessor
|
| }
|
| };
|
|
|
| +template <typename StringWrapperElementsAccessorSubclass,
|
| + typename BackingStoreAccessor, typename KindTraits>
|
| +class StringWrapperElementsAccessor
|
| + : public ElementsAccessorBase<StringWrapperElementsAccessorSubclass,
|
| + KindTraits> {
|
| + public:
|
| + explicit StringWrapperElementsAccessor(const char* name)
|
| + : ElementsAccessorBase<StringWrapperElementsAccessorSubclass, KindTraits>(
|
| + name) {
|
| + USE(KindTraits::Kind);
|
| + }
|
| +
|
| + static Handle<Object> GetImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + Isolate* isolate = holder->GetIsolate();
|
| + Handle<String> string(GetString(*holder), isolate);
|
| + uint32_t length = static_cast<uint32_t>(string->length());
|
| + if (entry < length) {
|
| + return isolate->factory()->LookupSingleCharacterStringFromCode(
|
| + String::Flatten(string)->Get(entry));
|
| + }
|
| + return BackingStoreAccessor::GetImpl(holder, entry - length);
|
| + }
|
| +
|
| + static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) {
|
| + uint32_t length = static_cast<uint32_t>(GetString(holder)->length());
|
| + if (entry < length) {
|
| + PropertyAttributes attributes =
|
| + static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
|
| + return PropertyDetails(attributes, v8::internal::DATA, 0,
|
| + PropertyCellType::kNoCell);
|
| + }
|
| + return BackingStoreAccessor::GetDetailsImpl(holder, entry - length);
|
| + }
|
| +
|
| + static uint32_t GetEntryForIndexImpl(JSObject* holder,
|
| + FixedArrayBase* backing_store,
|
| + uint32_t index, PropertyFilter filter) {
|
| + uint32_t length = static_cast<uint32_t>(GetString(holder)->length());
|
| + if (index < length) return index;
|
| + uint32_t backing_store_entry = BackingStoreAccessor::GetEntryForIndexImpl(
|
| + holder, backing_store, index, filter);
|
| + if (backing_store_entry == kMaxUInt32) return kMaxUInt32;
|
| + DCHECK(backing_store_entry < kMaxUInt32 - length);
|
| + return backing_store_entry + length;
|
| + }
|
| +
|
| + static void DeleteImpl(Handle<JSObject> holder, uint32_t entry) {
|
| + uint32_t length = static_cast<uint32_t>(GetString(*holder)->length());
|
| + if (entry < length) {
|
| + return; // String contents can't be deleted.
|
| + }
|
| + BackingStoreAccessor::DeleteImpl(holder, entry - length);
|
| + }
|
| +
|
| + static void SetImpl(Handle<JSObject> holder, uint32_t entry, Object* value) {
|
| + uint32_t length = static_cast<uint32_t>(GetString(*holder)->length());
|
| + if (entry < length) {
|
| + return; // String contents are read-only.
|
| + }
|
| + BackingStoreAccessor::SetImpl(holder->elements(), entry - length, value);
|
| + }
|
| +
|
| + static void AddImpl(Handle<JSObject> object, uint32_t index,
|
| + Handle<Object> value, PropertyAttributes attributes,
|
| + uint32_t new_capacity) {
|
| + DCHECK(index >= static_cast<uint32_t>(GetString(*object)->length()));
|
| + if ((KindTraits::Kind == FAST_STRING_WRAPPER_ELEMENTS &&
|
| + object->GetElementsKind() == SLOW_STRING_WRAPPER_ELEMENTS) ||
|
| + BackingStoreAccessor::GetCapacityImpl(*object, object->elements()) !=
|
| + new_capacity) {
|
| + StringWrapperElementsAccessorSubclass::GrowCapacityAndConvertImpl(
|
| + object, new_capacity);
|
| + }
|
| + BackingStoreAccessor::AddImpl(object, index, value, attributes,
|
| + new_capacity);
|
| + }
|
| +
|
| + static void ReconfigureImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> store, uint32_t entry,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + uint32_t length = static_cast<uint32_t>(GetString(*object)->length());
|
| + if (entry < length) {
|
| + return; // String contents can't be reconfigured.
|
| + }
|
| + BackingStoreAccessor::ReconfigureImpl(object, store, entry - length, value,
|
| + attributes);
|
| + }
|
| +
|
| + static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
|
| + KeyAccumulator* accumulator,
|
| + AddKeyConversion convert) {
|
| + Isolate* isolate = receiver->GetIsolate();
|
| + Handle<String> string(GetString(*receiver), isolate);
|
| + string = String::Flatten(string);
|
| + uint32_t length = static_cast<uint32_t>(string->length());
|
| + for (uint32_t i = 0; i < length; i++) {
|
| + accumulator->AddKey(
|
| + isolate->factory()->LookupSingleCharacterStringFromCode(
|
| + string->Get(i)),
|
| + convert);
|
| + }
|
| + BackingStoreAccessor::AddElementsToKeyAccumulatorImpl(receiver, accumulator,
|
| + convert);
|
| + }
|
| +
|
| + static void CollectElementIndicesImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> backing_store,
|
| + KeyAccumulator* keys, uint32_t range,
|
| + PropertyFilter filter,
|
| + uint32_t offset) {
|
| + if ((filter & ONLY_ALL_CAN_READ) == 0) {
|
| + uint32_t length = GetString(*object)->length();
|
| + for (uint32_t i = 0; i < length; i++) {
|
| + keys->AddKey(i);
|
| + }
|
| + }
|
| + BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store, keys,
|
| + range, filter, offset);
|
| + }
|
| +
|
| + static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| + FixedArrayBase* to, ElementsKind from_kind,
|
| + uint32_t to_start, int packed_size,
|
| + int copy_size) {
|
| + BackingStoreAccessor::CopyElementsImpl(from, from_start, to, from_kind,
|
| + to_start, packed_size, copy_size);
|
| + }
|
| +
|
| + private:
|
| + static String* GetString(JSObject* holder) {
|
| + DCHECK(holder->IsJSValue());
|
| + JSValue* js_value = JSValue::cast(holder);
|
| + DCHECK(js_value->value()->IsString());
|
| + return String::cast(js_value->value());
|
| + }
|
| +};
|
| +
|
| +class FastStringWrapperElementsAccessor
|
| + : public StringWrapperElementsAccessor<
|
| + FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>> {
|
| + public:
|
| + explicit FastStringWrapperElementsAccessor(const char* name)
|
| + : StringWrapperElementsAccessor<
|
| + FastStringWrapperElementsAccessor, FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_STRING_WRAPPER_ELEMENTS>>(name) {}
|
| +};
|
| +
|
| +class SlowStringWrapperElementsAccessor
|
| + : public StringWrapperElementsAccessor<
|
| + SlowStringWrapperElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_STRING_WRAPPER_ELEMENTS>> {
|
| + public:
|
| + explicit SlowStringWrapperElementsAccessor(const char* name)
|
| + : StringWrapperElementsAccessor<
|
| + SlowStringWrapperElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_STRING_WRAPPER_ELEMENTS>>(name) {}
|
| +};
|
|
|
| } // namespace
|
|
|
|
|