Chromium Code Reviews| Index: src/elements.cc |
| diff --git a/src/elements.cc b/src/elements.cc |
| index 7ea6554b32237ae8e6c3a8cb34f9fd7ba375e91b..59187fa0e90079fae5590305665c5a8623dbd5af 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: |
| + friend class SloppyArgumentsElementsAccessor< |
| + FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| explicit ElementsAccessorBase(const char* name) |
| : ElementsAccessor(name) { } |
| @@ -934,7 +936,10 @@ class FastElementsAccessor |
| protected: |
| friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; |
| - friend class SloppyArgumentsElementsAccessor; |
| + friend class FastSloppyArgumentsElementsAccessor; |
| + friend class SloppyArgumentsElementsAccessor< |
| + FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| + ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; |
| typedef typename KindTraits::BackingStore BackingStore; |
| @@ -1066,33 +1071,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 +1110,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 +1207,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) \ |
| @@ -1417,13 +1388,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 +1432,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 +1530,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 +1559,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; |
| @@ -1602,18 +1576,7 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< |
| 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 +1589,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); |
| + ArgumentsAccessor::SetImpl(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); |
| - } |
| - } |
| - |
| - 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 +1603,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 +1613,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 +1629,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 +1639,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 +1649,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 +1664,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 +1676,186 @@ 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); |
| -} |
| + 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 { |
| + FastHoleyObjectElementsAccessor::DeleteCommon(obj, key, language_mode); |
|
Igor Sheludko
2015/07/02 13:28:42
You can put the implementation of this to the pare
Toon Verwaest
2015/07/02 13:49:01
Done.
|
| + } |
| + } |
| + |
| + 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); |
| + } |
| + } |
| + |
| + 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 { |
| + DictionaryElementsAccessor::DeleteCommon(obj, key, language_mode); |
| + } |
| + } |
| +}; |
| void ElementsAccessor::InitializeOncePerProcess() { |