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