Mercurial > hg > graal-jvmci-8
annotate src/share/vm/gc_implementation/g1/g1MarkSweep.cpp @ 2149:7e37af9d69ef
7011379: G1: overly long concurrent marking cycles
Summary: This changeset introduces filtering of SATB buffers at the point when they are about to be enqueued. If this filtering clears enough entries on each buffer, the buffer can then be re-used and not enqueued. This cuts down the number of SATB buffers that need to be processed by the concurrent marking threads.
Reviewed-by: johnc, ysr
author | tonyp |
---|---|
date | Wed, 19 Jan 2011 09:35:17 -0500 |
parents | f95d63e2154a |
children | 9afee0b9fc1d 0fa27f37d4d4 |
rev | line source |
---|---|
342 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. |
342 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1387
diff
changeset
|
21 * questions. |
342 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "classfile/javaClasses.hpp" | |
27 #include "classfile/symbolTable.hpp" | |
28 #include "classfile/systemDictionary.hpp" | |
29 #include "classfile/vmSymbols.hpp" | |
30 #include "code/codeCache.hpp" | |
31 #include "code/icBuffer.hpp" | |
32 #include "gc_implementation/g1/g1MarkSweep.hpp" | |
33 #include "memory/gcLocker.hpp" | |
34 #include "memory/genCollectedHeap.hpp" | |
35 #include "memory/modRefBarrierSet.hpp" | |
36 #include "memory/referencePolicy.hpp" | |
37 #include "memory/space.hpp" | |
38 #include "oops/instanceRefKlass.hpp" | |
39 #include "oops/oop.inline.hpp" | |
40 #include "prims/jvmtiExport.hpp" | |
41 #include "runtime/aprofiler.hpp" | |
42 #include "runtime/biasedLocking.hpp" | |
43 #include "runtime/fprofiler.hpp" | |
44 #include "runtime/synchronizer.hpp" | |
45 #include "runtime/thread.hpp" | |
46 #include "runtime/vmThread.hpp" | |
47 #include "utilities/copy.hpp" | |
48 #include "utilities/events.hpp" | |
342 | 49 |
50 class HeapRegion; | |
51 | |
52 void G1MarkSweep::invoke_at_safepoint(ReferenceProcessor* rp, | |
53 bool clear_all_softrefs) { | |
54 assert(SafepointSynchronize::is_at_safepoint(), "must be at a safepoint"); | |
55 | |
1387
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
56 SharedHeap* sh = SharedHeap::heap(); |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
57 #ifdef ASSERT |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
58 if (sh->collector_policy()->should_clear_all_soft_refs()) { |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
59 assert(clear_all_softrefs, "Policy should have been checked earler"); |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
60 } |
0bfd3fb24150
6858496: Clear all SoftReferences before an out-of-memory due to GC overhead limit.
jmasa
parents:
1311
diff
changeset
|
61 #endif |
342 | 62 // hook up weak ref data so it can be used during Mark-Sweep |
63 assert(GenMarkSweep::ref_processor() == NULL, "no stomping"); | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
64 assert(rp != NULL, "should be non-NULL"); |
342 | 65 GenMarkSweep::_ref_processor = rp; |
457
27a80744a83b
6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents:
453
diff
changeset
|
66 rp->setup_policy(clear_all_softrefs); |
342 | 67 |
68 // When collecting the permanent generation methodOops may be moving, | |
69 // so we either have to flush all bcp data or convert it into bci. | |
70 CodeCache::gc_prologue(); | |
71 Threads::gc_prologue(); | |
72 | |
73 // Increment the invocation count for the permanent generation, since it is | |
74 // implicitly collected whenever we do a full mark sweep collection. | |
75 sh->perm_gen()->stat_record()->invocations++; | |
76 | |
77 bool marked_for_unloading = false; | |
78 | |
79 allocate_stacks(); | |
80 | |
358
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
81 // 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
|
82 // 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
|
83 BiasedLocking::preserve_marks(); |
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
84 |
342 | 85 mark_sweep_phase1(marked_for_unloading, clear_all_softrefs); |
86 | |
751 | 87 if (VerifyDuringGC) { |
342 | 88 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
89 g1h->checkConcurrentMark(); | |
90 } | |
91 | |
92 mark_sweep_phase2(); | |
93 | |
94 // Don't add any more derived pointers during phase3 | |
95 COMPILER2_PRESENT(DerivedPointerTable::set_active(false)); | |
96 | |
97 mark_sweep_phase3(); | |
98 | |
99 mark_sweep_phase4(); | |
100 | |
101 GenMarkSweep::restore_marks(); | |
358
8651a65ac4b4
6735416: G1: runThese javasoft.sqe.tests.lang.thrd011.thrd01101.thrd01101 fails
iveresov
parents:
342
diff
changeset
|
102 BiasedLocking::restore_marks(); |
342 | 103 GenMarkSweep::deallocate_stacks(); |
104 | |
105 // We must invalidate the perm-gen rs, so that it gets rebuilt. | |
106 GenRemSet* rs = sh->rem_set(); | |
107 rs->invalidate(sh->perm_gen()->used_region(), true /*whole_heap*/); | |
108 | |
109 // "free at last gc" is calculated from these. | |
110 // CHF: cheating for now!!! | |
111 // Universe::set_heap_capacity_at_last_gc(Universe::heap()->capacity()); | |
112 // Universe::set_heap_used_at_last_gc(Universe::heap()->used()); | |
113 | |
114 Threads::gc_epilogue(); | |
115 CodeCache::gc_epilogue(); | |
116 | |
117 // refs processing: clean slate | |
118 GenMarkSweep::_ref_processor = NULL; | |
119 } | |
120 | |
121 | |
122 void G1MarkSweep::allocate_stacks() { | |
123 GenMarkSweep::_preserved_count_max = 0; | |
124 GenMarkSweep::_preserved_marks = NULL; | |
125 GenMarkSweep::_preserved_count = 0; | |
126 } | |
127 | |
128 void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading, | |
129 bool clear_all_softrefs) { | |
130 // Recursively traverse all live objects and mark them | |
131 EventMark m("1 mark object"); | |
132 TraceTime tm("phase 1", PrintGC && Verbose, true, gclog_or_tty); | |
133 GenMarkSweep::trace(" 1"); | |
134 | |
135 SharedHeap* sh = SharedHeap::heap(); | |
136 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
137 sh->process_strong_roots(true, // activeate StrongRootsScope |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
138 true, // Collecting permanent generation. |
342 | 139 SharedHeap::SO_SystemClasses, |
140 &GenMarkSweep::follow_root_closure, | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
141 &GenMarkSweep::follow_code_root_closure, |
342 | 142 &GenMarkSweep::follow_root_closure); |
143 | |
144 // Process reference objects found during marking | |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
145 ReferenceProcessor* rp = GenMarkSweep::ref_processor(); |
457
27a80744a83b
6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
ysr
parents:
453
diff
changeset
|
146 rp->setup_policy(clear_all_softrefs); |
453
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
147 rp->process_discovered_references(&GenMarkSweep::is_alive, |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
148 &GenMarkSweep::keep_alive, |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
149 &GenMarkSweep::follow_stack_closure, |
c96030fff130
6684579: SoftReference processing can be made more efficient
ysr
parents:
358
diff
changeset
|
150 NULL); |
342 | 151 |
152 // Follow system dictionary roots and unload classes | |
153 bool purged_class = SystemDictionary::do_unloading(&GenMarkSweep::is_alive); | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1552
diff
changeset
|
154 assert(GenMarkSweep::_marking_stack.is_empty(), |
342 | 155 "stack should be empty by now"); |
156 | |
157 // Follow code cache roots (has to be done after system dictionary, | |
158 // assumes all live klasses are marked) | |
159 CodeCache::do_unloading(&GenMarkSweep::is_alive, | |
160 &GenMarkSweep::keep_alive, | |
161 purged_class); | |
941 | 162 GenMarkSweep::follow_stack(); |
342 | 163 |
164 // Update subklass/sibling/implementor links of live klasses | |
165 GenMarkSweep::follow_weak_klass_links(); | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1552
diff
changeset
|
166 assert(GenMarkSweep::_marking_stack.is_empty(), |
342 | 167 "stack should be empty by now"); |
168 | |
941 | 169 // Visit memoized MDO's and clear any unmarked weak refs |
170 GenMarkSweep::follow_mdo_weak_refs(); | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1552
diff
changeset
|
171 assert(GenMarkSweep::_marking_stack.is_empty(), "just drained"); |
941 | 172 |
173 | |
342 | 174 // Visit symbol and interned string tables and delete unmarked oops |
175 SymbolTable::unlink(&GenMarkSweep::is_alive); | |
176 StringTable::unlink(&GenMarkSweep::is_alive); | |
177 | |
1836
894b1d7c7e01
6423256: GC stacks should use a better data structure
jcoomes
parents:
1552
diff
changeset
|
178 assert(GenMarkSweep::_marking_stack.is_empty(), |
342 | 179 "stack should be empty by now"); |
180 } | |
181 | |
182 class G1PrepareCompactClosure: public HeapRegionClosure { | |
183 ModRefBarrierSet* _mrbs; | |
184 CompactPoint _cp; | |
185 | |
186 void free_humongous_region(HeapRegion* hr) { | |
187 HeapWord* bot = hr->bottom(); | |
188 HeapWord* end = hr->end(); | |
189 assert(hr->startsHumongous(), | |
190 "Only the start of a humongous region should be freed."); | |
191 G1CollectedHeap::heap()->free_region(hr); | |
192 hr->prepare_for_compaction(&_cp); | |
193 // Also clear the part of the card table that will be unused after | |
194 // compaction. | |
195 _mrbs->clear(MemRegion(hr->compaction_top(), hr->end())); | |
196 } | |
197 | |
198 public: | |
677 | 199 G1PrepareCompactClosure(CompactibleSpace* cs) : |
342 | 200 _cp(NULL, cs, cs->initialize_threshold()), |
677 | 201 _mrbs(G1CollectedHeap::heap()->mr_bs()) |
342 | 202 {} |
203 bool doHeapRegion(HeapRegion* hr) { | |
204 if (hr->isHumongous()) { | |
205 if (hr->startsHumongous()) { | |
206 oop obj = oop(hr->bottom()); | |
207 if (obj->is_gc_marked()) { | |
208 obj->forward_to(obj); | |
209 } else { | |
210 free_humongous_region(hr); | |
211 } | |
212 } else { | |
213 assert(hr->continuesHumongous(), "Invalid humongous."); | |
214 } | |
215 } else { | |
216 hr->prepare_for_compaction(&_cp); | |
217 // Also clear the part of the card table that will be unused after | |
218 // compaction. | |
219 _mrbs->clear(MemRegion(hr->compaction_top(), hr->end())); | |
220 } | |
221 return false; | |
222 } | |
223 }; | |
677 | 224 |
225 // Finds the first HeapRegion. | |
342 | 226 class FindFirstRegionClosure: public HeapRegionClosure { |
227 HeapRegion* _a_region; | |
228 public: | |
677 | 229 FindFirstRegionClosure() : _a_region(NULL) {} |
342 | 230 bool doHeapRegion(HeapRegion* r) { |
677 | 231 _a_region = r; |
232 return true; | |
342 | 233 } |
234 HeapRegion* result() { return _a_region; } | |
235 }; | |
236 | |
237 void G1MarkSweep::mark_sweep_phase2() { | |
238 // Now all live objects are marked, compute the new object addresses. | |
239 | |
240 // It is imperative that we traverse perm_gen LAST. If dead space is | |
241 // allowed a range of dead object may get overwritten by a dead int | |
242 // array. If perm_gen is not traversed last a klassOop may get | |
243 // overwritten. This is fine since it is dead, but if the class has dead | |
244 // instances we have to skip them, and in order to find their size we | |
245 // need the klassOop! | |
246 // | |
247 // It is not required that we traverse spaces in the same order in | |
248 // phase2, phase3 and phase4, but the ValidateMarkSweep live oops | |
249 // tracking expects us to do so. See comment under phase4. | |
250 | |
251 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
252 Generation* pg = g1h->perm_gen(); | |
253 | |
254 EventMark m("2 compute new addresses"); | |
255 TraceTime tm("phase 2", PrintGC && Verbose, true, gclog_or_tty); | |
256 GenMarkSweep::trace("2"); | |
257 | |
677 | 258 FindFirstRegionClosure cl; |
342 | 259 g1h->heap_region_iterate(&cl); |
260 HeapRegion *r = cl.result(); | |
261 CompactibleSpace* sp = r; | |
262 if (r->isHumongous() && oop(r->bottom())->is_gc_marked()) { | |
263 sp = r->next_compaction_space(); | |
264 } | |
265 | |
677 | 266 G1PrepareCompactClosure blk(sp); |
342 | 267 g1h->heap_region_iterate(&blk); |
268 | |
269 CompactPoint perm_cp(pg, NULL, NULL); | |
270 pg->prepare_for_compaction(&perm_cp); | |
271 } | |
272 | |
273 class G1AdjustPointersClosure: public HeapRegionClosure { | |
274 public: | |
275 bool doHeapRegion(HeapRegion* r) { | |
276 if (r->isHumongous()) { | |
277 if (r->startsHumongous()) { | |
278 // We must adjust the pointers on the single H object. | |
279 oop obj = oop(r->bottom()); | |
280 debug_only(GenMarkSweep::track_interior_pointers(obj)); | |
281 // point all the oops to the new location | |
282 obj->adjust_pointers(); | |
283 debug_only(GenMarkSweep::check_interior_pointers()); | |
284 } | |
285 } else { | |
286 // This really ought to be "as_CompactibleSpace"... | |
287 r->adjust_pointers(); | |
288 } | |
289 return false; | |
290 } | |
291 }; | |
292 | |
293 void G1MarkSweep::mark_sweep_phase3() { | |
294 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
295 Generation* pg = g1h->perm_gen(); | |
296 | |
297 // Adjust the pointers to reflect the new locations | |
298 EventMark m("3 adjust pointers"); | |
299 TraceTime tm("phase 3", PrintGC && Verbose, true, gclog_or_tty); | |
300 GenMarkSweep::trace("3"); | |
301 | |
302 SharedHeap* sh = SharedHeap::heap(); | |
303 | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
304 sh->process_strong_roots(true, // activate StrongRootsScope |
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
305 true, // Collecting permanent generation. |
342 | 306 SharedHeap::SO_AllClasses, |
307 &GenMarkSweep::adjust_root_pointer_closure, | |
989
148e5441d916
6863023: need non-perm oops in code cache for JSR 292
jrose
parents:
844
diff
changeset
|
308 NULL, // do not touch code cache here |
342 | 309 &GenMarkSweep::adjust_pointer_closure); |
310 | |
311 g1h->ref_processor()->weak_oops_do(&GenMarkSweep::adjust_root_pointer_closure); | |
312 | |
313 // Now adjust pointers in remaining weak roots. (All of which should | |
314 // have been cleared if they pointed to non-surviving objects.) | |
315 g1h->g1_process_weak_roots(&GenMarkSweep::adjust_root_pointer_closure, | |
316 &GenMarkSweep::adjust_pointer_closure); | |
317 | |
318 GenMarkSweep::adjust_marks(); | |
319 | |
320 G1AdjustPointersClosure blk; | |
321 g1h->heap_region_iterate(&blk); | |
322 pg->adjust_pointers(); | |
323 } | |
324 | |
325 class G1SpaceCompactClosure: public HeapRegionClosure { | |
326 public: | |
327 G1SpaceCompactClosure() {} | |
328 | |
329 bool doHeapRegion(HeapRegion* hr) { | |
330 if (hr->isHumongous()) { | |
331 if (hr->startsHumongous()) { | |
332 oop obj = oop(hr->bottom()); | |
333 if (obj->is_gc_marked()) { | |
334 obj->init_mark(); | |
335 } else { | |
336 assert(hr->is_empty(), "Should have been cleared in phase 2."); | |
337 } | |
338 hr->reset_during_compaction(); | |
339 } | |
340 } else { | |
341 hr->compact(); | |
342 } | |
343 return false; | |
344 } | |
345 }; | |
346 | |
347 void G1MarkSweep::mark_sweep_phase4() { | |
348 // All pointers are now adjusted, move objects accordingly | |
349 | |
350 // It is imperative that we traverse perm_gen first in phase4. All | |
351 // classes must be allocated earlier than their instances, and traversing | |
352 // perm_gen first makes sure that all klassOops have moved to their new | |
353 // location before any instance does a dispatch through it's klass! | |
354 | |
355 // The ValidateMarkSweep live oops tracking expects us to traverse spaces | |
356 // in the same order in phase2, phase3 and phase4. We don't quite do that | |
357 // here (perm_gen first rather than last), so we tell the validate code | |
358 // to use a higher index (saved from phase2) when verifying perm_gen. | |
359 G1CollectedHeap* g1h = G1CollectedHeap::heap(); | |
360 Generation* pg = g1h->perm_gen(); | |
361 | |
362 EventMark m("4 compact heap"); | |
363 TraceTime tm("phase 4", PrintGC && Verbose, true, gclog_or_tty); | |
364 GenMarkSweep::trace("4"); | |
365 | |
366 pg->compact(); | |
367 | |
368 G1SpaceCompactClosure blk; | |
369 g1h->heap_region_iterate(&blk); | |
370 | |
371 } | |
372 | |
373 // Local Variables: *** | |
374 // c-indentation-style: gnu *** | |
375 // End: *** |