30 #include "gc/g1/g1ConcurrentMark.inline.hpp" |
30 #include "gc/g1/g1ConcurrentMark.inline.hpp" |
31 #include "gc/g1/g1MMUTracker.hpp" |
31 #include "gc/g1/g1MMUTracker.hpp" |
32 #include "gc/g1/g1Policy.hpp" |
32 #include "gc/g1/g1Policy.hpp" |
33 #include "gc/g1/suspendibleThreadSet.hpp" |
33 #include "gc/g1/suspendibleThreadSet.hpp" |
34 #include "gc/g1/vm_operations_g1.hpp" |
34 #include "gc/g1/vm_operations_g1.hpp" |
|
35 #include "gc/shared/concurrentGCPhaseManager.hpp" |
35 #include "gc/shared/gcId.hpp" |
36 #include "gc/shared/gcId.hpp" |
36 #include "gc/shared/gcTrace.hpp" |
37 #include "gc/shared/gcTrace.hpp" |
37 #include "gc/shared/gcTraceTime.inline.hpp" |
38 #include "gc/shared/gcTraceTime.inline.hpp" |
38 #include "logging/log.hpp" |
39 #include "logging/log.hpp" |
39 #include "memory/resourceArea.hpp" |
40 #include "memory/resourceArea.hpp" |
40 #include "runtime/vmThread.hpp" |
41 #include "runtime/vmThread.hpp" |
|
42 #include "utilities/debug.hpp" |
41 |
43 |
42 // ======= Concurrent Mark Thread ======== |
44 // ======= Concurrent Mark Thread ======== |
|
45 |
|
46 // Check order in EXPAND_CURRENT_PHASES |
|
47 STATIC_ASSERT(ConcurrentGCPhaseManager::UNCONSTRAINED_PHASE < |
|
48 ConcurrentGCPhaseManager::IDLE_PHASE); |
|
49 |
|
50 #define EXPAND_CONCURRENT_PHASES(expander) \ |
|
51 expander(ANY, = ConcurrentGCPhaseManager::UNCONSTRAINED_PHASE, NULL) \ |
|
52 expander(IDLE, = ConcurrentGCPhaseManager::IDLE_PHASE, NULL) \ |
|
53 expander(CONCURRENT_CYCLE,, "Concurrent Cycle") \ |
|
54 expander(CLEAR_CLAIMED_MARKS,, "Concurrent Clear Claimed Marks") \ |
|
55 expander(SCAN_ROOT_REGIONS,, "Concurrent Scan Root Regions") \ |
|
56 expander(CONCURRENT_MARK,, "Concurrent Mark") \ |
|
57 expander(MARK_FROM_ROOTS,, "Concurrent Mark From Roots") \ |
|
58 expander(BEFORE_REMARK,, NULL) \ |
|
59 expander(REMARK,, NULL) \ |
|
60 expander(CREATE_LIVE_DATA,, "Concurrent Create Live Data") \ |
|
61 expander(COMPLETE_CLEANUP,, "Concurrent Complete Cleanup") \ |
|
62 expander(CLEANUP_FOR_NEXT_MARK,, "Concurrent Cleanup for Next Mark") \ |
|
63 /* */ |
|
64 |
|
65 class G1ConcurrentPhase : public AllStatic { |
|
66 public: |
|
67 enum { |
|
68 #define CONCURRENT_PHASE_ENUM(tag, value, ignore_title) tag value, |
|
69 EXPAND_CONCURRENT_PHASES(CONCURRENT_PHASE_ENUM) |
|
70 #undef CONCURRENT_PHASE_ENUM |
|
71 PHASE_ID_LIMIT |
|
72 }; |
|
73 }; |
43 |
74 |
44 // The CM thread is created when the G1 garbage collector is used |
75 // The CM thread is created when the G1 garbage collector is used |
45 |
76 |
46 ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) : |
77 ConcurrentMarkThread::ConcurrentMarkThread(G1ConcurrentMark* cm) : |
47 ConcurrentGCThread(), |
78 ConcurrentGCThread(), |
48 _cm(cm), |
79 _cm(cm), |
49 _state(Idle), |
80 _state(Idle), |
|
81 _phase_manager_stack(), |
50 _vtime_accum(0.0), |
82 _vtime_accum(0.0), |
51 _vtime_mark_accum(0.0) { |
83 _vtime_mark_accum(0.0) { |
52 |
84 |
53 set_name("G1 Main Marker"); |
85 set_name("G1 Main Marker"); |
54 create_and_start(); |
86 create_and_start(); |
95 class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> { |
127 class G1ConcPhaseTimer : public GCTraceConcTimeImpl<LogLevel::Info, LOG_TAGS(gc, marking)> { |
96 G1ConcurrentMark* _cm; |
128 G1ConcurrentMark* _cm; |
97 |
129 |
98 public: |
130 public: |
99 G1ConcPhaseTimer(G1ConcurrentMark* cm, const char* title) : |
131 G1ConcPhaseTimer(G1ConcurrentMark* cm, const char* title) : |
100 GCTraceConcTimeImpl<LogLevel::Info, LogTag::_gc, LogTag::_marking>(title), |
132 GCTraceConcTimeImpl<LogLevel::Info, LogTag::_gc, LogTag::_marking>(title), |
101 _cm(cm) { |
133 _cm(cm) |
|
134 { |
102 _cm->gc_timer_cm()->register_gc_concurrent_start(title); |
135 _cm->gc_timer_cm()->register_gc_concurrent_start(title); |
103 } |
136 } |
104 |
137 |
105 ~G1ConcPhaseTimer() { |
138 ~G1ConcPhaseTimer() { |
106 _cm->gc_timer_cm()->register_gc_concurrent_end(); |
139 _cm->gc_timer_cm()->register_gc_concurrent_end(); |
107 } |
140 } |
108 }; |
141 }; |
109 |
142 |
|
143 static const char* const concurrent_phase_names[] = { |
|
144 #define CONCURRENT_PHASE_NAME(tag, ignore_value, ignore_title) XSTR(tag), |
|
145 EXPAND_CONCURRENT_PHASES(CONCURRENT_PHASE_NAME) |
|
146 #undef CONCURRENT_PHASE_NAME |
|
147 NULL // terminator |
|
148 }; |
|
149 // Verify dense enum assumption. +1 for terminator. |
|
150 STATIC_ASSERT(G1ConcurrentPhase::PHASE_ID_LIMIT + 1 == |
|
151 ARRAY_SIZE(concurrent_phase_names)); |
|
152 |
|
153 // Returns the phase number for name, or a negative value if unknown. |
|
154 static int lookup_concurrent_phase(const char* name) { |
|
155 const char* const* names = concurrent_phase_names; |
|
156 for (uint i = 0; names[i] != NULL; ++i) { |
|
157 if (strcmp(name, names[i]) == 0) { |
|
158 return static_cast<int>(i); |
|
159 } |
|
160 } |
|
161 return -1; |
|
162 } |
|
163 |
|
164 // The phase must be valid and must have a title. |
|
165 static const char* lookup_concurrent_phase_title(int phase) { |
|
166 static const char* const titles[] = { |
|
167 #define CONCURRENT_PHASE_TITLE(ignore_tag, ignore_value, title) title, |
|
168 EXPAND_CONCURRENT_PHASES(CONCURRENT_PHASE_TITLE) |
|
169 #undef CONCURRENT_PHASE_TITLE |
|
170 }; |
|
171 // Verify dense enum assumption. |
|
172 STATIC_ASSERT(G1ConcurrentPhase::PHASE_ID_LIMIT == ARRAY_SIZE(titles)); |
|
173 |
|
174 assert(0 <= phase, "precondition"); |
|
175 assert((uint)phase < ARRAY_SIZE(titles), "precondition"); |
|
176 const char* title = titles[phase]; |
|
177 assert(title != NULL, "precondition"); |
|
178 return title; |
|
179 } |
|
180 |
|
181 class G1ConcPhaseManager : public StackObj { |
|
182 G1ConcurrentMark* _cm; |
|
183 ConcurrentGCPhaseManager _manager; |
|
184 |
|
185 public: |
|
186 G1ConcPhaseManager(int phase, ConcurrentMarkThread* thread) : |
|
187 _cm(thread->cm()), |
|
188 _manager(phase, thread->phase_manager_stack()) |
|
189 { } |
|
190 |
|
191 ~G1ConcPhaseManager() { |
|
192 // Deactivate the manager if marking aborted, to avoid blocking on |
|
193 // phase exit when the phase has been requested. |
|
194 if (_cm->has_aborted()) { |
|
195 _manager.deactivate(); |
|
196 } |
|
197 } |
|
198 |
|
199 void set_phase(int phase, bool force) { |
|
200 _manager.set_phase(phase, force); |
|
201 } |
|
202 }; |
|
203 |
|
204 // Combine phase management and timing into one convenient utility. |
|
205 class G1ConcPhase : public StackObj { |
|
206 G1ConcPhaseTimer _timer; |
|
207 G1ConcPhaseManager _manager; |
|
208 |
|
209 public: |
|
210 G1ConcPhase(int phase, ConcurrentMarkThread* thread) : |
|
211 _timer(thread->cm(), lookup_concurrent_phase_title(phase)), |
|
212 _manager(phase, thread) |
|
213 { } |
|
214 }; |
|
215 |
|
216 const char* const* ConcurrentMarkThread::concurrent_phases() const { |
|
217 return concurrent_phase_names; |
|
218 } |
|
219 |
|
220 bool ConcurrentMarkThread::request_concurrent_phase(const char* phase_name) { |
|
221 int phase = lookup_concurrent_phase(phase_name); |
|
222 if (phase < 0) return false; |
|
223 |
|
224 while (!ConcurrentGCPhaseManager::wait_for_phase(phase, |
|
225 phase_manager_stack())) { |
|
226 assert(phase != G1ConcurrentPhase::ANY, "Wait for ANY phase must succeed"); |
|
227 if ((phase != G1ConcurrentPhase::IDLE) && !during_cycle()) { |
|
228 // If idle and the goal is !idle, start a collection. |
|
229 G1CollectedHeap::heap()->collect(GCCause::_wb_conc_mark); |
|
230 } |
|
231 } |
|
232 return true; |
|
233 } |
|
234 |
110 void ConcurrentMarkThread::run_service() { |
235 void ConcurrentMarkThread::run_service() { |
111 _vtime_start = os::elapsedVTime(); |
236 _vtime_start = os::elapsedVTime(); |
112 |
237 |
113 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
238 G1CollectedHeap* g1h = G1CollectedHeap::heap(); |
114 G1Policy* g1_policy = g1h->g1_policy(); |
239 G1Policy* g1_policy = g1h->g1_policy(); |
|
240 |
|
241 G1ConcPhaseManager cpmanager(G1ConcurrentPhase::IDLE, this); |
115 |
242 |
116 while (!should_terminate()) { |
243 while (!should_terminate()) { |
117 // wait until started is set. |
244 // wait until started is set. |
118 sleepBeforeNextCycle(); |
245 sleepBeforeNextCycle(); |
119 if (should_terminate()) { |
246 if (should_terminate()) { |
120 break; |
247 break; |
121 } |
248 } |
122 |
249 |
|
250 cpmanager.set_phase(G1ConcurrentPhase::CONCURRENT_CYCLE, false /* force */); |
|
251 |
123 GCIdMark gc_id_mark; |
252 GCIdMark gc_id_mark; |
124 |
253 |
125 cm()->concurrent_cycle_start(); |
254 cm()->concurrent_cycle_start(); |
126 |
255 |
127 assert(GCId::current() != GCId::undefined(), "GC id should have been set up by the initial mark GC."); |
256 assert(GCId::current() != GCId::undefined(), "GC id should have been set up by the initial mark GC."); |
144 // subsequent GC could block us from joining the STS and proceed |
273 // subsequent GC could block us from joining the STS and proceed |
145 // without the root regions have been scanned which would be a |
274 // without the root regions have been scanned which would be a |
146 // correctness issue. |
275 // correctness issue. |
147 |
276 |
148 { |
277 { |
149 G1ConcPhaseTimer t(_cm, "Concurrent Scan Root Regions"); |
278 G1ConcPhase p(G1ConcurrentPhase::SCAN_ROOT_REGIONS, this); |
150 _cm->scan_root_regions(); |
279 _cm->scan_root_regions(); |
151 } |
280 } |
152 |
281 |
153 // It would be nice to use the GCTraceConcTime class here but |
282 // It would be nice to use the G1ConcPhase class here but |
154 // the "end" logging is inside the loop and not at the end of |
283 // the "end" logging is inside the loop and not at the end of |
155 // a scope. Mimicking the same log output as GCTraceConcTime instead. |
284 // a scope. Also, the timer doesn't support nesting. |
156 jlong mark_start = os::elapsed_counter(); |
285 // Mimicking the same log output instead. |
157 log_info(gc, marking)("Concurrent Mark (%.3fs)", TimeHelper::counter_to_seconds(mark_start)); |
286 { |
158 |
287 G1ConcPhaseManager mark_manager(G1ConcurrentPhase::CONCURRENT_MARK, this); |
159 for (uint iter = 1; true; ++iter) { |
288 jlong mark_start = os::elapsed_counter(); |
160 if (!cm()->has_aborted()) { |
289 const char* cm_title = |
161 G1ConcPhaseTimer t(_cm, "Concurrent Mark From Roots"); |
290 lookup_concurrent_phase_title(G1ConcurrentPhase::CONCURRENT_MARK); |
162 _cm->mark_from_roots(); |
291 log_info(gc, marking)("%s (%.3fs)", |
163 } |
292 cm_title, |
164 |
293 TimeHelper::counter_to_seconds(mark_start)); |
165 double mark_end_time = os::elapsedVTime(); |
294 for (uint iter = 1; !cm()->has_aborted(); ++iter) { |
166 jlong mark_end = os::elapsed_counter(); |
295 // Concurrent marking. |
167 _vtime_mark_accum += (mark_end_time - cycle_start); |
296 { |
168 if (!cm()->has_aborted()) { |
297 G1ConcPhase p(G1ConcurrentPhase::MARK_FROM_ROOTS, this); |
|
298 _cm->mark_from_roots(); |
|
299 } |
|
300 if (cm()->has_aborted()) break; |
|
301 |
|
302 // Provide a control point after mark_from_roots. |
|
303 { |
|
304 G1ConcPhaseManager p(G1ConcurrentPhase::BEFORE_REMARK, this); |
|
305 } |
|
306 if (cm()->has_aborted()) break; |
|
307 |
|
308 // Delay remark pause for MMU. |
|
309 double mark_end_time = os::elapsedVTime(); |
|
310 jlong mark_end = os::elapsed_counter(); |
|
311 _vtime_mark_accum += (mark_end_time - cycle_start); |
169 delay_to_keep_mmu(g1_policy, true /* remark */); |
312 delay_to_keep_mmu(g1_policy, true /* remark */); |
170 log_info(gc, marking)("Concurrent Mark (%.3fs, %.3fs) %.3fms", |
313 if (cm()->has_aborted()) break; |
|
314 |
|
315 // Pause Remark. |
|
316 log_info(gc, marking)("%s (%.3fs, %.3fs) %.3fms", |
|
317 cm_title, |
171 TimeHelper::counter_to_seconds(mark_start), |
318 TimeHelper::counter_to_seconds(mark_start), |
172 TimeHelper::counter_to_seconds(mark_end), |
319 TimeHelper::counter_to_seconds(mark_end), |
173 TimeHelper::counter_to_millis(mark_end - mark_start)); |
320 TimeHelper::counter_to_millis(mark_end - mark_start)); |
174 |
321 mark_manager.set_phase(G1ConcurrentPhase::REMARK, false); |
175 CMCheckpointRootsFinalClosure final_cl(_cm); |
322 CMCheckpointRootsFinalClosure final_cl(_cm); |
176 VM_CGC_Operation op(&final_cl, "Pause Remark"); |
323 VM_CGC_Operation op(&final_cl, "Pause Remark"); |
177 VMThread::execute(&op); |
324 VMThread::execute(&op); |
|
325 if (cm()->has_aborted()) { |
|
326 break; |
|
327 } else if (!cm()->restart_for_overflow()) { |
|
328 break; // Exit loop if no restart requested. |
|
329 } else { |
|
330 // Loop to restart for overflow. |
|
331 mark_manager.set_phase(G1ConcurrentPhase::CONCURRENT_MARK, false); |
|
332 log_info(gc, marking)("%s Restart for Mark Stack Overflow (iteration #%u)", |
|
333 cm_title, iter); |
|
334 } |
178 } |
335 } |
179 |
|
180 if (!cm()->restart_for_overflow() || cm()->has_aborted()) { |
|
181 break; |
|
182 } |
|
183 |
|
184 log_info(gc, marking)("Concurrent Mark Restart due to overflow" |
|
185 " (iteration #%u", iter); |
|
186 } |
336 } |
187 |
337 |
188 if (!cm()->has_aborted()) { |
338 if (!cm()->has_aborted()) { |
189 G1ConcPhaseTimer t(_cm, "Concurrent Create Live Data"); |
339 G1ConcPhase p(G1ConcurrentPhase::CREATE_LIVE_DATA, this); |
190 cm()->create_live_data(); |
340 cm()->create_live_data(); |
191 } |
341 } |
192 |
342 |
193 double end_time = os::elapsedVTime(); |
343 double end_time = os::elapsedVTime(); |
194 // Update the total virtual time before doing this, since it will try |
344 // Update the total virtual time before doing this, since it will try |
218 // takes place, then we would carry on freeing regions in |
368 // takes place, then we would carry on freeing regions in |
219 // case they are needed by the pause. If a Full GC takes |
369 // case they are needed by the pause. If a Full GC takes |
220 // place, it would wait for us to process the regions |
370 // place, it would wait for us to process the regions |
221 // reclaimed by cleanup. |
371 // reclaimed by cleanup. |
222 |
372 |
223 G1ConcPhaseTimer t(_cm, "Concurrent Complete Cleanup"); |
|
224 // Now do the concurrent cleanup operation. |
373 // Now do the concurrent cleanup operation. |
|
374 G1ConcPhase p(G1ConcurrentPhase::COMPLETE_CLEANUP, this); |
225 _cm->complete_cleanup(); |
375 _cm->complete_cleanup(); |
226 |
376 |
227 // Notify anyone who's waiting that there are no more free |
377 // Notify anyone who's waiting that there are no more free |
228 // regions coming. We have to do this before we join the STS |
378 // regions coming. We have to do this before we join the STS |
229 // (in fact, we should not attempt to join the STS in the |
379 // (in fact, we should not attempt to join the STS in the |