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 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 // TODO(dcarney): CallOptimization duplicates this logic, merge. | 1014 // TODO(dcarney): CallOptimization duplicates this logic, merge. |
1015 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate, | 1015 Object* FunctionTemplateInfo::GetCompatibleReceiver(Isolate* isolate, |
1016 Object* receiver) { | 1016 Object* receiver) { |
1017 // API calls are only supported with JSObject receivers. | 1017 // API calls are only supported with JSObject receivers. |
1018 if (!receiver->IsJSObject()) return isolate->heap()->null_value(); | 1018 if (!receiver->IsJSObject()) return isolate->heap()->null_value(); |
1019 Object* recv_type = this->signature(); | 1019 Object* recv_type = this->signature(); |
1020 // No signature, return holder. | 1020 // No signature, return holder. |
1021 if (recv_type->IsUndefined()) return receiver; | 1021 if (recv_type->IsUndefined()) return receiver; |
1022 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); | 1022 FunctionTemplateInfo* signature = FunctionTemplateInfo::cast(recv_type); |
1023 // Check the receiver. | 1023 // Check the receiver. |
1024 for (PrototypeIterator iter(isolate, receiver, | 1024 for (PrototypeIterator iter(isolate, JSObject::cast(receiver), |
1025 PrototypeIterator::START_AT_RECEIVER); | 1025 PrototypeIterator::START_AT_RECEIVER, |
1026 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { | 1026 PrototypeIterator::END_AT_NON_HIDDEN); |
| 1027 !iter.IsAtEnd(); iter.Advance()) { |
1027 if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent(); | 1028 if (signature->IsTemplateFor(iter.GetCurrent())) return iter.GetCurrent(); |
1028 } | 1029 } |
1029 return isolate->heap()->null_value(); | 1030 return isolate->heap()->null_value(); |
1030 } | 1031 } |
1031 | 1032 |
1032 | 1033 |
1033 // static | 1034 // static |
1034 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, | 1035 MaybeHandle<JSObject> JSObject::New(Handle<JSFunction> constructor, |
1035 Handle<JSReceiver> new_target, | 1036 Handle<JSReceiver> new_target, |
1036 Handle<AllocationSite> site) { | 1037 Handle<AllocationSite> site) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 } | 1092 } |
1092 Handle<JSReceiver> target(proxy->target(), isolate); | 1093 Handle<JSReceiver> target(proxy->target(), isolate); |
1093 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); | 1094 Handle<JSReceiver> handler(JSReceiver::cast(proxy->handler()), isolate); |
1094 | 1095 |
1095 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). | 1096 // 5. Let trap be ? GetMethod(handler, "getPrototypeOf"). |
1096 Handle<Object> trap; | 1097 Handle<Object> trap; |
1097 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name), | 1098 ASSIGN_RETURN_ON_EXCEPTION(isolate, trap, GetMethod(handler, trap_name), |
1098 Object); | 1099 Object); |
1099 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). | 1100 // 6. If trap is undefined, then return target.[[GetPrototypeOf]](). |
1100 if (trap->IsUndefined()) { | 1101 if (trap->IsUndefined()) { |
1101 return Object::GetPrototype(isolate, target); | 1102 return JSReceiver::GetPrototype(isolate, target); |
1102 } | 1103 } |
1103 // 7. Let handlerProto be ? Call(trap, handler, «target»). | 1104 // 7. Let handlerProto be ? Call(trap, handler, «target»). |
1104 Handle<Object> argv[] = {target}; | 1105 Handle<Object> argv[] = {target}; |
1105 Handle<Object> handler_proto; | 1106 Handle<Object> handler_proto; |
1106 ASSIGN_RETURN_ON_EXCEPTION( | 1107 ASSIGN_RETURN_ON_EXCEPTION( |
1107 isolate, handler_proto, | 1108 isolate, handler_proto, |
1108 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); | 1109 Execution::Call(isolate, trap, handler, arraysize(argv), argv), Object); |
1109 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. | 1110 // 8. If Type(handlerProto) is neither Object nor Null, throw a TypeError. |
1110 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) { | 1111 if (!(handler_proto->IsJSReceiver() || handler_proto->IsNull())) { |
1111 THROW_NEW_ERROR(isolate, | 1112 THROW_NEW_ERROR(isolate, |
1112 NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid), | 1113 NewTypeError(MessageTemplate::kProxyGetPrototypeOfInvalid), |
1113 Object); | 1114 Object); |
1114 } | 1115 } |
1115 // 9. Let extensibleTarget be ? IsExtensible(target). | 1116 // 9. Let extensibleTarget be ? IsExtensible(target). |
1116 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); | 1117 Maybe<bool> is_extensible = JSReceiver::IsExtensible(target); |
1117 MAYBE_RETURN_NULL(is_extensible); | 1118 MAYBE_RETURN_NULL(is_extensible); |
1118 // 10. If extensibleTarget is true, return handlerProto. | 1119 // 10. If extensibleTarget is true, return handlerProto. |
1119 if (is_extensible.FromJust()) return handler_proto; | 1120 if (is_extensible.FromJust()) return handler_proto; |
1120 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | 1121 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). |
1121 Handle<Object> target_proto; | 1122 Handle<Object> target_proto; |
1122 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto, | 1123 ASSIGN_RETURN_ON_EXCEPTION(isolate, target_proto, |
1123 Object::GetPrototype(isolate, target), Object); | 1124 JSReceiver::GetPrototype(isolate, target), Object); |
1124 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. | 1125 // 12. If SameValue(handlerProto, targetProto) is false, throw a TypeError. |
1125 if (!handler_proto->SameValue(*target_proto)) { | 1126 if (!handler_proto->SameValue(*target_proto)) { |
1126 THROW_NEW_ERROR( | 1127 THROW_NEW_ERROR( |
1127 isolate, | 1128 isolate, |
1128 NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible), | 1129 NewTypeError(MessageTemplate::kProxyGetPrototypeOfNonExtensible), |
1129 Object); | 1130 Object); |
1130 } | 1131 } |
1131 // 13. Return handlerProto. | 1132 // 13. Return handlerProto. |
1132 return handler_proto; | 1133 return handler_proto; |
1133 } | 1134 } |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1429 } else { | 1430 } else { |
1430 PropertyDetails original_details = property_dictionary->DetailsAt(entry); | 1431 PropertyDetails original_details = property_dictionary->DetailsAt(entry); |
1431 int enumeration_index = original_details.dictionary_index(); | 1432 int enumeration_index = original_details.dictionary_index(); |
1432 DCHECK(enumeration_index > 0); | 1433 DCHECK(enumeration_index > 0); |
1433 details = details.set_index(enumeration_index); | 1434 details = details.set_index(enumeration_index); |
1434 property_dictionary->SetEntry(entry, name, value, details); | 1435 property_dictionary->SetEntry(entry, name, value, details); |
1435 } | 1436 } |
1436 } | 1437 } |
1437 } | 1438 } |
1438 | 1439 |
1439 | 1440 Maybe<bool> JSReceiver::HasInPrototypeChain(Isolate* isolate, |
1440 Maybe<bool> Object::HasInPrototypeChain(Isolate* isolate, Handle<Object> object, | 1441 Handle<JSReceiver> object, |
1441 Handle<Object> proto) { | 1442 Handle<Object> proto) { |
1442 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER); | 1443 PrototypeIterator iter(isolate, object, PrototypeIterator::START_AT_RECEIVER); |
1443 while (true) { | 1444 while (true) { |
1444 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); | 1445 if (!iter.AdvanceFollowingProxies()) return Nothing<bool>(); |
1445 if (iter.IsAtEnd()) return Just(false); | 1446 if (iter.IsAtEnd()) return Just(false); |
1446 if (iter.IsAtEnd(proto)) return Just(true); | 1447 if (PrototypeIterator::GetCurrent(iter).is_identical_to(proto)) { |
| 1448 return Just(true); |
| 1449 } |
1447 } | 1450 } |
1448 } | 1451 } |
1449 | 1452 |
1450 | 1453 |
1451 Map* Object::GetRootMap(Isolate* isolate) { | 1454 Map* Object::GetRootMap(Isolate* isolate) { |
1452 DisallowHeapAllocation no_alloc; | 1455 DisallowHeapAllocation no_alloc; |
1453 if (IsSmi()) { | 1456 if (IsSmi()) { |
1454 Context* native_context = isolate->context()->native_context(); | 1457 Context* native_context = isolate->context()->native_context(); |
1455 return native_context->number_function()->initial_map(); | 1458 return native_context->number_function()->initial_map(); |
1456 } | 1459 } |
(...skipping 7278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8735 static Maybe<bool> GetKeys_Internal(Isolate* isolate, | 8738 static Maybe<bool> GetKeys_Internal(Isolate* isolate, |
8736 Handle<JSReceiver> receiver, | 8739 Handle<JSReceiver> receiver, |
8737 Handle<JSReceiver> object, | 8740 Handle<JSReceiver> object, |
8738 KeyCollectionType type, | 8741 KeyCollectionType type, |
8739 PropertyFilter filter, | 8742 PropertyFilter filter, |
8740 KeyAccumulator* accumulator) { | 8743 KeyAccumulator* accumulator) { |
8741 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 8744 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
8742 ? PrototypeIterator::END_AT_NON_HIDDEN | 8745 ? PrototypeIterator::END_AT_NON_HIDDEN |
8743 : PrototypeIterator::END_AT_NULL; | 8746 : PrototypeIterator::END_AT_NULL; |
8744 for (PrototypeIterator iter(isolate, object, | 8747 for (PrototypeIterator iter(isolate, object, |
8745 PrototypeIterator::START_AT_RECEIVER); | 8748 PrototypeIterator::START_AT_RECEIVER, end); |
8746 !iter.IsAtEnd(end); iter.Advance()) { | 8749 !iter.IsAtEnd(); iter.Advance()) { |
8747 Handle<JSReceiver> current = | 8750 Handle<JSReceiver> current = |
8748 PrototypeIterator::GetCurrent<JSReceiver>(iter); | 8751 PrototypeIterator::GetCurrent<JSReceiver>(iter); |
8749 Maybe<bool> result = Just(false); // Dummy initialization. | 8752 Maybe<bool> result = Just(false); // Dummy initialization. |
8750 if (current->IsJSProxy()) { | 8753 if (current->IsJSProxy()) { |
8751 if (type == OWN_ONLY) { | 8754 if (type == OWN_ONLY) { |
8752 result = JSProxy::OwnPropertyKeys(isolate, receiver, | 8755 result = JSProxy::OwnPropertyKeys(isolate, receiver, |
8753 Handle<JSProxy>::cast(current), | 8756 Handle<JSProxy>::cast(current), |
8754 filter, accumulator); | 8757 filter, accumulator); |
8755 } else { | 8758 } else { |
8756 DCHECK(type == INCLUDE_PROTOS); | 8759 DCHECK(type == INCLUDE_PROTOS); |
(...skipping 3559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12316 namespace { | 12319 namespace { |
12317 | 12320 |
12318 bool CheckEquivalent(Map* first, Map* second) { | 12321 bool CheckEquivalent(Map* first, Map* second) { |
12319 return first->GetConstructor() == second->GetConstructor() && | 12322 return first->GetConstructor() == second->GetConstructor() && |
12320 first->prototype() == second->prototype() && | 12323 first->prototype() == second->prototype() && |
12321 first->instance_type() == second->instance_type() && | 12324 first->instance_type() == second->instance_type() && |
12322 first->bit_field() == second->bit_field() && | 12325 first->bit_field() == second->bit_field() && |
12323 first->is_extensible() == second->is_extensible() && | 12326 first->is_extensible() == second->is_extensible() && |
12324 first->is_strong() == second->is_strong() && | 12327 first->is_strong() == second->is_strong() && |
12325 first->new_target_is_base() == second->new_target_is_base() && | 12328 first->new_target_is_base() == second->new_target_is_base() && |
12326 first->is_hidden_prototype() == second->is_hidden_prototype(); | 12329 first->has_hidden_prototype() == second->has_hidden_prototype(); |
12327 } | 12330 } |
12328 | 12331 |
12329 } // namespace | 12332 } // namespace |
12330 | 12333 |
12331 | 12334 |
12332 bool Map::EquivalentToForTransition(Map* other) { | 12335 bool Map::EquivalentToForTransition(Map* other) { |
12333 if (!CheckEquivalent(this, other)) return false; | 12336 if (!CheckEquivalent(this, other)) return false; |
12334 if (instance_type() == JS_FUNCTION_TYPE) { | 12337 if (instance_type() == JS_FUNCTION_TYPE) { |
12335 // JSFunctions require more checks to ensure that sloppy function is | 12338 // JSFunctions require more checks to ensure that sloppy function is |
12336 // not equvalent to strict function. | 12339 // not equvalent to strict function. |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12879 Handle<Cell> cell = isolate->factory()->NewCell( | 12882 Handle<Cell> cell = isolate->factory()->NewCell( |
12880 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate)); | 12883 handle(Smi::FromInt(Map::kPrototypeChainValid), isolate)); |
12881 proto_info->set_validity_cell(*cell); | 12884 proto_info->set_validity_cell(*cell); |
12882 return cell; | 12885 return cell; |
12883 } | 12886 } |
12884 | 12887 |
12885 | 12888 |
12886 // static | 12889 // static |
12887 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, | 12890 void Map::SetPrototype(Handle<Map> map, Handle<Object> prototype, |
12888 PrototypeOptimizationMode proto_mode) { | 12891 PrototypeOptimizationMode proto_mode) { |
| 12892 bool is_hidden = false; |
12889 if (prototype->IsJSObject()) { | 12893 if (prototype->IsJSObject()) { |
12890 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); | 12894 Handle<JSObject> prototype_jsobj = Handle<JSObject>::cast(prototype); |
12891 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); | 12895 JSObject::OptimizeAsPrototype(prototype_jsobj, proto_mode); |
| 12896 |
| 12897 Object* maybe_constructor = prototype_jsobj->map()->GetConstructor(); |
| 12898 if (maybe_constructor->IsJSFunction()) { |
| 12899 JSFunction* constructor = JSFunction::cast(maybe_constructor); |
| 12900 Object* data = constructor->shared()->function_data(); |
| 12901 is_hidden = (data->IsFunctionTemplateInfo() && |
| 12902 FunctionTemplateInfo::cast(data)->hidden_prototype()) || |
| 12903 prototype->IsJSGlobalObject(); |
| 12904 } |
12892 } | 12905 } |
| 12906 map->set_has_hidden_prototype(is_hidden); |
| 12907 |
12893 WriteBarrierMode wb_mode = | 12908 WriteBarrierMode wb_mode = |
12894 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; | 12909 prototype->IsNull() ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER; |
12895 map->set_prototype(*prototype, wb_mode); | 12910 map->set_prototype(*prototype, wb_mode); |
12896 } | 12911 } |
12897 | 12912 |
12898 | 12913 |
12899 Handle<Object> CacheInitialJSArrayMaps( | 12914 Handle<Object> CacheInitialJSArrayMaps( |
12900 Handle<Context> native_context, Handle<Map> initial_map) { | 12915 Handle<Context> native_context, Handle<Map> initial_map) { |
12901 // Replace all of the cached initial array maps in the native context with | 12916 // Replace all of the cached initial array maps in the native context with |
12902 // the appropriate transitioned elements kind maps. | 12917 // the appropriate transitioned elements kind maps. |
(...skipping 2741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15644 // 10. If extensibleTarget is true, return booleanTrapResult. | 15659 // 10. If extensibleTarget is true, return booleanTrapResult. |
15645 if (is_extensible.FromJust()) { | 15660 if (is_extensible.FromJust()) { |
15646 if (bool_trap_result) return Just(true); | 15661 if (bool_trap_result) return Just(true); |
15647 RETURN_FAILURE( | 15662 RETURN_FAILURE( |
15648 isolate, should_throw, | 15663 isolate, should_throw, |
15649 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name)); | 15664 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name)); |
15650 } | 15665 } |
15651 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). | 15666 // 11. Let targetProto be ? target.[[GetPrototypeOf]](). |
15652 Handle<Object> target_proto; | 15667 Handle<Object> target_proto; |
15653 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto, | 15668 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, target_proto, |
15654 Object::GetPrototype(isolate, target), | 15669 JSReceiver::GetPrototype(isolate, target), |
15655 Nothing<bool>()); | 15670 Nothing<bool>()); |
15656 // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false, | 15671 // 12. If booleanTrapResult is true and SameValue(V, targetProto) is false, |
15657 // throw a TypeError exception. | 15672 // throw a TypeError exception. |
15658 if (bool_trap_result && !value->SameValue(*target_proto)) { | 15673 if (bool_trap_result && !value->SameValue(*target_proto)) { |
15659 isolate->Throw(*isolate->factory()->NewTypeError( | 15674 isolate->Throw(*isolate->factory()->NewTypeError( |
15660 MessageTemplate::kProxySetPrototypeOfNonExtensible)); | 15675 MessageTemplate::kProxySetPrototypeOfNonExtensible)); |
15661 return Nothing<bool>(); | 15676 return Nothing<bool>(); |
15662 } | 15677 } |
15663 // 13. Return booleanTrapResult. | 15678 // 13. Return booleanTrapResult. |
15664 if (bool_trap_result) return Just(true); | 15679 if (bool_trap_result) return Just(true); |
15665 RETURN_FAILURE( | 15680 RETURN_FAILURE( |
15666 isolate, should_throw, | 15681 isolate, should_throw, |
15667 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name)); | 15682 NewTypeError(MessageTemplate::kProxyTrapReturnedFalsish, trap_name)); |
15668 } | 15683 } |
15669 | 15684 |
15670 | 15685 |
15671 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, | 15686 Maybe<bool> JSObject::SetPrototype(Handle<JSObject> object, |
15672 Handle<Object> value, bool from_javascript, | 15687 Handle<Object> value, bool from_javascript, |
15673 ShouldThrow should_throw) { | 15688 ShouldThrow should_throw) { |
15674 Isolate* isolate = object->GetIsolate(); | 15689 Isolate* isolate = object->GetIsolate(); |
15675 | 15690 |
15676 const bool observed = from_javascript && object->map()->is_observed(); | 15691 const bool observed = from_javascript && object->map()->is_observed(); |
15677 Handle<Object> old_value; | 15692 Handle<Object> old_value; |
15678 if (observed) { | 15693 if (observed) { |
15679 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value, | 15694 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, old_value, |
15680 Object::GetPrototype(isolate, object), | 15695 JSReceiver::GetPrototype(isolate, object), |
15681 Nothing<bool>()); | 15696 Nothing<bool>()); |
15682 } | 15697 } |
15683 | 15698 |
15684 Maybe<bool> result = | 15699 Maybe<bool> result = |
15685 SetPrototypeUnobserved(object, value, from_javascript, should_throw); | 15700 SetPrototypeUnobserved(object, value, from_javascript, should_throw); |
15686 MAYBE_RETURN(result, Nothing<bool>()); | 15701 MAYBE_RETURN(result, Nothing<bool>()); |
15687 | 15702 |
15688 if (result.FromJust() && observed) { | 15703 if (result.FromJust() && observed) { |
15689 Handle<Object> new_value; | 15704 Handle<Object> new_value; |
15690 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value, | 15705 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, new_value, |
15691 Object::GetPrototype(isolate, object), | 15706 JSReceiver::GetPrototype(isolate, object), |
15692 Nothing<bool>()); | 15707 Nothing<bool>()); |
15693 if (!new_value->SameValue(*old_value)) { | 15708 if (!new_value->SameValue(*old_value)) { |
15694 RETURN_ON_EXCEPTION_VALUE( | 15709 RETURN_ON_EXCEPTION_VALUE( |
15695 isolate, JSObject::EnqueueChangeRecord( | 15710 isolate, JSObject::EnqueueChangeRecord( |
15696 object, "setPrototype", | 15711 object, "setPrototype", |
15697 isolate->factory()->proto_string(), old_value), | 15712 isolate->factory()->proto_string(), old_value), |
15698 Nothing<bool>()); | 15713 Nothing<bool>()); |
15699 } | 15714 } |
15700 } | 15715 } |
15701 | 15716 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15737 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true); | 15752 if (!value->IsJSReceiver() && !value->IsNull()) return Just(true); |
15738 | 15753 |
15739 bool dictionary_elements_in_chain = | 15754 bool dictionary_elements_in_chain = |
15740 object->map()->DictionaryElementsInPrototypeChainOnly(); | 15755 object->map()->DictionaryElementsInPrototypeChainOnly(); |
15741 | 15756 |
15742 bool all_extensible = object->map()->is_extensible(); | 15757 bool all_extensible = object->map()->is_extensible(); |
15743 Handle<JSObject> real_receiver = object; | 15758 Handle<JSObject> real_receiver = object; |
15744 if (from_javascript) { | 15759 if (from_javascript) { |
15745 // Find the first object in the chain whose prototype object is not | 15760 // Find the first object in the chain whose prototype object is not |
15746 // hidden. | 15761 // hidden. |
15747 PrototypeIterator iter(isolate, real_receiver); | 15762 PrototypeIterator iter(isolate, real_receiver, |
15748 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 15763 PrototypeIterator::START_AT_PROTOTYPE, |
| 15764 PrototypeIterator::END_AT_NON_HIDDEN); |
| 15765 while (!iter.IsAtEnd()) { |
15749 // Casting to JSObject is fine because hidden prototypes are never | 15766 // Casting to JSObject is fine because hidden prototypes are never |
15750 // JSProxies. | 15767 // JSProxies. |
15751 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); | 15768 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); |
15752 iter.Advance(); | 15769 iter.Advance(); |
15753 all_extensible = all_extensible && real_receiver->map()->is_extensible(); | 15770 all_extensible = all_extensible && real_receiver->map()->is_extensible(); |
15754 } | 15771 } |
15755 } | 15772 } |
15756 Handle<Map> map(real_receiver->map()); | 15773 Handle<Map> map(real_receiver->map()); |
15757 | 15774 |
15758 // Nothing to do if prototype is already set. | 15775 // Nothing to do if prototype is already set. |
15759 if (map->prototype() == *value) return Just(true); | 15776 if (map->prototype() == *value) return Just(true); |
15760 | 15777 |
15761 // From 8.6.2 Object Internal Methods | 15778 // From 8.6.2 Object Internal Methods |
15762 // ... | 15779 // ... |
15763 // In addition, if [[Extensible]] is false the value of the [[Class]] and | 15780 // In addition, if [[Extensible]] is false the value of the [[Class]] and |
15764 // [[Prototype]] internal properties of the object may not be modified. | 15781 // [[Prototype]] internal properties of the object may not be modified. |
15765 // ... | 15782 // ... |
15766 // Implementation specific extensions that modify [[Class]], [[Prototype]] | 15783 // Implementation specific extensions that modify [[Class]], [[Prototype]] |
15767 // or [[Extensible]] must not violate the invariants defined in the preceding | 15784 // or [[Extensible]] must not violate the invariants defined in the preceding |
15768 // paragraph. | 15785 // paragraph. |
15769 if (!all_extensible) { | 15786 if (!all_extensible) { |
15770 RETURN_FAILURE(isolate, should_throw, | 15787 RETURN_FAILURE(isolate, should_throw, |
15771 NewTypeError(MessageTemplate::kNonExtensibleProto, object)); | 15788 NewTypeError(MessageTemplate::kNonExtensibleProto, object)); |
15772 } | 15789 } |
15773 | 15790 |
15774 // Before we can set the prototype we need to be sure prototype cycles are | 15791 // Before we can set the prototype we need to be sure prototype cycles are |
15775 // prevented. It is sufficient to validate that the receiver is not in the | 15792 // prevented. It is sufficient to validate that the receiver is not in the |
15776 // new prototype chain. | 15793 // new prototype chain. |
15777 for (PrototypeIterator iter(isolate, *value, | 15794 if (value->IsJSReceiver()) { |
15778 PrototypeIterator::START_AT_RECEIVER); | 15795 for (PrototypeIterator iter(isolate, JSReceiver::cast(*value), |
15779 !iter.IsAtEnd(); iter.Advance()) { | 15796 PrototypeIterator::START_AT_RECEIVER); |
15780 if (iter.GetCurrent<JSReceiver>() == *object) { | 15797 !iter.IsAtEnd(); iter.Advance()) { |
15781 // Cycle detected. | 15798 if (iter.GetCurrent<JSReceiver>() == *object) { |
15782 RETURN_FAILURE(isolate, should_throw, | 15799 // Cycle detected. |
15783 NewTypeError(MessageTemplate::kCyclicProto)); | 15800 RETURN_FAILURE(isolate, should_throw, |
| 15801 NewTypeError(MessageTemplate::kCyclicProto)); |
| 15802 } |
15784 } | 15803 } |
15785 } | 15804 } |
15786 | 15805 |
15787 // Set the new prototype of the object. | 15806 // Set the new prototype of the object. |
15788 | 15807 |
15789 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); | 15808 isolate->UpdateArrayProtectorOnSetPrototype(real_receiver); |
15790 | 15809 |
15791 PrototypeOptimizationMode mode = | 15810 PrototypeOptimizationMode mode = |
15792 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; | 15811 from_javascript ? REGULAR_PROTOTYPE : FAST_PROTOTYPE; |
15793 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); | 15812 Handle<Map> new_map = Map::TransitionToPrototype(map, value, mode); |
(...skipping 4052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19846 if (cell->value() != *new_value) { | 19865 if (cell->value() != *new_value) { |
19847 cell->set_value(*new_value); | 19866 cell->set_value(*new_value); |
19848 Isolate* isolate = cell->GetIsolate(); | 19867 Isolate* isolate = cell->GetIsolate(); |
19849 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19868 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19850 isolate, DependentCode::kPropertyCellChangedGroup); | 19869 isolate, DependentCode::kPropertyCellChangedGroup); |
19851 } | 19870 } |
19852 } | 19871 } |
19853 | 19872 |
19854 } // namespace internal | 19873 } // namespace internal |
19855 } // namespace v8 | 19874 } // namespace v8 |
OLD | NEW |