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 14 matching lines...) Expand all Loading... | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
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 // v8::internal::List is inefficient even for small number of elements, if we | |
36 // don't assign any initial capacity. | |
37 #define OBJECT_GROUP_CONNECTIONS_CAPACITY 20 | |
Michael Starzinger
2013/04/22 11:34:51
Make this a "static const int kObjectGroupConntect
marja
2013/04/22 13:49:07
Done.
| |
38 | |
35 namespace v8 { | 39 namespace v8 { |
36 namespace internal { | 40 namespace internal { |
37 | 41 |
38 | 42 |
39 ObjectGroup::~ObjectGroup() { | 43 ObjectGroup::~ObjectGroup() { |
40 if (info_ != NULL) info_->Dispose(); | 44 if (info != NULL) info->Dispose(); |
45 delete[] objects; | |
41 } | 46 } |
42 | 47 |
43 | 48 |
49 ImplicitRefGroup::~ImplicitRefGroup() { | |
50 delete[] children; | |
51 } | |
52 | |
53 | |
44 class GlobalHandles::Node { | 54 class GlobalHandles::Node { |
45 public: | 55 public: |
46 // State transition diagram: | 56 // State transition diagram: |
47 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } | 57 // FREE -> NORMAL <-> WEAK -> PENDING -> NEAR_DEATH -> { NORMAL, WEAK, FREE } |
48 enum State { | 58 enum State { |
49 FREE = 0, | 59 FREE = 0, |
50 NORMAL, // Normal global handle. | 60 NORMAL, // Normal global handle. |
51 WEAK, // Flagged as weak but not yet finalized. | 61 WEAK, // Flagged as weak but not yet finalized. |
52 PENDING, // Has been recognized as only reachable by weak handles. | 62 PENDING, // Has been recognized as only reachable by weak handles. |
53 NEAR_DEATH // Callback has informed the handle is near death. | 63 NEAR_DEATH // Callback has informed the handle is near death. |
(...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
431 DISALLOW_COPY_AND_ASSIGN(NodeIterator); | 441 DISALLOW_COPY_AND_ASSIGN(NodeIterator); |
432 }; | 442 }; |
433 | 443 |
434 | 444 |
435 GlobalHandles::GlobalHandles(Isolate* isolate) | 445 GlobalHandles::GlobalHandles(Isolate* isolate) |
436 : isolate_(isolate), | 446 : isolate_(isolate), |
437 number_of_global_handles_(0), | 447 number_of_global_handles_(0), |
438 first_block_(NULL), | 448 first_block_(NULL), |
439 first_used_block_(NULL), | 449 first_used_block_(NULL), |
440 first_free_(NULL), | 450 first_free_(NULL), |
441 post_gc_processing_count_(0) {} | 451 post_gc_processing_count_(0), |
452 object_group_connections_(OBJECT_GROUP_CONNECTIONS_CAPACITY) {} | |
442 | 453 |
443 | 454 |
444 GlobalHandles::~GlobalHandles() { | 455 GlobalHandles::~GlobalHandles() { |
445 NodeBlock* block = first_block_; | 456 NodeBlock* block = first_block_; |
446 while (block != NULL) { | 457 while (block != NULL) { |
447 NodeBlock* tmp = block->next(); | 458 NodeBlock* tmp = block->next(); |
448 delete block; | 459 delete block; |
449 block = tmp; | 460 block = tmp; |
450 } | 461 } |
451 first_block_ = NULL; | 462 first_block_ = NULL; |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
571 if ((node->is_independent() || node->is_partially_dependent()) && | 582 if ((node->is_independent() || node->is_partially_dependent()) && |
572 node->IsWeakRetainer()) { | 583 node->IsWeakRetainer()) { |
573 v->VisitPointer(node->location()); | 584 v->VisitPointer(node->location()); |
574 } | 585 } |
575 } | 586 } |
576 } | 587 } |
577 | 588 |
578 | 589 |
579 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 590 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
580 WeakSlotCallbackWithHeap can_skip) { | 591 WeakSlotCallbackWithHeap can_skip) { |
592 ComputeObjectGroupsAndImplicitReferences(); | |
581 int last = 0; | 593 int last = 0; |
582 bool any_group_was_visited = false; | 594 bool any_group_was_visited = false; |
583 for (int i = 0; i < object_groups_.length(); i++) { | 595 for (int i = 0; i < object_groups_.length(); i++) { |
584 ObjectGroup* entry = object_groups_.at(i); | 596 ObjectGroup* entry = object_groups_.at(i); |
585 ASSERT(entry != NULL); | 597 ASSERT(entry != NULL); |
586 | 598 |
587 Object*** objects = entry->objects_; | 599 Object*** objects = entry->objects; |
588 bool group_should_be_visited = false; | 600 bool group_should_be_visited = false; |
589 for (size_t j = 0; j < entry->length_; j++) { | 601 for (size_t j = 0; j < entry->length; j++) { |
590 Object* object = *objects[j]; | 602 Object* object = *objects[j]; |
591 if (object->IsHeapObject()) { | 603 if (object->IsHeapObject()) { |
592 if (!can_skip(isolate_->heap(), &object)) { | 604 if (!can_skip(isolate_->heap(), &object)) { |
593 group_should_be_visited = true; | 605 group_should_be_visited = true; |
594 break; | 606 break; |
595 } | 607 } |
596 } | 608 } |
597 } | 609 } |
598 | 610 |
599 if (!group_should_be_visited) { | 611 if (!group_should_be_visited) { |
600 object_groups_[last++] = entry; | 612 object_groups_[last++] = entry; |
601 continue; | 613 continue; |
602 } | 614 } |
603 | 615 |
604 // An object in the group requires visiting, so iterate over all | 616 // An object in the group requires visiting, so iterate over all |
605 // objects in the group. | 617 // objects in the group. |
606 for (size_t j = 0; j < entry->length_; ++j) { | 618 for (size_t j = 0; j < entry->length; ++j) { |
607 Object* object = *objects[j]; | 619 Object* object = *objects[j]; |
608 if (object->IsHeapObject()) { | 620 if (object->IsHeapObject()) { |
609 v->VisitPointer(&object); | 621 v->VisitPointer(&object); |
610 any_group_was_visited = true; | 622 any_group_was_visited = true; |
611 } | 623 } |
612 } | 624 } |
613 | 625 |
614 // Once the entire group has been iterated over, set the object | 626 // Once the entire group has been iterated over, set the object |
615 // group to NULL so it won't be processed again. | 627 // group to NULL so it won't be processed again. |
616 entry->Dispose(); | 628 delete entry; |
617 object_groups_.at(i) = NULL; | 629 object_groups_.at(i) = NULL; |
618 } | 630 } |
619 object_groups_.Rewind(last); | 631 object_groups_.Rewind(last); |
620 return any_group_was_visited; | 632 return any_group_was_visited; |
621 } | 633 } |
622 | 634 |
623 | 635 |
624 bool GlobalHandles::PostGarbageCollectionProcessing( | 636 bool GlobalHandles::PostGarbageCollectionProcessing( |
625 GarbageCollector collector, GCTracer* tracer) { | 637 GarbageCollector collector, GCTracer* tracer) { |
626 // Process weak global handle callbacks. This must be done after the | 638 // Process weak global handle callbacks. This must be done after the |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
817 v8::RetainedObjectInfo* info) { | 829 v8::RetainedObjectInfo* info) { |
818 #ifdef DEBUG | 830 #ifdef DEBUG |
819 for (size_t i = 0; i < length; ++i) { | 831 for (size_t i = 0; i < length; ++i) { |
820 ASSERT(!Node::FromLocation(handles[i])->is_independent()); | 832 ASSERT(!Node::FromLocation(handles[i])->is_independent()); |
821 } | 833 } |
822 #endif | 834 #endif |
823 if (length == 0) { | 835 if (length == 0) { |
824 if (info != NULL) info->Dispose(); | 836 if (info != NULL) info->Dispose(); |
825 return; | 837 return; |
826 } | 838 } |
827 object_groups_.Add(ObjectGroup::New(handles, length, info)); | 839 ObjectGroup* group = new ObjectGroup(length); |
840 for (size_t i = 0; i < length; ++i) | |
841 group->objects[i] = handles[i]; | |
842 group->info = info; | |
843 object_groups_.Add(group); | |
828 } | 844 } |
829 | 845 |
830 | 846 |
847 void GlobalHandles::SetObjectGroupId(Object** handle, | |
848 UniqueId id) { | |
849 object_group_connections_.Add(ObjectGroupConnection(id, handle)); | |
850 } | |
851 | |
852 | |
853 void GlobalHandles::SetRetainedObjectInfo(UniqueId id, | |
854 RetainedObjectInfo* info) { | |
855 retainer_infos_.Add(ObjectGroupRetainerInfo(id, info)); | |
856 } | |
857 | |
858 | |
831 void GlobalHandles::AddImplicitReferences(HeapObject** parent, | 859 void GlobalHandles::AddImplicitReferences(HeapObject** parent, |
832 Object*** children, | 860 Object*** children, |
833 size_t length) { | 861 size_t length) { |
834 #ifdef DEBUG | 862 #ifdef DEBUG |
835 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); | 863 ASSERT(!Node::FromLocation(BitCast<Object**>(parent))->is_independent()); |
836 for (size_t i = 0; i < length; ++i) { | 864 for (size_t i = 0; i < length; ++i) { |
837 ASSERT(!Node::FromLocation(children[i])->is_independent()); | 865 ASSERT(!Node::FromLocation(children[i])->is_independent()); |
838 } | 866 } |
839 #endif | 867 #endif |
840 if (length == 0) return; | 868 if (length == 0) return; |
841 implicit_ref_groups_.Add(ImplicitRefGroup::New(parent, children, length)); | 869 ImplicitRefGroup* group = new ImplicitRefGroup(parent, length); |
870 for (size_t i = 0; i < length; ++i) | |
871 group->children[i] = children[i]; | |
872 implicit_ref_groups_.Add(group); | |
873 } | |
874 | |
875 | |
876 void GlobalHandles::AddImplicitReference(UniqueId id, Object** child) { | |
877 ASSERT(!Node::FromLocation(child)->is_independent()); | |
878 implicit_ref_connections_.Add(ObjectGroupConnection(id, child)); | |
842 } | 879 } |
843 | 880 |
844 | 881 |
845 void GlobalHandles::RemoveObjectGroups() { | 882 void GlobalHandles::RemoveObjectGroups() { |
846 for (int i = 0; i < object_groups_.length(); i++) { | 883 for (int i = 0; i < object_groups_.length(); i++) |
847 object_groups_.at(i)->Dispose(); | 884 delete object_groups_.at(i); |
848 } | |
849 object_groups_.Clear(); | 885 object_groups_.Clear(); |
886 for (int i = 0; i < retainer_infos_.length(); ++i) | |
887 retainer_infos_[i].info->Dispose(); | |
888 retainer_infos_.Clear(); | |
889 object_group_connections_.Clear(); | |
890 object_group_connections_.Initialize(OBJECT_GROUP_CONNECTIONS_CAPACITY); | |
850 } | 891 } |
851 | 892 |
852 | 893 |
853 void GlobalHandles::RemoveImplicitRefGroups() { | 894 void GlobalHandles::RemoveImplicitRefGroups() { |
854 for (int i = 0; i < implicit_ref_groups_.length(); i++) { | 895 for (int i = 0; i < implicit_ref_groups_.length(); i++) { |
855 implicit_ref_groups_.at(i)->Dispose(); | 896 delete implicit_ref_groups_.at(i); |
856 } | 897 } |
857 implicit_ref_groups_.Clear(); | 898 implicit_ref_groups_.Clear(); |
899 implicit_ref_connections_.Clear(); | |
858 } | 900 } |
859 | 901 |
860 | 902 |
861 void GlobalHandles::TearDown() { | 903 void GlobalHandles::TearDown() { |
862 // TODO(1428): invoke weak callbacks. | 904 // TODO(1428): invoke weak callbacks. |
863 } | 905 } |
864 | 906 |
907 void GlobalHandles::ComputeObjectGroupsAndImplicitReferences() { | |
908 if (object_group_connections_.length() == 0) { | |
909 for (int i = 0; i < retainer_infos_.length(); ++i) | |
910 retainer_infos_[i].info->Dispose(); | |
911 retainer_infos_.Clear(); | |
912 implicit_ref_connections_.Clear(); | |
913 return; | |
914 } | |
915 | |
916 object_group_connections_.Sort(); | |
917 retainer_infos_.Sort(); | |
918 implicit_ref_connections_.Sort(); | |
919 | |
920 int info_index = 0; // For iterating retainer_infos_. | |
921 UniqueId current_group_id(0); | |
922 int current_group_start = 0; | |
923 | |
924 int current_implicit_refs_start = 0; | |
925 int current_implicit_refs_end = 0; | |
926 for (int i = 0; i <= object_group_connections_.length(); ++i) { | |
927 if (i == 0) | |
928 current_group_id = object_group_connections_[i].id; | |
929 if (i == object_group_connections_.length() || | |
930 current_group_id != object_group_connections_[i].id) { | |
931 // Group detected: objects in indices [current_group_start, i[. | |
932 | |
933 // Find out which implicit references are related to this group. (We want | |
934 // to ignore object groups which only have 1 object, but that object is | |
935 // needed as a representative object for the implicit refrerence group.) | |
936 while (current_implicit_refs_start < implicit_ref_connections_.length() && | |
937 implicit_ref_connections_[current_implicit_refs_start].id < | |
938 current_group_id) | |
939 ++current_implicit_refs_start; | |
940 current_implicit_refs_end = current_implicit_refs_start; | |
941 while (current_implicit_refs_end < implicit_ref_connections_.length() && | |
942 implicit_ref_connections_[current_implicit_refs_end].id == | |
943 current_group_id) | |
944 ++current_implicit_refs_end; | |
945 | |
946 if (current_implicit_refs_end > current_implicit_refs_start) { | |
947 // Find a representative object for the implicit references. | |
948 HeapObject** representative = NULL; | |
949 for (int j = current_group_start; j < i; ++j) { | |
950 Object** object = object_group_connections_[j].object; | |
951 if ((*object)->IsHeapObject()) { | |
952 representative = reinterpret_cast<HeapObject**>(object); | |
953 break; | |
954 } | |
955 } | |
956 if (representative) { | |
957 ImplicitRefGroup* group = new ImplicitRefGroup( | |
958 representative, | |
959 current_implicit_refs_end - current_implicit_refs_start); | |
960 for (int j = current_implicit_refs_start; | |
961 j < current_implicit_refs_end; | |
962 ++j) { | |
963 group->children[j - current_implicit_refs_start] = | |
964 implicit_ref_connections_[j].object; | |
965 } | |
966 implicit_ref_groups_.Add(group); | |
967 } | |
968 current_implicit_refs_start = current_implicit_refs_end; | |
969 } | |
970 | |
971 // Find a RetainedObjectInfo for the group. | |
972 RetainedObjectInfo* info = NULL; | |
973 while (info_index < retainer_infos_.length() && | |
974 retainer_infos_[info_index].id < current_group_id) { | |
975 retainer_infos_[info_index].info->Dispose(); | |
976 ++info_index; | |
977 } | |
978 if (info_index < retainer_infos_.length() && | |
979 retainer_infos_[info_index].id == current_group_id) { | |
980 // This object group has an associated ObjectGroupRetainerInfo. | |
981 info = retainer_infos_[info_index].info; | |
982 ++info_index; | |
983 } | |
984 | |
985 // Ignore groups which only contain one object. | |
986 if (i > current_group_start + 1) { | |
987 ObjectGroup* group = new ObjectGroup(i - current_group_start); | |
988 for (int j = current_group_start; j < i; ++j) { | |
989 group->objects[j - current_group_start] = | |
990 object_group_connections_[j].object; | |
991 } | |
992 group->info = info; | |
993 object_groups_.Add(group); | |
994 } else if (info) { | |
995 info->Dispose(); | |
996 } | |
997 | |
998 if (i < object_group_connections_.length()) { | |
999 current_group_id = object_group_connections_[i].id; | |
1000 current_group_start = i; | |
1001 } | |
1002 } | |
1003 } | |
1004 object_group_connections_.Clear(); | |
1005 object_group_connections_.Initialize(OBJECT_GROUP_CONNECTIONS_CAPACITY); | |
1006 retainer_infos_.Clear(); | |
1007 implicit_ref_connections_.Clear(); | |
1008 } | |
1009 | |
865 | 1010 |
866 } } // namespace v8::internal | 1011 } } // namespace v8::internal |
OLD | NEW |