| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 7057e7b70350d3bf549d870dbdf37118988c533e..0d01929b6998f6bb254f40480978cfab0577c131 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -1059,7 +1059,8 @@ MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor,
|
|
|
| Handle<FixedArray> JSObject::EnsureWritableFastElements(
|
| Handle<JSObject> object) {
|
| - DCHECK(object->HasFastSmiOrObjectElements());
|
| + DCHECK(object->HasFastSmiOrObjectElements() ||
|
| + object->HasFastStringWrapperElements());
|
| Isolate* isolate = object->GetIsolate();
|
| Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate);
|
| if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems;
|
| @@ -5873,14 +5874,18 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
|
|
| DCHECK(object->HasFastSmiOrObjectElements() ||
|
| object->HasFastDoubleElements() ||
|
| - object->HasFastArgumentsElements());
|
| + object->HasFastArgumentsElements() ||
|
| + object->HasFastStringWrapperElements());
|
|
|
| Handle<SeededNumberDictionary> dictionary =
|
| GetNormalizedElementDictionary(object, elements);
|
|
|
| // Switch to using the dictionary as the backing storage for elements.
|
| - ElementsKind target_kind =
|
| - is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS;
|
| + ElementsKind target_kind = is_arguments
|
| + ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS
|
| + : object->HasFastStringWrapperElements()
|
| + ? SLOW_STRING_WRAPPER_ELEMENTS
|
| + : DICTIONARY_ELEMENTS;
|
| Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind);
|
| // Set the new map first to satify the elements type assert in set_elements().
|
| JSObject::MigrateToMap(object, new_map);
|
| @@ -5901,7 +5906,9 @@ Handle<SeededNumberDictionary> JSObject::NormalizeElements(
|
| }
|
| #endif
|
|
|
| - DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements());
|
| + DCHECK(object->HasDictionaryElements() ||
|
| + object->HasSlowArgumentsElements() ||
|
| + object->HasSlowStringWrapperElements());
|
| return dictionary;
|
| }
|
|
|
| @@ -7404,9 +7411,7 @@ Maybe<bool> JSProxy::GetOwnPropertyDescriptor(Isolate* isolate,
|
| bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
|
| ElementsKind kind,
|
| Object* object) {
|
| - DCHECK(IsFastObjectElementsKind(kind) ||
|
| - kind == DICTIONARY_ELEMENTS);
|
| - if (IsFastObjectElementsKind(kind)) {
|
| + if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) {
|
| int length = IsJSArray()
|
| ? Smi::cast(JSArray::cast(this)->length())->value()
|
| : elements->length();
|
| @@ -7415,6 +7420,7 @@ bool JSObject::ReferencesObjectFromElements(FixedArray* elements,
|
| if (!element->IsTheHole() && element == object) return true;
|
| }
|
| } else {
|
| + DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS);
|
| Object* key =
|
| SeededNumberDictionary::cast(elements)->SlowReverseLookup(object);
|
| if (!key->IsUndefined()) return true;
|
| @@ -7465,7 +7471,9 @@ bool JSObject::ReferencesObject(Object* obj) {
|
| break;
|
| case FAST_ELEMENTS:
|
| case FAST_HOLEY_ELEMENTS:
|
| - case DICTIONARY_ELEMENTS: {
|
| + case DICTIONARY_ELEMENTS:
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS: {
|
| FixedArray* elements = FixedArray::cast(this->elements());
|
| if (ReferencesObjectFromElements(elements, kind, obj)) return true;
|
| break;
|
| @@ -7486,6 +7494,8 @@ bool JSObject::ReferencesObject(Object* obj) {
|
| if (ReferencesObjectFromElements(arguments, kind, obj)) return true;
|
| break;
|
| }
|
| + case NO_ELEMENTS:
|
| + break;
|
| }
|
|
|
| // For functions check the context.
|
| @@ -8131,12 +8141,8 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| }
|
|
|
| // Deep copy own elements.
|
| - // Pixel elements cannot be created using an object literal.
|
| - DCHECK(!copy->HasFixedTypedArrayElements());
|
| switch (kind) {
|
| - case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| - case FAST_HOLEY_SMI_ELEMENTS:
|
| case FAST_HOLEY_ELEMENTS: {
|
| Handle<FixedArray> elements(FixedArray::cast(copy->elements()));
|
| if (elements->map() == isolate->heap()->fixed_cow_array_map()) {
|
| @@ -8148,9 +8154,6 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| } else {
|
| for (int i = 0; i < elements->length(); i++) {
|
| Handle<Object> value(elements->get(i), isolate);
|
| - DCHECK(value->IsSmi() ||
|
| - value->IsTheHole() ||
|
| - (IsFastObjectElementsKind(copy->GetElementsKind())));
|
| if (value->IsJSObject()) {
|
| Handle<JSObject> result;
|
| ASSIGN_RETURN_ON_EXCEPTION(
|
| @@ -8191,16 +8194,25 @@ MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk(
|
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| UNIMPLEMENTED();
|
| break;
|
| -
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS:
|
| + UNREACHABLE();
|
| + break;
|
|
|
| #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| case TYPE##_ELEMENTS: \
|
|
|
| TYPED_ARRAYS(TYPED_ARRAY_CASE)
|
| #undef TYPED_ARRAY_CASE
|
| + // Typed elements cannot be created using an object literal.
|
| + UNREACHABLE();
|
| + break;
|
|
|
| + case FAST_SMI_ELEMENTS:
|
| + case FAST_HOLEY_SMI_ELEMENTS:
|
| case FAST_DOUBLE_ELEMENTS:
|
| case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| + case NO_ELEMENTS:
|
| // No contained objects, nothing to do.
|
| break;
|
| }
|
| @@ -8306,12 +8318,6 @@ MaybeHandle<Object> JSReceiver::OrdinaryToPrimitive(
|
|
|
| // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
|
| bool HasEnumerableElements(JSObject* object) {
|
| - if (object->IsJSValue()) {
|
| - Object* value = JSValue::cast(object)->value();
|
| - if (value->IsString()) {
|
| - if (String::cast(value)->length() > 0) return true;
|
| - }
|
| - }
|
| switch (object->GetElementsKind()) {
|
| case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| @@ -8363,6 +8369,14 @@ bool HasEnumerableElements(JSObject* object) {
|
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| // We're approximating non-empty arguments objects here.
|
| return true;
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS:
|
| + if (String::cast(JSValue::cast(object)->value())->length() > 0) {
|
| + return true;
|
| + }
|
| + return object->elements()->length() > 0;
|
| + case NO_ELEMENTS:
|
| + return false;
|
| }
|
| UNREACHABLE();
|
| return true;
|
| @@ -8595,8 +8609,8 @@ static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate,
|
| accumulator->AddElementKeysFromInterceptor(
|
| Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)));
|
| } else {
|
| - accumulator->AddKeys(
|
| - Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)));
|
| + accumulator->AddKeys(Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)),
|
| + DO_NOT_CONVERT);
|
| }
|
| return Just(true);
|
| }
|
| @@ -8652,7 +8666,7 @@ static Maybe<bool> GetKeysFromJSObject(Isolate* isolate,
|
| // Compute the property keys and cache them if possible.
|
| Handle<FixedArray> enum_keys =
|
| JSObject::GetEnumPropertyKeys(object, cache_enum_length);
|
| - accumulator->AddKeys(enum_keys);
|
| + accumulator->AddKeys(enum_keys, DO_NOT_CONVERT);
|
| } else {
|
| object->CollectOwnPropertyNames(accumulator, *filter);
|
| }
|
| @@ -15772,6 +15786,9 @@ static ElementsKind BestFittingFastElementsKind(JSObject* object) {
|
| if (object->HasSloppyArgumentsElements()) {
|
| return FAST_SLOPPY_ARGUMENTS_ELEMENTS;
|
| }
|
| + if (object->HasStringWrapperElements()) {
|
| + return FAST_STRING_WRAPPER_ELEMENTS;
|
| + }
|
| DCHECK(object->HasDictionaryElements());
|
| SeededNumberDictionary* dictionary = object->element_dictionary();
|
| ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS;
|
| @@ -15855,6 +15872,8 @@ Maybe<bool> JSObject::AddDataElement(Handle<JSObject> object, uint32_t index,
|
| if (IsSloppyArgumentsElements(kind)) {
|
| elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1));
|
| dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS;
|
| + } else if (IsStringWrapperElementsKind(kind)) {
|
| + dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS;
|
| }
|
|
|
| if (attributes != NONE) {
|
| @@ -16149,13 +16168,16 @@ int JSObject::GetFastElementsUsage() {
|
| // Fall through.
|
| case FAST_HOLEY_SMI_ELEMENTS:
|
| case FAST_HOLEY_ELEMENTS:
|
| + case FAST_STRING_WRAPPER_ELEMENTS:
|
| return FastHoleyElementsUsage(this, FixedArray::cast(store));
|
| case FAST_HOLEY_DOUBLE_ELEMENTS:
|
| if (elements()->length() == 0) return 0;
|
| return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store));
|
|
|
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS:
|
| case DICTIONARY_ELEMENTS:
|
| + case NO_ELEMENTS:
|
| #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
|
| case TYPE##_ELEMENTS: \
|
|
|
| @@ -16427,7 +16449,7 @@ void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
|
| }
|
| Name* key = descs->GetKey(i);
|
| if (key->FilterKey(filter)) continue;
|
| - keys->AddKey(key);
|
| + keys->AddKey(key, DO_NOT_CONVERT);
|
| }
|
| } else if (IsJSGlobalObject()) {
|
| GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
|
| @@ -16456,21 +16478,6 @@ void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
|
| KeyAccumulator* keys,
|
| PropertyFilter filter) {
|
| if (filter & SKIP_STRINGS) return;
|
| - uint32_t string_keys = 0;
|
| -
|
| - // If this is a String wrapper, add the string indices first,
|
| - // as they're guaranteed to precede the elements in numerical order
|
| - // and ascending order is required by ECMA-262, 6th, 9.1.12.
|
| - if (object->IsJSValue()) {
|
| - Object* val = JSValue::cast(*object)->value();
|
| - if (val->IsString() && (filter & ONLY_ALL_CAN_READ) == 0) {
|
| - String* str = String::cast(val);
|
| - string_keys = str->length();
|
| - for (uint32_t i = 0; i < string_keys; i++) {
|
| - keys->AddKey(i);
|
| - }
|
| - }
|
| - }
|
| ElementsAccessor* accessor = object->GetElementsAccessor();
|
| accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
|
| }
|
| @@ -16499,7 +16506,8 @@ int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
|
| case FAST_SMI_ELEMENTS:
|
| case FAST_ELEMENTS:
|
| case FAST_HOLEY_SMI_ELEMENTS:
|
| - case FAST_HOLEY_ELEMENTS: {
|
| + case FAST_HOLEY_ELEMENTS:
|
| + case FAST_STRING_WRAPPER_ELEMENTS: {
|
| int length = IsJSArray() ?
|
| Smi::cast(JSArray::cast(this)->length())->value() :
|
| FixedArray::cast(elements())->length();
|
| @@ -16548,7 +16556,8 @@ int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
|
| break;
|
| }
|
|
|
| - case DICTIONARY_ELEMENTS: {
|
| + case DICTIONARY_ELEMENTS:
|
| + case SLOW_STRING_WRAPPER_ELEMENTS: {
|
| if (storage != NULL) {
|
| element_dictionary()->CopyKeysTo(storage, counter, filter,
|
| SeededNumberDictionary::SORTED);
|
| @@ -16598,6 +16607,8 @@ int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
|
| }
|
| break;
|
| }
|
| + case NO_ELEMENTS:
|
| + break;
|
| }
|
|
|
| DCHECK(!storage || storage->length() == counter);
|
| @@ -18495,7 +18506,7 @@ void Dictionary<Derived, Shape, Key>::CollectKeysTo(
|
|
|
| for (int i = 0; i < array_size; i++) {
|
| int index = Smi::cast(array->get(i))->value();
|
| - keys->AddKey(dictionary->KeyAt(index));
|
| + keys->AddKey(dictionary->KeyAt(index), DO_NOT_CONVERT);
|
| }
|
| }
|
|
|
|
|