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

Side by Side Diff: src/objects.cc

Issue 1423603002: Fix corner-case behavior of JSObject::SetPrototype. (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 | « no previous file | test/mjsunit/harmony/reflect-set-prototype-of.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 13921 matching lines...) Expand 10 before | Expand all | Expand 10 after
13932 // setPrototypeOf. 13932 // setPrototypeOf.
13933 if (from_javascript && object->map()->is_strong()) { 13933 if (from_javascript && object->map()->is_strong()) {
13934 RETURN_FAILURE(isolate, should_throw, 13934 RETURN_FAILURE(isolate, should_throw,
13935 NewTypeError(MessageTemplate::kStrongSetProto, object)); 13935 NewTypeError(MessageTemplate::kStrongSetProto, object));
13936 } 13936 }
13937 Heap* heap = isolate->heap(); 13937 Heap* heap = isolate->heap();
13938 // 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.
13939 // SpiderMonkey behaves this way. 13939 // SpiderMonkey behaves this way.
13940 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true); 13940 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true);
13941 13941
13942 bool dictionary_elements_in_chain =
13943 object->map()->DictionaryElementsInPrototypeChainOnly();
13944
13945 bool all_extensible = object->map()->is_extensible();
13946 Handle<JSObject> real_receiver = object;
13947 if (from_javascript) {
13948 // Find the first object in the chain whose prototype object is not
13949 // hidden.
13950 PrototypeIterator iter(isolate, real_receiver);
13951 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
13952 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
Toon Verwaest 2015/10/22 13:21:07 This code is a bit overkill, since this is only re
13953 iter.Advance();
13954 all_extensible = all_extensible && real_receiver->map()->is_extensible();
13955 }
13956 }
13957 Handle<Map> map(real_receiver->map());
Toon Verwaest 2015/10/22 13:21:07 Slight overkill to allocate a handle to just deref
neis 2015/10/23 14:26:54 It's used again further down.
13958
13959 // Nothing to do if prototype is already set.
13960 if (map->prototype() == *value) return Just(true);
13961
13942 // From 8.6.2 Object Internal Methods 13962 // From 8.6.2 Object Internal Methods
13943 // ... 13963 // ...
13944 // In addition, if [[Extensible]] is false the value of the [[Class]] and 13964 // In addition, if [[Extensible]] is false the value of the [[Class]] and
13945 // [[Prototype]] internal properties of the object may not be modified. 13965 // [[Prototype]] internal properties of the object may not be modified.
13946 // ... 13966 // ...
13947 // Implementation specific extensions that modify [[Class]], [[Prototype]] 13967 // Implementation specific extensions that modify [[Class]], [[Prototype]]
13948 // or [[Extensible]] must not violate the invariants defined in the preceding 13968 // or [[Extensible]] must not violate the invariants defined in the preceding
13949 // paragraph. 13969 // paragraph.
13950 if (!object->map()->is_extensible()) { 13970 if (!all_extensible) {
13951 RETURN_FAILURE(isolate, should_throw, 13971 RETURN_FAILURE(isolate, should_throw,
13952 NewTypeError(MessageTemplate::kNonExtensibleProto, object)); 13972 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
13953 // TODO(neis): Don't fail if new and old prototype happen to be the same.
13954 } 13973 }
13955 13974
13956 // Before we can set the prototype we need to be sure 13975 // Before we can set the prototype we need to be sure prototype cycles are
13957 // prototype cycles are prevented. 13976 // prevented. It is sufficient to validate that the receiver is not in the
13958 // It is sufficient to validate that the receiver is not in the new prototype 13977 // new prototype chain.
13959 // chain.
13960 for (PrototypeIterator iter(isolate, *value, 13978 for (PrototypeIterator iter(isolate, *value,
13961 PrototypeIterator::START_AT_RECEIVER); 13979 PrototypeIterator::START_AT_RECEIVER);
13962 !iter.IsAtEnd(); iter.Advance()) { 13980 !iter.IsAtEnd(); iter.Advance()) {
13963 if (iter.GetCurrent<JSReceiver>() == *object) { 13981 if (iter.GetCurrent<JSReceiver>() == *object) {
13964 // Cycle detected. 13982 // Cycle detected.
13965 RETURN_FAILURE(isolate, should_throw, 13983 RETURN_FAILURE(isolate, should_throw,
13966 NewTypeError(MessageTemplate::kCyclicProto)); 13984 NewTypeError(MessageTemplate::kCyclicProto));
13967 } 13985 }
13968 } 13986 }
13969 13987
13970 bool dictionary_elements_in_chain =
13971 object->map()->DictionaryElementsInPrototypeChainOnly();
13972 Handle<JSObject> real_receiver = object;
13973
13974 if (from_javascript) {
13975 // Find the first object in the chain whose prototype object is not
13976 // hidden and set the new prototype on that object.
13977 PrototypeIterator iter(isolate, real_receiver);
13978 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
13979 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter);
13980 iter.Advance();
13981 if (!real_receiver->map()->is_extensible()) {
13982 RETURN_FAILURE(
13983 isolate, should_throw,
13984 NewTypeError(MessageTemplate::kNonExtensibleProto, object));
13985 }
13986 }
13987 }
13988
13989 // Set the new prototype of the object. 13988 // Set the new prototype of the object.
13990 Handle<Map> map(real_receiver->map());
13991
13992 // Nothing to do if prototype is already set.
13993 if (map->prototype() == *value) return Just(true);
13994 13989
13995 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); 13990 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver);
13996 13991
13997 PrototypeOptimizationMode mode = 13992 PrototypeOptimizationMode mode =
13998 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; 13993 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE;
13999 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); 13994 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode);
14000 DCHECK(new_map->prototype() == *value); 13995 DCHECK(new_map->prototype() == *value);
14001 JSObject::MigrateToMap(real_receiver, new_map); 13996 JSObject::MigrateToMap(real_receiver, new_map);
14002 13997
14003 if (from_javascript && !dictionary_elements_in_chain && 13998 if (from_javascript && !dictionary_elements_in_chain &&
(...skipping 3806 matching lines...) Expand 10 before | Expand all | Expand 10 after
17810 if (cell->value() != *new_value) { 17805 if (cell->value() != *new_value) {
17811 cell->set_value(*new_value); 17806 cell->set_value(*new_value);
17812 Isolate* isolate = cell->GetIsolate(); 17807 Isolate* isolate = cell->GetIsolate();
17813 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17808 cell->dependent_code()->DeoptimizeDependentCodeGroup(
17814 isolate, DependentCode::kPropertyCellChangedGroup); 17809 isolate, DependentCode::kPropertyCellChangedGroup);
17815 } 17810 }
17816 } 17811 }
17817 17812
17818 } // namespace internal 17813 } // namespace internal
17819 } // namespace v8 17814 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/harmony/reflect-set-prototype-of.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698