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

Side by Side Diff: src/objects.cc

Issue 1417243002: [es6] Partially implement Reflect.setPrototypeOf. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 2 months 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/objects.h ('k') | src/runtime/runtime-array.cc » ('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 6704 matching lines...) Expand 10 before | Expand all | Expand 10 after
6715 6715
6716 return context->extension_object()->ReferencesObject(obj); 6716 return context->extension_object()->ReferencesObject(obj);
6717 } 6717 }
6718 } 6718 }
6719 6719
6720 // No references to object. 6720 // No references to object.
6721 return false; 6721 return false;
6722 } 6722 }
6723 6723
6724 6724
6725 #define RETURN_FAILURE(isolate, should_throw, call) \
6726 do { \
6727 if ((should_throw) == DONT_THROW) { \
6728 return Just(false); \
6729 } else { \
6730 isolate->Throw(*isolate->factory()->call); \
6731 return Nothing<bool>(); \
6732 } \
6733 } while (false)
6734
6735
6736 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object, 6725 Maybe<bool> JSReceiver::PreventExtensions(Handle<JSReceiver> object,
6737 ShouldThrow should_throw) { 6726 ShouldThrow should_throw) {
6738 if (!object->IsJSObject()) return Just(false); 6727 if (!object->IsJSObject()) return Just(false);
6739 // TODO(neis): Deal with proxies. 6728 // TODO(neis): Deal with proxies.
6740 return JSObject::PreventExtensions(Handle<JSObject>::cast(object), 6729 return JSObject::PreventExtensions(Handle<JSObject>::cast(object),
6741 should_throw); 6730 should_throw);
6742 } 6731 }
6743 6732
6744 6733
6745 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object, 6734 Maybe<bool> JSObject::PreventExtensions(Handle<JSObject> object,
(...skipping 7125 matching lines...) Expand 10 before | Expand all | Expand 10 after
13871 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype); 13860 Handle<Map> new_map = TransitionArray::GetPrototypeTransition(map, prototype);
13872 if (new_map.is_null()) { 13861 if (new_map.is_null()) {
13873 new_map = Copy(map, "TransitionToPrototype"); 13862 new_map = Copy(map, "TransitionToPrototype");
13874 TransitionArray::PutPrototypeTransition(map, prototype, new_map); 13863 TransitionArray::PutPrototypeTransition(map, prototype, new_map);
13875 Map::SetPrototype(new_map, prototype, mode); 13864 Map::SetPrototype(new_map, prototype, mode);
13876 } 13865 }
13877 return new_map; 13866 return new_map;
13878 } 13867 }
13879 13868
13880 13869
13881 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, 13870 Maybe<bool> JSReceiver::SetPrototype(Handle<JSReceiver> object,
13882 Handle<Object> value, 13871 Handle<Object> value, bool from_javascript,
13883 bool from_javascript) { 13872 ShouldThrow should_throw) {
13873 if (!object->IsJSObject()) return Just(false);
13874 // TODO(neis): Deal with proxies.
13875 return JSObject::SetPrototype(Handle<JSObject>::cast(object), value,
13876 from_javascript, should_throw);
13877 }
13878
13879
13880 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object,
13881 Handle<Object> value, bool from_javascript,
13882 ShouldThrow should_throw) {
13884 Isolate* isolate = object->GetIsolate(); 13883 Isolate* isolate = object->GetIsolate();
13885 13884
13886 const bool observed = from_javascript && object->map()->is_observed(); 13885 const bool observed = from_javascript && object->map()->is_observed();
13887 Handle<Object> old_value; 13886 Handle<Object> old_value;
13888 if (observed) { 13887 if (observed) {
13889 old_value = Object::GetPrototype(isolate, object); 13888 old_value = Object::GetPrototype(isolate, object);
13890 } 13889 }
13891 13890
13892 Handle<Object> result; 13891 Maybe<bool> result =
13893 ASSIGN_RETURN_ON_EXCEPTION( 13892 SetPrototypeUnobserved(object, value, from_javascript, should_throw);
13894 isolate, result, SetPrototypeUnobserved(object, value, from_javascript), 13893 MAYBE_RETURN(result, Nothing<bool>());
13895 Object);
13896 13894
13897 if (observed) { 13895 if (result.FromJust() && observed) {
13898 Handle<Object> new_value = Object::GetPrototype(isolate, object); 13896 Handle<Object> new_value = Object::GetPrototype(isolate, object);
13899 if (!new_value->SameValue(*old_value)) { 13897 if (!new_value->SameValue(*old_value)) {
13900 RETURN_ON_EXCEPTION(isolate, 13898 RETURN_ON_EXCEPTION_VALUE(
13901 JSObject::EnqueueChangeRecord( 13899 isolate, JSObject::EnqueueChangeRecord(
13902 object, "setPrototype", 13900 object, "setPrototype",
13903 isolate->factory()->proto_string(), old_value), 13901 isolate->factory()->proto_string(), old_value),
13904 Object); 13902 Nothing<bool>());
13905 } 13903 }
13906 } 13904 }
13907 13905
13908 return result; 13906 return result;
13909 } 13907 }
13910 13908
13911 13909
13912 MaybeHandle<Object> JSObject::SetPrototypeUnobserved(Handle<JSObject> object, 13910 Maybe<bool> JSObject::SetPrototypeUnobserved(Handle<JSObject> object,
13913 Handle<Object> value, 13911 Handle<Object> value,
13914 bool from_javascript) { 13912 bool from_javascript,
13913 ShouldThrow should_throw) {
13915 #ifdef DEBUG 13914 #ifdef DEBUG
13916 int size = object->Size(); 13915 int size = object->Size();
13917 #endif 13916 #endif
13918 13917
13919 Isolate* isolate = object->GetIsolate(); 13918 Isolate* isolate = object->GetIsolate();
13920 13919
13921 if (from_javascript) { 13920 if (from_javascript) {
13922 if (object->IsAccessCheckNeeded() && 13921 if (object->IsAccessCheckNeeded() &&
13923 !isolate->MayAccess(handle(isolate->context()), object)) { 13922 !isolate->MayAccess(handle(isolate->context()), object)) {
13924 isolate->ReportFailedAccessCheck(object); 13923 isolate->ReportFailedAccessCheck(object);
13925 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); 13924 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Nothing<bool>());
13926 return isolate->factory()->undefined_value(); 13925 UNREACHABLE();
13927 } 13926 }
13928 } else { 13927 } else {
13929 DCHECK(!object->IsAccessCheckNeeded()); 13928 DCHECK(!object->IsAccessCheckNeeded());
13930 } 13929 }
13931 13930
13932 // Strong objects may not have their prototype set via __proto__ or 13931 // Strong objects may not have their prototype set via __proto__ or
13933 // setPrototypeOf. 13932 // setPrototypeOf.
13934 if (from_javascript && object->map()->is_strong()) { 13933 if (from_javascript && object->map()->is_strong()) {
13935 THROW_NEW_ERROR(isolate, 13934 RETURN_FAILURE(isolate, should_throw,
13936 NewTypeError(MessageTemplate::kStrongSetProto, object), 13935 NewTypeError(MessageTemplate::kStrongSetProto, object));
13937 Object);
13938 } 13936 }
13939 Heap* heap = isolate->heap(); 13937 Heap* heap = isolate->heap();
13940 // Silently ignore the change if value is not a JSObject or null. 13938 // Silently ignore the change if value is not a JSObject or null.
13941 // SpiderMonkey behaves this way. 13939 // SpiderMonkey behaves this way.
13942 if (!value->IsJSReceiver() && !value->IsNull()) return value; 13940 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true);
13943 13941
13944 // From 8.6.2 Object Internal Methods 13942 // From 8.6.2 Object Internal Methods
13945 // ... 13943 // ...
13946 // In addition, if [[Extensible]] is false the value of the [[Class]] and 13944 // In addition, if [[Extensible]] is false the value of the [[Class]] and
13947 // [[Prototype]] internal properties of the object may not be modified. 13945 // [[Prototype]] internal properties of the object may not be modified.
13948 // ... 13946 // ...
13949 // Implementation specific extensions that modify [[Class]], [[Prototype]] 13947 // Implementation specific extensions that modify [[Class]], [[Prototype]]
13950 // or [[Extensible]] must not violate the invariants defined in the preceding 13948 // or [[Extensible]] must not violate the invariants defined in the preceding
13951 // paragraph. 13949 // paragraph.
13952 if (!object->map()->is_extensible()) { 13950 if (!object->map()->is_extensible()) {
13953 THROW_NEW_ERROR(isolate, 13951 RETURN_FAILURE(isolate, should_throw,
13954 NewTypeError(MessageTemplate::kNonExtensibleProto, object), 13952 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
13955 Object); 13953 // TODO(neis): Don't fail if new and old prototype happen to be the same.
13956 } 13954 }
13957 13955
13958 // Before we can set the prototype we need to be sure 13956 // Before we can set the prototype we need to be sure
13959 // prototype cycles are prevented. 13957 // prototype cycles are prevented.
13960 // It is sufficient to validate that the receiver is not in the new prototype 13958 // It is sufficient to validate that the receiver is not in the new prototype
13961 // chain. 13959 // chain.
13962 for (PrototypeIterator iter(isolate, *value, 13960 for (PrototypeIterator iter(isolate, *value,
13963 PrototypeIterator::START_AT_RECEIVER); 13961 PrototypeIterator::START_AT_RECEIVER);
13964 !iter.IsAtEnd(); iter.Advance()) { 13962 !iter.IsAtEnd(); iter.Advance()) {
13965 if (iter.GetCurrent<JSReceiver>() == *object) { 13963 if (iter.GetCurrent<JSReceiver>() == *object) {
13966 // Cycle detected. 13964 // Cycle detected.
13967 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto), 13965 RETURN_FAILURE(isolate, should_throw,
13968 Object); 13966 NewTypeError(MessageTemplate::kCyclicProto));
13969 } 13967 }
13970 } 13968 }
13971 13969
13972 bool dictionary_elements_in_chain = 13970 bool dictionary_elements_in_chain =
13973 object->map()->DictionaryElementsInPrototypeChainOnly(); 13971 object->map()->DictionaryElementsInPrototypeChainOnly();
13974 Handle<JSObject> real_receiver = object; 13972 Handle<JSObject> real_receiver = object;
13975 13973
13976 if (from_javascript) { 13974 if (from_javascript) {
13977 // Find the first object in the chain whose prototype object is not 13975 // Find the first object in the chain whose prototype object is not
13978 // hidden and set the new prototype on that object. 13976 // hidden and set the new prototype on that object.
13979 PrototypeIterator iter(isolate, real_receiver); 13977 PrototypeIterator iter(isolate, real_receiver);
13980 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 13978 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
13981 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); 13979 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
13982 iter.Advance(); 13980 iter.Advance();
13983 if (!real_receiver->map()->is_extensible()) { 13981 if (!real_receiver->map()->is_extensible()) {
13984 THROW_NEW_ERROR( 13982 RETURN_FAILURE(
13985 isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object), 13983 isolate, should_throw,
13986 Object); 13984 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
13987 } 13985 }
13988 } 13986 }
13989 } 13987 }
13990 13988
13991 // Set the new prototype of the object. 13989 // Set the new prototype of the object.
13992 Handle<Map> map(real_receiver->map()); 13990 Handle<Map> map(real_receiver->map());
13993 13991
13994 // Nothing to do if prototype is already set. 13992 // Nothing to do if prototype is already set.
13995 if (map->prototype() == *value) return value; 13993 if (map->prototype() == *value) return Just(true);
13996 13994
13997 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); 13995 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
13998 13996
13999 PrototypeOptimizationMode mode = 13997 PrototypeOptimizationMode mode =
14000 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 13998 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
14001 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); 13999 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
14002 DCHECK(new_map->prototype() == *value); 14000 DCHECK(new_map->prototype() == *value);
14003 JSObject::MigrateToMap(real_receiver, new_map); 14001 JSObject::MigrateToMap(real_receiver, new_map);
14004 14002
14005 if (from_javascript && !dictionary_elements_in_chain && 14003 if (from_javascript && !dictionary_elements_in_chain &&
14006 new_map->DictionaryElementsInPrototypeChainOnly()) { 14004 new_map->DictionaryElementsInPrototypeChainOnly()) {
14007 // If the prototype chain didn't previously have element callbacks, then 14005 // If the prototype chain didn't previously have element callbacks, then
14008 // KeyedStoreICs need to be cleared to ensure any that involve this 14006 // KeyedStoreICs need to be cleared to ensure any that involve this
14009 // map go generic. 14007 // map go generic.
14010 object->GetHeap()->ClearAllKeyedStoreICs(); 14008 object->GetHeap()->ClearAllKeyedStoreICs();
14011 } 14009 }
14012 14010
14013 heap->ClearInstanceofCache(); 14011 heap->ClearInstanceofCache();
14014 DCHECK(size == object->Size()); 14012 DCHECK(size == object->Size());
14015 return value; 14013 return Just(true);
14016 } 14014 }
14017 14015
14018 14016
14019 void JSObject::EnsureCanContainElements(Handle<JSObject> object, 14017 void JSObject::EnsureCanContainElements(Handle<JSObject> object,
14020 Arguments* args, 14018 Arguments* args,
14021 uint32_t first_arg, 14019 uint32_t first_arg,
14022 uint32_t arg_count, 14020 uint32_t arg_count,
14023 EnsureElementsMode mode) { 14021 EnsureElementsMode mode) {
14024 // Elements in |Arguments| are ordered backwards (because they're on the 14022 // Elements in |Arguments| are ordered backwards (because they're on the
14025 // stack), but the method that's called here iterates over them in forward 14023 // stack), but the method that's called here iterates over them in forward
(...skipping 3786 matching lines...) Expand 10 before | Expand all | Expand 10 after
17812 if (cell->value() != *new_value) { 17810 if (cell->value() != *new_value) {
17813 cell->set_value(*new_value); 17811 cell->set_value(*new_value);
17814 Isolate* isolate = cell->GetIsolate(); 17812 Isolate* isolate = cell->GetIsolate();
17815 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17813 cell->dependent_code()->DeoptimizeDependentCodeGroup(
17816 isolate, DependentCode::kPropertyCellChangedGroup); 17814 isolate, DependentCode::kPropertyCellChangedGroup);
17817 } 17815 }
17818 } 17816 }
17819 17817
17820 } // namespace internal 17818 } // namespace internal
17821 } // namespace v8 17819 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/runtime/runtime-array.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698