OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 6776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6787 } | 6787 } |
6788 | 6788 |
6789 if (object->IsJSGlobalProxy()) { | 6789 if (object->IsJSGlobalProxy()) { |
6790 PrototypeIterator iter(isolate, object); | 6790 PrototypeIterator iter(isolate, object); |
6791 if (iter.IsAtEnd()) return Just(true); | 6791 if (iter.IsAtEnd()) return Just(true); |
6792 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6792 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
6793 return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter), | 6793 return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter), |
6794 should_throw); | 6794 should_throw); |
6795 } | 6795 } |
6796 | 6796 |
6797 // It's not possible to seal objects with external array elements | 6797 if (!object->HasFixedTypedArrayElements()) { |
6798 if (object->HasFixedTypedArrayElements()) { | 6798 // If there are fast elements we normalize. |
6799 isolate->Throw(*isolate->factory()->NewTypeError( | 6799 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
6800 MessageTemplate::kCannotPreventExtExternalArray)); | 6800 DCHECK(object->HasDictionaryElements() || |
6801 return Nothing<bool>(); | 6801 object->HasSlowArgumentsElements()); |
| 6802 |
| 6803 // Make sure that we never go back to fast case. |
| 6804 object->RequireSlowElements(*dictionary); |
6802 } | 6805 } |
6803 | 6806 |
6804 // If there are fast elements we normalize. | |
6805 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | |
6806 DCHECK(object->HasDictionaryElements() || object->HasSlowArgumentsElements()); | |
6807 | |
6808 // Make sure that we never go back to fast case. | |
6809 object->RequireSlowElements(*dictionary); | |
6810 | |
6811 // Do a map transition, other objects with this map may still | 6807 // Do a map transition, other objects with this map may still |
6812 // be extensible. | 6808 // be extensible. |
6813 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 6809 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
6814 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); | 6810 Handle<Map> new_map = Map::Copy(handle(object->map()), "PreventExtensions"); |
6815 | 6811 |
6816 new_map->set_is_extensible(false); | 6812 new_map->set_is_extensible(false); |
6817 JSObject::MigrateToMap(object, new_map); | 6813 JSObject::MigrateToMap(object, new_map); |
6818 DCHECK(!object->map()->is_extensible()); | 6814 DCHECK(!object->map()->is_extensible()); |
6819 | 6815 |
6820 if (object->map()->is_observed()) { | 6816 if (object->map()->is_observed()) { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6888 } | 6884 } |
6889 | 6885 |
6890 if (object->IsJSGlobalProxy()) { | 6886 if (object->IsJSGlobalProxy()) { |
6891 PrototypeIterator iter(isolate, object); | 6887 PrototypeIterator iter(isolate, object); |
6892 if (iter.IsAtEnd()) return Just(true); | 6888 if (iter.IsAtEnd()) return Just(true); |
6893 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 6889 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
6894 return PreventExtensionsWithTransition<attrs>( | 6890 return PreventExtensionsWithTransition<attrs>( |
6895 PrototypeIterator::GetCurrent<JSObject>(iter), should_throw); | 6891 PrototypeIterator::GetCurrent<JSObject>(iter), should_throw); |
6896 } | 6892 } |
6897 | 6893 |
6898 // It's not possible to seal or freeze objects with external array elements | |
6899 if (object->HasFixedTypedArrayElements()) { | |
6900 isolate->Throw(*isolate->factory()->NewTypeError( | |
6901 MessageTemplate::kCannotPreventExtExternalArray)); | |
6902 return Nothing<bool>(); | |
6903 } | |
6904 | |
6905 Handle<SeededNumberDictionary> new_element_dictionary; | 6894 Handle<SeededNumberDictionary> new_element_dictionary; |
6906 if (!object->HasDictionaryElements()) { | 6895 if (!object->HasFixedTypedArrayElements() && |
| 6896 !object->HasDictionaryElements()) { |
6907 int length = | 6897 int length = |
6908 object->IsJSArray() | 6898 object->IsJSArray() |
6909 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() | 6899 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
6910 : object->elements()->length(); | 6900 : object->elements()->length(); |
6911 new_element_dictionary = | 6901 new_element_dictionary = |
6912 length == 0 ? isolate->factory()->empty_slow_element_dictionary() | 6902 length == 0 ? isolate->factory()->empty_slow_element_dictionary() |
6913 : GetNormalizedElementDictionary( | 6903 : GetNormalizedElementDictionary( |
6914 object, handle(object->elements())); | 6904 object, handle(object->elements())); |
6915 } | 6905 } |
6916 | 6906 |
6917 Handle<Symbol> transition_marker; | 6907 Handle<Symbol> transition_marker; |
6918 if (attrs == NONE) { | 6908 if (attrs == NONE) { |
6919 transition_marker = isolate->factory()->nonextensible_symbol(); | 6909 transition_marker = isolate->factory()->nonextensible_symbol(); |
6920 } else if (attrs == SEALED) { | 6910 } else if (attrs == SEALED) { |
6921 transition_marker = isolate->factory()->sealed_symbol(); | 6911 transition_marker = isolate->factory()->sealed_symbol(); |
6922 } else { | 6912 } else { |
6923 DCHECK(attrs == FROZEN); | 6913 DCHECK(attrs == FROZEN); |
6924 transition_marker = isolate->factory()->frozen_symbol(); | 6914 transition_marker = isolate->factory()->frozen_symbol(); |
6925 } | 6915 } |
6926 | 6916 |
6927 Handle<Map> old_map(object->map(), isolate); | 6917 Handle<Map> old_map(object->map(), isolate); |
6928 Map* transition = | 6918 Map* transition = |
6929 TransitionArray::SearchSpecial(*old_map, *transition_marker); | 6919 TransitionArray::SearchSpecial(*old_map, *transition_marker); |
6930 if (transition != NULL) { | 6920 if (transition != NULL) { |
6931 Handle<Map> transition_map(transition, isolate); | 6921 Handle<Map> transition_map(transition, isolate); |
6932 DCHECK(transition_map->has_dictionary_elements()); | 6922 DCHECK(transition_map->has_dictionary_elements() || |
| 6923 transition_map->has_fixed_typed_array_elements()); |
6933 DCHECK(!transition_map->is_extensible()); | 6924 DCHECK(!transition_map->is_extensible()); |
6934 JSObject::MigrateToMap(object, transition_map); | 6925 JSObject::MigrateToMap(object, transition_map); |
6935 } else if (TransitionArray::CanHaveMoreTransitions(old_map)) { | 6926 } else if (TransitionArray::CanHaveMoreTransitions(old_map)) { |
6936 // Create a new descriptor array with the appropriate property attributes | 6927 // Create a new descriptor array with the appropriate property attributes |
6937 Handle<Map> new_map = Map::CopyForPreventExtensions( | 6928 Handle<Map> new_map = Map::CopyForPreventExtensions( |
6938 old_map, attrs, transition_marker, "CopyForPreventExtensions"); | 6929 old_map, attrs, transition_marker, "CopyForPreventExtensions"); |
6939 JSObject::MigrateToMap(object, new_map); | 6930 JSObject::MigrateToMap(object, new_map); |
6940 } else { | 6931 } else { |
6941 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); | 6932 DCHECK(old_map->is_dictionary_map() || !old_map->is_prototype_map()); |
6942 // Slow path: need to normalize properties for safety | 6933 // Slow path: need to normalize properties for safety |
6943 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, | 6934 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0, |
6944 "SlowPreventExtensions"); | 6935 "SlowPreventExtensions"); |
6945 | 6936 |
6946 // Create a new map, since other objects with this map may be extensible. | 6937 // Create a new map, since other objects with this map may be extensible. |
6947 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 6938 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
6948 Handle<Map> new_map = | 6939 Handle<Map> new_map = |
6949 Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions"); | 6940 Map::Copy(handle(object->map()), "SlowCopyForPreventExtensions"); |
6950 new_map->set_is_extensible(false); | 6941 new_map->set_is_extensible(false); |
6951 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 6942 if (!new_element_dictionary.is_null()) { |
| 6943 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 6944 } |
6952 JSObject::MigrateToMap(object, new_map); | 6945 JSObject::MigrateToMap(object, new_map); |
6953 | 6946 |
6954 if (attrs != NONE) { | 6947 if (attrs != NONE) { |
6955 if (object->IsGlobalObject()) { | 6948 if (object->IsGlobalObject()) { |
6956 ApplyAttributesToDictionary(object->global_dictionary(), attrs); | 6949 ApplyAttributesToDictionary(object->global_dictionary(), attrs); |
6957 } else { | 6950 } else { |
6958 ApplyAttributesToDictionary(object->property_dictionary(), attrs); | 6951 ApplyAttributesToDictionary(object->property_dictionary(), attrs); |
6959 } | 6952 } |
6960 } | 6953 } |
6961 } | 6954 } |
6962 | 6955 |
| 6956 // Both seal and preventExtensions always go through without modifications to |
| 6957 // typed array elements. Freeze works only if there are no actual elements. |
| 6958 if (object->HasFixedTypedArrayElements()) { |
| 6959 if (attrs == FROZEN && |
| 6960 JSArrayBufferView::cast(*object)->byte_length()->Number() > 0) { |
| 6961 isolate->Throw(*isolate->factory()->NewTypeError( |
| 6962 MessageTemplate::kCannotFreezeArrayBufferView)); |
| 6963 return Nothing<bool>(); |
| 6964 } |
| 6965 return Just(true); |
| 6966 } |
| 6967 |
6963 DCHECK(object->map()->has_dictionary_elements()); | 6968 DCHECK(object->map()->has_dictionary_elements()); |
6964 if (!new_element_dictionary.is_null()) { | 6969 if (!new_element_dictionary.is_null()) { |
6965 object->set_elements(*new_element_dictionary); | 6970 object->set_elements(*new_element_dictionary); |
6966 } | 6971 } |
6967 | 6972 |
6968 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { | 6973 if (object->elements() != isolate->heap()->empty_slow_element_dictionary()) { |
6969 SeededNumberDictionary* dictionary = object->element_dictionary(); | 6974 SeededNumberDictionary* dictionary = object->element_dictionary(); |
6970 // Make sure we never go back to the fast case | 6975 // Make sure we never go back to the fast case |
6971 object->RequireSlowElements(dictionary); | 6976 object->RequireSlowElements(dictionary); |
6972 if (attrs != NONE) { | 6977 if (attrs != NONE) { |
(...skipping 1540 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8513 Isolate* isolate = map->GetIsolate(); | 8518 Isolate* isolate = map->GetIsolate(); |
8514 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( | 8519 Handle<DescriptorArray> new_desc = DescriptorArray::CopyUpToAddAttributes( |
8515 handle(map->instance_descriptors(), isolate), num_descriptors, | 8520 handle(map->instance_descriptors(), isolate), num_descriptors, |
8516 attrs_to_add); | 8521 attrs_to_add); |
8517 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(), | 8522 Handle<LayoutDescriptor> new_layout_descriptor(map->GetLayoutDescriptor(), |
8518 isolate); | 8523 isolate); |
8519 Handle<Map> new_map = CopyReplaceDescriptors( | 8524 Handle<Map> new_map = CopyReplaceDescriptors( |
8520 map, new_desc, new_layout_descriptor, INSERT_TRANSITION, | 8525 map, new_desc, new_layout_descriptor, INSERT_TRANSITION, |
8521 transition_marker, reason, SPECIAL_TRANSITION); | 8526 transition_marker, reason, SPECIAL_TRANSITION); |
8522 new_map->set_is_extensible(false); | 8527 new_map->set_is_extensible(false); |
8523 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 8528 if (!IsFixedTypedArrayElementsKind(map->elements_kind())) { |
| 8529 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 8530 } |
8524 return new_map; | 8531 return new_map; |
8525 } | 8532 } |
8526 | 8533 |
8527 | 8534 |
8528 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) { | 8535 Handle<Map> Map::FixProxy(Handle<Map> map, InstanceType type, int size) { |
8529 DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE); | 8536 DCHECK(type == JS_OBJECT_TYPE || type == JS_FUNCTION_TYPE); |
8530 DCHECK(map->IsJSProxyMap()); | 8537 DCHECK(map->IsJSProxyMap()); |
8531 | 8538 |
8532 Isolate* isolate = map->GetIsolate(); | 8539 Isolate* isolate = map->GetIsolate(); |
8533 | 8540 |
(...skipping 9313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
17847 if (cell->value() != *new_value) { | 17854 if (cell->value() != *new_value) { |
17848 cell->set_value(*new_value); | 17855 cell->set_value(*new_value); |
17849 Isolate* isolate = cell->GetIsolate(); | 17856 Isolate* isolate = cell->GetIsolate(); |
17850 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 17857 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
17851 isolate, DependentCode::kPropertyCellChangedGroup); | 17858 isolate, DependentCode::kPropertyCellChangedGroup); |
17852 } | 17859 } |
17853 } | 17860 } |
17854 | 17861 |
17855 } // namespace internal | 17862 } // namespace internal |
17856 } // namespace v8 | 17863 } // namespace v8 |
OLD | NEW |