Mercurial > hg > graal-jvmci-8
comparison src/share/vm/oops/methodDataOop.cpp @ 941:8b46c4d82093
4957990: Perm heap bloat in JVM
Summary: Treat ProfileData in MDO's as a source of weak, not strong, roots. Fixes the bug for stop-world collection -- the case of concurrent collection will be fixed separately.
Reviewed-by: jcoomes, jmasa, kvn, never
author | ysr |
---|---|
date | Wed, 02 Sep 2009 00:04:29 -0700 |
parents | bd02caa94611 |
children | c18cbe5936b8 |
comparison
equal
deleted
inserted
replaced
940:8624da129f0b | 941:8b46c4d82093 |
---|---|
47 if (needs_array_len(tag)) { | 47 if (needs_array_len(tag)) { |
48 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. | 48 set_cell_at(ArrayData::array_len_off_set, cell_count - 1); // -1 for header. |
49 } | 49 } |
50 } | 50 } |
51 | 51 |
52 void DataLayout::follow_weak_refs(BoolObjectClosure* cl) { | |
53 ResourceMark m; | |
54 data_in()->follow_weak_refs(cl); | |
55 } | |
56 | |
57 | |
52 // ================================================================== | 58 // ================================================================== |
53 // ProfileData | 59 // ProfileData |
54 // | 60 // |
55 // A ProfileData object is created to refer to a section of profiling | 61 // A ProfileData object is created to refer to a section of profiling |
56 // data in a structured way. | 62 // data in a structured way. |
143 // dynamic type check. It consists of a counter which counts the total times | 149 // dynamic type check. It consists of a counter which counts the total times |
144 // that the check is reached, and a series of (klassOop, count) pairs | 150 // that the check is reached, and a series of (klassOop, count) pairs |
145 // which are used to store a type profile for the receiver of the check. | 151 // which are used to store a type profile for the receiver of the check. |
146 | 152 |
147 void ReceiverTypeData::follow_contents() { | 153 void ReceiverTypeData::follow_contents() { |
148 for (uint row = 0; row < row_limit(); row++) { | 154 // This is a set of weak references that need |
149 if (receiver(row) != NULL) { | 155 // to be followed at the end of the strong marking |
150 MarkSweep::mark_and_push(adr_receiver(row)); | 156 // phase. Memoize this object so it can be visited |
151 } | 157 // in the weak roots processing phase. |
152 } | 158 MarkSweep::revisit_mdo(data()); |
153 } | 159 } |
154 | 160 |
155 #ifndef SERIALGC | 161 #ifndef SERIALGC |
156 void ReceiverTypeData::follow_contents(ParCompactionManager* cm) { | 162 void ReceiverTypeData::follow_contents(ParCompactionManager* cm) { |
157 for (uint row = 0; row < row_limit(); row++) { | 163 // This is a set of weak references that need |
158 if (receiver(row) != NULL) { | 164 // to be followed at the end of the strong marking |
159 PSParallelCompact::mark_and_push(cm, adr_receiver(row)); | 165 // phase. Memoize this object so it can be visited |
160 } | 166 // in the weak roots processing phase. |
161 } | 167 PSParallelCompact::revisit_mdo(cm, data()); |
162 } | 168 } |
163 #endif // SERIALGC | 169 #endif // SERIALGC |
164 | 170 |
165 void ReceiverTypeData::oop_iterate(OopClosure* blk) { | 171 void ReceiverTypeData::oop_iterate(OopClosure* blk) { |
166 for (uint row = 0; row < row_limit(); row++) { | 172 if (blk->should_remember_mdo()) { |
167 if (receiver(row) != NULL) { | 173 // This is a set of weak references that need |
168 blk->do_oop(adr_receiver(row)); | 174 // to be followed at the end of the strong marking |
175 // phase. Memoize this object so it can be visited | |
176 // in the weak roots processing phase. | |
177 blk->remember_mdo(data()); | |
178 } else { // normal scan | |
179 for (uint row = 0; row < row_limit(); row++) { | |
180 if (receiver(row) != NULL) { | |
181 oop* adr = adr_receiver(row); | |
182 blk->do_oop(adr); | |
183 } | |
169 } | 184 } |
170 } | 185 } |
171 } | 186 } |
172 | 187 |
173 void ReceiverTypeData::oop_iterate_m(OopClosure* blk, MemRegion mr) { | 188 void ReceiverTypeData::oop_iterate_m(OopClosure* blk, MemRegion mr) { |
189 // Currently, this interface is called only during card-scanning for | |
190 // a young gen gc, in which case this object cannot contribute anything, | |
191 // since it does not contain any references that cross out of | |
192 // the perm gen. However, for future more general use we allow | |
193 // the possibility of calling for instance from more general | |
194 // iterators (for example, a future regionalized perm gen for G1, | |
195 // or the possibility of moving some references out of perm in | |
196 // the case of other collectors). In that case, you will need | |
197 // to relax or remove some of the assertions below. | |
198 #ifdef ASSERT | |
199 // Verify that none of the embedded oop references cross out of | |
200 // this generation. | |
174 for (uint row = 0; row < row_limit(); row++) { | 201 for (uint row = 0; row < row_limit(); row++) { |
175 if (receiver(row) != NULL) { | 202 if (receiver(row) != NULL) { |
176 oop* adr = adr_receiver(row); | 203 oop* adr = adr_receiver(row); |
177 if (mr.contains(adr)) { | 204 CollectedHeap* h = Universe::heap(); |
178 blk->do_oop(adr); | 205 assert(h->is_permanent(adr) && h->is_permanent_or_null(*adr), "Not intra-perm"); |
206 } | |
207 } | |
208 #endif // ASSERT | |
209 assert(!blk->should_remember_mdo(), "Not expected to remember MDO"); | |
210 return; // Nothing to do, see comment above | |
211 #if 0 | |
212 if (blk->should_remember_mdo()) { | |
213 // This is a set of weak references that need | |
214 // to be followed at the end of the strong marking | |
215 // phase. Memoize this object so it can be visited | |
216 // in the weak roots processing phase. | |
217 blk->remember_mdo(data()); | |
218 } else { // normal scan | |
219 for (uint row = 0; row < row_limit(); row++) { | |
220 if (receiver(row) != NULL) { | |
221 oop* adr = adr_receiver(row); | |
222 if (mr.contains(adr)) { | |
223 blk->do_oop(adr); | |
224 } else if ((HeapWord*)adr >= mr.end()) { | |
225 // Test that the current cursor and the two ends of the range | |
226 // that we may have skipped iterating over are monotonically ordered; | |
227 // this is just a paranoid assertion, just in case represetations | |
228 // should change in the future rendering the short-circuit return | |
229 // here invalid. | |
230 assert((row+1 >= row_limit() || adr_receiver(row+1) > adr) && | |
231 (row+2 >= row_limit() || adr_receiver(row_limit()-1) > adr_receiver(row+1)), "Reducing?"); | |
232 break; // remaining should be outside this mr too | |
233 } | |
179 } | 234 } |
180 } | 235 } |
181 } | 236 } |
237 #endif | |
182 } | 238 } |
183 | 239 |
184 void ReceiverTypeData::adjust_pointers() { | 240 void ReceiverTypeData::adjust_pointers() { |
185 for (uint row = 0; row < row_limit(); row++) { | 241 for (uint row = 0; row < row_limit(); row++) { |
186 if (receiver(row) != NULL) { | 242 if (receiver(row) != NULL) { |
187 MarkSweep::adjust_pointer(adr_receiver(row)); | 243 MarkSweep::adjust_pointer(adr_receiver(row)); |
244 } | |
245 } | |
246 } | |
247 | |
248 void ReceiverTypeData::follow_weak_refs(BoolObjectClosure* is_alive_cl) { | |
249 for (uint row = 0; row < row_limit(); row++) { | |
250 klassOop p = receiver(row); | |
251 if (p != NULL && !is_alive_cl->do_object_b(p)) { | |
252 clear_row(row); | |
188 } | 253 } |
189 } | 254 } |
190 } | 255 } |
191 | 256 |
192 #ifndef SERIALGC | 257 #ifndef SERIALGC |
623 ProfileData* methodDataOopDesc::data_at(int data_index) { | 688 ProfileData* methodDataOopDesc::data_at(int data_index) { |
624 if (out_of_bounds(data_index)) { | 689 if (out_of_bounds(data_index)) { |
625 return NULL; | 690 return NULL; |
626 } | 691 } |
627 DataLayout* data_layout = data_layout_at(data_index); | 692 DataLayout* data_layout = data_layout_at(data_index); |
628 | 693 return data_layout->data_in(); |
629 switch (data_layout->tag()) { | 694 } |
695 | |
696 ProfileData* DataLayout::data_in() { | |
697 switch (tag()) { | |
630 case DataLayout::no_tag: | 698 case DataLayout::no_tag: |
631 default: | 699 default: |
632 ShouldNotReachHere(); | 700 ShouldNotReachHere(); |
633 return NULL; | 701 return NULL; |
634 case DataLayout::bit_data_tag: | 702 case DataLayout::bit_data_tag: |
635 return new BitData(data_layout); | 703 return new BitData(this); |
636 case DataLayout::counter_data_tag: | 704 case DataLayout::counter_data_tag: |
637 return new CounterData(data_layout); | 705 return new CounterData(this); |
638 case DataLayout::jump_data_tag: | 706 case DataLayout::jump_data_tag: |
639 return new JumpData(data_layout); | 707 return new JumpData(this); |
640 case DataLayout::receiver_type_data_tag: | 708 case DataLayout::receiver_type_data_tag: |
641 return new ReceiverTypeData(data_layout); | 709 return new ReceiverTypeData(this); |
642 case DataLayout::virtual_call_data_tag: | 710 case DataLayout::virtual_call_data_tag: |
643 return new VirtualCallData(data_layout); | 711 return new VirtualCallData(this); |
644 case DataLayout::ret_data_tag: | 712 case DataLayout::ret_data_tag: |
645 return new RetData(data_layout); | 713 return new RetData(this); |
646 case DataLayout::branch_data_tag: | 714 case DataLayout::branch_data_tag: |
647 return new BranchData(data_layout); | 715 return new BranchData(this); |
648 case DataLayout::multi_branch_data_tag: | 716 case DataLayout::multi_branch_data_tag: |
649 return new MultiBranchData(data_layout); | 717 return new MultiBranchData(this); |
650 case DataLayout::arg_info_data_tag: | 718 case DataLayout::arg_info_data_tag: |
651 return new ArgInfoData(data_layout); | 719 return new ArgInfoData(this); |
652 }; | 720 }; |
653 } | 721 } |
654 | 722 |
655 // Iteration over data. | 723 // Iteration over data. |
656 ProfileData* methodDataOopDesc::next_data(ProfileData* current) { | 724 ProfileData* methodDataOopDesc::next_data(ProfileData* current) { |