OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/global-handles.h" | 5 #include "src/global-handles.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 #include "src/vm-state-inl.h" | 9 #include "src/vm-state-inl.h" |
10 | 10 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } | 57 } |
58 | 58 |
59 #ifdef ENABLE_HANDLE_ZAPPING | 59 #ifdef ENABLE_HANDLE_ZAPPING |
60 ~Node() { | 60 ~Node() { |
61 // TODO(1428): if it's a weak handle we should have invoked its callback. | 61 // TODO(1428): if it's a weak handle we should have invoked its callback. |
62 // Zap the values for eager trapping. | 62 // Zap the values for eager trapping. |
63 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 63 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
64 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 64 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
65 index_ = 0; | 65 index_ = 0; |
66 set_independent(false); | 66 set_independent(false); |
67 if (FLAG_scavenge_reclaim_unmodified_objects) { | 67 set_partially_dependent(false); |
68 set_unmodified(false); | |
69 } else { | |
70 set_partially_dependent(false); | |
71 } | |
72 set_in_new_space_list(false); | 68 set_in_new_space_list(false); |
73 parameter_or_next_free_.next_free = NULL; | 69 parameter_or_next_free_.next_free = NULL; |
74 weak_callback_ = NULL; | 70 weak_callback_ = NULL; |
75 } | 71 } |
76 #endif | 72 #endif |
77 | 73 |
78 void Initialize(int index, Node** first_free) { | 74 void Initialize(int index, Node** first_free) { |
79 index_ = static_cast<uint8_t>(index); | 75 index_ = static_cast<uint8_t>(index); |
80 DCHECK(static_cast<int>(index_) == index); | 76 DCHECK(static_cast<int>(index_) == index); |
81 set_state(FREE); | 77 set_state(FREE); |
82 set_weakness_type(NORMAL_WEAK); | 78 set_weakness_type(NORMAL_WEAK); |
83 set_in_new_space_list(false); | 79 set_in_new_space_list(false); |
84 if (FLAG_scavenge_reclaim_unmodified_objects) { | |
85 set_unmodified(false); | |
86 } | |
87 parameter_or_next_free_.next_free = *first_free; | 80 parameter_or_next_free_.next_free = *first_free; |
88 *first_free = this; | 81 *first_free = this; |
89 } | 82 } |
90 | 83 |
91 void Acquire(Object* object) { | 84 void Acquire(Object* object) { |
92 DCHECK(state() == FREE); | 85 DCHECK(state() == FREE); |
93 object_ = object; | 86 object_ = object; |
94 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 87 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
95 set_independent(false); | 88 set_independent(false); |
96 if (FLAG_scavenge_reclaim_unmodified_objects) { | 89 set_partially_dependent(false); |
97 set_unmodified(false); | |
98 } else { | |
99 set_partially_dependent(false); | |
100 } | |
101 set_state(NORMAL); | 90 set_state(NORMAL); |
102 parameter_or_next_free_.parameter = NULL; | 91 parameter_or_next_free_.parameter = NULL; |
103 weak_callback_ = NULL; | 92 weak_callback_ = NULL; |
104 IncreaseBlockUses(); | 93 IncreaseBlockUses(); |
105 } | 94 } |
106 | 95 |
107 void Zap() { | 96 void Zap() { |
108 DCHECK(IsInUse()); | 97 DCHECK(IsInUse()); |
109 // Zap the values for eager trapping. | 98 // Zap the values for eager trapping. |
110 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 99 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
111 } | 100 } |
112 | 101 |
113 void Release() { | 102 void Release() { |
114 DCHECK(IsInUse()); | 103 DCHECK(IsInUse()); |
115 set_state(FREE); | 104 set_state(FREE); |
116 // Zap the values for eager trapping. | 105 // Zap the values for eager trapping. |
117 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); | 106 object_ = reinterpret_cast<Object*>(kGlobalHandleZapValue); |
118 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; | 107 class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId; |
119 set_independent(false); | 108 set_independent(false); |
120 if (FLAG_scavenge_reclaim_unmodified_objects) { | 109 set_partially_dependent(false); |
121 set_unmodified(false); | |
122 } else { | |
123 set_partially_dependent(false); | |
124 } | |
125 weak_callback_ = NULL; | 110 weak_callback_ = NULL; |
126 DecreaseBlockUses(); | 111 DecreaseBlockUses(); |
127 } | 112 } |
128 | 113 |
129 // Object slot accessors. | 114 // Object slot accessors. |
130 Object* object() const { return object_; } | 115 Object* object() const { return object_; } |
131 Object** location() { return &object_; } | 116 Object** location() { return &object_; } |
132 Handle<Object> handle() { return Handle<Object>(location()); } | 117 Handle<Object> handle() { return Handle<Object>(location()); } |
133 | 118 |
134 // Wrapper class ID accessors. | 119 // Wrapper class ID accessors. |
(...skipping 13 matching lines...) Expand all Loading... |
148 } | 133 } |
149 | 134 |
150 bool is_independent() { | 135 bool is_independent() { |
151 return IsIndependent::decode(flags_); | 136 return IsIndependent::decode(flags_); |
152 } | 137 } |
153 void set_independent(bool v) { | 138 void set_independent(bool v) { |
154 flags_ = IsIndependent::update(flags_, v); | 139 flags_ = IsIndependent::update(flags_, v); |
155 } | 140 } |
156 | 141 |
157 bool is_partially_dependent() { | 142 bool is_partially_dependent() { |
158 CHECK(!FLAG_scavenge_reclaim_unmodified_objects); | |
159 return IsPartiallyDependent::decode(flags_); | 143 return IsPartiallyDependent::decode(flags_); |
160 } | 144 } |
161 void set_partially_dependent(bool v) { | 145 void set_partially_dependent(bool v) { |
162 CHECK(!FLAG_scavenge_reclaim_unmodified_objects); | |
163 flags_ = IsPartiallyDependent::update(flags_, v); | 146 flags_ = IsPartiallyDependent::update(flags_, v); |
164 } | 147 } |
165 | 148 |
166 bool is_unmodified() { | |
167 CHECK(FLAG_scavenge_reclaim_unmodified_objects); | |
168 return IsUnmodified::decode(flags_); | |
169 } | |
170 void set_unmodified(bool v) { | |
171 CHECK(FLAG_scavenge_reclaim_unmodified_objects); | |
172 flags_ = IsUnmodified::update(flags_, v); | |
173 } | |
174 | |
175 bool is_in_new_space_list() { | 149 bool is_in_new_space_list() { |
176 return IsInNewSpaceList::decode(flags_); | 150 return IsInNewSpaceList::decode(flags_); |
177 } | 151 } |
178 void set_in_new_space_list(bool v) { | 152 void set_in_new_space_list(bool v) { |
179 flags_ = IsInNewSpaceList::update(flags_, v); | 153 flags_ = IsInNewSpaceList::update(flags_, v); |
180 } | 154 } |
181 | 155 |
182 WeaknessType weakness_type() const { | 156 WeaknessType weakness_type() const { |
183 return NodeWeaknessType::decode(flags_); | 157 return NodeWeaknessType::decode(flags_); |
184 } | 158 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 // Wrapper class ID. | 342 // Wrapper class ID. |
369 uint16_t class_id_; | 343 uint16_t class_id_; |
370 | 344 |
371 // Index in the containing handle block. | 345 // Index in the containing handle block. |
372 uint8_t index_; | 346 uint8_t index_; |
373 | 347 |
374 // This stores three flags (independent, partially_dependent and | 348 // This stores three flags (independent, partially_dependent and |
375 // in_new_space_list) and a State. | 349 // in_new_space_list) and a State. |
376 class NodeState : public BitField<State, 0, 3> {}; | 350 class NodeState : public BitField<State, 0, 3> {}; |
377 class IsIndependent : public BitField<bool, 3, 1> {}; | 351 class IsIndependent : public BitField<bool, 3, 1> {}; |
378 // The following two fields are mutually exclusive | |
379 class IsUnmodified : public BitField<bool, 4, 1> {}; | |
380 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; | 352 class IsPartiallyDependent : public BitField<bool, 4, 1> {}; |
381 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; | 353 class IsInNewSpaceList : public BitField<bool, 5, 1> {}; |
382 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; | 354 class NodeWeaknessType : public BitField<WeaknessType, 6, 2> {}; |
383 | 355 |
384 uint8_t flags_; | 356 uint8_t flags_; |
385 | 357 |
386 // Handle specific callback - might be a weak reference in disguise. | 358 // Handle specific callback - might be a weak reference in disguise. |
387 WeakCallback weak_callback_; | 359 WeakCallback weak_callback_; |
388 | 360 |
389 // Provided data for callback. In FREE state, this is used for | 361 // Provided data for callback. In FREE state, this is used for |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 if (it.node()->IsWeak() && f(it.node()->location())) { | 639 if (it.node()->IsWeak() && f(it.node()->location())) { |
668 it.node()->MarkPending(); | 640 it.node()->MarkPending(); |
669 } | 641 } |
670 } | 642 } |
671 } | 643 } |
672 | 644 |
673 | 645 |
674 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { | 646 void GlobalHandles::IterateNewSpaceStrongAndDependentRoots(ObjectVisitor* v) { |
675 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 647 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
676 Node* node = new_space_nodes_[i]; | 648 Node* node = new_space_nodes_[i]; |
677 if (FLAG_scavenge_reclaim_unmodified_objects) { | 649 if (node->IsStrongRetainer() || |
678 if (node->IsStrongRetainer() || | 650 (node->IsWeakRetainer() && !node->is_independent() && |
679 (node->IsWeakRetainer() && !node->is_independent() && | 651 !node->is_partially_dependent())) { |
680 !node->is_unmodified())) { | |
681 v->VisitPointer(node->location()); | 652 v->VisitPointer(node->location()); |
682 } | |
683 } else { | |
684 if (node->IsStrongRetainer() || | |
685 (node->IsWeakRetainer() && !node->is_independent() && | |
686 !node->is_partially_dependent())) { | |
687 v->VisitPointer(node->location()); | |
688 } | |
689 } | 653 } |
690 } | 654 } |
691 } | 655 } |
692 | 656 |
693 | 657 |
694 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( | 658 void GlobalHandles::IdentifyNewSpaceWeakIndependentHandles( |
695 WeakSlotCallbackWithHeap f) { | 659 WeakSlotCallbackWithHeap f) { |
696 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 660 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
697 Node* node = new_space_nodes_[i]; | 661 Node* node = new_space_nodes_[i]; |
698 DCHECK(node->is_in_new_space_list()); | 662 DCHECK(node->is_in_new_space_list()); |
(...skipping 17 matching lines...) Expand all Loading... |
716 node->CollectPhantomCallbackData(isolate(), | 680 node->CollectPhantomCallbackData(isolate(), |
717 &pending_phantom_callbacks_); | 681 &pending_phantom_callbacks_); |
718 } else { | 682 } else { |
719 v->VisitPointer(node->location()); | 683 v->VisitPointer(node->location()); |
720 } | 684 } |
721 } | 685 } |
722 } | 686 } |
723 } | 687 } |
724 | 688 |
725 | 689 |
726 void GlobalHandles::IdentifyWeakUnmodifiedObjects( | |
727 WeakSlotCallback is_unmodified) { | |
728 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
729 Node* node = new_space_nodes_[i]; | |
730 if (node->IsWeak() && is_unmodified(node->location())) { | |
731 node->set_unmodified(true); | |
732 } | |
733 } | |
734 } | |
735 | |
736 | |
737 void GlobalHandles::MarkNewSpaceWeakUnmodifiedObjectsPending( | |
738 WeakSlotCallbackWithHeap is_unscavenged) { | |
739 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
740 Node* node = new_space_nodes_[i]; | |
741 DCHECK(node->is_in_new_space_list()); | |
742 if ((node->is_independent() || node->is_unmodified()) && node->IsWeak() && | |
743 is_unscavenged(isolate_->heap(), node->location())) { | |
744 node->MarkPending(); | |
745 } | |
746 } | |
747 } | |
748 | |
749 | |
750 void GlobalHandles::IterateNewSpaceWeakUnmodifiedRoots(ObjectVisitor* v) { | |
751 for (int i = 0; i < new_space_nodes_.length(); ++i) { | |
752 Node* node = new_space_nodes_[i]; | |
753 DCHECK(node->is_in_new_space_list()); | |
754 if ((node->is_independent() || node->is_unmodified()) && | |
755 node->IsWeakRetainer()) { | |
756 // Pending weak phantom handles die immediately. Everything else survives. | |
757 if (node->state() == Node::PENDING && | |
758 node->weakness_type() != NORMAL_WEAK) { | |
759 node->CollectPhantomCallbackData(isolate(), | |
760 &pending_phantom_callbacks_); | |
761 } else { | |
762 v->VisitPointer(node->location()); | |
763 } | |
764 } | |
765 } | |
766 } | |
767 | |
768 | |
769 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, | 690 bool GlobalHandles::IterateObjectGroups(ObjectVisitor* v, |
770 WeakSlotCallbackWithHeap can_skip) { | 691 WeakSlotCallbackWithHeap can_skip) { |
771 ComputeObjectGroupsAndImplicitReferences(); | 692 ComputeObjectGroupsAndImplicitReferences(); |
772 int last = 0; | 693 int last = 0; |
773 bool any_group_was_visited = false; | 694 bool any_group_was_visited = false; |
774 for (int i = 0; i < object_groups_.length(); i++) { | 695 for (int i = 0; i < object_groups_.length(); i++) { |
775 ObjectGroup* entry = object_groups_.at(i); | 696 ObjectGroup* entry = object_groups_.at(i); |
776 DCHECK(entry != NULL); | 697 DCHECK(entry != NULL); |
777 | 698 |
778 Object*** objects = entry->objects; | 699 Object*** objects = entry->objects; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
829 const int initial_post_gc_processing_count) { | 750 const int initial_post_gc_processing_count) { |
830 int freed_nodes = 0; | 751 int freed_nodes = 0; |
831 for (int i = 0; i < new_space_nodes_.length(); ++i) { | 752 for (int i = 0; i < new_space_nodes_.length(); ++i) { |
832 Node* node = new_space_nodes_[i]; | 753 Node* node = new_space_nodes_[i]; |
833 DCHECK(node->is_in_new_space_list()); | 754 DCHECK(node->is_in_new_space_list()); |
834 if (!node->IsRetainer()) { | 755 if (!node->IsRetainer()) { |
835 // Free nodes do not have weak callbacks. Do not use them to compute | 756 // Free nodes do not have weak callbacks. Do not use them to compute |
836 // the freed_nodes. | 757 // the freed_nodes. |
837 continue; | 758 continue; |
838 } | 759 } |
839 // Skip dependent or unmodified handles. Their weak callbacks might expect | 760 // Skip dependent handles. Their weak callbacks might expect to be |
840 // to be | |
841 // called between two global garbage collection callbacks which | 761 // called between two global garbage collection callbacks which |
842 // are not called for minor collections. | 762 // are not called for minor collections. |
843 if (FLAG_scavenge_reclaim_unmodified_objects) { | 763 if (!node->is_independent() && !node->is_partially_dependent()) { |
844 if (!node->is_independent() && !node->is_unmodified()) { | 764 continue; |
845 continue; | |
846 } | |
847 node->set_unmodified(false); | |
848 } else { | |
849 if (!node->is_independent() && !node->is_partially_dependent()) { | |
850 continue; | |
851 } | |
852 node->clear_partially_dependent(); | |
853 } | 765 } |
854 | 766 node->clear_partially_dependent(); |
855 if (node->PostGarbageCollectionProcessing(isolate_)) { | 767 if (node->PostGarbageCollectionProcessing(isolate_)) { |
856 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 768 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
857 // Weak callback triggered another GC and another round of | 769 // Weak callback triggered another GC and another round of |
858 // PostGarbageCollection processing. The current node might | 770 // PostGarbageCollection processing. The current node might |
859 // have been deleted in that round, so we need to bail out (or | 771 // have been deleted in that round, so we need to bail out (or |
860 // restart the processing). | 772 // restart the processing). |
861 return freed_nodes; | 773 return freed_nodes; |
862 } | 774 } |
863 } | 775 } |
864 if (!node->IsRetainer()) { | 776 if (!node->IsRetainer()) { |
865 freed_nodes++; | 777 freed_nodes++; |
866 } | 778 } |
867 } | 779 } |
868 return freed_nodes; | 780 return freed_nodes; |
869 } | 781 } |
870 | 782 |
871 | 783 |
872 int GlobalHandles::PostMarkSweepProcessing( | 784 int GlobalHandles::PostMarkSweepProcessing( |
873 const int initial_post_gc_processing_count) { | 785 const int initial_post_gc_processing_count) { |
874 int freed_nodes = 0; | 786 int freed_nodes = 0; |
875 for (NodeIterator it(this); !it.done(); it.Advance()) { | 787 for (NodeIterator it(this); !it.done(); it.Advance()) { |
876 if (!it.node()->IsRetainer()) { | 788 if (!it.node()->IsRetainer()) { |
877 // Free nodes do not have weak callbacks. Do not use them to compute | 789 // Free nodes do not have weak callbacks. Do not use them to compute |
878 // the freed_nodes. | 790 // the freed_nodes. |
879 continue; | 791 continue; |
880 } | 792 } |
881 if (FLAG_scavenge_reclaim_unmodified_objects) { | 793 it.node()->clear_partially_dependent(); |
882 it.node()->set_unmodified(false); | |
883 } else { | |
884 it.node()->clear_partially_dependent(); | |
885 } | |
886 if (it.node()->PostGarbageCollectionProcessing(isolate_)) { | 794 if (it.node()->PostGarbageCollectionProcessing(isolate_)) { |
887 if (initial_post_gc_processing_count != post_gc_processing_count_) { | 795 if (initial_post_gc_processing_count != post_gc_processing_count_) { |
888 // See the comment above. | 796 // See the comment above. |
889 return freed_nodes; | 797 return freed_nodes; |
890 } | 798 } |
891 } | 799 } |
892 if (!it.node()->IsRetainer()) { | 800 if (!it.node()->IsRetainer()) { |
893 freed_nodes++; | 801 freed_nodes++; |
894 } | 802 } |
895 } | 803 } |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 blocks_[block][offset] = object; | 1274 blocks_[block][offset] = object; |
1367 if (isolate->heap()->InNewSpace(object)) { | 1275 if (isolate->heap()->InNewSpace(object)) { |
1368 new_space_indices_.Add(size_); | 1276 new_space_indices_.Add(size_); |
1369 } | 1277 } |
1370 *index = size_++; | 1278 *index = size_++; |
1371 } | 1279 } |
1372 | 1280 |
1373 | 1281 |
1374 } // namespace internal | 1282 } // namespace internal |
1375 } // namespace v8 | 1283 } // namespace v8 |
OLD | NEW |