Mercurial > hg > truffle
annotate src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @ 452:00b023ae2d78
6722113: CMS: Incorrect overflow handling during precleaning of Reference lists
Summary: When we encounter marking stack overflow during precleaning of Reference lists, we were using the overflow list mechanism, which can cause problems on account of mutating the mark word of the header because of conflicts with mutator accesses and updates of that field. Instead we should use the usual mechanism for overflow handling in concurrent phases, namely dirtying of the card on which the overflowed object lies. Since precleaning effectively does a form of discovered list processing, albeit with discovery enabled, we needed to adjust some code to be correct in the face of interleaved processing and discovery.
Reviewed-by: apetrusenko, jcoomes
author | ysr |
---|---|
date | Thu, 20 Nov 2008 12:27:41 -0800 |
parents | 8651a65ac4b4 |
children | c96030fff130 |
rev | line source |
---|---|
342 | 1 /* |
2 * Copyright 2001-2007 Sun Microsystems, Inc. All Rights Reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, | |
20 * CA 95054 USA or visit www.sun.com if you need additional information or | |
21 * have any questions. | |
22 * | |
23 */ | |
24 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_g1MarkSweep.cpp.incl" | |
27 | |
28 class HeapRegion; | |
29 | |
30 void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, | |
31 bool clear_all_softrefs) { | |
32 assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); | |
33 | |
34 // hook up weak ref data so it can be used during Mark-Sweep | |
35 assert(GenMarkSweep::ref_processor() == NULL, "no stomping"); | |
36 GenMarkSweep::_ref_processor = rp; | |
37 assert(rp != NULL, "should be non-NULL"); | |
38 | |
39 // When collecting the permanent generation methodOops may be moving, | |
40 // so we either have to flush all bcp data or convert it into bci. | |
41 CodeCache::gc_prologue(); | |
42 Threads::gc_prologue(); | |
43 | |
44 // Increment the invocation count for the permanent generation, since it is | |
45 // implicitly collected whenever we do a full mark sweep collection. | |
46 SharedHeap* sh = SharedHeap::heap(); | |
47 sh->perm_gen()->stat_record()->invocations++; | |
48 | |
49 bool marked_for_unloading = false; | |
50 | |
51 allocate_stacks(); | |
52 | |
358
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
53 // We should save the marks of the currently locked biased monitors. |
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
54 // The marking doesn't preserve the marks of biased objects. |
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
55 BiasedLocking::preserve_marks(); |
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
56 |
342 | 57 mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); |
58 | |
59 if (G1VerifyConcMark) { | |
60 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
61 g1h->checkConcurrentMark(); | |
62 } | |
63 | |
64 mark_sweep_phase2(); | |
65 | |
66 // Don't add any more derived pointers during phase3 | |
67 COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); | |
68 | |
69 mark_sweep_phase3(); | |
70 | |
71 mark_sweep_phase4(); | |
72 | |
73 GenMarkSweep::restore_marks(); | |
358
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
74 BiasedLocking::restore_marks(); |
342 | 75 GenMarkSweep::deallocate_stacks(); |
76 | |
77 // We must invalidate the perm-gen rs, so that it gets rebuilt. | |
78 GenRemSet* rs = sh->rem_set(); | |
79 rs->invalidate(sh->perm_gen()->used_region(), true /*whole_heap*/); | |
80 | |
81 // "free at last gc" is calculated from these. | |
82 // CHF: cheating for now!!! | |
83 // Universe::set_heap_capacity_at_last_gc(Universe::heap()->capacity()); | |
84 // Universe::set_heap_used_at_last_gc(Universe::heap()->used()); | |
85 | |
86 Threads::gc_epilogue(); | |
87 CodeCache::gc_epilogue(); | |
88 | |
89 // refs processing: clean slate | |
90 GenMarkSweep::_ref_processor = NULL; | |
91 } | |
92 | |
93 | |
94 void G1MarkSweep::allocate_stacks() { | |
95 GenMarkSweep::_preserved_count_max = 0; | |
96 GenMarkSweep::_preserved_marks = NULL; | |
97 GenMarkSweep::_preserved_count = 0; | |
98 GenMarkSweep::_preserved_mark_stack = NULL; | |
99 GenMarkSweep::_preserved_oop_stack = NULL; | |
100 | |
101 GenMarkSweep::_marking_stack = | |
102 new (ResourceObj::C_HEAP) GrowableArray<oop>(4000, true); | |
103 | |
104 size_t size = SystemDictionary::number_of_classes() * 2; | |
105 GenMarkSweep::_revisit_klass_stack = | |
106 new (ResourceObj::C_HEAP) GrowableArray<Klass*>((int)size, true); | |
107 } | |
108 | |
109 void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, | |
110 bool clear_all_softrefs) { | |
111 // Recursively traverse all live objects and mark them | |
112 EventMark m("1 mark object"); | |
113 TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty); | |
114 GenMarkSweep::trace(" 1"); | |
115 | |
116 SharedHeap* sh = SharedHeap::heap(); | |
117 | |
118 sh->process_strong_roots(true, // Collecting permanent generation. | |
119 SharedHeap::SO_SystemClasses, | |
120 &GenMarkSweep::follow_root_closure, | |
121 &GenMarkSweep::follow_root_closure); | |
122 | |
123 // Process reference objects found during marking | |
124 ReferencePolicy *soft_ref_policy; | |
125 if (clear_all_softrefs) { | |
126 soft_ref_policy = new AlwaysClearPolicy(); | |
127 } else { | |
128 #ifdef COMPILER2 | |
129 soft_ref_policy = new LRUMaxHeapPolicy(); | |
130 #else | |
131 soft_ref_policy = new LRUCurrentHeapPolicy(); | |
132 #endif | |
133 } | |
134 assert(soft_ref_policy != NULL,"No soft reference policy"); | |
135 GenMarkSweep::ref_processor()->process_discovered_references( | |
136 soft_ref_policy, | |
137 &GenMarkSweep::is_alive, | |
138 &GenMarkSweep::keep_alive, | |
139 &GenMarkSweep::follow_stack_closure, | |
140 NULL); | |
141 | |
142 // Follow system dictionary roots and unload classes | |
143 bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive); | |
144 assert(GenMarkSweep::_marking_stack->is_empty(), | |
145 "stack should be empty by now"); | |
146 | |
147 // Follow code cache roots (has to be done after system dictionary, | |
148 // assumes all live klasses are marked) | |
149 CodeCache::do_unloading(&GenMarkSweep::is_alive, | |
150 &GenMarkSweep::keep_alive, | |
151 purged_class); | |
152 GenMarkSweep::follow_stack(); | |
153 | |
154 // Update subklass/sibling/implementor links of live klasses | |
155 GenMarkSweep::follow_weak_klass_links(); | |
156 assert(GenMarkSweep::_marking_stack->is_empty(), | |
157 "stack should be empty by now"); | |
158 | |
159 // Visit symbol and interned string tables and delete unmarked oops | |
160 SymbolTable::unlink(&GenMarkSweep::is_alive); | |
161 StringTable::unlink(&GenMarkSweep::is_alive); | |
162 | |
163 assert(GenMarkSweep::_marking_stack->is_empty(), | |
164 "stack should be empty by now"); | |
165 } | |
166 | |
167 class G1PrepareCompactClosure: public HeapRegionClosure { | |
168 ModRefBarrierSet* _mrbs; | |
169 CompactPoint _cp; | |
170 bool _popular_only; | |
171 | |
172 void free_humongous_region(HeapRegion* hr) { | |
173 HeapWord* bot = hr->bottom(); | |
174 HeapWord* end = hr->end(); | |
175 assert(hr->startsHumongous(), | |
176 "Only the start of a humongous region should be freed."); | |
177 G1CollectedHeap::heap()->free_region(hr); | |
178 hr->prepare_for_compaction(&_cp); | |
179 // Also clear the part of the card table that will be unused after | |
180 // compaction. | |
181 _mrbs->clear(MemRegion(hr->compaction_top(), hr->end())); | |
182 } | |
183 | |
184 public: | |
185 G1PrepareCompactClosure(CompactibleSpace* cs, bool popular_only) : | |
186 _cp(NULL, cs, cs->initialize_threshold()), | |
187 _mrbs(G1CollectedHeap::heap()->mr_bs()), | |
188 _popular_only(popular_only) | |
189 {} | |
190 bool doHeapRegion(HeapRegion* hr) { | |
191 if (_popular_only && !hr->popular()) | |
192 return true; // terminate early | |
193 else if (!_popular_only && hr->popular()) | |
194 return false; // skip this one. | |
195 | |
196 if (hr->isHumongous()) { | |
197 if (hr->startsHumongous()) { | |
198 oop obj = oop(hr->bottom()); | |
199 if (obj->is_gc_marked()) { | |
200 obj->forward_to(obj); | |
201 } else { | |
202 free_humongous_region(hr); | |
203 } | |
204 } else { | |
205 assert(hr->continuesHumongous(), "Invalid humongous."); | |
206 } | |
207 } else { | |
208 hr->prepare_for_compaction(&_cp); | |
209 // Also clear the part of the card table that will be unused after | |
210 // compaction. | |
211 _mrbs->clear(MemRegion(hr->compaction_top(), hr->end())); | |
212 } | |
213 return false; | |
214 } | |
215 }; | |
216 // Stolen verbatim from g1CollectedHeap.cpp | |
217 class FindFirstRegionClosure: public HeapRegionClosure { | |
218 HeapRegion* _a_region; | |
219 bool _find_popular; | |
220 public: | |
221 FindFirstRegionClosure(bool find_popular) : | |
222 _a_region(NULL), _find_popular(find_popular) {} | |
223 bool doHeapRegion(HeapRegion* r) { | |
224 if (r->popular() == _find_popular) { | |
225 _a_region = r; | |
226 return true; | |
227 } else { | |
228 return false; | |
229 } | |
230 } | |
231 HeapRegion* result() { return _a_region; } | |
232 }; | |
233 | |
234 void G1MarkSweep::mark_sweep_phase2() { | |
235 // Now all live objects are marked, compute the new object addresses. | |
236 | |
237 // It is imperative that we traverse perm_gen LAST. If dead space is | |
238 // allowed a range of dead object may get overwritten by a dead int | |
239 // array. If perm_gen is not traversed last a klassOop may get | |
240 // overwritten. This is fine since it is dead, but if the class has dead | |
241 // instances we have to skip them, and in order to find their size we | |
242 // need the klassOop! | |
243 // | |
244 // It is not required that we traverse spaces in the same order in | |
245 // phase2, phase3 and phase4, but the ValidateMarkSweep live oops | |
246 // tracking expects us to do so. See comment under phase4. | |
247 | |
248 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
249 Generation* pg = g1h->perm_gen(); | |
250 | |
251 EventMark m("2 compute new addresses"); | |
252 TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); | |
253 GenMarkSweep::trace("2"); | |
254 | |
255 // First we compact the popular regions. | |
256 if (G1NumPopularRegions > 0) { | |
257 CompactibleSpace* sp = g1h->first_compactible_space(); | |
258 FindFirstRegionClosure cl(true /*find_popular*/); | |
259 g1h->heap_region_iterate(&cl); | |
260 HeapRegion *r = cl.result(); | |
261 assert(r->popular(), "should have found a popular region."); | |
262 assert(r == sp, "first popular heap region should " | |
263 "== first compactible space"); | |
264 G1PrepareCompactClosure blk(sp, true/*popular_only*/); | |
265 g1h->heap_region_iterate(&blk); | |
266 } | |
267 | |
268 // Now we do the regular regions. | |
269 FindFirstRegionClosure cl(false /*find_popular*/); | |
270 g1h->heap_region_iterate(&cl); | |
271 HeapRegion *r = cl.result(); | |
272 assert(!r->popular(), "should have founda non-popular region."); | |
273 CompactibleSpace* sp = r; | |
274 if (r->isHumongous() && oop(r->bottom())->is_gc_marked()) { | |
275 sp = r->next_compaction_space(); | |
276 } | |
277 | |
278 G1PrepareCompactClosure blk(sp, false/*popular_only*/); | |
279 g1h->heap_region_iterate(&blk); | |
280 | |
281 CompactPoint perm_cp(pg, NULL, NULL); | |
282 pg->prepare_for_compaction(&perm_cp); | |
283 } | |
284 | |
285 class G1AdjustPointersClosure: public HeapRegionClosure { | |
286 public: | |
287 bool doHeapRegion(HeapRegion* r) { | |
288 if (r->isHumongous()) { | |
289 if (r->startsHumongous()) { | |
290 // We must adjust the pointers on the single H object. | |
291 oop obj = oop(r->bottom()); | |
292 debug_only(GenMarkSweep::track_interior_pointers(obj)); | |
293 // point all the oops to the new location | |
294 obj->adjust_pointers(); | |
295 debug_only(GenMarkSweep::check_interior_pointers()); | |
296 } | |
297 } else { | |
298 // This really ought to be "as_CompactibleSpace"... | |
299 r->adjust_pointers(); | |
300 } | |
301 return false; | |
302 } | |
303 }; | |
304 | |
305 void G1MarkSweep::mark_sweep_phase3() { | |
306 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
307 Generation* pg = g1h->perm_gen(); | |
308 | |
309 // Adjust the pointers to reflect the new locations | |
310 EventMark m("3 adjust pointers"); | |
311 TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty); | |
312 GenMarkSweep::trace("3"); | |
313 | |
314 SharedHeap* sh = SharedHeap::heap(); | |
315 | |
316 sh->process_strong_roots(true, // Collecting permanent generation. | |
317 SharedHeap::SO_AllClasses, | |
318 &GenMarkSweep::adjust_root_pointer_closure, | |
319 &GenMarkSweep::adjust_pointer_closure); | |
320 | |
321 g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); | |
322 | |
323 // Now adjust pointers in remaining weak roots. (All of which should | |
324 // have been cleared if they pointed to non-surviving objects.) | |
325 g1h->g1_process_weak_roots(&GenMarkSweep::adjust_root_pointer_closure, | |
326 &GenMarkSweep::adjust_pointer_closure); | |
327 | |
328 GenMarkSweep::adjust_marks(); | |
329 | |
330 G1AdjustPointersClosure blk; | |
331 g1h->heap_region_iterate(&blk); | |
332 pg->adjust_pointers(); | |
333 } | |
334 | |
335 class G1SpaceCompactClosure: public HeapRegionClosure { | |
336 public: | |
337 G1SpaceCompactClosure() {} | |
338 | |
339 bool doHeapRegion(HeapRegion* hr) { | |
340 if (hr->isHumongous()) { | |
341 if (hr->startsHumongous()) { | |
342 oop obj = oop(hr->bottom()); | |
343 if (obj->is_gc_marked()) { | |
344 obj->init_mark(); | |
345 } else { | |
346 assert(hr->is_empty(), "Should have been cleared in phase 2."); | |
347 } | |
348 hr->reset_during_compaction(); | |
349 } | |
350 } else { | |
351 hr->compact(); | |
352 } | |
353 return false; | |
354 } | |
355 }; | |
356 | |
357 void G1MarkSweep::mark_sweep_phase4() { | |
358 // All pointers are now adjusted, move objects accordingly | |
359 | |
360 // It is imperative that we traverse perm_gen first in phase4. All | |
361 // classes must be allocated earlier than their instances, and traversing | |
362 // perm_gen first makes sure that all klassOops have moved to their new | |
363 // location before any instance does a dispatch through it's klass! | |
364 | |
365 // The ValidateMarkSweep live oops tracking expects us to traverse spaces | |
366 // in the same order in phase2, phase3 and phase4. We don't quite do that | |
367 // here (perm_gen first rather than last), so we tell the validate code | |
368 // to use a higher index (saved from phase2) when verifying perm_gen. | |
369 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
370 Generation* pg = g1h->perm_gen(); | |
371 | |
372 EventMark m("4 compact heap"); | |
373 TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty); | |
374 GenMarkSweep::trace("4"); | |
375 | |
376 pg->compact(); | |
377 | |
378 G1SpaceCompactClosure blk; | |
379 g1h->heap_region_iterate(&blk); | |
380 | |
381 } | |
382 | |
383 // Local Variables: *** | |
384 // c-indentation-style: gnu *** | |
385 // End: *** |