Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/objects.cc

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

Powered by Google App Engine
This is Rietveld 408576698