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 5565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5576 } | 5576 } |
5577 | 5577 |
5578 | 5578 |
5579 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5579 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
5580 Isolate* isolate = object->GetIsolate(); | 5580 Isolate* isolate = object->GetIsolate(); |
5581 CALL_HEAP_FUNCTION(isolate, | 5581 CALL_HEAP_FUNCTION(isolate, |
5582 isolate->heap()->CopyJSObject(*object), JSObject); | 5582 isolate->heap()->CopyJSObject(*object), JSObject); |
5583 } | 5583 } |
5584 | 5584 |
5585 | 5585 |
5586 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { | 5586 class JSObjectWalkVisitor { |
| 5587 public: |
| 5588 explicit JSObjectWalkVisitor() {} |
| 5589 virtual ~JSObjectWalkVisitor() {} |
| 5590 |
| 5591 Handle<JSObject> Visit(Handle<JSObject> object) { |
| 5592 return StructureWalk(object); |
| 5593 } |
| 5594 |
| 5595 // Returns true if the visitor is a copying visitor. |
| 5596 virtual bool is_copying() = 0; |
| 5597 |
| 5598 protected: |
| 5599 Handle<JSObject> StructureWalk(Handle<JSObject> object); |
| 5600 |
| 5601 // The returned handle should point to a new object if the visitor is a |
| 5602 // copying visitor, otherwise it should be the same as the input object. |
| 5603 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) = 0; |
| 5604 |
| 5605 // The returned handle should point to a new value if the visitor is a |
| 5606 // copying visitor, otherwise it should be the same as the input value. |
| 5607 virtual Handle<JSObject> VisitElementOrProperty(Handle<JSObject> object, |
| 5608 Handle<JSObject> value) = 0; |
| 5609 }; |
| 5610 |
| 5611 |
| 5612 class JSObjectCopyVisitor: public JSObjectWalkVisitor { |
| 5613 public: |
| 5614 explicit JSObjectCopyVisitor() {} |
| 5615 |
| 5616 virtual bool is_copying() V8_OVERRIDE { return true; } |
| 5617 |
| 5618 protected: |
| 5619 virtual Handle<JSObject> VisitObject(Handle<JSObject> object) V8_OVERRIDE { |
| 5620 return JSObject::Copy(object); |
| 5621 } |
| 5622 |
| 5623 virtual Handle<JSObject> VisitElementOrProperty( |
| 5624 Handle<JSObject> object, |
| 5625 Handle<JSObject> value) V8_OVERRIDE { |
| 5626 return StructureWalk(value); |
| 5627 } |
| 5628 }; |
| 5629 |
| 5630 |
| 5631 Handle<JSObject> JSObjectWalkVisitor::StructureWalk(Handle<JSObject> object) { |
| 5632 bool copying = is_copying(); |
5587 Isolate* isolate = object->GetIsolate(); | 5633 Isolate* isolate = object->GetIsolate(); |
5588 StackLimitCheck check(isolate); | 5634 StackLimitCheck check(isolate); |
5589 if (check.HasOverflowed()) { | 5635 if (check.HasOverflowed()) { |
5590 isolate->StackOverflow(); | 5636 isolate->StackOverflow(); |
5591 return Handle<JSObject>::null(); | 5637 return Handle<JSObject>::null(); |
5592 } | 5638 } |
5593 | 5639 |
5594 if (object->map()->is_deprecated()) { | 5640 if (object->map()->is_deprecated()) { |
5595 MigrateInstance(object); | 5641 JSObject::MigrateInstance(object); |
5596 } | 5642 } |
5597 | 5643 |
5598 Handle<JSObject> copy = Copy(object); | 5644 Handle<JSObject> copy = VisitObject(object); |
| 5645 ASSERT(copying || copy.is_identical_to(object)); |
5599 | 5646 |
5600 HandleScope scope(isolate); | 5647 HandleScope scope(isolate); |
5601 | 5648 |
5602 // Deep copy local properties. | 5649 // Deep copy local properties. |
5603 if (copy->HasFastProperties()) { | 5650 if (copy->HasFastProperties()) { |
5604 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); | 5651 Handle<DescriptorArray> descriptors(copy->map()->instance_descriptors()); |
5605 int limit = copy->map()->NumberOfOwnDescriptors(); | 5652 int limit = copy->map()->NumberOfOwnDescriptors(); |
5606 for (int i = 0; i < limit; i++) { | 5653 for (int i = 0; i < limit; i++) { |
5607 PropertyDetails details = descriptors->GetDetails(i); | 5654 PropertyDetails details = descriptors->GetDetails(i); |
5608 if (details.type() != FIELD) continue; | 5655 if (details.type() != FIELD) continue; |
5609 int index = descriptors->GetFieldIndex(i); | 5656 int index = descriptors->GetFieldIndex(i); |
5610 Handle<Object> value(object->RawFastPropertyAt(index), isolate); | 5657 Handle<Object> value(object->RawFastPropertyAt(index), isolate); |
5611 if (value->IsJSObject()) { | 5658 if (value->IsJSObject()) { |
5612 value = DeepCopy(Handle<JSObject>::cast(value)); | 5659 value = VisitElementOrProperty(copy, Handle<JSObject>::cast(value)); |
5613 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>()); | 5660 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, value, Handle<JSObject>()); |
5614 } else { | 5661 } else { |
5615 Representation representation = details.representation(); | 5662 Representation representation = details.representation(); |
5616 value = NewStorageFor(isolate, value, representation); | 5663 value = NewStorageFor(isolate, value, representation); |
5617 } | 5664 } |
5618 copy->FastPropertyAtPut(index, *value); | 5665 if (copying) { |
| 5666 copy->FastPropertyAtPut(index, *value); |
| 5667 } |
5619 } | 5668 } |
5620 } else { | 5669 } else { |
5621 Handle<FixedArray> names = | 5670 Handle<FixedArray> names = |
5622 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); | 5671 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); |
5623 copy->GetLocalPropertyNames(*names, 0); | 5672 copy->GetLocalPropertyNames(*names, 0); |
5624 for (int i = 0; i < names->length(); i++) { | 5673 for (int i = 0; i < names->length(); i++) { |
5625 ASSERT(names->get(i)->IsString()); | 5674 ASSERT(names->get(i)->IsString()); |
5626 Handle<String> key_string(String::cast(names->get(i))); | 5675 Handle<String> key_string(String::cast(names->get(i))); |
5627 PropertyAttributes attributes = | 5676 PropertyAttributes attributes = |
5628 copy->GetLocalPropertyAttribute(*key_string); | 5677 copy->GetLocalPropertyAttribute(*key_string); |
5629 // Only deep copy fields from the object literal expression. | 5678 // Only deep copy fields from the object literal expression. |
5630 // In particular, don't try to copy the length attribute of | 5679 // In particular, don't try to copy the length attribute of |
5631 // an array. | 5680 // an array. |
5632 if (attributes != NONE) continue; | 5681 if (attributes != NONE) continue; |
5633 Handle<Object> value( | 5682 Handle<Object> value( |
5634 copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(), | 5683 copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(), |
5635 isolate); | 5684 isolate); |
5636 if (value->IsJSObject()) { | 5685 if (value->IsJSObject()) { |
5637 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5686 Handle<JSObject> result = VisitElementOrProperty( |
| 5687 copy, Handle<JSObject>::cast(value)); |
5638 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5688 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); |
5639 // Creating object copy for literals. No strict mode needed. | 5689 if (copying) { |
5640 CHECK_NOT_EMPTY_HANDLE(isolate, SetProperty( | 5690 // Creating object copy for literals. No strict mode needed. |
5641 copy, key_string, result, NONE, kNonStrictMode)); | 5691 CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty( |
| 5692 copy, key_string, result, NONE, kNonStrictMode)); |
| 5693 } |
5642 } | 5694 } |
5643 } | 5695 } |
5644 } | 5696 } |
5645 | 5697 |
5646 // Deep copy local elements. | 5698 // Deep copy local elements. |
5647 // Pixel elements cannot be created using an object literal. | 5699 // Pixel elements cannot be created using an object literal. |
5648 ASSERT(!copy->HasExternalArrayElements()); | 5700 ASSERT(!copy->HasExternalArrayElements()); |
5649 switch (copy->GetElementsKind()) { | 5701 switch (copy->GetElementsKind()) { |
5650 case FAST_SMI_ELEMENTS: | 5702 case FAST_SMI_ELEMENTS: |
5651 case FAST_ELEMENTS: | 5703 case FAST_ELEMENTS: |
5652 case FAST_HOLEY_SMI_ELEMENTS: | 5704 case FAST_HOLEY_SMI_ELEMENTS: |
5653 case FAST_HOLEY_ELEMENTS: { | 5705 case FAST_HOLEY_ELEMENTS: { |
5654 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); | 5706 Handle<FixedArray> elements(FixedArray::cast(copy->elements())); |
5655 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { | 5707 if (elements->map() == isolate->heap()->fixed_cow_array_map()) { |
5656 isolate->counters()->cow_arrays_created_runtime()->Increment(); | 5708 isolate->counters()->cow_arrays_created_runtime()->Increment(); |
5657 #ifdef DEBUG | 5709 #ifdef DEBUG |
5658 for (int i = 0; i < elements->length(); i++) { | 5710 for (int i = 0; i < elements->length(); i++) { |
5659 ASSERT(!elements->get(i)->IsJSObject()); | 5711 ASSERT(!elements->get(i)->IsJSObject()); |
5660 } | 5712 } |
5661 #endif | 5713 #endif |
5662 } else { | 5714 } else { |
5663 for (int i = 0; i < elements->length(); i++) { | 5715 for (int i = 0; i < elements->length(); i++) { |
5664 Handle<Object> value(elements->get(i), isolate); | 5716 Handle<Object> value(elements->get(i), isolate); |
5665 ASSERT(value->IsSmi() || | 5717 ASSERT(value->IsSmi() || |
5666 value->IsTheHole() || | 5718 value->IsTheHole() || |
5667 (IsFastObjectElementsKind(copy->GetElementsKind()))); | 5719 (IsFastObjectElementsKind(copy->GetElementsKind()))); |
5668 if (value->IsJSObject()) { | 5720 if (value->IsJSObject()) { |
5669 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5721 Handle<JSObject> result = VisitElementOrProperty( |
| 5722 copy, Handle<JSObject>::cast(value)); |
5670 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5723 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); |
5671 elements->set(i, *result); | 5724 if (copying) { |
| 5725 elements->set(i, *result); |
| 5726 } |
5672 } | 5727 } |
5673 } | 5728 } |
5674 } | 5729 } |
5675 break; | 5730 break; |
5676 } | 5731 } |
5677 case DICTIONARY_ELEMENTS: { | 5732 case DICTIONARY_ELEMENTS: { |
5678 Handle<SeededNumberDictionary> element_dictionary( | 5733 Handle<SeededNumberDictionary> element_dictionary( |
5679 copy->element_dictionary()); | 5734 copy->element_dictionary()); |
5680 int capacity = element_dictionary->Capacity(); | 5735 int capacity = element_dictionary->Capacity(); |
5681 for (int i = 0; i < capacity; i++) { | 5736 for (int i = 0; i < capacity; i++) { |
5682 Object* k = element_dictionary->KeyAt(i); | 5737 Object* k = element_dictionary->KeyAt(i); |
5683 if (element_dictionary->IsKey(k)) { | 5738 if (element_dictionary->IsKey(k)) { |
5684 Handle<Object> value(element_dictionary->ValueAt(i), isolate); | 5739 Handle<Object> value(element_dictionary->ValueAt(i), isolate); |
5685 if (value->IsJSObject()) { | 5740 if (value->IsJSObject()) { |
5686 Handle<Object> result = DeepCopy(Handle<JSObject>::cast(value)); | 5741 Handle<JSObject> result = VisitElementOrProperty( |
| 5742 copy, Handle<JSObject>::cast(value)); |
5687 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5743 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); |
5688 element_dictionary->ValueAtPut(i, *result); | 5744 if (copying) { |
| 5745 element_dictionary->ValueAtPut(i, *result); |
| 5746 } |
5689 } | 5747 } |
5690 } | 5748 } |
5691 } | 5749 } |
5692 break; | 5750 break; |
5693 } | 5751 } |
5694 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5752 case NON_STRICT_ARGUMENTS_ELEMENTS: |
5695 UNIMPLEMENTED(); | 5753 UNIMPLEMENTED(); |
5696 break; | 5754 break; |
5697 case EXTERNAL_PIXEL_ELEMENTS: | 5755 case EXTERNAL_PIXEL_ELEMENTS: |
5698 case EXTERNAL_BYTE_ELEMENTS: | 5756 case EXTERNAL_BYTE_ELEMENTS: |
5699 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 5757 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
5700 case EXTERNAL_SHORT_ELEMENTS: | 5758 case EXTERNAL_SHORT_ELEMENTS: |
5701 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 5759 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
5702 case EXTERNAL_INT_ELEMENTS: | 5760 case EXTERNAL_INT_ELEMENTS: |
5703 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 5761 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
5704 case EXTERNAL_FLOAT_ELEMENTS: | 5762 case EXTERNAL_FLOAT_ELEMENTS: |
5705 case EXTERNAL_DOUBLE_ELEMENTS: | 5763 case EXTERNAL_DOUBLE_ELEMENTS: |
5706 case FAST_DOUBLE_ELEMENTS: | 5764 case FAST_DOUBLE_ELEMENTS: |
5707 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5765 case FAST_HOLEY_DOUBLE_ELEMENTS: |
5708 // No contained objects, nothing to do. | 5766 // No contained objects, nothing to do. |
5709 break; | 5767 break; |
5710 } | 5768 } |
5711 return copy; | 5769 return copy; |
5712 } | 5770 } |
5713 | 5771 |
5714 | 5772 |
| 5773 Handle<JSObject> JSObject::DeepCopy(Handle<JSObject> object) { |
| 5774 JSObjectCopyVisitor v; |
| 5775 Handle<JSObject> copy = v.Visit(object); |
| 5776 ASSERT(v.is_copying() && !copy.is_identical_to(object)); |
| 5777 return copy; |
| 5778 } |
| 5779 |
| 5780 |
5715 // Tests for the fast common case for property enumeration: | 5781 // Tests for the fast common case for property enumeration: |
5716 // - This object and all prototypes has an enum cache (which means that | 5782 // - This object and all prototypes has an enum cache (which means that |
5717 // it is no proxy, has no interceptors and needs no access checks). | 5783 // it is no proxy, has no interceptors and needs no access checks). |
5718 // - This object has no elements. | 5784 // - This object has no elements. |
5719 // - No prototype has enumerable properties/elements. | 5785 // - No prototype has enumerable properties/elements. |
5720 bool JSReceiver::IsSimpleEnum() { | 5786 bool JSReceiver::IsSimpleEnum() { |
5721 Heap* heap = GetHeap(); | 5787 Heap* heap = GetHeap(); |
5722 for (Object* o = this; | 5788 for (Object* o = this; |
5723 o != heap->null_value(); | 5789 o != heap->null_value(); |
5724 o = JSObject::cast(o)->GetPrototype()) { | 5790 o = JSObject::cast(o)->GetPrototype()) { |
(...skipping 10394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16119 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16185 #define ERROR_MESSAGES_TEXTS(C, T) T, |
16120 static const char* error_messages_[] = { | 16186 static const char* error_messages_[] = { |
16121 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16187 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
16122 }; | 16188 }; |
16123 #undef ERROR_MESSAGES_TEXTS | 16189 #undef ERROR_MESSAGES_TEXTS |
16124 return error_messages_[reason]; | 16190 return error_messages_[reason]; |
16125 } | 16191 } |
16126 | 16192 |
16127 | 16193 |
16128 } } // namespace v8::internal | 16194 } } // namespace v8::internal |
OLD | NEW |