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 |