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