OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 5843 matching lines...) Loading... |
5854 | 5854 |
5855 template<class ContextObject> | 5855 template<class ContextObject> |
5856 class JSObjectWalkVisitor { | 5856 class JSObjectWalkVisitor { |
5857 public: | 5857 public: |
5858 JSObjectWalkVisitor(ContextObject* site_context, bool copying, | 5858 JSObjectWalkVisitor(ContextObject* site_context, bool copying, |
5859 JSObject::DeepCopyHints hints) | 5859 JSObject::DeepCopyHints hints) |
5860 : site_context_(site_context), | 5860 : site_context_(site_context), |
5861 copying_(copying), | 5861 copying_(copying), |
5862 hints_(hints) {} | 5862 hints_(hints) {} |
5863 | 5863 |
5864 Handle<JSObject> StructureWalk(Handle<JSObject> object); | 5864 MUST_USE_RESULT MaybeHandle<JSObject> StructureWalk(Handle<JSObject> object); |
5865 | 5865 |
5866 protected: | 5866 protected: |
5867 inline Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, | 5867 MUST_USE_RESULT inline MaybeHandle<JSObject> VisitElementOrProperty( |
5868 Handle<JSObject> value) { | 5868 Handle<JSObject> object, |
| 5869 Handle<JSObject> value) { |
5869 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); | 5870 Handle<AllocationSite> current_site = site_context()->EnterNewScope(); |
5870 Handle<JSObject> copy_of_value = StructureWalk(value); | 5871 MaybeHandle<JSObject> copy_of_value = StructureWalk(value); |
5871 site_context()->ExitScope(current_site, value); | 5872 site_context()->ExitScope(current_site, value); |
5872 return copy_of_value; | 5873 return copy_of_value; |
5873 } | 5874 } |
5874 | 5875 |
5875 inline ContextObject* site_context() { return site_context_; } | 5876 inline ContextObject* site_context() { return site_context_; } |
5876 inline Isolate* isolate() { return site_context()->isolate(); } | 5877 inline Isolate* isolate() { return site_context()->isolate(); } |
5877 | 5878 |
5878 inline bool copying() const { return copying_; } | 5879 inline bool copying() const { return copying_; } |
5879 | 5880 |
5880 private: | 5881 private: |
5881 ContextObject* site_context_; | 5882 ContextObject* site_context_; |
5882 const bool copying_; | 5883 const bool copying_; |
5883 const JSObject::DeepCopyHints hints_; | 5884 const JSObject::DeepCopyHints hints_; |
5884 }; | 5885 }; |
5885 | 5886 |
5886 | 5887 |
5887 template <class ContextObject> | 5888 template <class ContextObject> |
5888 Handle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( | 5889 MaybeHandle<JSObject> JSObjectWalkVisitor<ContextObject>::StructureWalk( |
5889 Handle<JSObject> object) { | 5890 Handle<JSObject> object) { |
5890 Isolate* isolate = this->isolate(); | 5891 Isolate* isolate = this->isolate(); |
5891 bool copying = this->copying(); | 5892 bool copying = this->copying(); |
5892 bool shallow = hints_ == JSObject::kObjectIsShallowArray; | 5893 bool shallow = hints_ == JSObject::kObjectIsShallowArray; |
5893 | 5894 |
5894 if (!shallow) { | 5895 if (!shallow) { |
5895 StackLimitCheck check(isolate); | 5896 StackLimitCheck check(isolate); |
5896 | 5897 |
5897 if (check.HasOverflowed()) { | 5898 if (check.HasOverflowed()) { |
5898 isolate->StackOverflow(); | 5899 isolate->StackOverflow(); |
5899 return Handle<JSObject>::null(); | 5900 return MaybeHandle<JSObject>(); |
5900 } | 5901 } |
5901 } | 5902 } |
5902 | 5903 |
5903 if (object->map()->is_deprecated()) { | 5904 if (object->map()->is_deprecated()) { |
5904 JSObject::MigrateInstance(object); | 5905 JSObject::MigrateInstance(object); |
5905 } | 5906 } |
5906 | 5907 |
5907 Handle<JSObject> copy; | 5908 Handle<JSObject> copy; |
5908 if (copying) { | 5909 if (copying) { |
5909 Handle<AllocationSite> site_to_pass; | 5910 Handle<AllocationSite> site_to_pass; |
(...skipping 20 matching lines...) Loading... |
5930 // Deep copy local properties. | 5931 // Deep copy local properties. |
5931 if (copy->HasFastProperties()) { | 5932 if (copy->HasFastProperties()) { |
5932 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); | 5933 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); |
5933 int limit = copy->map()->NumberOfOwnDescriptors(); | 5934 int limit = copy->map()->NumberOfOwnDescriptors(); |
5934 for (int i = 0; i < limit; i++) { | 5935 for (int i = 0; i < limit; i++) { |
5935 PropertyDetails details = descriptors->GetDetails(i); | 5936 PropertyDetails details = descriptors->GetDetails(i); |
5936 if (details.type() != FIELD) continue; | 5937 if (details.type() != FIELD) continue; |
5937 int index = descriptors->GetFieldIndex(i); | 5938 int index = descriptors->GetFieldIndex(i); |
5938 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 5939 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
5939 if (value->IsJSObject()) { | 5940 if (value->IsJSObject()) { |
5940 value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value)); | 5941 ASSIGN_RETURN_ON_EXCEPTION( |
5941 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>()); | 5942 isolate, value, |
| 5943 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 5944 JSObject); |
5942 } else { | 5945 } else { |
5943 Representation representation = details.representation(); | 5946 Representation representation = details.representation(); |
5944 value = Object::NewStorageFor(isolate, value, representation); | 5947 value = Object::NewStorageFor(isolate, value, representation); |
5945 } | 5948 } |
5946 if (copying) { | 5949 if (copying) { |
5947 copy->FastPropertyAtPut(index, *value); | 5950 copy->FastPropertyAtPut(index, *value); |
5948 } | 5951 } |
5949 } | 5952 } |
5950 } else { | 5953 } else { |
5951 Handle<FixedArray> names = | 5954 Handle<FixedArray> names = |
5952 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); | 5955 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); |
5953 copy->GetLocalPropertyNames(*names, 0); | 5956 copy->GetLocalPropertyNames(*names, 0); |
5954 for (int i = 0; i < names->length(); i++) { | 5957 for (int i = 0; i < names->length(); i++) { |
5955 ASSERT(names->get(i)->IsString()); | 5958 ASSERT(names->get(i)->IsString()); |
5956 Handle<String> key_string(String::cast(names->get(i))); | 5959 Handle<String> key_string(String::cast(names->get(i))); |
5957 PropertyAttributes attributes = | 5960 PropertyAttributes attributes = |
5958 JSReceiver::GetLocalPropertyAttribute(copy, key_string); | 5961 JSReceiver::GetLocalPropertyAttribute(copy, key_string); |
5959 // Only deep copy fields from the object literal expression. | 5962 // Only deep copy fields from the object literal expression. |
5960 // In particular, don't try to copy the length attribute of | 5963 // In particular, don't try to copy the length attribute of |
5961 // an array. | 5964 // an array. |
5962 if (attributes != NONE) continue; | 5965 if (attributes != NONE) continue; |
5963 Handle<Object> value = | 5966 Handle<Object> value = |
5964 Object::GetProperty(copy, key_string).ToHandleChecked(); | 5967 Object::GetProperty(copy, key_string).ToHandleChecked(); |
5965 if (value->IsJSObject()) { | 5968 if (value->IsJSObject()) { |
5966 Handle<JSObject> result = VisitElementOrProperty( | 5969 Handle<JSObject> result; |
5967 copy, Handle<JSObject>::cast(value)); | 5970 ASSIGN_RETURN_ON_EXCEPTION( |
5968 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5971 isolate, result, |
| 5972 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 5973 JSObject); |
5969 if (copying) { | 5974 if (copying) { |
5970 // Creating object copy for literals. No strict mode needed. | 5975 // Creating object copy for literals. No strict mode needed. |
5971 JSObject::SetProperty( | 5976 JSObject::SetProperty( |
5972 copy, key_string, result, NONE, SLOPPY).Assert(); | 5977 copy, key_string, result, NONE, SLOPPY).Assert(); |
5973 } | 5978 } |
5974 } | 5979 } |
5975 } | 5980 } |
5976 } | 5981 } |
5977 | 5982 |
5978 // Deep copy local elements. | 5983 // Deep copy local elements. |
(...skipping 11 matching lines...) Loading... |
5990 ASSERT(!elements->get(i)->IsJSObject()); | 5995 ASSERT(!elements->get(i)->IsJSObject()); |
5991 } | 5996 } |
5992 #endif | 5997 #endif |
5993 } else { | 5998 } else { |
5994 for (int i = 0; i < elements->length(); i++) { | 5999 for (int i = 0; i < elements->length(); i++) { |
5995 Handle<Object> value(elements->get(i), isolate); | 6000 Handle<Object> value(elements->get(i), isolate); |
5996 ASSERT(value->IsSmi() || | 6001 ASSERT(value->IsSmi() || |
5997 value->IsTheHole() || | 6002 value->IsTheHole() || |
5998 (IsFastObjectElementsKind(copy->GetElementsKind()))); | 6003 (IsFastObjectElementsKind(copy->GetElementsKind()))); |
5999 if (value->IsJSObject()) { | 6004 if (value->IsJSObject()) { |
6000 Handle<JSObject> result = VisitElementOrProperty( | 6005 Handle<JSObject> result; |
6001 copy, Handle<JSObject>::cast(value)); | 6006 ASSIGN_RETURN_ON_EXCEPTION( |
6002 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 6007 isolate, result, |
| 6008 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 6009 JSObject); |
6003 if (copying) { | 6010 if (copying) { |
6004 elements->set(i, *result); | 6011 elements->set(i, *result); |
6005 } | 6012 } |
6006 } | 6013 } |
6007 } | 6014 } |
6008 } | 6015 } |
6009 break; | 6016 break; |
6010 } | 6017 } |
6011 case DICTIONARY_ELEMENTS: { | 6018 case DICTIONARY_ELEMENTS: { |
6012 Handle<SeededNumberDictionary> element_dictionary( | 6019 Handle<SeededNumberDictionary> element_dictionary( |
6013 copy->element_dictionary()); | 6020 copy->element_dictionary()); |
6014 int capacity = element_dictionary->Capacity(); | 6021 int capacity = element_dictionary->Capacity(); |
6015 for (int i = 0; i < capacity; i++) { | 6022 for (int i = 0; i < capacity; i++) { |
6016 Object* k = element_dictionary->KeyAt(i); | 6023 Object* k = element_dictionary->KeyAt(i); |
6017 if (element_dictionary->IsKey(k)) { | 6024 if (element_dictionary->IsKey(k)) { |
6018 Handle<Object> value(element_dictionary->ValueAt(i), isolate); | 6025 Handle<Object> value(element_dictionary->ValueAt(i), isolate); |
6019 if (value->IsJSObject()) { | 6026 if (value->IsJSObject()) { |
6020 Handle<JSObject> result = VisitElementOrProperty( | 6027 Handle<JSObject> result; |
6021 copy, Handle<JSObject>::cast(value)); | 6028 ASSIGN_RETURN_ON_EXCEPTION( |
6022 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 6029 isolate, result, |
| 6030 VisitElementOrProperty(copy, Handle<JSObject>::cast(value)), |
| 6031 JSObject); |
6023 if (copying) { | 6032 if (copying) { |
6024 element_dictionary->ValueAtPut(i, *result); | 6033 element_dictionary->ValueAtPut(i, *result); |
6025 } | 6034 } |
6026 } | 6035 } |
6027 } | 6036 } |
6028 } | 6037 } |
6029 break; | 6038 break; |
6030 } | 6039 } |
6031 case SLOPPY_ARGUMENTS_ELEMENTS: | 6040 case SLOPPY_ARGUMENTS_ELEMENTS: |
6032 UNIMPLEMENTED(); | 6041 UNIMPLEMENTED(); |
(...skipping 11 matching lines...) Loading... |
6044 case FAST_HOLEY_DOUBLE_ELEMENTS: | 6053 case FAST_HOLEY_DOUBLE_ELEMENTS: |
6045 // No contained objects, nothing to do. | 6054 // No contained objects, nothing to do. |
6046 break; | 6055 break; |
6047 } | 6056 } |
6048 } | 6057 } |
6049 | 6058 |
6050 return copy; | 6059 return copy; |
6051 } | 6060 } |
6052 | 6061 |
6053 | 6062 |
6054 Handle<JSObject> JSObject::DeepWalk( | 6063 MaybeHandle<JSObject> JSObject::DeepWalk( |
6055 Handle<JSObject> object, | 6064 Handle<JSObject> object, |
6056 AllocationSiteCreationContext* site_context) { | 6065 AllocationSiteCreationContext* site_context) { |
6057 JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, | 6066 JSObjectWalkVisitor<AllocationSiteCreationContext> v(site_context, false, |
6058 kNoHints); | 6067 kNoHints); |
6059 Handle<JSObject> result = v.StructureWalk(object); | 6068 MaybeHandle<JSObject> result = v.StructureWalk(object); |
6060 ASSERT(result.is_null() || result.is_identical_to(object)); | 6069 Handle<JSObject> for_assert; |
| 6070 ASSERT(!result.ToHandle(&for_assert) || for_assert.is_identical_to(object)); |
6061 return result; | 6071 return result; |
6062 } | 6072 } |
6063 | 6073 |
6064 | 6074 |
6065 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object, | 6075 MaybeHandle<JSObject> JSObject::DeepCopy( |
6066 AllocationSiteUsageContext* site_context, | 6076 Handle<JSObject> object, |
6067 DeepCopyHints hints) { | 6077 AllocationSiteUsageContext* site_context, |
| 6078 DeepCopyHints hints) { |
6068 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); | 6079 JSObjectWalkVisitor<AllocationSiteUsageContext> v(site_context, true, hints); |
6069 Handle<JSObject> copy = v.StructureWalk(object); | 6080 MaybeHandle<JSObject> copy = v.StructureWalk(object); |
6070 ASSERT(!copy.is_identical_to(object)); | 6081 Handle<JSObject> for_assert; |
| 6082 ASSERT(!copy.ToHandle(&for_assert) || !for_assert.is_identical_to(object)); |
6071 return copy; | 6083 return copy; |
6072 } | 6084 } |
6073 | 6085 |
6074 | 6086 |
6075 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, | 6087 Handle<Object> JSObject::GetDataProperty(Handle<JSObject> object, |
6076 Handle<Name> key) { | 6088 Handle<Name> key) { |
6077 Isolate* isolate = object->GetIsolate(); | 6089 Isolate* isolate = object->GetIsolate(); |
6078 LookupResult lookup(isolate); | 6090 LookupResult lookup(isolate); |
6079 { | 6091 { |
6080 DisallowHeapAllocation no_allocation; | 6092 DisallowHeapAllocation no_allocation; |
(...skipping 6309 matching lines...) Loading... |
12390 Handle<Map> new_map = GetPrototypeTransition(map, prototype); | 12402 Handle<Map> new_map = GetPrototypeTransition(map, prototype); |
12391 if (new_map.is_null()) { | 12403 if (new_map.is_null()) { |
12392 new_map = Copy(map); | 12404 new_map = Copy(map); |
12393 PutPrototypeTransition(map, prototype, new_map); | 12405 PutPrototypeTransition(map, prototype, new_map); |
12394 new_map->set_prototype(*prototype); | 12406 new_map->set_prototype(*prototype); |
12395 } | 12407 } |
12396 return new_map; | 12408 return new_map; |
12397 } | 12409 } |
12398 | 12410 |
12399 | 12411 |
12400 Handle<Object> JSObject::SetPrototype(Handle<JSObject> object, | 12412 MaybeHandle<Object> JSObject::SetPrototype(Handle<JSObject> object, |
12401 Handle<Object> value, | 12413 Handle<Object> value, |
12402 bool skip_hidden_prototypes) { | 12414 bool skip_hidden_prototypes) { |
12403 #ifdef DEBUG | 12415 #ifdef DEBUG |
12404 int size = object->Size(); | 12416 int size = object->Size(); |
12405 #endif | 12417 #endif |
12406 | 12418 |
12407 Isolate* isolate = object->GetIsolate(); | 12419 Isolate* isolate = object->GetIsolate(); |
12408 Heap* heap = isolate->heap(); | 12420 Heap* heap = isolate->heap(); |
12409 // Silently ignore the change if value is not a JSObject or null. | 12421 // Silently ignore the change if value is not a JSObject or null. |
12410 // SpiderMonkey behaves this way. | 12422 // SpiderMonkey behaves this way. |
12411 if (!value->IsJSReceiver() && !value->IsNull()) return value; | 12423 if (!value->IsJSReceiver() && !value->IsNull()) return value; |
12412 | 12424 |
12413 // From 8.6.2 Object Internal Methods | 12425 // From 8.6.2 Object Internal Methods |
12414 // ... | 12426 // ... |
12415 // In addition, if [[Extensible]] is false the value of the [[Class]] and | 12427 // In addition, if [[Extensible]] is false the value of the [[Class]] and |
12416 // [[Prototype]] internal properties of the object may not be modified. | 12428 // [[Prototype]] internal properties of the object may not be modified. |
12417 // ... | 12429 // ... |
12418 // Implementation specific extensions that modify [[Class]], [[Prototype]] | 12430 // Implementation specific extensions that modify [[Class]], [[Prototype]] |
12419 // or [[Extensible]] must not violate the invariants defined in the preceding | 12431 // or [[Extensible]] must not violate the invariants defined in the preceding |
12420 // paragraph. | 12432 // paragraph. |
12421 if (!object->map()->is_extensible()) { | 12433 if (!object->map()->is_extensible()) { |
12422 Handle<Object> args[] = { object }; | 12434 Handle<Object> args[] = { object }; |
12423 Handle<Object> error = isolate->factory()->NewTypeError( | 12435 Handle<Object> error = isolate->factory()->NewTypeError( |
12424 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); | 12436 "non_extensible_proto", HandleVector(args, ARRAY_SIZE(args))); |
12425 isolate->Throw(*error); | 12437 return isolate->Throw<Object>(error); |
12426 return Handle<Object>(); | |
12427 } | 12438 } |
12428 | 12439 |
12429 // Before we can set the prototype we need to be sure | 12440 // Before we can set the prototype we need to be sure |
12430 // prototype cycles are prevented. | 12441 // prototype cycles are prevented. |
12431 // It is sufficient to validate that the receiver is not in the new prototype | 12442 // It is sufficient to validate that the receiver is not in the new prototype |
12432 // chain. | 12443 // chain. |
12433 for (Object* pt = *value; | 12444 for (Object* pt = *value; |
12434 pt != heap->null_value(); | 12445 pt != heap->null_value(); |
12435 pt = pt->GetPrototype(isolate)) { | 12446 pt = pt->GetPrototype(isolate)) { |
12436 if (JSReceiver::cast(pt) == *object) { | 12447 if (JSReceiver::cast(pt) == *object) { |
12437 // Cycle detected. | 12448 // Cycle detected. |
12438 Handle<Object> error = isolate->factory()->NewError( | 12449 Handle<Object> error = isolate->factory()->NewError( |
12439 "cyclic_proto", HandleVector<Object>(NULL, 0)); | 12450 "cyclic_proto", HandleVector<Object>(NULL, 0)); |
12440 isolate->Throw(*error); | 12451 return isolate->Throw<Object>(error); |
12441 return Handle<Object>(); | |
12442 } | 12452 } |
12443 } | 12453 } |
12444 | 12454 |
12445 bool dictionary_elements_in_chain = | 12455 bool dictionary_elements_in_chain = |
12446 object->map()->DictionaryElementsInPrototypeChainOnly(); | 12456 object->map()->DictionaryElementsInPrototypeChainOnly(); |
12447 Handle<JSObject> real_receiver = object; | 12457 Handle<JSObject> real_receiver = object; |
12448 | 12458 |
12449 if (skip_hidden_prototypes) { | 12459 if (skip_hidden_prototypes) { |
12450 // Find the first object in the chain whose prototype object is not | 12460 // Find the first object in the chain whose prototype object is not |
12451 // hidden and set the new prototype on that object. | 12461 // hidden and set the new prototype on that object. |
(...skipping 4665 matching lines...) Loading... |
17117 #define ERROR_MESSAGES_TEXTS(C, T) T, | 17127 #define ERROR_MESSAGES_TEXTS(C, T) T, |
17118 static const char* error_messages_[] = { | 17128 static const char* error_messages_[] = { |
17119 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 17129 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
17120 }; | 17130 }; |
17121 #undef ERROR_MESSAGES_TEXTS | 17131 #undef ERROR_MESSAGES_TEXTS |
17122 return error_messages_[reason]; | 17132 return error_messages_[reason]; |
17123 } | 17133 } |
17124 | 17134 |
17125 | 17135 |
17126 } } // namespace v8::internal | 17136 } } // namespace v8::internal |
OLD | NEW |