Mercurial > hg > graal-jvmci-8
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); |