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