| 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 |