| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1051 Handle<JSObject> result = | 1051 Handle<JSObject> result = |
| 1052 isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site); | 1052 isolate->factory()->NewJSObjectFromMap(initial_map, NOT_TENURED, site); |
| 1053 isolate->counters()->constructed_objects()->Increment(); | 1053 isolate->counters()->constructed_objects()->Increment(); |
| 1054 isolate->counters()->constructed_objects_runtime()->Increment(); | 1054 isolate->counters()->constructed_objects_runtime()->Increment(); |
| 1055 return result; | 1055 return result; |
| 1056 } | 1056 } |
| 1057 | 1057 |
| 1058 | 1058 |
| 1059 Handle<FixedArray> JSObject::EnsureWritableFastElements( | 1059 Handle<FixedArray> JSObject::EnsureWritableFastElements( |
| 1060 Handle<JSObject> object) { | 1060 Handle<JSObject> object) { |
| 1061 DCHECK(object->HasFastSmiOrObjectElements()); | 1061 DCHECK(object->HasFastSmiOrObjectElements() || |
| 1062 object->HasFastStringWrapperElements()); |
| 1062 Isolate* isolate = object->GetIsolate(); | 1063 Isolate* isolate = object->GetIsolate(); |
| 1063 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); | 1064 Handle<FixedArray> elems(FixedArray::cast(object->elements()), isolate); |
| 1064 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; | 1065 if (elems->map() != isolate->heap()->fixed_cow_array_map()) return elems; |
| 1065 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( | 1066 Handle<FixedArray> writable_elems = isolate->factory()->CopyFixedArrayWithMap( |
| 1066 elems, isolate->factory()->fixed_array_map()); | 1067 elems, isolate->factory()->fixed_array_map()); |
| 1067 object->set_elements(*writable_elems); | 1068 object->set_elements(*writable_elems); |
| 1068 isolate->counters()->cow_arrays_converted()->Increment(); | 1069 isolate->counters()->cow_arrays_converted()->Increment(); |
| 1069 return writable_elems; | 1070 return writable_elems; |
| 1070 } | 1071 } |
| 1071 | 1072 |
| (...skipping 4797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5869 FixedArray* parameter_map = FixedArray::cast(*elements); | 5870 FixedArray* parameter_map = FixedArray::cast(*elements); |
| 5870 elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate); | 5871 elements = handle(FixedArrayBase::cast(parameter_map->get(1)), isolate); |
| 5871 } | 5872 } |
| 5872 | 5873 |
| 5873 if (elements->IsDictionary()) { | 5874 if (elements->IsDictionary()) { |
| 5874 return Handle<SeededNumberDictionary>::cast(elements); | 5875 return Handle<SeededNumberDictionary>::cast(elements); |
| 5875 } | 5876 } |
| 5876 | 5877 |
| 5877 DCHECK(object->HasFastSmiOrObjectElements() || | 5878 DCHECK(object->HasFastSmiOrObjectElements() || |
| 5878 object->HasFastDoubleElements() || | 5879 object->HasFastDoubleElements() || |
| 5879 object->HasFastArgumentsElements()); | 5880 object->HasFastArgumentsElements() || |
| 5881 object->HasFastStringWrapperElements()); |
| 5880 | 5882 |
| 5881 Handle<SeededNumberDictionary> dictionary = | 5883 Handle<SeededNumberDictionary> dictionary = |
| 5882 GetNormalizedElementDictionary(object, elements); | 5884 GetNormalizedElementDictionary(object, elements); |
| 5883 | 5885 |
| 5884 // Switch to using the dictionary as the backing storage for elements. | 5886 // Switch to using the dictionary as the backing storage for elements. |
| 5885 ElementsKind target_kind = | 5887 ElementsKind target_kind = is_arguments |
| 5886 is_arguments ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS : DICTIONARY_ELEMENTS; | 5888 ? SLOW_SLOPPY_ARGUMENTS_ELEMENTS |
| 5889 : object->HasFastStringWrapperElements() |
| 5890 ? SLOW_STRING_WRAPPER_ELEMENTS |
| 5891 : DICTIONARY_ELEMENTS; |
| 5887 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind); | 5892 Handle<Map> new_map = JSObject::GetElementsTransitionMap(object, target_kind); |
| 5888 // Set the new map first to satify the elements type assert in set_elements(). | 5893 // Set the new map first to satify the elements type assert in set_elements(). |
| 5889 JSObject::MigrateToMap(object, new_map); | 5894 JSObject::MigrateToMap(object, new_map); |
| 5890 | 5895 |
| 5891 if (is_arguments) { | 5896 if (is_arguments) { |
| 5892 FixedArray::cast(object->elements())->set(1, *dictionary); | 5897 FixedArray::cast(object->elements())->set(1, *dictionary); |
| 5893 } else { | 5898 } else { |
| 5894 object->set_elements(*dictionary); | 5899 object->set_elements(*dictionary); |
| 5895 } | 5900 } |
| 5896 | 5901 |
| 5897 isolate->counters()->elements_to_dictionary()->Increment(); | 5902 isolate->counters()->elements_to_dictionary()->Increment(); |
| 5898 | 5903 |
| 5899 #ifdef DEBUG | 5904 #ifdef DEBUG |
| 5900 if (FLAG_trace_normalization) { | 5905 if (FLAG_trace_normalization) { |
| 5901 OFStream os(stdout); | 5906 OFStream os(stdout); |
| 5902 os << "Object elements have been normalized:\n"; | 5907 os << "Object elements have been normalized:\n"; |
| 5903 object->Print(os); | 5908 object->Print(os); |
| 5904 } | 5909 } |
| 5905 #endif | 5910 #endif |
| 5906 | 5911 |
| 5907 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); | 5912 DCHECK(object->HasDictionaryElements() || |
| 5913 object->HasSlowArgumentsElements() || |
| 5914 object->HasSlowStringWrapperElements()); |
| 5908 return dictionary; | 5915 return dictionary; |
| 5909 } | 5916 } |
| 5910 | 5917 |
| 5911 | 5918 |
| 5912 static Smi* GenerateIdentityHash(Isolate* isolate) { | 5919 static Smi* GenerateIdentityHash(Isolate* isolate) { |
| 5913 int hash_value; | 5920 int hash_value; |
| 5914 int attempts = 0; | 5921 int attempts = 0; |
| 5915 do { | 5922 do { |
| 5916 // Generate a random 32-bit hash value but limit range to fit | 5923 // Generate a random 32-bit hash value but limit range to fit |
| 5917 // within a smi. | 5924 // within a smi. |
| (...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7400 } | 7407 } |
| 7401 } | 7408 } |
| 7402 // 18. Return resultDesc. | 7409 // 18. Return resultDesc. |
| 7403 return Just(true); | 7410 return Just(true); |
| 7404 } | 7411 } |
| 7405 | 7412 |
| 7406 | 7413 |
| 7407 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, | 7414 bool JSObject::ReferencesObjectFromElements(FixedArray* elements, |
| 7408 ElementsKind kind, | 7415 ElementsKind kind, |
| 7409 Object* object) { | 7416 Object* object) { |
| 7410 DCHECK(IsFastObjectElementsKind(kind) || | 7417 if (IsFastObjectElementsKind(kind) || kind == FAST_STRING_WRAPPER_ELEMENTS) { |
| 7411 kind == DICTIONARY_ELEMENTS); | |
| 7412 if (IsFastObjectElementsKind(kind)) { | |
| 7413 int length = IsJSArray() | 7418 int length = IsJSArray() |
| 7414 ? Smi::cast(JSArray::cast(this)->length())->value() | 7419 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 7415 : elements->length(); | 7420 : elements->length(); |
| 7416 for (int i = 0; i < length; ++i) { | 7421 for (int i = 0; i < length; ++i) { |
| 7417 Object* element = elements->get(i); | 7422 Object* element = elements->get(i); |
| 7418 if (!element->IsTheHole() && element == object) return true; | 7423 if (!element->IsTheHole() && element == object) return true; |
| 7419 } | 7424 } |
| 7420 } else { | 7425 } else { |
| 7426 DCHECK(kind == DICTIONARY_ELEMENTS || kind == SLOW_STRING_WRAPPER_ELEMENTS); |
| 7421 Object* key = | 7427 Object* key = |
| 7422 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); | 7428 SeededNumberDictionary::cast(elements)->SlowReverseLookup(object); |
| 7423 if (!key->IsUndefined()) return true; | 7429 if (!key->IsUndefined()) return true; |
| 7424 } | 7430 } |
| 7425 return false; | 7431 return false; |
| 7426 } | 7432 } |
| 7427 | 7433 |
| 7428 | 7434 |
| 7429 // Check whether this object references another object. | 7435 // Check whether this object references another object. |
| 7430 bool JSObject::ReferencesObject(Object* obj) { | 7436 bool JSObject::ReferencesObject(Object* obj) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 7461 #undef TYPED_ARRAY_CASE | 7467 #undef TYPED_ARRAY_CASE |
| 7462 | 7468 |
| 7463 case FAST_DOUBLE_ELEMENTS: | 7469 case FAST_DOUBLE_ELEMENTS: |
| 7464 case FAST_HOLEY_DOUBLE_ELEMENTS: | 7470 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 7465 break; | 7471 break; |
| 7466 case FAST_SMI_ELEMENTS: | 7472 case FAST_SMI_ELEMENTS: |
| 7467 case FAST_HOLEY_SMI_ELEMENTS: | 7473 case FAST_HOLEY_SMI_ELEMENTS: |
| 7468 break; | 7474 break; |
| 7469 case FAST_ELEMENTS: | 7475 case FAST_ELEMENTS: |
| 7470 case FAST_HOLEY_ELEMENTS: | 7476 case FAST_HOLEY_ELEMENTS: |
| 7471 case DICTIONARY_ELEMENTS: { | 7477 case DICTIONARY_ELEMENTS: |
| 7478 case FAST_STRING_WRAPPER_ELEMENTS: |
| 7479 case SLOW_STRING_WRAPPER_ELEMENTS: { |
| 7472 FixedArray* elements = FixedArray::cast(this->elements()); | 7480 FixedArray* elements = FixedArray::cast(this->elements()); |
| 7473 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 7481 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 7474 break; | 7482 break; |
| 7475 } | 7483 } |
| 7476 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 7484 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 7477 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | 7485 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 7478 FixedArray* parameter_map = FixedArray::cast(elements()); | 7486 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 7479 // Check the mapped parameters. | 7487 // Check the mapped parameters. |
| 7480 int length = parameter_map->length(); | 7488 int length = parameter_map->length(); |
| 7481 for (int i = 2; i < length; ++i) { | 7489 for (int i = 2; i < length; ++i) { |
| 7482 Object* value = parameter_map->get(i); | 7490 Object* value = parameter_map->get(i); |
| 7483 if (!value->IsTheHole() && value == obj) return true; | 7491 if (!value->IsTheHole() && value == obj) return true; |
| 7484 } | 7492 } |
| 7485 // Check the arguments. | 7493 // Check the arguments. |
| 7486 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 7494 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 7487 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : | 7495 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
| 7488 FAST_HOLEY_ELEMENTS; | 7496 FAST_HOLEY_ELEMENTS; |
| 7489 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 7497 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
| 7490 break; | 7498 break; |
| 7491 } | 7499 } |
| 7500 case NO_ELEMENTS: |
| 7501 break; |
| 7492 } | 7502 } |
| 7493 | 7503 |
| 7494 // For functions check the context. | 7504 // For functions check the context. |
| 7495 if (IsJSFunction()) { | 7505 if (IsJSFunction()) { |
| 7496 // Get the constructor function for arguments array. | 7506 // Get the constructor function for arguments array. |
| 7497 Map* arguments_map = | 7507 Map* arguments_map = |
| 7498 heap->isolate()->context()->native_context()->sloppy_arguments_map(); | 7508 heap->isolate()->context()->native_context()->sloppy_arguments_map(); |
| 7499 JSFunction* arguments_function = | 7509 JSFunction* arguments_function = |
| 7500 JSFunction::cast(arguments_map->GetConstructor()); | 7510 JSFunction::cast(arguments_map->GetConstructor()); |
| 7501 | 7511 |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7863 if (object->IsJSGlobalProxy()) { | 7873 if (object->IsJSGlobalProxy()) { |
| 7864 PrototypeIterator iter(isolate, object); | 7874 PrototypeIterator iter(isolate, object); |
| 7865 if (iter.IsAtEnd()) return Just(true); | 7875 if (iter.IsAtEnd()) return Just(true); |
| 7866 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 7876 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
| 7867 return PreventExtensionsWithTransition<attrs>( | 7877 return PreventExtensionsWithTransition<attrs>( |
| 7868 PrototypeIterator::GetCurrent<JSObject>(iter), should_throw); | 7878 PrototypeIterator::GetCurrent<JSObject>(iter), should_throw); |
| 7869 } | 7879 } |
| 7870 | 7880 |
| 7871 Handle<SeededNumberDictionary> new_element_dictionary; | 7881 Handle<SeededNumberDictionary> new_element_dictionary; |
| 7872 if (!object->HasFixedTypedArrayElements() && | 7882 if (!object->HasFixedTypedArrayElements() && |
| 7873 !object->HasDictionaryElements()) { | 7883 !object->HasDictionaryElements() && |
| 7884 !object->HasSlowStringWrapperElements()) { |
| 7874 int length = | 7885 int length = |
| 7875 object->IsJSArray() | 7886 object->IsJSArray() |
| 7876 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() | 7887 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
| 7877 : object->elements()->length(); | 7888 : object->elements()->length(); |
| 7878 new_element_dictionary = | 7889 new_element_dictionary = |
| 7879 length == 0 ? isolate->factory()->empty_slow_element_dictionary() | 7890 length == 0 ? isolate->factory()->empty_slow_element_dictionary() |
| 7880 : GetNormalizedElementDictionary( | 7891 : GetNormalizedElementDictionary( |
| 7881 object, handle(object->elements())); | 7892 object, handle(object->elements())); |
| 7882 } | 7893 } |
| 7883 | 7894 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 7910 // Slow path: need to normalize properties for safety | 7921 // Slow path: need to normalize properties for safety |
| 7911 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, | 7922 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, |
| 7912 "SlowPreventExtensions"); | 7923 "SlowPreventExtensions"); |
| 7913 | 7924 |
| 7914 // Create a new map, since other objects with this map may be extensible. | 7925 // Create a new map, since other objects with this map may be extensible. |
| 7915 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 7926 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 7916 Handle<Map> new_map = | 7927 Handle<Map> new_map = |
| 7917 Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions"); | 7928 Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions"); |
| 7918 new_map->set_is_extensible(false); | 7929 new_map->set_is_extensible(false); |
| 7919 if (!new_element_dictionary.is_null()) { | 7930 if (!new_element_dictionary.is_null()) { |
| 7920 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 7931 ElementsKind new_kind = |
| 7932 IsStringWrapperElementsKind(old_map->elements_kind()) |
| 7933 ? SLOW_STRING_WRAPPER_ELEMENTS |
| 7934 : DICTIONARY_ELEMENTS; |
| 7935 new_map->set_elements_kind(new_kind); |
| 7921 } | 7936 } |
| 7922 JSObject::MigrateToMap(object, new_map); | 7937 JSObject::MigrateToMap(object, new_map); |
| 7923 | 7938 |
| 7924 if (attrs != NONE) { | 7939 if (attrs != NONE) { |
| 7925 if (object->IsJSGlobalObject()) { | 7940 if (object->IsJSGlobalObject()) { |
| 7926 ApplyAttributesToDictionary(object->global_dictionary(), attrs); | 7941 ApplyAttributesToDictionary(object->global_dictionary(), attrs); |
| 7927 } else { | 7942 } else { |
| 7928 ApplyAttributesToDictionary(object->property_dictionary(), attrs); | 7943 ApplyAttributesToDictionary(object->property_dictionary(), attrs); |
| 7929 } | 7944 } |
| 7930 } | 7945 } |
| 7931 } | 7946 } |
| 7932 | 7947 |
| 7933 // Both seal and preventExtensions always go through without modifications to | 7948 // Both seal and preventExtensions always go through without modifications to |
| 7934 // typed array elements. Freeze works only if there are no actual elements. | 7949 // typed array elements. Freeze works only if there are no actual elements. |
| 7935 if (object->HasFixedTypedArrayElements()) { | 7950 if (object->HasFixedTypedArrayElements()) { |
| 7936 if (attrs == FROZEN && | 7951 if (attrs == FROZEN && |
| 7937 JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) { | 7952 JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) { |
| 7938 isolate->Throw(*isolate->factory()->NewTypeError( | 7953 isolate->Throw(*isolate->factory()->NewTypeError( |
| 7939 MessageTemplate::kCannotFreezeArrayBufferView)); | 7954 MessageTemplate::kCannotFreezeArrayBufferView)); |
| 7940 return Nothing<bool>(); | 7955 return Nothing<bool>(); |
| 7941 } | 7956 } |
| 7942 return Just(true); | 7957 return Just(true); |
| 7943 } | 7958 } |
| 7944 | 7959 |
| 7945 DCHECK(object->map()->has_dictionary_elements()); | 7960 DCHECK(object->map()->has_dictionary_elements() || |
| 7961 object->map()->elements_kind() == SLOW_STRING_WRAPPER_ELEMENTS); |
| 7946 if (!new_element_dictionary.is_null()) { | 7962 if (!new_element_dictionary.is_null()) { |
| 7947 object->set_elements(*new_element_dictionary); | 7963 object->set_elements(*new_element_dictionary); |
| 7948 } | 7964 } |
| 7949 | 7965 |
| 7950 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { | 7966 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
| 7951 SeededNumberDictionary* dictionary = object->element_dictionary(); | 7967 SeededNumberDictionary* dictionary = object->element_dictionary(); |
| 7952 // Make sure we never go back to the fast case | 7968 // Make sure we never go back to the fast case |
| 7953 object->RequireSlowElements(dictionary); | 7969 object->RequireSlowElements(dictionary); |
| 7954 if (attrs != NONE) { | 7970 if (attrs != NONE) { |
| 7955 ApplyAttributesToDictionary(dictionary, attrs); | 7971 ApplyAttributesToDictionary(dictionary, attrs); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8127 JSObject); | 8143 JSObject); |
| 8128 if (copying) { | 8144 if (copying) { |
| 8129 // Creating object copy for literals. No strict mode needed. | 8145 // Creating object copy for literals. No strict mode needed. |
| 8130 JSObject::SetProperty(copy, name, result, SLOPPY).Assert(); | 8146 JSObject::SetProperty(copy, name, result, SLOPPY).Assert(); |
| 8131 } | 8147 } |
| 8132 } | 8148 } |
| 8133 } | 8149 } |
| 8134 } | 8150 } |
| 8135 | 8151 |
| 8136 // Deep copy own elements. | 8152 // Deep copy own elements. |
| 8137 // Pixel elements cannot be created using an object literal. | |
| 8138 DCHECK(!copy->HasFixedTypedArrayElements()); | |
| 8139 switch (kind) { | 8153 switch (kind) { |
| 8140 case FAST_SMI_ELEMENTS: | |
| 8141 case FAST_ELEMENTS: | 8154 case FAST_ELEMENTS: |
| 8142 case FAST_HOLEY_SMI_ELEMENTS: | |
| 8143 case FAST_HOLEY_ELEMENTS: { | 8155 case FAST_HOLEY_ELEMENTS: { |
| 8144 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); | 8156 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); |
| 8145 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { | 8157 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { |
| 8146 #ifdef DEBUG | 8158 #ifdef DEBUG |
| 8147 for (int i = 0; i < elements->length(); i++) { | 8159 for (int i = 0; i < elements->length(); i++) { |
| 8148 DCHECK(!elements->get(i)->IsJSObject()); | 8160 DCHECK(!elements->get(i)->IsJSObject()); |
| 8149 } | 8161 } |
| 8150 #endif | 8162 #endif |
| 8151 } else { | 8163 } else { |
| 8152 for (int i = 0; i < elements->length(); i++) { | 8164 for (int i = 0; i < elements->length(); i++) { |
| 8153 Handle<Object> value(elements->get(i), isolate); | 8165 Handle<Object> value(elements->get(i), isolate); |
| 8154 DCHECK(value->IsSmi() || | |
| 8155 value->IsTheHole() || | |
| 8156 (IsFastObjectElementsKind(copy->GetElementsKind()))); | |
| 8157 if (value->IsJSObject()) { | 8166 if (value->IsJSObject()) { |
| 8158 Handle<JSObject> result; | 8167 Handle<JSObject> result; |
| 8159 ASSIGN_RETURN_ON_EXCEPTION( | 8168 ASSIGN_RETURN_ON_EXCEPTION( |
| 8160 isolate, result, | 8169 isolate, result, |
| 8161 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), | 8170 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 8162 JSObject); | 8171 JSObject); |
| 8163 if (copying) { | 8172 if (copying) { |
| 8164 elements->set(i, *result); | 8173 elements->set(i, *result); |
| 8165 } | 8174 } |
| 8166 } | 8175 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 8187 } | 8196 } |
| 8188 } | 8197 } |
| 8189 } | 8198 } |
| 8190 } | 8199 } |
| 8191 break; | 8200 break; |
| 8192 } | 8201 } |
| 8193 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 8202 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8194 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: | 8203 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8195 UNIMPLEMENTED(); | 8204 UNIMPLEMENTED(); |
| 8196 break; | 8205 break; |
| 8197 | 8206 case FAST_STRING_WRAPPER_ELEMENTS: |
| 8207 case SLOW_STRING_WRAPPER_ELEMENTS: |
| 8208 UNREACHABLE(); |
| 8209 break; |
| 8198 | 8210 |
| 8199 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 8211 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 8200 case TYPE##_ELEMENTS: \ | 8212 case TYPE##_ELEMENTS: \ |
| 8201 | 8213 |
| 8202 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 8214 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 8203 #undef TYPED_ARRAY_CASE | 8215 #undef TYPED_ARRAY_CASE |
| 8216 // Typed elements cannot be created using an object literal. |
| 8217 UNREACHABLE(); |
| 8218 break; |
| 8204 | 8219 |
| 8220 case FAST_SMI_ELEMENTS: |
| 8221 case FAST_HOLEY_SMI_ELEMENTS: |
| 8205 case FAST_DOUBLE_ELEMENTS: | 8222 case FAST_DOUBLE_ELEMENTS: |
| 8206 case FAST_HOLEY_DOUBLE_ELEMENTS: | 8223 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 8224 case NO_ELEMENTS: |
| 8207 // No contained objects, nothing to do. | 8225 // No contained objects, nothing to do. |
| 8208 break; | 8226 break; |
| 8209 } | 8227 } |
| 8210 } | 8228 } |
| 8211 | 8229 |
| 8212 return copy; | 8230 return copy; |
| 8213 } | 8231 } |
| 8214 | 8232 |
| 8215 | 8233 |
| 8216 MaybeHandle<JSObject> JSObject::DeepWalk( | 8234 MaybeHandle<JSObject> JSObject::DeepWalk( |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8302 } | 8320 } |
| 8303 } | 8321 } |
| 8304 THROW_NEW_ERROR(isolate, | 8322 THROW_NEW_ERROR(isolate, |
| 8305 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), | 8323 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), |
| 8306 Object); | 8324 Object); |
| 8307 } | 8325 } |
| 8308 | 8326 |
| 8309 | 8327 |
| 8310 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. | 8328 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. |
| 8311 bool HasEnumerableElements(JSObject* object) { | 8329 bool HasEnumerableElements(JSObject* object) { |
| 8312 if (object->IsJSValue()) { | |
| 8313 Object* value = JSValue::cast(object)->value(); | |
| 8314 if (value->IsString()) { | |
| 8315 if (String::cast(value)->length() > 0) return true; | |
| 8316 } | |
| 8317 } | |
| 8318 switch (object->GetElementsKind()) { | 8330 switch (object->GetElementsKind()) { |
| 8319 case FAST_SMI_ELEMENTS: | 8331 case FAST_SMI_ELEMENTS: |
| 8320 case FAST_ELEMENTS: | 8332 case FAST_ELEMENTS: |
| 8321 case FAST_DOUBLE_ELEMENTS: { | 8333 case FAST_DOUBLE_ELEMENTS: { |
| 8322 int length = object->IsJSArray() | 8334 int length = object->IsJSArray() |
| 8323 ? Smi::cast(JSArray::cast(object)->length())->value() | 8335 ? Smi::cast(JSArray::cast(object)->length())->value() |
| 8324 : object->elements()->length(); | 8336 : object->elements()->length(); |
| 8325 return length > 0; | 8337 return length > 0; |
| 8326 } | 8338 } |
| 8327 case FAST_HOLEY_SMI_ELEMENTS: | 8339 case FAST_HOLEY_SMI_ELEMENTS: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8359 } | 8371 } |
| 8360 case DICTIONARY_ELEMENTS: { | 8372 case DICTIONARY_ELEMENTS: { |
| 8361 SeededNumberDictionary* elements = | 8373 SeededNumberDictionary* elements = |
| 8362 SeededNumberDictionary::cast(object->elements()); | 8374 SeededNumberDictionary::cast(object->elements()); |
| 8363 return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0; | 8375 return elements->NumberOfElementsFilterAttributes(ONLY_ENUMERABLE) > 0; |
| 8364 } | 8376 } |
| 8365 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 8377 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8366 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: | 8378 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 8367 // We're approximating non-empty arguments objects here. | 8379 // We're approximating non-empty arguments objects here. |
| 8368 return true; | 8380 return true; |
| 8381 case FAST_STRING_WRAPPER_ELEMENTS: |
| 8382 case SLOW_STRING_WRAPPER_ELEMENTS: |
| 8383 if (String::cast(JSValue::cast(object)->value())->length() > 0) { |
| 8384 return true; |
| 8385 } |
| 8386 return object->elements()->length() > 0; |
| 8387 case NO_ELEMENTS: |
| 8388 return false; |
| 8369 } | 8389 } |
| 8370 UNREACHABLE(); | 8390 UNREACHABLE(); |
| 8371 return true; | 8391 return true; |
| 8372 } | 8392 } |
| 8373 | 8393 |
| 8374 | 8394 |
| 8375 // Tests for the fast common case for property enumeration: | 8395 // Tests for the fast common case for property enumeration: |
| 8376 // - This object and all prototypes has an enum cache (which means that | 8396 // - This object and all prototypes has an enum cache (which means that |
| 8377 // it is no proxy, has no interceptors and needs no access checks). | 8397 // it is no proxy, has no interceptors and needs no access checks). |
| 8378 // - This object has no elements. | 8398 // - This object has no elements. |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8591 if (result.IsEmpty()) return Just(true); | 8611 if (result.IsEmpty()) return Just(true); |
| 8592 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || | 8612 DCHECK(v8::Utils::OpenHandle(*result)->IsJSArray() || |
| 8593 (v8::Utils::OpenHandle(*result)->IsJSObject() && | 8613 (v8::Utils::OpenHandle(*result)->IsJSObject() && |
| 8594 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) | 8614 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)) |
| 8595 ->HasSloppyArgumentsElements())); | 8615 ->HasSloppyArgumentsElements())); |
| 8596 // The accumulator takes care of string/symbol filtering. | 8616 // The accumulator takes care of string/symbol filtering. |
| 8597 if (type == kIndexed) { | 8617 if (type == kIndexed) { |
| 8598 accumulator->AddElementKeysFromInterceptor( | 8618 accumulator->AddElementKeysFromInterceptor( |
| 8599 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8619 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); |
| 8600 } else { | 8620 } else { |
| 8601 accumulator->AddKeys( | 8621 accumulator->AddKeys(Handle<JSObject>::cast(v8::Utils::OpenHandle(*result)), |
| 8602 Handle<JSObject>::cast(v8::Utils::OpenHandle(*result))); | 8622 DO_NOT_CONVERT); |
| 8603 } | 8623 } |
| 8604 return Just(true); | 8624 return Just(true); |
| 8605 } | 8625 } |
| 8606 | 8626 |
| 8607 | 8627 |
| 8608 // Returns |true| on success, |false| if prototype walking should be stopped, | 8628 // Returns |true| on success, |false| if prototype walking should be stopped, |
| 8609 // |nothing| if an exception was thrown. | 8629 // |nothing| if an exception was thrown. |
| 8610 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, | 8630 static Maybe<bool> GetKeysFromJSObject(Isolate* isolate, |
| 8611 Handle<JSReceiver> receiver, | 8631 Handle<JSReceiver> receiver, |
| 8612 Handle<JSObject> object, | 8632 Handle<JSObject> object, |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8648 // use the cache says yes, so we should not create a cache. | 8668 // use the cache says yes, so we should not create a cache. |
| 8649 Handle<JSFunction> arguments_function( | 8669 Handle<JSFunction> arguments_function( |
| 8650 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 8670 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
| 8651 bool cache_enum_length = | 8671 bool cache_enum_length = |
| 8652 ((object->map()->GetConstructor() != *arguments_function) && | 8672 ((object->map()->GetConstructor() != *arguments_function) && |
| 8653 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | 8673 !object->IsJSValue() && !object->IsAccessCheckNeeded() && |
| 8654 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | 8674 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); |
| 8655 // Compute the property keys and cache them if possible. | 8675 // Compute the property keys and cache them if possible. |
| 8656 Handle<FixedArray> enum_keys = | 8676 Handle<FixedArray> enum_keys = |
| 8657 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | 8677 JSObject::GetEnumPropertyKeys(object, cache_enum_length); |
| 8658 accumulator->AddKeys(enum_keys); | 8678 accumulator->AddKeys(enum_keys, DO_NOT_CONVERT); |
| 8659 } else { | 8679 } else { |
| 8660 object->CollectOwnPropertyNames(accumulator, *filter); | 8680 object->CollectOwnPropertyNames(accumulator, *filter); |
| 8661 } | 8681 } |
| 8662 | 8682 |
| 8663 // Add the property keys from the interceptor. | 8683 // Add the property keys from the interceptor. |
| 8664 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | 8684 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, |
| 8665 kNamed>(isolate, receiver, object, *filter, | 8685 kNamed>(isolate, receiver, object, *filter, |
| 8666 accumulator); | 8686 accumulator); |
| 8667 MAYBE_RETURN(success, Nothing<bool>()); | 8687 MAYBE_RETURN(success, Nothing<bool>()); |
| 8668 return Just(true); | 8688 return Just(true); |
| (...skipping 1072 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9741 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( | 9761 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( |
| 9742 handle(map->instance_descriptors(), isolate), num_descriptors, | 9762 handle(map->instance_descriptors(), isolate), num_descriptors, |
| 9743 attrs_to_add); | 9763 attrs_to_add); |
| 9744 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(), | 9764 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(), |
| 9745 isolate); | 9765 isolate); |
| 9746 Handle<Map> new_map = CopyReplaceDescriptors( | 9766 Handle<Map> new_map = CopyReplaceDescriptors( |
| 9747 map, new_desc, new_layout_descriptor, INSERT_TRANSITION, | 9767 map, new_desc, new_layout_descriptor, INSERT_TRANSITION, |
| 9748 transition_marker, reason, SPECIAL_TRANSITION); | 9768 transition_marker, reason, SPECIAL_TRANSITION); |
| 9749 new_map->set_is_extensible(false); | 9769 new_map->set_is_extensible(false); |
| 9750 if (!IsFixedTypedArrayElementsKind(map->elements_kind())) { | 9770 if (!IsFixedTypedArrayElementsKind(map->elements_kind())) { |
| 9751 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 9771 ElementsKind new_kind = IsStringWrapperElementsKind(map->elements_kind()) |
| 9772 ? SLOW_STRING_WRAPPER_ELEMENTS |
| 9773 : DICTIONARY_ELEMENTS; |
| 9774 new_map->set_elements_kind(new_kind); |
| 9752 } | 9775 } |
| 9753 return new_map; | 9776 return new_map; |
| 9754 } | 9777 } |
| 9755 | 9778 |
| 9756 | 9779 |
| 9757 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { | 9780 bool DescriptorArray::CanHoldValue(int descriptor, Object* value) { |
| 9758 PropertyDetails details = GetDetails(descriptor); | 9781 PropertyDetails details = GetDetails(descriptor); |
| 9759 switch (details.type()) { | 9782 switch (details.type()) { |
| 9760 case DATA: | 9783 case DATA: |
| 9761 return value->FitsRepresentation(details.representation()) && | 9784 return value->FitsRepresentation(details.representation()) && |
| (...skipping 6014 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15776 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); | 15799 return ShouldConvertToSlowElements(this, capacity, index, &new_capacity); |
| 15777 } | 15800 } |
| 15778 return false; | 15801 return false; |
| 15779 } | 15802 } |
| 15780 | 15803 |
| 15781 | 15804 |
| 15782 static ElementsKind BestFittingFastElementsKind(JSObject* object) { | 15805 static ElementsKind BestFittingFastElementsKind(JSObject* object) { |
| 15783 if (object->HasSloppyArgumentsElements()) { | 15806 if (object->HasSloppyArgumentsElements()) { |
| 15784 return FAST_SLOPPY_ARGUMENTS_ELEMENTS; | 15807 return FAST_SLOPPY_ARGUMENTS_ELEMENTS; |
| 15785 } | 15808 } |
| 15809 if (object->HasStringWrapperElements()) { |
| 15810 return FAST_STRING_WRAPPER_ELEMENTS; |
| 15811 } |
| 15786 DCHECK(object->HasDictionaryElements()); | 15812 DCHECK(object->HasDictionaryElements()); |
| 15787 SeededNumberDictionary* dictionary = object->element_dictionary(); | 15813 SeededNumberDictionary* dictionary = object->element_dictionary(); |
| 15788 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; | 15814 ElementsKind kind = FAST_HOLEY_SMI_ELEMENTS; |
| 15789 for (int i = 0; i < dictionary->Capacity(); i++) { | 15815 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 15790 Object* key = dictionary->KeyAt(i); | 15816 Object* key = dictionary->KeyAt(i); |
| 15791 if (key->IsNumber()) { | 15817 if (key->IsNumber()) { |
| 15792 Object* value = dictionary->ValueAt(i); | 15818 Object* value = dictionary->ValueAt(i); |
| 15793 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; | 15819 if (!value->IsNumber()) return FAST_HOLEY_ELEMENTS; |
| 15794 if (!value->IsSmi()) { | 15820 if (!value->IsSmi()) { |
| 15795 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS; | 15821 if (!FLAG_unbox_double_arrays) return FAST_HOLEY_ELEMENTS; |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15859 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); | 15885 old_length_handle = handle(JSArray::cast(*object)->length(), isolate); |
| 15860 } | 15886 } |
| 15861 } | 15887 } |
| 15862 | 15888 |
| 15863 ElementsKind kind = object->GetElementsKind(); | 15889 ElementsKind kind = object->GetElementsKind(); |
| 15864 FixedArrayBase* elements = object->elements(); | 15890 FixedArrayBase* elements = object->elements(); |
| 15865 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; | 15891 ElementsKind dictionary_kind = DICTIONARY_ELEMENTS; |
| 15866 if (IsSloppyArgumentsElements(kind)) { | 15892 if (IsSloppyArgumentsElements(kind)) { |
| 15867 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); | 15893 elements = FixedArrayBase::cast(FixedArray::cast(elements)->get(1)); |
| 15868 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; | 15894 dictionary_kind = SLOW_SLOPPY_ARGUMENTS_ELEMENTS; |
| 15895 } else if (IsStringWrapperElementsKind(kind)) { |
| 15896 dictionary_kind = SLOW_STRING_WRAPPER_ELEMENTS; |
| 15869 } | 15897 } |
| 15870 | 15898 |
| 15871 if (attributes != NONE) { | 15899 if (attributes != NONE) { |
| 15872 kind = dictionary_kind; | 15900 kind = dictionary_kind; |
| 15873 } else if (elements->IsSeededNumberDictionary()) { | 15901 } else if (elements->IsSeededNumberDictionary()) { |
| 15874 kind = ShouldConvertToFastElements(*object, | 15902 kind = ShouldConvertToFastElements(*object, |
| 15875 SeededNumberDictionary::cast(elements), | 15903 SeededNumberDictionary::cast(elements), |
| 15876 index, &new_capacity) | 15904 index, &new_capacity) |
| 15877 ? BestFittingFastElementsKind(*object) | 15905 ? BestFittingFastElementsKind(*object) |
| 15878 : dictionary_kind; // Overwrite in case of arguments. | 15906 : dictionary_kind; // Overwrite in case of arguments. |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16154 case FAST_SMI_ELEMENTS: | 16182 case FAST_SMI_ELEMENTS: |
| 16155 case FAST_DOUBLE_ELEMENTS: | 16183 case FAST_DOUBLE_ELEMENTS: |
| 16156 case FAST_ELEMENTS: | 16184 case FAST_ELEMENTS: |
| 16157 return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value() | 16185 return IsJSArray() ? Smi::cast(JSArray::cast(this)->length())->value() |
| 16158 : store->length(); | 16186 : store->length(); |
| 16159 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 16187 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 16160 store = FixedArray::cast(FixedArray::cast(store)->get(1)); | 16188 store = FixedArray::cast(FixedArray::cast(store)->get(1)); |
| 16161 // Fall through. | 16189 // Fall through. |
| 16162 case FAST_HOLEY_SMI_ELEMENTS: | 16190 case FAST_HOLEY_SMI_ELEMENTS: |
| 16163 case FAST_HOLEY_ELEMENTS: | 16191 case FAST_HOLEY_ELEMENTS: |
| 16192 case FAST_STRING_WRAPPER_ELEMENTS: |
| 16164 return FastHoleyElementsUsage(this, FixedArray::cast(store)); | 16193 return FastHoleyElementsUsage(this, FixedArray::cast(store)); |
| 16165 case FAST_HOLEY_DOUBLE_ELEMENTS: | 16194 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 16166 if (elements()->length() == 0) return 0; | 16195 if (elements()->length() == 0) return 0; |
| 16167 return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store)); | 16196 return FastHoleyElementsUsage(this, FixedDoubleArray::cast(store)); |
| 16168 | 16197 |
| 16169 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: | 16198 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| 16199 case SLOW_STRING_WRAPPER_ELEMENTS: |
| 16170 case DICTIONARY_ELEMENTS: | 16200 case DICTIONARY_ELEMENTS: |
| 16201 case NO_ELEMENTS: |
| 16171 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 16202 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 16172 case TYPE##_ELEMENTS: \ | 16203 case TYPE##_ELEMENTS: \ |
| 16173 | 16204 |
| 16174 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 16205 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 16175 #undef TYPED_ARRAY_CASE | 16206 #undef TYPED_ARRAY_CASE |
| 16176 UNREACHABLE(); | 16207 UNREACHABLE(); |
| 16177 } | 16208 } |
| 16178 return 0; | 16209 return 0; |
| 16179 } | 16210 } |
| 16180 | 16211 |
| (...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16432 PropertyDetails details = descs->GetDetails(i); | 16463 PropertyDetails details = descs->GetDetails(i); |
| 16433 if ((details.attributes() & filter) != 0) continue; | 16464 if ((details.attributes() & filter) != 0) continue; |
| 16434 if (filter & ONLY_ALL_CAN_READ) { | 16465 if (filter & ONLY_ALL_CAN_READ) { |
| 16435 if (details.kind() != kAccessor) continue; | 16466 if (details.kind() != kAccessor) continue; |
| 16436 Object* accessors = descs->GetValue(i); | 16467 Object* accessors = descs->GetValue(i); |
| 16437 if (!accessors->IsAccessorInfo()) continue; | 16468 if (!accessors->IsAccessorInfo()) continue; |
| 16438 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 16469 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
| 16439 } | 16470 } |
| 16440 Name* key = descs->GetKey(i); | 16471 Name* key = descs->GetKey(i); |
| 16441 if (key->FilterKey(filter)) continue; | 16472 if (key->FilterKey(filter)) continue; |
| 16442 keys->AddKey(key); | 16473 keys->AddKey(key, DO_NOT_CONVERT); |
| 16443 } | 16474 } |
| 16444 } else if (IsJSGlobalObject()) { | 16475 } else if (IsJSGlobalObject()) { |
| 16445 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); | 16476 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); |
| 16446 } else { | 16477 } else { |
| 16447 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); | 16478 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); |
| 16448 } | 16479 } |
| 16449 } | 16480 } |
| 16450 | 16481 |
| 16451 | 16482 |
| 16452 int JSObject::NumberOfOwnElements(PropertyFilter filter) { | 16483 int JSObject::NumberOfOwnElements(PropertyFilter filter) { |
| 16453 // Fast case for objects with no elements. | 16484 // Fast case for objects with no elements. |
| 16454 if (!IsJSValue() && HasFastElements()) { | 16485 if (!IsJSValue() && HasFastElements()) { |
| 16455 uint32_t length = | 16486 uint32_t length = |
| 16456 IsJSArray() | 16487 IsJSArray() |
| 16457 ? static_cast<uint32_t>( | 16488 ? static_cast<uint32_t>( |
| 16458 Smi::cast(JSArray::cast(this)->length())->value()) | 16489 Smi::cast(JSArray::cast(this)->length())->value()) |
| 16459 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); | 16490 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); |
| 16460 if (length == 0) return 0; | 16491 if (length == 0) return 0; |
| 16461 } | 16492 } |
| 16462 // Compute the number of enumerable elements. | 16493 // Compute the number of enumerable elements. |
| 16463 return GetOwnElementKeys(NULL, filter); | 16494 return GetOwnElementKeys(NULL, filter); |
| 16464 } | 16495 } |
| 16465 | 16496 |
| 16466 | 16497 |
| 16467 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, | 16498 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, |
| 16468 KeyAccumulator* keys, | 16499 KeyAccumulator* keys, |
| 16469 PropertyFilter filter) { | 16500 PropertyFilter filter) { |
| 16470 if (filter & SKIP_STRINGS) return; | 16501 if (filter & SKIP_STRINGS) return; |
| 16471 uint32_t string_keys = 0; | |
| 16472 | |
| 16473 // If this is a String wrapper, add the string indices first, | |
| 16474 // as they're guaranteed to precede the elements in numerical order | |
| 16475 // and ascending order is required by ECMA-262, 6th, 9.1.12. | |
| 16476 if (object->IsJSValue()) { | |
| 16477 Object* val = JSValue::cast(*object)->value(); | |
| 16478 if (val->IsString() && (filter & ONLY_ALL_CAN_READ) == 0) { | |
| 16479 String* str = String::cast(val); | |
| 16480 string_keys = str->length(); | |
| 16481 for (uint32_t i = 0; i < string_keys; i++) { | |
| 16482 keys->AddKey(i); | |
| 16483 } | |
| 16484 } | |
| 16485 } | |
| 16486 ElementsAccessor* accessor = object->GetElementsAccessor(); | 16502 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 16487 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); | 16503 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); |
| 16488 } | 16504 } |
| 16489 | 16505 |
| 16490 | 16506 |
| 16491 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { | 16507 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { |
| 16492 int counter = 0; | 16508 int counter = 0; |
| 16493 | 16509 |
| 16494 // If this is a String wrapper, add the string indices first, | 16510 // If this is a String wrapper, add the string indices first, |
| 16495 // as they're guaranteed to precede the elements in numerical order | 16511 // as they're guaranteed to precede the elements in numerical order |
| 16496 // and ascending order is required by ECMA-262, 6th, 9.1.12. | 16512 // and ascending order is required by ECMA-262, 6th, 9.1.12. |
| 16497 if (IsJSValue()) { | 16513 if (IsJSValue()) { |
| 16498 Object* val = JSValue::cast(this)->value(); | 16514 Object* val = JSValue::cast(this)->value(); |
| 16499 if (val->IsString()) { | 16515 if (val->IsString()) { |
| 16500 String* str = String::cast(val); | 16516 String* str = String::cast(val); |
| 16501 if (storage) { | 16517 if (storage) { |
| 16502 for (int i = 0; i < str->length(); i++) { | 16518 for (int i = 0; i < str->length(); i++) { |
| 16503 storage->set(counter + i, Smi::FromInt(i)); | 16519 storage->set(counter + i, Smi::FromInt(i)); |
| 16504 } | 16520 } |
| 16505 } | 16521 } |
| 16506 counter += str->length(); | 16522 counter += str->length(); |
| 16507 } | 16523 } |
| 16508 } | 16524 } |
| 16509 | 16525 |
| 16510 switch (GetElementsKind()) { | 16526 switch (GetElementsKind()) { |
| 16511 case FAST_SMI_ELEMENTS: | 16527 case FAST_SMI_ELEMENTS: |
| 16512 case FAST_ELEMENTS: | 16528 case FAST_ELEMENTS: |
| 16513 case FAST_HOLEY_SMI_ELEMENTS: | 16529 case FAST_HOLEY_SMI_ELEMENTS: |
| 16514 case FAST_HOLEY_ELEMENTS: { | 16530 case FAST_HOLEY_ELEMENTS: |
| 16531 case FAST_STRING_WRAPPER_ELEMENTS: { |
| 16515 int length = IsJSArray() ? | 16532 int length = IsJSArray() ? |
| 16516 Smi::cast(JSArray::cast(this)->length())->value() : | 16533 Smi::cast(JSArray::cast(this)->length())->value() : |
| 16517 FixedArray::cast(elements())->length(); | 16534 FixedArray::cast(elements())->length(); |
| 16518 for (int i = 0; i < length; i++) { | 16535 for (int i = 0; i < length; i++) { |
| 16519 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 16536 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 16520 if (storage != NULL) { | 16537 if (storage != NULL) { |
| 16521 storage->set(counter, Smi::FromInt(i)); | 16538 storage->set(counter, Smi::FromInt(i)); |
| 16522 } | 16539 } |
| 16523 counter++; | 16540 counter++; |
| 16524 } | 16541 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 16553 while (counter < length) { | 16570 while (counter < length) { |
| 16554 if (storage != NULL) { | 16571 if (storage != NULL) { |
| 16555 storage->set(counter, Smi::FromInt(counter)); | 16572 storage->set(counter, Smi::FromInt(counter)); |
| 16556 } | 16573 } |
| 16557 counter++; | 16574 counter++; |
| 16558 } | 16575 } |
| 16559 DCHECK(!storage || storage->length() >= counter); | 16576 DCHECK(!storage || storage->length() >= counter); |
| 16560 break; | 16577 break; |
| 16561 } | 16578 } |
| 16562 | 16579 |
| 16563 case DICTIONARY_ELEMENTS: { | 16580 case DICTIONARY_ELEMENTS: |
| 16581 case SLOW_STRING_WRAPPER_ELEMENTS: { |
| 16564 if (storage != NULL) { | 16582 if (storage != NULL) { |
| 16565 element_dictionary()->CopyKeysTo(storage, counter, filter, | 16583 element_dictionary()->CopyKeysTo(storage, counter, filter, |
| 16566 SeededNumberDictionary::SORTED); | 16584 SeededNumberDictionary::SORTED); |
| 16567 } | 16585 } |
| 16568 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 16586 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 16569 break; | 16587 break; |
| 16570 } | 16588 } |
| 16571 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 16589 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 16572 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | 16590 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 16573 FixedArray* parameter_map = FixedArray::cast(elements()); | 16591 FixedArray* parameter_map = FixedArray::cast(elements()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 16603 ++counter; | 16621 ++counter; |
| 16604 } | 16622 } |
| 16605 } | 16623 } |
| 16606 for (; i < backing_length; ++i) { | 16624 for (; i < backing_length; ++i) { |
| 16607 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); | 16625 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
| 16608 ++counter; | 16626 ++counter; |
| 16609 } | 16627 } |
| 16610 } | 16628 } |
| 16611 break; | 16629 break; |
| 16612 } | 16630 } |
| 16631 case NO_ELEMENTS: |
| 16632 break; |
| 16613 } | 16633 } |
| 16614 | 16634 |
| 16615 DCHECK(!storage || storage->length() == counter); | 16635 DCHECK(!storage || storage->length() == counter); |
| 16616 return counter; | 16636 return counter; |
| 16617 } | 16637 } |
| 16618 | 16638 |
| 16619 | 16639 |
| 16620 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, | 16640 MaybeHandle<String> Object::ObjectProtoToString(Isolate* isolate, |
| 16621 Handle<Object> object) { | 16641 Handle<Object> object) { |
| 16622 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); | 16642 if (object->IsUndefined()) return isolate->factory()->undefined_to_string(); |
| (...skipping 1877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 18500 array->set(array_size++, Smi::FromInt(i)); | 18520 array->set(array_size++, Smi::FromInt(i)); |
| 18501 } | 18521 } |
| 18502 | 18522 |
| 18503 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); | 18523 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); |
| 18504 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); | 18524 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); |
| 18505 std::sort(start, start + array_size, cmp); | 18525 std::sort(start, start + array_size, cmp); |
| 18506 } | 18526 } |
| 18507 | 18527 |
| 18508 for (int i = 0; i < array_size; i++) { | 18528 for (int i = 0; i < array_size; i++) { |
| 18509 int index = Smi::cast(array->get(i))->value(); | 18529 int index = Smi::cast(array->get(i))->value(); |
| 18510 keys->AddKey(dictionary->KeyAt(index)); | 18530 keys->AddKey(dictionary->KeyAt(index), DO_NOT_CONVERT); |
| 18511 } | 18531 } |
| 18512 } | 18532 } |
| 18513 | 18533 |
| 18514 | 18534 |
| 18515 // Backwards lookup (slow). | 18535 // Backwards lookup (slow). |
| 18516 template<typename Derived, typename Shape, typename Key> | 18536 template<typename Derived, typename Shape, typename Key> |
| 18517 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { | 18537 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
| 18518 int capacity = this->Capacity(); | 18538 int capacity = this->Capacity(); |
| 18519 for (int i = 0; i < capacity; i++) { | 18539 for (int i = 0; i < capacity; i++) { |
| 18520 Object* k = this->KeyAt(i); | 18540 Object* k = this->KeyAt(i); |
| (...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19749 if (cell->value() != *new_value) { | 19769 if (cell->value() != *new_value) { |
| 19750 cell->set_value(*new_value); | 19770 cell->set_value(*new_value); |
| 19751 Isolate* isolate = cell->GetIsolate(); | 19771 Isolate* isolate = cell->GetIsolate(); |
| 19752 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19772 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 19753 isolate, DependentCode::kPropertyCellChangedGroup); | 19773 isolate, DependentCode::kPropertyCellChangedGroup); |
| 19754 } | 19774 } |
| 19755 } | 19775 } |
| 19756 | 19776 |
| 19757 } // namespace internal | 19777 } // namespace internal |
| 19758 } // namespace v8 | 19778 } // namespace v8 |
| OLD | NEW |