31 #include "gc/shared/gcTimer.hpp" |
31 #include "gc/shared/gcTimer.hpp" |
32 #include "gc/shared/gcTraceTime.inline.hpp" |
32 #include "gc/shared/gcTraceTime.inline.hpp" |
33 #include "gc/shared/isGCActiveMark.hpp" |
33 #include "gc/shared/isGCActiveMark.hpp" |
34 #include "runtime/interfaceSupport.hpp" |
34 #include "runtime/interfaceSupport.hpp" |
35 |
35 |
36 VM_G1CollectForAllocation::VM_G1CollectForAllocation(uint gc_count_before, |
|
37 size_t word_size) |
|
38 : VM_G1OperationWithAllocRequest(gc_count_before, word_size, |
|
39 GCCause::_allocation_failure) { |
|
40 guarantee(word_size != 0, "An allocation should always be requested with this operation."); |
|
41 } |
|
42 |
|
43 void VM_G1CollectForAllocation::doit() { |
|
44 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
|
45 GCCauseSetter x(g1h, _gc_cause); |
|
46 |
|
47 _result = g1h->satisfy_failed_allocation(_word_size, allocation_context(), &_pause_succeeded); |
|
48 assert(_result == NULL || _pause_succeeded, |
|
49 "if we get back a result, the pause should have succeeded"); |
|
50 } |
|
51 |
|
52 void VM_G1CollectFull::doit() { |
36 void VM_G1CollectFull::doit() { |
53 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
37 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
54 GCCauseSetter x(g1h, _gc_cause); |
38 GCCauseSetter x(g1h, _gc_cause); |
55 g1h->do_full_collection(false /* clear_all_soft_refs */); |
39 g1h->do_full_collection(false /* clear_all_soft_refs */); |
56 } |
40 } |
57 |
41 |
58 VM_G1IncCollectionPause::VM_G1IncCollectionPause(uint gc_count_before, |
42 VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size, |
59 size_t word_size, |
43 uint gc_count_before, |
60 bool should_initiate_conc_mark, |
44 GCCause::Cause gc_cause, |
61 double target_pause_time_ms, |
45 bool should_initiate_conc_mark, |
62 GCCause::Cause gc_cause) |
46 double target_pause_time_ms, |
63 : VM_G1OperationWithAllocRequest(gc_count_before, word_size, gc_cause), |
47 AllocationContext_t allocation_context) |
|
48 : VM_CollectForAllocation(word_size, gc_count_before, gc_cause), |
|
49 _pause_succeeded(false), |
|
50 _allocation_context(allocation_context), |
64 _should_initiate_conc_mark(should_initiate_conc_mark), |
51 _should_initiate_conc_mark(should_initiate_conc_mark), |
65 _target_pause_time_ms(target_pause_time_ms), |
52 _target_pause_time_ms(target_pause_time_ms), |
66 _should_retry_gc(false), |
53 _should_retry_gc(false), |
67 _old_marking_cycles_completed_before(0) { |
54 _old_marking_cycles_completed_before(0) { |
68 guarantee(target_pause_time_ms > 0.0, |
55 guarantee(target_pause_time_ms > 0.0, |
69 "target_pause_time_ms = %1.6lf should be positive", |
56 "target_pause_time_ms = %1.6lf should be positive", |
70 target_pause_time_ms); |
57 target_pause_time_ms); |
71 _gc_cause = gc_cause; |
58 _gc_cause = gc_cause; |
72 } |
59 } |
73 |
60 |
74 bool VM_G1IncCollectionPause::doit_prologue() { |
61 bool VM_G1CollectForAllocation::doit_prologue() { |
75 bool res = VM_G1OperationWithAllocRequest::doit_prologue(); |
62 bool res = VM_CollectForAllocation::doit_prologue(); |
76 if (!res) { |
63 if (!res) { |
77 if (_should_initiate_conc_mark) { |
64 if (_should_initiate_conc_mark) { |
78 // The prologue can fail for a couple of reasons. The first is that another GC |
65 // The prologue can fail for a couple of reasons. The first is that another GC |
79 // got scheduled and prevented the scheduling of the initial mark GC. The |
66 // got scheduled and prevented the scheduling of the initial mark GC. The |
80 // second is that the GC locker may be active and the heap can't be expanded. |
67 // second is that the GC locker may be active and the heap can't be expanded. |
85 } |
72 } |
86 } |
73 } |
87 return res; |
74 return res; |
88 } |
75 } |
89 |
76 |
90 void VM_G1IncCollectionPause::doit() { |
77 void VM_G1CollectForAllocation::doit() { |
91 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
78 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
92 assert(!_should_initiate_conc_mark || g1h->should_do_concurrent_full_gc(_gc_cause), |
79 assert(!_should_initiate_conc_mark || g1h->should_do_concurrent_full_gc(_gc_cause), |
93 "only a GC locker, a System.gc(), stats update, whitebox, or a hum allocation induced GC should start a cycle"); |
80 "only a GC locker, a System.gc(), stats update, whitebox, or a hum allocation induced GC should start a cycle"); |
94 |
81 |
95 if (_word_size > 0) { |
82 if (_word_size > 0) { |
96 // An allocation has been requested. So, try to do that first. |
83 // An allocation has been requested. So, try to do that first. |
97 _result = g1h->attempt_allocation_at_safepoint(_word_size, |
84 _result = g1h->attempt_allocation_at_safepoint(_word_size, |
98 allocation_context(), |
85 _allocation_context, |
99 false /* expect_null_cur_alloc_region */); |
86 false /* expect_null_cur_alloc_region */); |
100 if (_result != NULL) { |
87 if (_result != NULL) { |
101 // If we can successfully allocate before we actually do the |
88 // If we can successfully allocate before we actually do the |
102 // pause then we will consider this pause successful. |
89 // pause then we will consider this pause successful. |
103 _pause_succeeded = true; |
90 _pause_succeeded = true; |
142 } |
129 } |
143 return; |
130 return; |
144 } |
131 } |
145 } |
132 } |
146 |
133 |
147 _pause_succeeded = |
134 // Try a partial collection of some kind. |
148 g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); |
135 _pause_succeeded = g1h->do_collection_pause_at_safepoint(_target_pause_time_ms); |
149 if (_pause_succeeded && _word_size > 0) { |
136 |
150 // An allocation had been requested. |
137 if (_pause_succeeded) { |
151 _result = g1h->attempt_allocation_at_safepoint(_word_size, |
138 if (_word_size > 0) { |
152 allocation_context(), |
139 // An allocation had been requested. Do it, eventually trying a stronger |
153 true /* expect_null_cur_alloc_region */); |
140 // kind of GC. |
|
141 _result = g1h->satisfy_failed_allocation(_word_size, _allocation_context, &_pause_succeeded); |
|
142 } else if (!g1h->has_regions_left_for_allocation()) { |
|
143 // There has been a request to perform a GC to free some space. We have no |
|
144 // information on how much memory has been asked for. In case there are |
|
145 // absolutely no regions left to allocate into, do a maximally compacting full GC. |
|
146 log_info(gc, ergo)("Attempting maximally compacting collection"); |
|
147 _pause_succeeded = g1h->do_full_collection(false, /* explicit gc */ |
|
148 true /* clear_all_soft_refs */); |
|
149 } |
|
150 guarantee(_pause_succeeded, "Elevated collections during the safepoint must always succeed."); |
154 } else { |
151 } else { |
155 assert(_result == NULL, "invariant"); |
152 assert(_result == NULL, "invariant"); |
156 if (!_pause_succeeded) { |
153 // The only reason for the pause to not be successful is that, the GC locker is |
157 // Another possible reason reason for the pause to not be successful |
154 // active (or has become active since the prologue was executed). In this case |
158 // is that, again, the GC locker is active (and has become active |
155 // we should retry the pause after waiting for the GC locker to become inactive. |
159 // since the prologue was executed). In this case we should retry |
156 _should_retry_gc = true; |
160 // the pause after waiting for the GC locker to become inactive. |
157 } |
161 _should_retry_gc = true; |
158 } |
162 } |
159 |
163 } |
160 void VM_G1CollectForAllocation::doit_epilogue() { |
164 } |
161 VM_CollectForAllocation::doit_epilogue(); |
165 |
|
166 void VM_G1IncCollectionPause::doit_epilogue() { |
|
167 VM_G1OperationWithAllocRequest::doit_epilogue(); |
|
168 |
162 |
169 // If the pause was initiated by a System.gc() and |
163 // If the pause was initiated by a System.gc() and |
170 // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle |
164 // +ExplicitGCInvokesConcurrent, we have to wait here for the cycle |
171 // that just started (or maybe one that was already in progress) to |
165 // that just started (or maybe one that was already in progress) to |
172 // finish. |
166 // finish. |