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 <iomanip> | 7 #include <iomanip> |
8 #include <sstream> | 8 #include <sstream> |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 5058 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5069 | 5069 |
5070 Object* JSObject::GetHiddenProperty(Handle<Name> key) { | 5070 Object* JSObject::GetHiddenProperty(Handle<Name> key) { |
5071 DisallowHeapAllocation no_gc; | 5071 DisallowHeapAllocation no_gc; |
5072 DCHECK(key->IsUniqueName()); | 5072 DCHECK(key->IsUniqueName()); |
5073 if (IsJSGlobalProxy()) { | 5073 if (IsJSGlobalProxy()) { |
5074 // For a proxy, use the prototype as target object. | 5074 // For a proxy, use the prototype as target object. |
5075 PrototypeIterator iter(GetIsolate(), this); | 5075 PrototypeIterator iter(GetIsolate(), this); |
5076 // If the proxy is detached, return undefined. | 5076 // If the proxy is detached, return undefined. |
5077 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); | 5077 if (iter.IsAtEnd()) return GetHeap()->the_hole_value(); |
5078 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | 5078 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
5079 return JSObject::cast(iter.GetCurrent())->GetHiddenProperty(key); | 5079 return iter.GetCurrent<JSObject>()->GetHiddenProperty(key); |
5080 } | 5080 } |
5081 DCHECK(!IsJSGlobalProxy()); | 5081 DCHECK(!IsJSGlobalProxy()); |
5082 Object* inline_value = GetHiddenPropertiesHashTable(); | 5082 Object* inline_value = GetHiddenPropertiesHashTable(); |
5083 | 5083 |
5084 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); | 5084 if (inline_value->IsUndefined()) return GetHeap()->the_hole_value(); |
5085 | 5085 |
5086 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); | 5086 ObjectHashTable* hashtable = ObjectHashTable::cast(inline_value); |
5087 Object* entry = hashtable->Lookup(key); | 5087 Object* entry = hashtable->Lookup(key); |
5088 return entry; | 5088 return entry; |
5089 } | 5089 } |
5090 | 5090 |
5091 | 5091 |
5092 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, | 5092 Handle<Object> JSObject::SetHiddenProperty(Handle<JSObject> object, |
5093 Handle<Name> key, | 5093 Handle<Name> key, |
5094 Handle<Object> value) { | 5094 Handle<Object> value) { |
5095 Isolate* isolate = object->GetIsolate(); | 5095 Isolate* isolate = object->GetIsolate(); |
5096 | 5096 |
5097 DCHECK(key->IsUniqueName()); | 5097 DCHECK(key->IsUniqueName()); |
5098 if (object->IsJSGlobalProxy()) { | 5098 if (object->IsJSGlobalProxy()) { |
5099 // For a proxy, use the prototype as target object. | 5099 // For a proxy, use the prototype as target object. |
5100 PrototypeIterator iter(isolate, object); | 5100 PrototypeIterator iter(isolate, object); |
5101 // If the proxy is detached, return undefined. | 5101 // If the proxy is detached, return undefined. |
5102 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); | 5102 if (iter.IsAtEnd()) return isolate->factory()->undefined_value(); |
5103 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5103 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5104 return SetHiddenProperty( | 5104 return SetHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), key, |
5105 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key, | 5105 value); |
5106 value); | |
5107 } | 5106 } |
5108 DCHECK(!object->IsJSGlobalProxy()); | 5107 DCHECK(!object->IsJSGlobalProxy()); |
5109 | 5108 |
5110 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); | 5109 Handle<Object> inline_value(object->GetHiddenPropertiesHashTable(), isolate); |
5111 | 5110 |
5112 Handle<ObjectHashTable> hashtable = | 5111 Handle<ObjectHashTable> hashtable = |
5113 GetOrCreateHiddenPropertiesHashtable(object); | 5112 GetOrCreateHiddenPropertiesHashtable(object); |
5114 | 5113 |
5115 // If it was found, check if the key is already in the dictionary. | 5114 // If it was found, check if the key is already in the dictionary. |
5116 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, | 5115 Handle<ObjectHashTable> new_table = ObjectHashTable::Put(hashtable, key, |
(...skipping 10 matching lines...) Expand all Loading... |
5127 | 5126 |
5128 | 5127 |
5129 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { | 5128 void JSObject::DeleteHiddenProperty(Handle<JSObject> object, Handle<Name> key) { |
5130 Isolate* isolate = object->GetIsolate(); | 5129 Isolate* isolate = object->GetIsolate(); |
5131 DCHECK(key->IsUniqueName()); | 5130 DCHECK(key->IsUniqueName()); |
5132 | 5131 |
5133 if (object->IsJSGlobalProxy()) { | 5132 if (object->IsJSGlobalProxy()) { |
5134 PrototypeIterator iter(isolate, object); | 5133 PrototypeIterator iter(isolate, object); |
5135 if (iter.IsAtEnd()) return; | 5134 if (iter.IsAtEnd()) return; |
5136 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5135 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5137 return DeleteHiddenProperty( | 5136 return DeleteHiddenProperty(PrototypeIterator::GetCurrent<JSObject>(iter), |
5138 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), key); | 5137 key); |
5139 } | 5138 } |
5140 | 5139 |
5141 Object* inline_value = object->GetHiddenPropertiesHashTable(); | 5140 Object* inline_value = object->GetHiddenPropertiesHashTable(); |
5142 | 5141 |
5143 if (inline_value->IsUndefined()) return; | 5142 if (inline_value->IsUndefined()) return; |
5144 | 5143 |
5145 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 5144 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
5146 bool was_present = false; | 5145 bool was_present = false; |
5147 ObjectHashTable::Remove(hashtable, key, &was_present); | 5146 ObjectHashTable::Remove(hashtable, key, &was_present); |
5148 } | 5147 } |
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5541 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { | 5540 if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) { |
5542 isolate->ReportFailedAccessCheck(object); | 5541 isolate->ReportFailedAccessCheck(object); |
5543 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5542 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5544 return isolate->factory()->false_value(); | 5543 return isolate->factory()->false_value(); |
5545 } | 5544 } |
5546 | 5545 |
5547 if (object->IsJSGlobalProxy()) { | 5546 if (object->IsJSGlobalProxy()) { |
5548 PrototypeIterator iter(isolate, object); | 5547 PrototypeIterator iter(isolate, object); |
5549 if (iter.IsAtEnd()) return object; | 5548 if (iter.IsAtEnd()) return object; |
5550 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5549 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5551 return PreventExtensions( | 5550 return PreventExtensions(PrototypeIterator::GetCurrent<JSObject>(iter)); |
5552 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | |
5553 } | 5551 } |
5554 | 5552 |
5555 // It's not possible to seal objects with external array elements | 5553 // It's not possible to seal objects with external array elements |
5556 if (object->HasFixedTypedArrayElements()) { | 5554 if (object->HasFixedTypedArrayElements()) { |
5557 THROW_NEW_ERROR( | 5555 THROW_NEW_ERROR( |
5558 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), | 5556 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), |
5559 Object); | 5557 Object); |
5560 } | 5558 } |
5561 | 5559 |
5562 // If there are fast elements we normalize. | 5560 // If there are fast elements we normalize. |
(...skipping 21 matching lines...) Expand all Loading... |
5584 } | 5582 } |
5585 return object; | 5583 return object; |
5586 } | 5584 } |
5587 | 5585 |
5588 | 5586 |
5589 bool JSObject::IsExtensible() { | 5587 bool JSObject::IsExtensible() { |
5590 if (IsJSGlobalProxy()) { | 5588 if (IsJSGlobalProxy()) { |
5591 PrototypeIterator iter(GetIsolate(), this); | 5589 PrototypeIterator iter(GetIsolate(), this); |
5592 if (iter.IsAtEnd()) return false; | 5590 if (iter.IsAtEnd()) return false; |
5593 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); | 5591 DCHECK(iter.GetCurrent()->IsJSGlobalObject()); |
5594 return JSObject::cast(iter.GetCurrent())->map()->is_extensible(); | 5592 return iter.GetCurrent<JSObject>()->map()->is_extensible(); |
5595 } | 5593 } |
5596 return map()->is_extensible(); | 5594 return map()->is_extensible(); |
5597 } | 5595 } |
5598 | 5596 |
5599 | 5597 |
5600 template <typename Dictionary> | 5598 template <typename Dictionary> |
5601 static void ApplyAttributesToDictionary(Dictionary* dictionary, | 5599 static void ApplyAttributesToDictionary(Dictionary* dictionary, |
5602 const PropertyAttributes attributes) { | 5600 const PropertyAttributes attributes) { |
5603 int capacity = dictionary->Capacity(); | 5601 int capacity = dictionary->Capacity(); |
5604 for (int i = 0; i < capacity; i++) { | 5602 for (int i = 0; i < capacity; i++) { |
(...skipping 30 matching lines...) Expand all Loading... |
5635 isolate->ReportFailedAccessCheck(object); | 5633 isolate->ReportFailedAccessCheck(object); |
5636 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5634 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); |
5637 return isolate->factory()->false_value(); | 5635 return isolate->factory()->false_value(); |
5638 } | 5636 } |
5639 | 5637 |
5640 if (object->IsJSGlobalProxy()) { | 5638 if (object->IsJSGlobalProxy()) { |
5641 PrototypeIterator iter(isolate, object); | 5639 PrototypeIterator iter(isolate, object); |
5642 if (iter.IsAtEnd()) return object; | 5640 if (iter.IsAtEnd()) return object; |
5643 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); | 5641 DCHECK(PrototypeIterator::GetCurrent(iter)->IsJSGlobalObject()); |
5644 return PreventExtensionsWithTransition<attrs>( | 5642 return PreventExtensionsWithTransition<attrs>( |
5645 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter))); | 5643 PrototypeIterator::GetCurrent<JSObject>(iter)); |
5646 } | 5644 } |
5647 | 5645 |
5648 // It's not possible to seal or freeze objects with external array elements | 5646 // It's not possible to seal or freeze objects with external array elements |
5649 if (object->HasFixedTypedArrayElements()) { | 5647 if (object->HasFixedTypedArrayElements()) { |
5650 THROW_NEW_ERROR( | 5648 THROW_NEW_ERROR( |
5651 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), | 5649 isolate, NewTypeError(MessageTemplate::kCannotPreventExtExternalArray), |
5652 Object); | 5650 Object); |
5653 } | 5651 } |
5654 | 5652 |
5655 Handle<SeededNumberDictionary> new_element_dictionary; | 5653 Handle<SeededNumberDictionary> new_element_dictionary; |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6090 // Tests for the fast common case for property enumeration: | 6088 // Tests for the fast common case for property enumeration: |
6091 // - This object and all prototypes has an enum cache (which means that | 6089 // - This object and all prototypes has an enum cache (which means that |
6092 // it is no proxy, has no interceptors and needs no access checks). | 6090 // it is no proxy, has no interceptors and needs no access checks). |
6093 // - This object has no elements. | 6091 // - This object has no elements. |
6094 // - No prototype has enumerable properties/elements. | 6092 // - No prototype has enumerable properties/elements. |
6095 bool JSReceiver::IsSimpleEnum() { | 6093 bool JSReceiver::IsSimpleEnum() { |
6096 for (PrototypeIterator iter(GetIsolate(), this, | 6094 for (PrototypeIterator iter(GetIsolate(), this, |
6097 PrototypeIterator::START_AT_RECEIVER); | 6095 PrototypeIterator::START_AT_RECEIVER); |
6098 !iter.IsAtEnd(); iter.Advance()) { | 6096 !iter.IsAtEnd(); iter.Advance()) { |
6099 if (!iter.GetCurrent()->IsJSObject()) return false; | 6097 if (!iter.GetCurrent()->IsJSObject()) return false; |
6100 JSObject* curr = JSObject::cast(iter.GetCurrent()); | 6098 JSObject* current = iter.GetCurrent<JSObject>(); |
6101 int enum_length = curr->map()->EnumLength(); | 6099 int enum_length = current->map()->EnumLength(); |
6102 if (enum_length == kInvalidEnumCacheSentinel) return false; | 6100 if (enum_length == kInvalidEnumCacheSentinel) return false; |
6103 if (curr->IsAccessCheckNeeded()) return false; | 6101 if (current->IsAccessCheckNeeded()) return false; |
6104 DCHECK(!curr->HasNamedInterceptor()); | 6102 DCHECK(!current->HasNamedInterceptor()); |
6105 DCHECK(!curr->HasIndexedInterceptor()); | 6103 DCHECK(!current->HasIndexedInterceptor()); |
6106 if (curr->NumberOfEnumElements() > 0) return false; | 6104 if (current->NumberOfEnumElements() > 0) return false; |
6107 if (curr != this && enum_length != 0) return false; | 6105 if (current != this && enum_length != 0) return false; |
6108 } | 6106 } |
6109 return true; | 6107 return true; |
6110 } | 6108 } |
6111 | 6109 |
6112 | 6110 |
6113 static bool FilterKey(Object* key, PropertyAttributes filter) { | 6111 static bool FilterKey(Object* key, PropertyAttributes filter) { |
6114 if ((filter & SYMBOLIC) && key->IsSymbol()) { | 6112 if ((filter & SYMBOLIC) && key->IsSymbol()) { |
6115 return true; | 6113 return true; |
6116 } | 6114 } |
6117 | 6115 |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6298 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | 6296 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); |
6299 | 6297 |
6300 PrototypeIterator::WhereToEnd end = type == OWN_ONLY | 6298 PrototypeIterator::WhereToEnd end = type == OWN_ONLY |
6301 ? PrototypeIterator::END_AT_NON_HIDDEN | 6299 ? PrototypeIterator::END_AT_NON_HIDDEN |
6302 : PrototypeIterator::END_AT_NULL; | 6300 : PrototypeIterator::END_AT_NULL; |
6303 // Only collect keys if access is permitted. | 6301 // Only collect keys if access is permitted. |
6304 for (PrototypeIterator iter(isolate, object, | 6302 for (PrototypeIterator iter(isolate, object, |
6305 PrototypeIterator::START_AT_RECEIVER); | 6303 PrototypeIterator::START_AT_RECEIVER); |
6306 !iter.IsAtEnd(end); iter.Advance()) { | 6304 !iter.IsAtEnd(end); iter.Advance()) { |
6307 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 6305 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
6308 Handle<JSProxy> proxy(JSProxy::cast(*PrototypeIterator::GetCurrent(iter)), | 6306 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); |
6309 isolate); | |
6310 Handle<Object> args[] = { proxy }; | 6307 Handle<Object> args[] = { proxy }; |
6311 Handle<Object> names; | 6308 Handle<Object> names; |
6312 ASSIGN_RETURN_ON_EXCEPTION( | 6309 ASSIGN_RETURN_ON_EXCEPTION( |
6313 isolate, names, | 6310 isolate, names, |
6314 Execution::Call(isolate, | 6311 Execution::Call(isolate, |
6315 isolate->proxy_enumerate(), | 6312 isolate->proxy_enumerate(), |
6316 object, | 6313 object, |
6317 arraysize(args), | 6314 arraysize(args), |
6318 args), | 6315 args), |
6319 FixedArray); | 6316 FixedArray); |
6320 ASSIGN_RETURN_ON_EXCEPTION( | 6317 ASSIGN_RETURN_ON_EXCEPTION( |
6321 isolate, content, | 6318 isolate, content, |
6322 FixedArray::AddKeysFromArrayLike( | 6319 FixedArray::AddKeysFromArrayLike( |
6323 content, Handle<JSObject>::cast(names)), | 6320 content, Handle<JSObject>::cast(names)), |
6324 FixedArray); | 6321 FixedArray); |
6325 break; | 6322 break; |
6326 } | 6323 } |
6327 | 6324 |
6328 Handle<JSObject> current = | 6325 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); |
6329 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
6330 | 6326 |
6331 // Check access rights if required. | 6327 // Check access rights if required. |
6332 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { | 6328 if (current->IsAccessCheckNeeded() && !isolate->MayAccess(current)) { |
6333 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 6329 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
6334 isolate->ReportFailedAccessCheck(current); | 6330 isolate->ReportFailedAccessCheck(current); |
6335 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); | 6331 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); |
6336 } | 6332 } |
6337 break; | 6333 break; |
6338 } | 6334 } |
6339 | 6335 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6402 bool Map::DictionaryElementsInPrototypeChainOnly() { | 6398 bool Map::DictionaryElementsInPrototypeChainOnly() { |
6403 if (IsDictionaryElementsKind(elements_kind())) { | 6399 if (IsDictionaryElementsKind(elements_kind())) { |
6404 return false; | 6400 return false; |
6405 } | 6401 } |
6406 | 6402 |
6407 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { | 6403 for (PrototypeIterator iter(this); !iter.IsAtEnd(); iter.Advance()) { |
6408 // Be conservative, don't walk into proxies. | 6404 // Be conservative, don't walk into proxies. |
6409 if (iter.GetCurrent()->IsJSProxy()) return true; | 6405 if (iter.GetCurrent()->IsJSProxy()) return true; |
6410 // String wrappers have non-configurable, non-writable elements. | 6406 // String wrappers have non-configurable, non-writable elements. |
6411 if (iter.GetCurrent()->IsStringWrapper()) return true; | 6407 if (iter.GetCurrent()->IsStringWrapper()) return true; |
6412 JSObject* current = JSObject::cast(iter.GetCurrent()); | 6408 JSObject* current = iter.GetCurrent<JSObject>(); |
6413 | 6409 |
6414 if (current->HasDictionaryElements() && | 6410 if (current->HasDictionaryElements() && |
6415 current->element_dictionary()->requires_slow_elements()) { | 6411 current->element_dictionary()->requires_slow_elements()) { |
6416 return true; | 6412 return true; |
6417 } | 6413 } |
6418 | 6414 |
6419 if (current->HasSlowArgumentsElements()) { | 6415 if (current->HasSlowArgumentsElements()) { |
6420 FixedArray* parameter_map = FixedArray::cast(current->elements()); | 6416 FixedArray* parameter_map = FixedArray::cast(current->elements()); |
6421 Object* arguments = parameter_map->get(1); | 6417 Object* arguments = parameter_map->get(1); |
6422 if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) { | 6418 if (SeededNumberDictionary::cast(arguments)->requires_slow_elements()) { |
(...skipping 3538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9961 if (!user->prototype_info()->IsPrototypeInfo()) return false; | 9957 if (!user->prototype_info()->IsPrototypeInfo()) return false; |
9962 // If it doesn't have a prototype, it can't be registered. | 9958 // If it doesn't have a prototype, it can't be registered. |
9963 if (!user->prototype()->IsJSObject()) return false; | 9959 if (!user->prototype()->IsJSObject()) return false; |
9964 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); | 9960 Handle<JSObject> prototype(JSObject::cast(user->prototype()), isolate); |
9965 Handle<PrototypeInfo> user_info = | 9961 Handle<PrototypeInfo> user_info = |
9966 Map::GetOrCreatePrototypeInfo(user, isolate); | 9962 Map::GetOrCreatePrototypeInfo(user, isolate); |
9967 int slot = user_info->registry_slot(); | 9963 int slot = user_info->registry_slot(); |
9968 if (slot == PrototypeInfo::UNREGISTERED) return false; | 9964 if (slot == PrototypeInfo::UNREGISTERED) return false; |
9969 if (prototype->IsJSGlobalProxy()) { | 9965 if (prototype->IsJSGlobalProxy()) { |
9970 PrototypeIterator iter(isolate, prototype); | 9966 PrototypeIterator iter(isolate, prototype); |
9971 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 9967 prototype = PrototypeIterator::GetCurrent<JSObject>(iter); |
9972 } | 9968 } |
9973 DCHECK(prototype->map()->is_prototype_map()); | 9969 DCHECK(prototype->map()->is_prototype_map()); |
9974 Object* maybe_proto_info = prototype->map()->prototype_info(); | 9970 Object* maybe_proto_info = prototype->map()->prototype_info(); |
9975 // User knows its registry slot, prototype info and user registry must exist. | 9971 // User knows its registry slot, prototype info and user registry must exist. |
9976 DCHECK(maybe_proto_info->IsPrototypeInfo()); | 9972 DCHECK(maybe_proto_info->IsPrototypeInfo()); |
9977 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), | 9973 Handle<PrototypeInfo> proto_info(PrototypeInfo::cast(maybe_proto_info), |
9978 isolate); | 9974 isolate); |
9979 Object* maybe_registry = proto_info->prototype_users(); | 9975 Object* maybe_registry = proto_info->prototype_users(); |
9980 DCHECK(maybe_registry->IsWeakFixedArray()); | 9976 DCHECK(maybe_registry->IsWeakFixedArray()); |
9981 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); | 9977 DCHECK(WeakFixedArray::cast(maybe_registry)->Get(slot) == *user); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10013 } | 10009 } |
10014 } | 10010 } |
10015 | 10011 |
10016 | 10012 |
10017 // static | 10013 // static |
10018 void JSObject::InvalidatePrototypeChains(Map* map) { | 10014 void JSObject::InvalidatePrototypeChains(Map* map) { |
10019 if (!FLAG_eliminate_prototype_chain_checks) return; | 10015 if (!FLAG_eliminate_prototype_chain_checks) return; |
10020 DisallowHeapAllocation no_gc; | 10016 DisallowHeapAllocation no_gc; |
10021 if (map->IsJSGlobalProxyMap()) { | 10017 if (map->IsJSGlobalProxyMap()) { |
10022 PrototypeIterator iter(map); | 10018 PrototypeIterator iter(map); |
10023 map = JSObject::cast(iter.GetCurrent())->map(); | 10019 map = iter.GetCurrent<JSObject>()->map(); |
10024 } | 10020 } |
10025 InvalidatePrototypeChainsInternal(map); | 10021 InvalidatePrototypeChainsInternal(map); |
10026 } | 10022 } |
10027 | 10023 |
10028 | 10024 |
10029 // static | 10025 // static |
10030 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, | 10026 Handle<PrototypeInfo> Map::GetOrCreatePrototypeInfo(Handle<JSObject> prototype, |
10031 Isolate* isolate) { | 10027 Isolate* isolate) { |
10032 Object* maybe_proto_info = prototype->map()->prototype_info(); | 10028 Object* maybe_proto_info = prototype->map()->prototype_info(); |
10033 if (maybe_proto_info->IsPrototypeInfo()) { | 10029 if (maybe_proto_info->IsPrototypeInfo()) { |
(...skipping 19 matching lines...) Expand all Loading... |
10053 | 10049 |
10054 | 10050 |
10055 // static | 10051 // static |
10056 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, | 10052 Handle<Cell> Map::GetOrCreatePrototypeChainValidityCell(Handle<Map> map, |
10057 Isolate* isolate) { | 10053 Isolate* isolate) { |
10058 Handle<Object> maybe_prototype(map->prototype(), isolate); | 10054 Handle<Object> maybe_prototype(map->prototype(), isolate); |
10059 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); | 10055 if (!maybe_prototype->IsJSObject()) return Handle<Cell>::null(); |
10060 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); | 10056 Handle<JSObject> prototype = Handle<JSObject>::cast(maybe_prototype); |
10061 if (prototype->IsJSGlobalProxy()) { | 10057 if (prototype->IsJSGlobalProxy()) { |
10062 PrototypeIterator iter(isolate, prototype); | 10058 PrototypeIterator iter(isolate, prototype); |
10063 prototype = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | 10059 prototype = PrototypeIterator::GetCurrent<JSObject>(iter); |
10064 } | 10060 } |
10065 // Ensure the prototype is registered with its own prototypes so its cell | 10061 // Ensure the prototype is registered with its own prototypes so its cell |
10066 // will be invalidated when necessary. | 10062 // will be invalidated when necessary. |
10067 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), | 10063 JSObject::LazyRegisterPrototypeUser(handle(prototype->map(), isolate), |
10068 isolate); | 10064 isolate); |
10069 Handle<PrototypeInfo> proto_info = | 10065 Handle<PrototypeInfo> proto_info = |
10070 GetOrCreatePrototypeInfo(prototype, isolate); | 10066 GetOrCreatePrototypeInfo(prototype, isolate); |
10071 Object* maybe_cell = proto_info->validity_cell(); | 10067 Object* maybe_cell = proto_info->validity_cell(); |
10072 // Return existing cell if it's still valid. | 10068 // Return existing cell if it's still valid. |
10073 if (maybe_cell->IsCell()) { | 10069 if (maybe_cell->IsCell()) { |
(...skipping 2310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12384 Object); | 12380 Object); |
12385 } | 12381 } |
12386 | 12382 |
12387 // Before we can set the prototype we need to be sure | 12383 // Before we can set the prototype we need to be sure |
12388 // prototype cycles are prevented. | 12384 // prototype cycles are prevented. |
12389 // It is sufficient to validate that the receiver is not in the new prototype | 12385 // It is sufficient to validate that the receiver is not in the new prototype |
12390 // chain. | 12386 // chain. |
12391 for (PrototypeIterator iter(isolate, *value, | 12387 for (PrototypeIterator iter(isolate, *value, |
12392 PrototypeIterator::START_AT_RECEIVER); | 12388 PrototypeIterator::START_AT_RECEIVER); |
12393 !iter.IsAtEnd(); iter.Advance()) { | 12389 !iter.IsAtEnd(); iter.Advance()) { |
12394 if (JSReceiver::cast(iter.GetCurrent()) == *object) { | 12390 if (iter.GetCurrent<JSReceiver>() == *object) { |
12395 // Cycle detected. | 12391 // Cycle detected. |
12396 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto), | 12392 THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kCyclicProto), |
12397 Object); | 12393 Object); |
12398 } | 12394 } |
12399 } | 12395 } |
12400 | 12396 |
12401 bool dictionary_elements_in_chain = | 12397 bool dictionary_elements_in_chain = |
12402 object->map()->DictionaryElementsInPrototypeChainOnly(); | 12398 object->map()->DictionaryElementsInPrototypeChainOnly(); |
12403 Handle<JSObject> real_receiver = object; | 12399 Handle<JSObject> real_receiver = object; |
12404 | 12400 |
12405 if (from_javascript) { | 12401 if (from_javascript) { |
12406 // Find the first object in the chain whose prototype object is not | 12402 // Find the first object in the chain whose prototype object is not |
12407 // hidden and set the new prototype on that object. | 12403 // hidden and set the new prototype on that object. |
12408 PrototypeIterator iter(isolate, real_receiver); | 12404 PrototypeIterator iter(isolate, real_receiver); |
12409 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 12405 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
12410 real_receiver = | 12406 real_receiver = PrototypeIterator::GetCurrent<JSObject>(iter); |
12411 Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)); | |
12412 iter.Advance(); | 12407 iter.Advance(); |
12413 if (!real_receiver->map()->is_extensible()) { | 12408 if (!real_receiver->map()->is_extensible()) { |
12414 THROW_NEW_ERROR( | 12409 THROW_NEW_ERROR( |
12415 isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object), | 12410 isolate, NewTypeError(MessageTemplate::kNonExtensibleProto, object), |
12416 Object); | 12411 Object); |
12417 } | 12412 } |
12418 } | 12413 } |
12419 } | 12414 } |
12420 | 12415 |
12421 // Set the new prototype of the object. | 12416 // Set the new prototype of the object. |
(...skipping 3742 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16164 if (cell->value() != *new_value) { | 16159 if (cell->value() != *new_value) { |
16165 cell->set_value(*new_value); | 16160 cell->set_value(*new_value); |
16166 Isolate* isolate = cell->GetIsolate(); | 16161 Isolate* isolate = cell->GetIsolate(); |
16167 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 16162 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
16168 isolate, DependentCode::kPropertyCellChangedGroup); | 16163 isolate, DependentCode::kPropertyCellChangedGroup); |
16169 } | 16164 } |
16170 } | 16165 } |
16171 | 16166 |
16172 } // namespace internal | 16167 } // namespace internal |
16173 } // namespace v8 | 16168 } // namespace v8 |
OLD | NEW |