| Index: src/elements.cc
|
| diff --git a/src/elements.cc b/src/elements.cc
|
| index 7ea6554b32237ae8e6c3a8cb34f9fd7ba375e91b..3c6e2726ce4f8803b2d23a8313aeb3ba57806dfe 100644
|
| --- a/src/elements.cc
|
| +++ b/src/elements.cc
|
| @@ -47,6 +47,8 @@
|
| // - FixedUint8ClampedElementsAccessor
|
| // - DictionaryElementsAccessor
|
| // - SloppyArgumentsElementsAccessor
|
| +// - FastSloppyArgumentsElementsAccessor
|
| +// - SlowSloppyArgumentsElementsAccessor
|
|
|
|
|
| namespace v8 {
|
| @@ -61,48 +63,45 @@ static const int kPackedSizeNotKnown = -1;
|
| // 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(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(SloppyArgumentsElementsAccessor, SLOPPY_ARGUMENTS_ELEMENTS, \
|
| - FixedArray) \
|
| - V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, \
|
| - ExternalInt8Array) \
|
| - V(ExternalUint8ElementsAccessor, \
|
| - EXTERNAL_UINT8_ELEMENTS, ExternalUint8Array) \
|
| - V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \
|
| - ExternalInt16Array) \
|
| - V(ExternalUint16ElementsAccessor, \
|
| - EXTERNAL_UINT16_ELEMENTS, ExternalUint16Array) \
|
| - V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \
|
| - ExternalInt32Array) \
|
| - V(ExternalUint32ElementsAccessor, \
|
| - EXTERNAL_UINT32_ELEMENTS, ExternalUint32Array) \
|
| - V(ExternalFloat32ElementsAccessor, \
|
| - EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array) \
|
| - V(ExternalFloat64ElementsAccessor, \
|
| - EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array) \
|
| - V(ExternalUint8ClampedElementsAccessor, \
|
| - EXTERNAL_UINT8_CLAMPED_ELEMENTS, \
|
| - ExternalUint8ClampedArray) \
|
| - V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
|
| - V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
|
| - V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
|
| - V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
|
| - V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
|
| - V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
|
| - V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
|
| - V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
|
| - V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
|
| +#define ELEMENTS_LIST(V) \
|
| + 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(FastSloppyArgumentsElementsAccessor, FAST_SLOPPY_ARGUMENTS_ELEMENTS, \
|
| + FixedArray) \
|
| + V(SlowSloppyArgumentsElementsAccessor, SLOW_SLOPPY_ARGUMENTS_ELEMENTS, \
|
| + FixedArray) \
|
| + V(ExternalInt8ElementsAccessor, EXTERNAL_INT8_ELEMENTS, ExternalInt8Array) \
|
| + V(ExternalUint8ElementsAccessor, EXTERNAL_UINT8_ELEMENTS, \
|
| + ExternalUint8Array) \
|
| + V(ExternalInt16ElementsAccessor, EXTERNAL_INT16_ELEMENTS, \
|
| + ExternalInt16Array) \
|
| + V(ExternalUint16ElementsAccessor, EXTERNAL_UINT16_ELEMENTS, \
|
| + ExternalUint16Array) \
|
| + V(ExternalInt32ElementsAccessor, EXTERNAL_INT32_ELEMENTS, \
|
| + ExternalInt32Array) \
|
| + V(ExternalUint32ElementsAccessor, EXTERNAL_UINT32_ELEMENTS, \
|
| + ExternalUint32Array) \
|
| + V(ExternalFloat32ElementsAccessor, EXTERNAL_FLOAT32_ELEMENTS, \
|
| + ExternalFloat32Array) \
|
| + V(ExternalFloat64ElementsAccessor, EXTERNAL_FLOAT64_ELEMENTS, \
|
| + ExternalFloat64Array) \
|
| + V(ExternalUint8ClampedElementsAccessor, EXTERNAL_UINT8_CLAMPED_ELEMENTS, \
|
| + ExternalUint8ClampedArray) \
|
| + V(FixedUint8ElementsAccessor, UINT8_ELEMENTS, FixedUint8Array) \
|
| + V(FixedInt8ElementsAccessor, INT8_ELEMENTS, FixedInt8Array) \
|
| + V(FixedUint16ElementsAccessor, UINT16_ELEMENTS, FixedUint16Array) \
|
| + V(FixedInt16ElementsAccessor, INT16_ELEMENTS, FixedInt16Array) \
|
| + V(FixedUint32ElementsAccessor, UINT32_ELEMENTS, FixedUint32Array) \
|
| + V(FixedInt32ElementsAccessor, INT32_ELEMENTS, FixedInt32Array) \
|
| + V(FixedFloat32ElementsAccessor, FLOAT32_ELEMENTS, FixedFloat32Array) \
|
| + V(FixedFloat64ElementsAccessor, FLOAT64_ELEMENTS, FixedFloat64Array) \
|
| + V(FixedUint8ClampedElementsAccessor, UINT8_CLAMPED_ELEMENTS, \
|
| FixedUint8ClampedArray)
|
|
|
|
|
| @@ -550,6 +549,9 @@ template <typename ElementsAccessorSubclass,
|
| typename ElementsTraitsParam>
|
| class ElementsAccessorBase : public ElementsAccessor {
|
| protected:
|
| + template <typename SloppyArgumentsElementsAccessorSubclass,
|
| + typename ArgumentsAccessor, typename KindTraits>
|
| + friend class SloppyArgumentsElementsAccessor;
|
| explicit ElementsAccessorBase(const char* name)
|
| : ElementsAccessor(name) { }
|
|
|
| @@ -922,6 +924,12 @@ class ElementsAccessorBase : public ElementsAccessor {
|
| };
|
|
|
|
|
| +class FastSloppyArgumentsElementsAccessor;
|
| +class FastHoleyObjectElementsAccessor;
|
| +template <typename SloppyArgumentsElementsAccessorSubclass,
|
| + typename ArgumentsAccessor, typename KindTraits>
|
| +class SloppyArgumentsElementsAccessor;
|
| +
|
| // Super class for all fast element arrays.
|
| template<typename FastElementsAccessorSubclass,
|
| typename KindTraits>
|
| @@ -934,7 +942,9 @@ class FastElementsAccessor
|
|
|
| protected:
|
| friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>;
|
| - friend class SloppyArgumentsElementsAccessor;
|
| + friend class SloppyArgumentsElementsAccessor<
|
| + FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
|
|
| typedef typename KindTraits::BackingStore BackingStore;
|
|
|
| @@ -1066,33 +1076,6 @@ class FastElementsAccessor
|
| };
|
|
|
|
|
| -static inline ElementsKind ElementsKindForArray(FixedArrayBase* array) {
|
| - switch (array->map()->instance_type()) {
|
| - case FIXED_ARRAY_TYPE:
|
| - if (array->IsDictionary()) {
|
| - return DICTIONARY_ELEMENTS;
|
| - } else {
|
| - return FAST_HOLEY_ELEMENTS;
|
| - }
|
| - case FIXED_DOUBLE_ARRAY_TYPE:
|
| - return FAST_HOLEY_DOUBLE_ELEMENTS;
|
| -
|
| -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| - case EXTERNAL_##TYPE##_ARRAY_TYPE: \
|
| - return EXTERNAL_##TYPE##_ELEMENTS; \
|
| - case FIXED_##TYPE##_ARRAY_TYPE: \
|
| - return TYPE##_ELEMENTS;
|
| -
|
| - TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| -#undef TYPED_ARRAY_CASE
|
| -
|
| - default:
|
| - UNREACHABLE();
|
| - }
|
| - return FAST_HOLEY_ELEMENTS;
|
| -}
|
| -
|
| -
|
| template<typename FastElementsAccessorSubclass,
|
| typename KindTraits>
|
| class FastSmiOrObjectElementsAccessor
|
| @@ -1132,17 +1115,9 @@ class FastSmiOrObjectElementsAccessor
|
| CopyDictionaryToObjectElements(from, from_start, to, to_kind, to_start,
|
| copy_size);
|
| break;
|
| - case SLOPPY_ARGUMENTS_ELEMENTS: {
|
| - // TODO(verwaest): This is a temporary hack to support extending
|
| - // SLOPPY_ARGUMENTS_ELEMENTS in GrowCapacityAndConvert.
|
| - // This case should be UNREACHABLE().
|
| - FixedArray* parameter_map = FixedArray::cast(from);
|
| - FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
| - ElementsKind from_kind = ElementsKindForArray(arguments);
|
| - CopyElementsImpl(arguments, from_start, to, from_kind,
|
| - to_start, packed_size, copy_size);
|
| - break;
|
| - }
|
| + case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
| + case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| + UNREACHABLE();
|
| #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| case EXTERNAL_##TYPE##_ELEMENTS: \
|
| case TYPE##_ELEMENTS: \
|
| @@ -1237,7 +1212,8 @@ class FastDoubleElementsAccessor
|
| CopyDictionaryToDoubleElements(from, from_start, to, to_start,
|
| copy_size);
|
| break;
|
| - case SLOPPY_ARGUMENTS_ELEMENTS:
|
| + case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
|
| + case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| UNREACHABLE();
|
|
|
| #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| @@ -1355,6 +1331,8 @@ TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR)
|
| #undef FIXED_ELEMENTS_ACCESSOR
|
|
|
|
|
| +class SlowSloppyArgumentsElementsAccessor;
|
| +
|
|
|
| class DictionaryElementsAccessor
|
| : public ElementsAccessorBase<DictionaryElementsAccessor,
|
| @@ -1417,13 +1395,28 @@ class DictionaryElementsAccessor
|
| array->set_length(*length_obj);
|
| }
|
|
|
| + static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| + FixedArrayBase* to, ElementsKind from_kind,
|
| + uint32_t to_start, int packed_size,
|
| + int copy_size) {
|
| + UNREACHABLE();
|
| + }
|
| +
|
| +
|
| + protected:
|
| + friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
| + ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
| + friend class SlowSloppyArgumentsElementsAccessor;
|
| + friend class SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| +
|
| static void DeleteCommon(Handle<JSObject> obj, uint32_t key,
|
| LanguageMode language_mode) {
|
| Isolate* isolate = obj->GetIsolate();
|
| Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()),
|
| isolate);
|
| - bool is_arguments =
|
| - (obj->GetElementsKind() == SLOPPY_ARGUMENTS_ELEMENTS);
|
| + bool is_arguments = obj->HasSloppyArgumentsElements();
|
| if (is_arguments) {
|
| backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate);
|
| }
|
| @@ -1446,18 +1439,6 @@ class DictionaryElementsAccessor
|
| }
|
| }
|
|
|
| - static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| - FixedArrayBase* to, ElementsKind from_kind,
|
| - uint32_t to_start, int packed_size,
|
| - int copy_size) {
|
| - UNREACHABLE();
|
| - }
|
| -
|
| -
|
| - protected:
|
| - friend class ElementsAccessorBase<DictionaryElementsAccessor,
|
| - ElementsKindTraits<DICTIONARY_ELEMENTS> >;
|
| -
|
| virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| LanguageMode language_mode) final {
|
| DeleteCommon(obj, key, language_mode);
|
| @@ -1556,18 +1537,19 @@ class DictionaryElementsAccessor
|
| };
|
|
|
|
|
| -class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| - SloppyArgumentsElementsAccessor,
|
| - ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| +template <typename SloppyArgumentsElementsAccessorSubclass,
|
| + typename ArgumentsAccessor, typename KindTraits>
|
| +class SloppyArgumentsElementsAccessor
|
| + : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| + KindTraits> {
|
| public:
|
| explicit SloppyArgumentsElementsAccessor(const char* name)
|
| - : ElementsAccessorBase<
|
| - SloppyArgumentsElementsAccessor,
|
| - ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
| + : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| + KindTraits>(name) {}
|
| +
|
| protected:
|
| - friend class ElementsAccessorBase<
|
| - SloppyArgumentsElementsAccessor,
|
| - ElementsKindTraits<SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| + friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass,
|
| + KindTraits>;
|
|
|
| static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key,
|
| Handle<FixedArrayBase> parameters) {
|
| @@ -1584,8 +1566,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| // Object is not mapped, defer to the arguments.
|
| Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)),
|
| isolate);
|
| - Handle<Object> result =
|
| - ElementsAccessor::ForArray(arguments)->Get(obj, key, arguments);
|
| + Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments);
|
| // Elements of the arguments object in slow mode might be slow aliases.
|
| if (result->IsAliasedArgumentsEntry()) {
|
| DisallowHeapAllocation no_gc;
|
| @@ -1600,20 +1581,22 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| }
|
| }
|
|
|
| + virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| + LanguageMode language_mode) final {
|
| + FixedArray* parameter_map = FixedArray::cast(obj->elements());
|
| + if (!GetParameterMapArg(parameter_map, key)->IsTheHole()) {
|
| + // TODO(kmillikin): We could check if this was the last aliased
|
| + // parameter, and revert to normal elements in that case. That
|
| + // would enable GC of the context.
|
| + parameter_map->set_the_hole(key + 2);
|
| + } else {
|
| + ArgumentsAccessor::DeleteCommon(obj, key, language_mode);
|
| + }
|
| + }
|
| +
|
| static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
| uint32_t capacity) {
|
| - Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| - Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1)));
|
| - ElementsKind from_kind = old_elements->IsDictionary() ? DICTIONARY_ELEMENTS
|
| - : FAST_HOLEY_ELEMENTS;
|
| - // This method should only be called if there's a reason to update the
|
| - // elements.
|
| - DCHECK(IsDictionaryElementsKind(from_kind) ||
|
| - static_cast<uint32_t>(old_elements->length()) < capacity);
|
| - Handle<FixedArrayBase> elements =
|
| - ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
| - parameter_map->set(1, *elements);
|
| - JSObject::ValidateElements(object);
|
| + UNREACHABLE();
|
| }
|
|
|
| static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) {
|
| @@ -1626,62 +1609,10 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| context->set(context_index, value);
|
| } else {
|
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| - ElementsAccessor::ForArray(arguments)->Set(arguments, key, value);
|
| - }
|
| - }
|
| -
|
| - static void ReconfigureImpl(Handle<JSObject> object,
|
| - Handle<FixedArrayBase> store, uint32_t index,
|
| - Handle<Object> value,
|
| - PropertyAttributes attributes) {
|
| - Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
|
| - uint32_t length = parameter_map->length() - 2;
|
| - if (index < length) {
|
| - Object* probe = parameter_map->get(index + 2);
|
| - DCHECK(!probe->IsTheHole());
|
| - Context* context = Context::cast(parameter_map->get(0));
|
| - int context_index = Smi::cast(probe)->value();
|
| - DCHECK(!context->get(context_index)->IsTheHole());
|
| - context->set(context_index, *value);
|
| -
|
| - // Redefining attributes of an aliased element destroys fast aliasing.
|
| - parameter_map->set_the_hole(index + 2);
|
| - // For elements that are still writable we re-establish slow aliasing.
|
| - if ((attributes & READ_ONLY) == 0) {
|
| - Isolate* isolate = store->GetIsolate();
|
| - value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
|
| - }
|
| -
|
| - PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| - Handle<SeededNumberDictionary> arguments =
|
| - parameter_map->get(1)->IsSeededNumberDictionary()
|
| - ? handle(SeededNumberDictionary::cast(parameter_map->get(1)))
|
| - : JSObject::NormalizeElements(object);
|
| - arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
| - value, details);
|
| - parameter_map->set(1, *arguments);
|
| - } else {
|
| - Handle<FixedArrayBase> arguments(
|
| - FixedArrayBase::cast(parameter_map->get(1)));
|
| - ElementsAccessor::ForArray(arguments)
|
| - ->Reconfigure(object, arguments, index - length, value, attributes);
|
| + ArgumentsAccessor::SetImpl(arguments, key, value);
|
| }
|
| }
|
|
|
| - static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| - Handle<Object> value, PropertyAttributes attributes,
|
| - uint32_t new_capacity) {
|
| - DCHECK_EQ(NONE, attributes);
|
| - Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| - Handle<FixedArrayBase> old_elements(
|
| - FixedArrayBase::cast(parameter_map->get(1)));
|
| - if (old_elements->IsSeededNumberDictionary() ||
|
| - static_cast<uint32_t>(old_elements->length()) < new_capacity) {
|
| - GrowCapacityAndConvertImpl(object, new_capacity);
|
| - }
|
| - SetImpl(object->elements(), key, *value);
|
| - }
|
| -
|
| static MaybeHandle<AccessorPair> GetAccessorPairImpl(
|
| Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> parameters) {
|
| Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters);
|
| @@ -1692,8 +1623,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| } else {
|
| // If not aliased, check the arguments.
|
| Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
| - return ElementsAccessor::ForArray(arguments)
|
| - ->GetAccessorPair(obj, key, arguments);
|
| + return ArgumentsAccessor::GetAccessorPairImpl(obj, key, arguments);
|
| }
|
| }
|
|
|
| @@ -1703,50 +1633,12 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| UNREACHABLE();
|
| }
|
|
|
| - virtual void Delete(Handle<JSObject> obj, uint32_t key,
|
| - LanguageMode language_mode) final {
|
| - Isolate* isolate = obj->GetIsolate();
|
| - Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements()));
|
| - Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate);
|
| - if (!probe->IsTheHole()) {
|
| - // TODO(kmillikin): We could check if this was the last aliased
|
| - // parameter, and revert to normal elements in that case. That
|
| - // would enable GC of the context.
|
| - parameter_map->set_the_hole(key + 2);
|
| - } else {
|
| - Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)));
|
| - if (arguments->IsDictionary()) {
|
| - DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode);
|
| - } else {
|
| - // 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.
|
| - FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode);
|
| - }
|
| - }
|
| - }
|
| -
|
| - static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| - FixedArrayBase* to, ElementsKind from_kind,
|
| - uint32_t to_start, int packed_size,
|
| - int copy_size) {
|
| - DCHECK(!to->IsDictionary());
|
| - if (from_kind == DICTIONARY_ELEMENTS) {
|
| - CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
|
| - to_start, copy_size);
|
| - } else {
|
| - DCHECK_EQ(FAST_HOLEY_ELEMENTS, from_kind);
|
| - CopyObjectToObjectElements(from, from_kind, from_start, to,
|
| - FAST_HOLEY_ELEMENTS, to_start, copy_size);
|
| - }
|
| - }
|
| -
|
| static uint32_t GetCapacityImpl(JSObject* holder,
|
| FixedArrayBase* backing_store) {
|
| FixedArray* parameter_map = FixedArray::cast(backing_store);
|
| FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
| return parameter_map->length() - 2 +
|
| - ForArray(arguments)->GetCapacity(holder, arguments);
|
| + ArgumentsAccessor::GetCapacityImpl(holder, arguments);
|
| }
|
|
|
| static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) {
|
| @@ -1757,7 +1649,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| }
|
|
|
| FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1));
|
| - return ForArray(arguments)->HasIndex(arguments, index - length);
|
| + return ArgumentsAccessor::HasIndexImpl(arguments, index - length);
|
| }
|
|
|
| static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters,
|
| @@ -1767,7 +1659,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| if (index < length) return index;
|
|
|
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| - return ForArray(arguments)->GetKeyForIndex(arguments, index - length);
|
| + return ArgumentsAccessor::GetKeyForIndexImpl(arguments, index - length);
|
| }
|
|
|
| static uint32_t GetIndexForKeyImpl(JSObject* holder,
|
| @@ -1777,8 +1669,8 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| if (!probe->IsTheHole()) return key;
|
|
|
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| - uint32_t index = ElementsAccessor::ForArray(arguments)
|
| - ->GetIndexForKey(holder, arguments, key);
|
| + uint32_t index =
|
| + ArgumentsAccessor::GetIndexForKeyImpl(holder, arguments, key);
|
| if (index == kMaxUInt32) return index;
|
| return (parameter_map->length() - 2) + index;
|
| }
|
| @@ -1792,10 +1684,9 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| }
|
| index -= length;
|
| FixedArray* arguments = FixedArray::cast(parameter_map->get(1));
|
| - return ElementsAccessor::ForArray(arguments)->GetDetails(arguments, index);
|
| + return ArgumentsAccessor::GetDetailsImpl(arguments, index);
|
| }
|
|
|
| - private:
|
| static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) {
|
| uint32_t length = parameter_map->length() - 2;
|
| return key < length
|
| @@ -1805,14 +1696,160 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase<
|
| };
|
|
|
|
|
| -ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) {
|
| - return elements_accessors_[ElementsKindForArray(array)];
|
| -}
|
| +class FastSloppyArgumentsElementsAccessor
|
| + : public SloppyArgumentsElementsAccessor<
|
| + FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| + public:
|
| + friend class SloppyArgumentsElementsAccessor<
|
| + FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| + friend class ElementsAccessorBase<
|
| + FastSloppyArgumentsElementsAccessor,
|
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| + explicit FastSloppyArgumentsElementsAccessor(const char* name)
|
| + : SloppyArgumentsElementsAccessor<
|
| + FastSloppyArgumentsElementsAccessor,
|
| + FastHoleyObjectElementsAccessor,
|
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
| +
|
| + protected:
|
| + static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| + Handle<Object> value, PropertyAttributes attributes,
|
| + uint32_t new_capacity) {
|
| + DCHECK_EQ(NONE, attributes);
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| + Handle<FixedArrayBase> old_elements(
|
| + FixedArrayBase::cast(parameter_map->get(1)));
|
| + if (old_elements->IsSeededNumberDictionary() ||
|
| + static_cast<uint32_t>(old_elements->length()) < new_capacity) {
|
| + GrowCapacityAndConvertImpl(object, new_capacity);
|
| + }
|
| + SetImpl(object->elements(), key, *value);
|
| + }
|
|
|
| + static void ReconfigureImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> store, uint32_t index,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Handle<SeededNumberDictionary> dictionary =
|
| + JSObject::NormalizeElements(object);
|
| + FixedArray::cast(*store)->set(1, *dictionary);
|
| + uint32_t length = static_cast<uint32_t>(store->length()) - 2;
|
| + if (index >= length) {
|
| + index = dictionary->FindEntry(index - length) + length;
|
| + }
|
| + object->GetElementsAccessor()->Reconfigure(object, store, index, value,
|
| + attributes);
|
| + }
|
|
|
| -ElementsAccessor* ElementsAccessor::ForArray(Handle<FixedArrayBase> array) {
|
| - return ForArray(*array);
|
| -}
|
| + static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start,
|
| + FixedArrayBase* to, ElementsKind from_kind,
|
| + uint32_t to_start, int packed_size,
|
| + int copy_size) {
|
| + DCHECK(!to->IsDictionary());
|
| + if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) {
|
| + CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS,
|
| + to_start, copy_size);
|
| + } else {
|
| + DCHECK_EQ(FAST_SLOPPY_ARGUMENTS_ELEMENTS, from_kind);
|
| + CopyObjectToObjectElements(from, FAST_HOLEY_ELEMENTS, from_start, to,
|
| + FAST_HOLEY_ELEMENTS, to_start, copy_size);
|
| + }
|
| + }
|
| +
|
| + static void GrowCapacityAndConvertImpl(Handle<JSObject> object,
|
| + uint32_t capacity) {
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| + Handle<FixedArray> old_elements(FixedArray::cast(parameter_map->get(1)));
|
| + ElementsKind from_kind = object->GetElementsKind();
|
| + // This method should only be called if there's a reason to update the
|
| + // elements.
|
| + DCHECK(from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS ||
|
| + static_cast<uint32_t>(old_elements->length()) < capacity);
|
| + Handle<FixedArrayBase> elements =
|
| + ConvertElementsWithCapacity(object, old_elements, from_kind, capacity);
|
| + Handle<Map> new_map = JSObject::GetElementsTransitionMap(
|
| + object, FAST_SLOPPY_ARGUMENTS_ELEMENTS);
|
| + JSObject::MigrateToMap(object, new_map);
|
| + parameter_map->set(1, *elements);
|
| + JSObject::ValidateElements(object);
|
| + }
|
| +};
|
| +
|
| +
|
| +class SlowSloppyArgumentsElementsAccessor
|
| + : public SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > {
|
| + public:
|
| + friend class ElementsAccessorBase<
|
| + SlowSloppyArgumentsElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| + friend class SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >;
|
| + explicit SlowSloppyArgumentsElementsAccessor(const char* name)
|
| + : SloppyArgumentsElementsAccessor<
|
| + SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor,
|
| + ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {}
|
| +
|
| + protected:
|
| + static void AddImpl(Handle<JSObject> object, uint32_t key,
|
| + Handle<Object> value, PropertyAttributes attributes,
|
| + uint32_t new_capacity) {
|
| + Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()));
|
| + Handle<FixedArrayBase> old_elements(
|
| + FixedArrayBase::cast(parameter_map->get(1)));
|
| + Handle<SeededNumberDictionary> dictionary =
|
| + old_elements->IsSeededNumberDictionary()
|
| + ? Handle<SeededNumberDictionary>::cast(old_elements)
|
| + : JSObject::NormalizeElements(object);
|
| + PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| + Handle<SeededNumberDictionary> new_dictionary =
|
| + SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details);
|
| + if (attributes != NONE) new_dictionary->set_requires_slow_elements();
|
| + if (*dictionary != *new_dictionary) {
|
| + FixedArray::cast(object->elements())->set(1, *new_dictionary);
|
| + }
|
| + }
|
| +
|
| + static void ReconfigureImpl(Handle<JSObject> object,
|
| + Handle<FixedArrayBase> store, uint32_t index,
|
| + Handle<Object> value,
|
| + PropertyAttributes attributes) {
|
| + Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store);
|
| + uint32_t length = parameter_map->length() - 2;
|
| + if (index < length) {
|
| + Object* probe = parameter_map->get(index + 2);
|
| + DCHECK(!probe->IsTheHole());
|
| + Context* context = Context::cast(parameter_map->get(0));
|
| + int context_index = Smi::cast(probe)->value();
|
| + DCHECK(!context->get(context_index)->IsTheHole());
|
| + context->set(context_index, *value);
|
| +
|
| + // Redefining attributes of an aliased element destroys fast aliasing.
|
| + parameter_map->set_the_hole(index + 2);
|
| + // For elements that are still writable we re-establish slow aliasing.
|
| + if ((attributes & READ_ONLY) == 0) {
|
| + Isolate* isolate = store->GetIsolate();
|
| + value = isolate->factory()->NewAliasedArgumentsEntry(context_index);
|
| + }
|
| +
|
| + PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
| + Handle<SeededNumberDictionary> arguments(
|
| + SeededNumberDictionary::cast(parameter_map->get(1)));
|
| + arguments = SeededNumberDictionary::AddNumberEntry(arguments, index,
|
| + value, details);
|
| + parameter_map->set(1, *arguments);
|
| + } else {
|
| + Handle<FixedArrayBase> arguments(
|
| + FixedArrayBase::cast(parameter_map->get(1)));
|
| + DictionaryElementsAccessor::ReconfigureImpl(
|
| + object, arguments, index - length, value, attributes);
|
| + }
|
| + }
|
| +};
|
|
|
|
|
| void ElementsAccessor::InitializeOncePerProcess() {
|
|
|