comparison src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @ 1656:4e5661ba9d98

6944166: G1: explicit GCs are not always handled correctly Summary: G1 was not handling explicit GCs correctly in many ways. It does now. See the CR for the list of improvements contained in this changeset. Reviewed-by: iveresov, ysr, johnc
author tonyp
date Mon, 28 Jun 2010 14:13:17 -0400
parents c18cbe5936b8
children f95d63e2154a
comparison
equal deleted inserted replaced
1655:e7ec8cd4dd8a 1656:4e5661ba9d98
40 } 40 }
41 41
42 void VM_G1IncCollectionPause::doit() { 42 void VM_G1IncCollectionPause::doit() {
43 JvmtiGCForAllocationMarker jgcm; 43 JvmtiGCForAllocationMarker jgcm;
44 G1CollectedHeap* g1h = G1CollectedHeap::heap(); 44 G1CollectedHeap* g1h = G1CollectedHeap::heap();
45 assert(!_should_initiate_conc_mark ||
46 ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||
47 (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent)),
48 "only a GC locker or a System.gc() induced GC should start a cycle");
49
45 GCCauseSetter x(g1h, _gc_cause); 50 GCCauseSetter x(g1h, _gc_cause);
46 g1h->do_collection_pause_at_safepoint(); 51 if (_should_initiate_conc_mark) {
52 // It's safer to read full_collections_completed() here, given
53 // that noone else will be updating it concurrently. Since we'll
54 // only need it if we're initiating a marking cycle, no point in
55 // setting it earlier.
56 _full_collections_completed_before = g1h->full_collections_completed();
57
58 // At this point we are supposed to start a concurrent cycle. We
59 // will do so if one is not already in progress.
60 bool res = g1h->g1_policy()->force_initial_mark_if_outside_cycle();
61 }
62 g1h->do_collection_pause_at_safepoint(_target_pause_time_ms);
63 }
64
65 void VM_G1IncCollectionPause::doit_epilogue() {
66 VM_GC_Operation::doit_epilogue();
67
68 // If the pause was initiated by a System.gc() and
69 // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle
70 // that just started (or maybe one that was already in progress) to
71 // finish.
72 if (_gc_cause == GCCause::_java_lang_system_gc &&
73 _should_initiate_conc_mark) {
74 assert(ExplicitGCInvokesConcurrent,
75 "the only way to be here is if ExplicitGCInvokesConcurrent is set");
76
77 G1CollectedHeap* g1h = G1CollectedHeap::heap();
78
79 // In the doit() method we saved g1h->full_collections_completed()
80 // in the _full_collections_completed_before field. We have to
81 // wait until we observe that g1h->full_collections_completed()
82 // has increased by at least one. This can happen if a) we started
83 // a cycle and it completes, b) a cycle already in progress
84 // completes, or c) a Full GC happens.
85
86 // If the condition has already been reached, there's no point in
87 // actually taking the lock and doing the wait.
88 if (g1h->full_collections_completed() <=
89 _full_collections_completed_before) {
90 // The following is largely copied from CMS
91
92 Thread* thr = Thread::current();
93 assert(thr->is_Java_thread(), "invariant");
94 JavaThread* jt = (JavaThread*)thr;
95 ThreadToNativeFromVM native(jt);
96
97 MutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);
98 while (g1h->full_collections_completed() <=
99 _full_collections_completed_before) {
100 FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);
101 }
102 }
103 }
47 } 104 }
48 105
49 void VM_CGC_Operation::doit() { 106 void VM_CGC_Operation::doit() {
50 gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps); 107 gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
51 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty); 108 TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);