OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #include "api.h" | 30 #include "api.h" |
31 #include "global-handles.h" | 31 #include "global-handles.h" |
32 | 32 |
33 #include "vm-state-inl.h" | 33 #include "vm-state-inl.h" |
34 | 34 |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
| 39 ObjectGroup::~ObjectGroup() { |
| 40 if (info_ != NULL) info_->Dispose(); |
| 41 } |
| 42 |
| 43 |
39 class GlobalHandles::Node { | 44 class GlobalHandles::Node { |
40 public: | 45 public: |
41 // State transition diagram: | 46 // State transition diagram: |
42 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
43 enum State { | 48 enum State { |
44 FREE = 0, | 49 FREE = 0, |
45 NORMAL, // Normal global handle. | 50 NORMAL, // Normal global handle. |
46 WEAK, // Flagged as weak but not yet finalized. | 51 WEAK, // Flagged as weak but not yet finalized. |
47 PENDING, // Has been recognized as only reachable by weak handles. | 52 PENDING, // Has been recognized as only reachable by weak handles. |
48 NEAR_DEATH // Callback has informed the handle is near death. | 53 NEAR_DEATH // Callback has informed the handle is near death. |
(...skipping 517 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 if ((node->is_independent() || node->is_partially_dependent()) && | 571 if ((node->is_independent() || node->is_partially_dependent()) && |
567 node->IsWeakRetainer()) { | 572 node->IsWeakRetainer()) { |
568 v->VisitPointer(node->location()); | 573 v->VisitPointer(node->location()); |
569 } | 574 } |
570 } | 575 } |
571 } | 576 } |
572 | 577 |
573 | 578 |
574 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 579 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
575 WeakSlotCallbackWithHeap can_skip) { | 580 WeakSlotCallbackWithHeap can_skip) { |
576 if (object_groups_.length() == 0) | 581 int last = 0; |
577 return false; | 582 bool any_group_was_visited = false; |
| 583 for (int i = 0; i < object_groups_.length(); i++) { |
| 584 ObjectGroup* entry = object_groups_.at(i); |
| 585 ASSERT(entry != NULL); |
578 | 586 |
579 object_groups_.Sort(); | 587 Object*** objects = entry->objects_; |
580 retainer_infos_.Sort(); | 588 bool group_should_be_visited = false; |
581 | 589 for (size_t j = 0; j < entry->length_; j++) { |
582 // During the iteration, some of the elements of object_groups are | 590 Object* object = *objects[j]; |
583 // deleted. This is done by moving surviving elements at the front of the list | 591 if (object->IsHeapObject()) { |
584 // and deleting from the end. This index tracks where the next surviving | 592 if (!can_skip(isolate_->heap(), &object)) { |
585 // element should be moved. | 593 group_should_be_visited = true; |
586 int surviving_element_index = 0; | 594 break; |
587 int info_index = 0; // For iterating retainer_infos_. | |
588 int surviving_info_index = 0; | |
589 | |
590 UniqueId current_group_id(0); | |
591 int current_group_start = 0; | |
592 bool any_group_was_visited = false; | |
593 | |
594 for (int i = 0; i <= object_groups_.length(); ++i) { | |
595 if (i == 0) | |
596 current_group_id = object_groups_[i].id; | |
597 if (i == object_groups_.length() || | |
598 current_group_id != object_groups_[i].id) { | |
599 // Group detected: objects in indices [current_group_start, i[. | |
600 bool group_should_be_visited = false; | |
601 for (int j = current_group_start; j < i; ++j) { | |
602 Object* object = *(object_groups_[j].object); | |
603 if (object->IsHeapObject()) { | |
604 if (!can_skip(isolate_->heap(), &object)) { | |
605 group_should_be_visited = true; | |
606 break; | |
607 } | |
608 } | 595 } |
609 } | 596 } |
| 597 } |
610 | 598 |
611 if (!group_should_be_visited) { | 599 if (!group_should_be_visited) { |
612 for (int j = current_group_start; j < i; ++j) | 600 object_groups_[last++] = entry; |
613 object_groups_[surviving_element_index++] = object_groups_[j]; | 601 continue; |
614 } else { | 602 } |
615 // An object in the group requires visiting, so iterate over all | |
616 // objects in the group. | |
617 for (int j = current_group_start; j < i; ++j) { | |
618 Object* object = *(object_groups_[j].object); | |
619 if (object->IsHeapObject()) { | |
620 v->VisitPointer(&object); | |
621 any_group_was_visited = true; | |
622 } | |
623 } | |
624 } | |
625 | 603 |
626 if (info_index < retainer_infos_.length() && | 604 // An object in the group requires visiting, so iterate over all |
627 retainer_infos_[info_index].id == | 605 // objects in the group. |
628 object_groups_[current_group_start].id) { | 606 for (size_t j = 0; j < entry->length_; ++j) { |
629 // This object group has an associated ObjectGroupRetainerInfo. | 607 Object* object = *objects[j]; |
630 if (!group_should_be_visited) { | 608 if (object->IsHeapObject()) { |
631 retainer_infos_[surviving_info_index++] = | 609 v->VisitPointer(&object); |
632 retainer_infos_[info_index]; | 610 any_group_was_visited = true; |
633 } else if (retainer_infos_[info_index].info != NULL) { | |
634 retainer_infos_[info_index].info->Dispose(); | |
635 retainer_infos_[info_index].info = NULL; | |
636 } | |
637 ++info_index; | |
638 } | |
639 if (i < object_groups_.length()) { | |
640 current_group_id = object_groups_[i].id; | |
641 current_group_start = i; | |
642 } | 611 } |
643 } | 612 } |
| 613 |
| 614 // Once the entire group has been iterated over, set the object |
| 615 // group to NULL so it won't be processed again. |
| 616 entry->Dispose(); |
| 617 object_groups_.at(i) = NULL; |
644 } | 618 } |
645 object_groups_.Rewind(surviving_element_index); | 619 object_groups_.Rewind(last); |
646 retainer_infos_.Rewind(surviving_info_index); | |
647 return any_group_was_visited; | 620 return any_group_was_visited; |
648 } | 621 } |
649 | 622 |
650 | 623 |
651 bool GlobalHandles::PostGarbageCollectionProcessing( | 624 bool GlobalHandles::PostGarbageCollectionProcessing( |
652 GarbageCollector collector, GCTracer* tracer) { | 625 GarbageCollector collector, GCTracer* tracer) { |
653 // Process weak global handle callbacks. This must be done after the | 626 // Process weak global handle callbacks. This must be done after the |
654 // GC is completely done, because the callbacks may invoke arbitrary | 627 // GC is completely done, because the callbacks may invoke arbitrary |
655 // API functions. | 628 // API functions. |
656 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); | 629 ASSERT(isolate_->heap()->gc_state() == Heap::NOT_IN_GC); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
844 v8::RetainedObjectInfo* info) { | 817 v8::RetainedObjectInfo* info) { |
845 #ifdef DEBUG | 818 #ifdef DEBUG |
846 for (size_t i = 0; i < length; ++i) { | 819 for (size_t i = 0; i < length; ++i) { |
847 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 820 ASSERT(!Node::FromLocation(handles[i])->is_independent()); |
848 } | 821 } |
849 #endif | 822 #endif |
850 if (length == 0) { | 823 if (length == 0) { |
851 if (info != NULL) info->Dispose(); | 824 if (info != NULL) info->Dispose(); |
852 return; | 825 return; |
853 } | 826 } |
854 for (size_t i = 0; i < length; ++i) { | 827 object_groups_.Add(ObjectGroup::New(handles, length, info)); |
855 object_groups_.Add(ObjectGroupConnection( | |
856 UniqueId(reinterpret_cast<intptr_t>(handles[0])), handles[i])); | |
857 } | |
858 for (size_t i = 0; i < length; ++i) { | |
859 if ((*handles[i])->IsHeapObject()) { | |
860 representative_objects_.Add(ObjectGroupRepresentative( | |
861 UniqueId(reinterpret_cast<intptr_t>(handles[0])), | |
862 reinterpret_cast<HeapObject**>(handles[i]))); | |
863 break; | |
864 } | |
865 } | |
866 if (info != NULL) { | |
867 retainer_infos_.Add(ObjectGroupRetainerInfo( | |
868 UniqueId(reinterpret_cast<intptr_t>(handles[0])), info)); | |
869 } | |
870 } | |
871 | |
872 void GlobalHandles::SetObjectGroupId(Object** handle, | |
873 UniqueId id) { | |
874 object_groups_.Add(ObjectGroupConnection(id, handle)); | |
875 } | 828 } |
876 | 829 |
877 | 830 |
878 void GlobalHandles::SetRetainedObjectInfo(UniqueId id, | |
879 RetainedObjectInfo* info) { | |
880 retainer_infos_.Add(ObjectGroupRetainerInfo(id, info)); | |
881 } | |
882 | |
883 | |
884 void GlobalHandles::SetObjectGroupRepresentative( | |
885 UniqueId id, | |
886 HeapObject** representative_object) { | |
887 representative_objects_.Add( | |
888 ObjectGroupRepresentative(id, representative_object)); | |
889 } | |
890 | |
891 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 831 void GlobalHandles::AddImplicitReferences(HeapObject** parent, |
892 Object*** children, | 832 Object*** children, |
893 size_t length) { | 833 size_t length) { |
894 #ifdef DEBUG | 834 #ifdef DEBUG |
895 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 835 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); |
896 for (size_t i = 0; i < length; ++i) { | 836 for (size_t i = 0; i < length; ++i) { |
897 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 837 ASSERT(!Node::FromLocation(children[i])->is_independent()); |
898 } | 838 } |
899 #endif | 839 #endif |
900 for (size_t i = 0; i < length; ++i) { | 840 if (length == 0) return; |
901 implicit_ref_groups_.Add(ObjectGroupConnection( | 841 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); |
902 UniqueId(reinterpret_cast<intptr_t>(parent)), children[i])); | |
903 } | |
904 } | |
905 | |
906 | |
907 void GlobalHandles::AddImplicitReference(UniqueId id, Object** child) { | |
908 ASSERT(!Node::FromLocation(child)->is_independent()); | |
909 implicit_ref_groups_.Add(ObjectGroupConnection(id, child)); | |
910 } | 842 } |
911 | 843 |
912 | 844 |
913 void GlobalHandles::RemoveObjectGroups() { | 845 void GlobalHandles::RemoveObjectGroups() { |
| 846 for (int i = 0; i < object_groups_.length(); i++) { |
| 847 object_groups_.at(i)->Dispose(); |
| 848 } |
914 object_groups_.Clear(); | 849 object_groups_.Clear(); |
915 for (int i = 0; i < retainer_infos_.length(); ++i) { | |
916 if (retainer_infos_[i].info != NULL) | |
917 retainer_infos_[i].info->Dispose(); | |
918 } | |
919 retainer_infos_.Clear(); | |
920 } | 850 } |
921 | 851 |
922 | 852 |
923 void GlobalHandles::RemoveImplicitRefGroups() { | 853 void GlobalHandles::RemoveImplicitRefGroups() { |
924 representative_objects_.Clear(); | 854 for (int i = 0; i < implicit_ref_groups_.length(); i++) { |
| 855 implicit_ref_groups_.at(i)->Dispose(); |
| 856 } |
925 implicit_ref_groups_.Clear(); | 857 implicit_ref_groups_.Clear(); |
926 } | 858 } |
927 | 859 |
928 | 860 |
929 void GlobalHandles::TearDown() { | 861 void GlobalHandles::TearDown() { |
930 // TODO(1428): invoke weak callbacks. | 862 // TODO(1428): invoke weak callbacks. |
931 } | 863 } |
932 | 864 |
933 | 865 |
934 } } // namespace v8::internal | 866 } } // namespace v8::internal |
OLD | NEW |