42 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue"); |
42 static const ZStatPhaseConcurrent ZPhaseConcurrentMarkContinue("Concurrent Mark Continue"); |
43 static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End"); |
43 static const ZStatPhasePause ZPhasePauseMarkEnd("Pause Mark End"); |
44 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References"); |
44 static const ZStatPhaseConcurrent ZPhaseConcurrentProcessNonStrongReferences("Concurrent Process Non-Strong References"); |
45 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); |
45 static const ZStatPhaseConcurrent ZPhaseConcurrentResetRelocationSet("Concurrent Reset Relocation Set"); |
46 static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); |
46 static const ZStatPhaseConcurrent ZPhaseConcurrentDestroyDetachedPages("Concurrent Destroy Detached Pages"); |
47 static const ZStatPhasePause ZPhasePauseVerify("Pause Verify"); |
|
48 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); |
47 static const ZStatPhaseConcurrent ZPhaseConcurrentSelectRelocationSet("Concurrent Select Relocation Set"); |
49 static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set"); |
48 static const ZStatPhaseConcurrent ZPhaseConcurrentPrepareRelocationSet("Concurrent Prepare Relocation Set"); |
50 static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start"); |
49 static const ZStatPhasePause ZPhasePauseRelocateStart("Pause Relocate Start"); |
51 static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate"); |
50 static const ZStatPhaseConcurrent ZPhaseConcurrentRelocated("Concurrent Relocate"); |
52 static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */); |
51 static const ZStatCriticalPhase ZCriticalPhaseGCLockerStall("GC Locker Stall", false /* verbose */); |
53 static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads); |
52 static const ZStatSampler ZSamplerJavaThreads("System", "Java Threads", ZStatUnitThreads); |
54 |
53 |
55 class ZOperationClosure : public StackObj { |
|
56 public: |
|
57 virtual const char* name() const = 0; |
|
58 |
|
59 virtual bool needs_inactive_gc_locker() const { |
|
60 // An inactive GC locker is needed in operations where we change the good |
|
61 // mask or move objects. Changing the good mask will invalidate all oops, |
|
62 // which makes it conceptually the same thing as moving all objects. |
|
63 return false; |
|
64 } |
|
65 |
|
66 virtual bool do_operation() = 0; |
|
67 }; |
|
68 |
|
69 class VM_ZOperation : public VM_Operation { |
54 class VM_ZOperation : public VM_Operation { |
70 private: |
55 private: |
71 ZOperationClosure* _cl; |
56 const uint _gc_id; |
72 uint _gc_id; |
57 bool _gc_locked; |
73 bool _gc_locked; |
58 bool _success; |
74 bool _success; |
|
75 |
59 |
76 public: |
60 public: |
77 VM_ZOperation(ZOperationClosure* cl) : |
61 VM_ZOperation() : |
78 _cl(cl), |
|
79 _gc_id(GCId::current()), |
62 _gc_id(GCId::current()), |
80 _gc_locked(false), |
63 _gc_locked(false), |
81 _success(false) {} |
64 _success(false) {} |
82 |
65 |
83 virtual VMOp_Type type() const { |
66 virtual bool needs_inactive_gc_locker() const { |
84 return VMOp_ZOperation; |
67 // An inactive GC locker is needed in operations where we change the bad |
85 } |
68 // mask or move objects. Changing the bad mask will invalidate all oops, |
86 |
69 // which makes it conceptually the same thing as moving all objects. |
87 virtual const char* name() const { |
70 return false; |
88 return _cl->name(); |
71 } |
89 } |
72 |
|
73 virtual bool do_operation() = 0; |
90 |
74 |
91 virtual bool doit_prologue() { |
75 virtual bool doit_prologue() { |
92 Heap_lock->lock(); |
76 Heap_lock->lock(); |
93 return true; |
77 return true; |
94 } |
78 } |
95 |
79 |
96 virtual void doit() { |
80 virtual void doit() { |
97 assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint"); |
81 // Abort if GC locker state is incompatible |
98 |
82 if (needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) { |
|
83 _gc_locked = true; |
|
84 return; |
|
85 } |
|
86 |
|
87 // Setup GC id and active marker |
|
88 GCIdMark gc_id_mark(_gc_id); |
|
89 IsGCActiveMark gc_active_mark; |
|
90 |
|
91 // Execute operation |
|
92 _success = do_operation(); |
|
93 |
|
94 // Update statistics |
99 ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads()); |
95 ZStatSample(ZSamplerJavaThreads, Threads::number_of_threads()); |
100 |
|
101 // Setup GC id |
|
102 GCIdMark gcid(_gc_id); |
|
103 |
|
104 if (_cl->needs_inactive_gc_locker() && GCLocker::check_active_before_gc()) { |
|
105 // GC locker is active, bail out |
|
106 _gc_locked = true; |
|
107 } else { |
|
108 // Execute operation |
|
109 IsGCActiveMark mark; |
|
110 _success = _cl->do_operation(); |
|
111 } |
|
112 } |
96 } |
113 |
97 |
114 virtual void doit_epilogue() { |
98 virtual void doit_epilogue() { |
115 Heap_lock->unlock(); |
99 Heap_lock->unlock(); |
116 } |
100 } |
117 |
101 |
118 bool gc_locked() { |
102 bool gc_locked() const { |
119 return _gc_locked; |
103 return _gc_locked; |
120 } |
104 } |
121 |
105 |
122 bool success() const { |
106 bool success() const { |
123 return _success; |
107 return _success; |
192 ZHeap::heap()->mark_start(); |
176 ZHeap::heap()->mark_start(); |
193 return true; |
177 return true; |
194 } |
178 } |
195 }; |
179 }; |
196 |
180 |
197 class ZMarkEndClosure : public ZOperationClosure { |
181 class VM_ZMarkEnd : public VM_ZOperation { |
198 public: |
182 public: |
199 virtual const char* name() const { |
183 virtual VMOp_Type type() const { |
200 return "ZMarkEnd"; |
184 return VMOp_ZMarkEnd; |
201 } |
185 } |
202 |
186 |
203 virtual bool do_operation() { |
187 virtual bool do_operation() { |
204 ZStatTimer timer(ZPhasePauseMarkEnd); |
188 ZStatTimer timer(ZPhasePauseMarkEnd); |
205 ZServiceabilityMarkEndTracer tracer; |
189 ZServiceabilityMarkEndTracer tracer; |
206 |
|
207 return ZHeap::heap()->mark_end(); |
190 return ZHeap::heap()->mark_end(); |
208 } |
191 } |
209 }; |
192 }; |
210 |
193 |
211 class ZVerifyClosure : public ZOperationClosure { |
194 class VM_ZRelocateStart : public VM_ZOperation { |
212 public: |
195 public: |
213 virtual const char* name() const { |
196 virtual VMOp_Type type() const { |
214 return "ZVerify"; |
197 return VMOp_ZRelocateStart; |
215 } |
|
216 |
|
217 virtual bool do_operation() { |
|
218 ZStatTimer timer(ZPhasePauseVerify); |
|
219 Universe::verify(); |
|
220 return true; |
|
221 } |
|
222 }; |
|
223 |
|
224 class ZRelocateStartClosure : public ZOperationClosure { |
|
225 public: |
|
226 virtual const char* name() const { |
|
227 return "ZRelocateStart"; |
|
228 } |
198 } |
229 |
199 |
230 virtual bool needs_inactive_gc_locker() const { |
200 virtual bool needs_inactive_gc_locker() const { |
231 return true; |
201 return true; |
232 } |
202 } |
233 |
203 |
234 virtual bool do_operation() { |
204 virtual bool do_operation() { |
235 ZStatTimer timer(ZPhasePauseRelocateStart); |
205 ZStatTimer timer(ZPhasePauseRelocateStart); |
236 ZServiceabilityRelocateStartTracer tracer; |
206 ZServiceabilityRelocateStartTracer tracer; |
237 |
|
238 ZHeap::heap()->relocate_start(); |
207 ZHeap::heap()->relocate_start(); |
239 return true; |
208 return true; |
240 } |
209 } |
241 }; |
210 }; |
242 |
211 |
243 ZDriver::ZDriver() : |
212 ZDriver::ZDriver() : |
244 _gc_cycle_port(), |
213 _gc_cycle_port(), |
245 _gc_locker_port() { |
214 _gc_locker_port() { |
246 set_name("ZDriver"); |
215 set_name("ZDriver"); |
247 create_and_start(); |
216 create_and_start(); |
248 } |
|
249 |
|
250 bool ZDriver::vm_operation(ZOperationClosure* cl) { |
|
251 for (;;) { |
|
252 VM_ZOperation op(cl); |
|
253 VMThread::execute(&op); |
|
254 if (op.gc_locked()) { |
|
255 // Wait for GC to become unlocked and restart the VM operation |
|
256 ZStatTimer timer(ZCriticalPhaseGCLockerStall); |
|
257 _gc_locker_port.wait(); |
|
258 continue; |
|
259 } |
|
260 |
|
261 // Notify VM operation completed |
|
262 _gc_locker_port.ack(); |
|
263 |
|
264 return op.success(); |
|
265 } |
|
266 } |
217 } |
267 |
218 |
268 void ZDriver::collect(GCCause::Cause cause) { |
219 void ZDriver::collect(GCCause::Cause cause) { |
269 switch (cause) { |
220 switch (cause) { |
270 case GCCause::_wb_young_gc: |
221 case GCCause::_wb_young_gc: |
300 fatal("Unsupported GC cause (%s)", GCCause::to_string(cause)); |
251 fatal("Unsupported GC cause (%s)", GCCause::to_string(cause)); |
301 break; |
252 break; |
302 } |
253 } |
303 } |
254 } |
304 |
255 |
305 GCCause::Cause ZDriver::start_gc_cycle() { |
256 template <typename T> |
306 // Wait for GC request |
257 bool ZDriver::pause() { |
307 return _gc_cycle_port.receive(); |
258 for (;;) { |
308 } |
259 T op; |
309 |
260 VMThread::execute(&op); |
310 class ZDriverCycleScope : public StackObj { |
261 if (op.gc_locked()) { |
|
262 // Wait for GC to become unlocked and restart the VM operation |
|
263 ZStatTimer timer(ZCriticalPhaseGCLockerStall); |
|
264 _gc_locker_port.wait(); |
|
265 continue; |
|
266 } |
|
267 |
|
268 // Notify VM operation completed |
|
269 _gc_locker_port.ack(); |
|
270 |
|
271 return op.success(); |
|
272 } |
|
273 } |
|
274 |
|
275 void ZDriver::pause_mark_start() { |
|
276 pause<VM_ZMarkStart>(); |
|
277 } |
|
278 |
|
279 void ZDriver::concurrent_mark() { |
|
280 ZStatTimer timer(ZPhaseConcurrentMark); |
|
281 ZHeap::heap()->mark(true /* initial */); |
|
282 } |
|
283 |
|
284 bool ZDriver::pause_mark_end() { |
|
285 return pause<VM_ZMarkEnd>(); |
|
286 } |
|
287 |
|
288 void ZDriver::concurrent_mark_continue() { |
|
289 ZStatTimer timer(ZPhaseConcurrentMarkContinue); |
|
290 ZHeap::heap()->mark(false /* initial */); |
|
291 } |
|
292 |
|
293 void ZDriver::concurrent_process_non_strong_references() { |
|
294 ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences); |
|
295 ZHeap::heap()->process_non_strong_references(); |
|
296 } |
|
297 |
|
298 void ZDriver::concurrent_reset_relocation_set() { |
|
299 ZStatTimer timer(ZPhaseConcurrentResetRelocationSet); |
|
300 ZHeap::heap()->reset_relocation_set(); |
|
301 } |
|
302 |
|
303 void ZDriver::concurrent_destroy_detached_pages() { |
|
304 ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages); |
|
305 ZHeap::heap()->destroy_detached_pages(); |
|
306 } |
|
307 |
|
308 void ZDriver::pause_verify() { |
|
309 if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) { |
|
310 VM_Verify op; |
|
311 VMThread::execute(&op); |
|
312 } |
|
313 } |
|
314 |
|
315 void ZDriver::concurrent_select_relocation_set() { |
|
316 ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet); |
|
317 ZHeap::heap()->select_relocation_set(); |
|
318 } |
|
319 |
|
320 void ZDriver::concurrent_prepare_relocation_set() { |
|
321 ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet); |
|
322 ZHeap::heap()->prepare_relocation_set(); |
|
323 } |
|
324 |
|
325 void ZDriver::pause_relocate_start() { |
|
326 pause<VM_ZRelocateStart>(); |
|
327 } |
|
328 |
|
329 void ZDriver::concurrent_relocate() { |
|
330 ZStatTimer timer(ZPhaseConcurrentRelocated); |
|
331 ZHeap::heap()->relocate(); |
|
332 } |
|
333 |
|
334 void ZDriver::check_out_of_memory() { |
|
335 ZHeap::heap()->check_out_of_memory(); |
|
336 } |
|
337 |
|
338 class ZDriverGCScope : public StackObj { |
311 private: |
339 private: |
312 GCIdMark _gc_id; |
340 GCIdMark _gc_id; |
313 GCCauseSetter _gc_cause_setter; |
341 GCCauseSetter _gc_cause_setter; |
314 ZStatTimer _timer; |
342 ZStatTimer _timer; |
315 |
343 |
316 public: |
344 public: |
317 ZDriverCycleScope(GCCause::Cause cause) : |
345 ZDriverGCScope(GCCause::Cause cause) : |
318 _gc_id(), |
346 _gc_id(), |
319 _gc_cause_setter(ZCollectedHeap::heap(), cause), |
347 _gc_cause_setter(ZCollectedHeap::heap(), cause), |
320 _timer(ZPhaseCycle) { |
348 _timer(ZPhaseCycle) { |
321 // Update statistics |
349 // Update statistics |
322 ZStatCycle::at_start(); |
350 ZStatCycle::at_start(); |
323 } |
351 } |
324 |
352 |
325 ~ZDriverCycleScope() { |
353 ~ZDriverGCScope() { |
326 // Calculate boost factor |
354 // Calculate boost factor |
327 const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() / |
355 const double boost_factor = (double)ZHeap::heap()->nconcurrent_worker_threads() / |
328 (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); |
356 (double)ZHeap::heap()->nconcurrent_no_boost_worker_threads(); |
329 |
357 |
330 // Update statistics |
358 // Update statistics |
333 // Update data used by soft reference policy |
361 // Update data used by soft reference policy |
334 Universe::update_heap_info_at_gc(); |
362 Universe::update_heap_info_at_gc(); |
335 } |
363 } |
336 }; |
364 }; |
337 |
365 |
338 void ZDriver::run_gc_cycle(GCCause::Cause cause) { |
366 void ZDriver::gc(GCCause::Cause cause) { |
339 ZDriverCycleScope scope(cause); |
367 ZDriverGCScope scope(cause); |
340 |
368 |
341 // Phase 1: Pause Mark Start |
369 // Phase 1: Pause Mark Start |
342 { |
370 pause_mark_start(); |
343 ZMarkStartClosure cl; |
|
344 vm_operation(&cl); |
|
345 } |
|
346 |
371 |
347 // Phase 2: Concurrent Mark |
372 // Phase 2: Concurrent Mark |
348 { |
373 concurrent_mark(); |
349 ZStatTimer timer(ZPhaseConcurrentMark); |
|
350 ZHeap::heap()->mark(true /* initial */); |
|
351 } |
|
352 |
374 |
353 // Phase 3: Pause Mark End |
375 // Phase 3: Pause Mark End |
354 { |
376 while (!pause_mark_end()) { |
355 ZMarkEndClosure cl; |
377 // Phase 3.5: Concurrent Mark Continue |
356 while (!vm_operation(&cl)) { |
378 concurrent_mark_continue(); |
357 // Phase 3.5: Concurrent Mark Continue |
|
358 ZStatTimer timer(ZPhaseConcurrentMarkContinue); |
|
359 ZHeap::heap()->mark(false /* initial */); |
|
360 } |
|
361 } |
379 } |
362 |
380 |
363 // Phase 4: Concurrent Process Non-Strong References |
381 // Phase 4: Concurrent Process Non-Strong References |
364 { |
382 concurrent_process_non_strong_references(); |
365 ZStatTimer timer(ZPhaseConcurrentProcessNonStrongReferences); |
|
366 ZHeap::heap()->process_non_strong_references(); |
|
367 } |
|
368 |
383 |
369 // Phase 5: Concurrent Reset Relocation Set |
384 // Phase 5: Concurrent Reset Relocation Set |
370 { |
385 concurrent_reset_relocation_set(); |
371 ZStatTimer timer(ZPhaseConcurrentResetRelocationSet); |
|
372 ZHeap::heap()->reset_relocation_set(); |
|
373 } |
|
374 |
386 |
375 // Phase 6: Concurrent Destroy Detached Pages |
387 // Phase 6: Concurrent Destroy Detached Pages |
376 { |
388 concurrent_destroy_detached_pages(); |
377 ZStatTimer timer(ZPhaseConcurrentDestroyDetachedPages); |
|
378 ZHeap::heap()->destroy_detached_pages(); |
|
379 } |
|
380 |
389 |
381 // Phase 7: Pause Verify |
390 // Phase 7: Pause Verify |
382 if (VerifyBeforeGC || VerifyDuringGC || VerifyAfterGC) { |
391 pause_verify(); |
383 ZVerifyClosure cl; |
|
384 vm_operation(&cl); |
|
385 } |
|
386 |
392 |
387 // Phase 8: Concurrent Select Relocation Set |
393 // Phase 8: Concurrent Select Relocation Set |
388 { |
394 concurrent_select_relocation_set(); |
389 ZStatTimer timer(ZPhaseConcurrentSelectRelocationSet); |
|
390 ZHeap::heap()->select_relocation_set(); |
|
391 } |
|
392 |
395 |
393 // Phase 9: Concurrent Prepare Relocation Set |
396 // Phase 9: Concurrent Prepare Relocation Set |
394 { |
397 concurrent_prepare_relocation_set(); |
395 ZStatTimer timer(ZPhaseConcurrentPrepareRelocationSet); |
|
396 ZHeap::heap()->prepare_relocation_set(); |
|
397 } |
|
398 |
398 |
399 // Phase 10: Pause Relocate Start |
399 // Phase 10: Pause Relocate Start |
400 { |
400 pause_relocate_start(); |
401 ZRelocateStartClosure cl; |
|
402 vm_operation(&cl); |
|
403 } |
|
404 |
401 |
405 // Phase 11: Concurrent Relocate |
402 // Phase 11: Concurrent Relocate |
406 { |
403 concurrent_relocate(); |
407 ZStatTimer timer(ZPhaseConcurrentRelocated); |
|
408 ZHeap::heap()->relocate(); |
|
409 } |
|
410 } |
|
411 |
|
412 void ZDriver::end_gc_cycle() { |
|
413 // Notify GC cycle completed |
|
414 _gc_cycle_port.ack(); |
|
415 |
|
416 // Check for out of memory condition |
|
417 ZHeap::heap()->check_out_of_memory(); |
|
418 } |
404 } |
419 |
405 |
420 void ZDriver::run_service() { |
406 void ZDriver::run_service() { |
421 // Main loop |
407 // Main loop |
422 while (!should_terminate()) { |
408 while (!should_terminate()) { |
423 const GCCause::Cause cause = start_gc_cycle(); |
409 // Wait for GC request |
424 if (cause != GCCause::_no_gc) { |
410 const GCCause::Cause cause = _gc_cycle_port.receive(); |
425 run_gc_cycle(cause); |
411 if (cause == GCCause::_no_gc) { |
426 end_gc_cycle(); |
412 continue; |
427 } |
413 } |
|
414 |
|
415 // Run GC |
|
416 gc(cause); |
|
417 |
|
418 // Notify GC completed |
|
419 _gc_cycle_port.ack(); |
|
420 |
|
421 // Check for out of memory condition |
|
422 check_out_of_memory(); |
428 } |
423 } |
429 } |
424 } |
430 |
425 |
431 void ZDriver::stop_service() { |
426 void ZDriver::stop_service() { |
432 _gc_cycle_port.send_async(GCCause::_no_gc); |
427 _gc_cycle_port.send_async(GCCause::_no_gc); |