Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: src/objects.cc

Issue 1419823008: Fix Object.preventExtensions, .seal, .freeze on typed arrays (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/messages.h ('k') | test/mjsunit/compiler/regress-447567.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/messages.h ('k') | test/mjsunit/compiler/regress-447567.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698