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() { |