296 }
297 os::naked_short_sleep(sleep);
298 }
299
300 // Wait for the actual stop(), can't leave run_service() earlier.
301 while (!should_terminate()) {
302 os::naked_short_sleep(ShenandoahControlIntervalMin);
303 }
304 }
305
306 void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cause) {
307 // Normal cycle goes via all concurrent phases. If allocation failure (af) happens during
308 // any of the concurrent phases, it first degrades to Degenerated GC and completes GC there.
309 // If second allocation failure happens during Degenerated GC cycle (for example, when GC
310 // tries to evac something and no memory is available), cycle degrades to Full GC.
311 //
312 // There are also a shortcut through the normal cycle: immediate garbage shortcut, when
313 // heuristics says there are no regions to compact, and all the collection comes from immediately
314 // reclaimable regions.
315 //
316 // ................................................................................................
317 //
318 // (immediate garbage shortcut) Concurrent GC
319 // /-------------------------------------------\
320 // | |
321 // | |
322 // | |
323 // | v
324 // [START] ----> Conc Mark ----o----> Conc Evac --o--> Conc Update-Refs ---o----> [END]
325 // | | | ^
326 // | (af) | (af) | (af) |
327 // ..................|....................|.................|..............|.......................
328 // | | | |
329 // | | | | Degenerated GC
330 // v v v |
331 // STW Mark ----------> STW Evac ----> STW Update-Refs ----->o
332 // | | | ^
333 // | (af) | (af) | (af) |
334 // ..................|....................|.................|..............|.......................
335 // | | | |
336 // | v | | Full GC
337 // \------------------->o<----------------/ |
338 // | |
339 // v |
340 // Full GC --------------------------/
341 //
342 ShenandoahHeap* heap = ShenandoahHeap::heap();
343
344 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_outside_cycle)) return;
345
346 GCIdMark gc_id_mark;
347 ShenandoahGCSession session(cause);
348
349 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
350
351 // Reset for upcoming marking
352 heap->entry_reset();
353
354 // Start initial mark under STW
355 heap->vmop_entry_init_mark();
356
357 // Continue concurrent mark
358 heap->entry_mark();
359 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_mark)) return;
360
377 ShenandoahHeapLocker locker(heap->lock());
378 heap->free_set()->log_status();
379 }
380
381 // Perform concurrent class unloading
382 if (heap->is_concurrent_weak_root_in_progress()) {
383 heap->entry_class_unloading();
384 }
385
386 // Processing strong roots
387 // This may be skipped if there is nothing to update/evacuate.
388 // If so, strong_root_in_progress would be unset.
389 if (heap->is_concurrent_strong_root_in_progress()) {
390 heap->entry_strong_roots();
391 }
392
393 // Continue the cycle with evacuation and optional update-refs.
394 // This may be skipped if there is nothing to evacuate.
395 // If so, evac_in_progress would be unset by collection set preparation code.
396 if (heap->is_evacuation_in_progress()) {
397 // Concurrently evacuate
398 heap->entry_evac();
399 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_evac)) return;
400
401 // Perform update-refs phase.
402 heap->vmop_entry_init_updaterefs();
403 heap->entry_updaterefs();
404 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_updaterefs)) return;
405
406 heap->vmop_entry_final_updaterefs();
407
408 // Update references freed up collection set, kick the cleanup to reclaim the space.
409 heap->entry_cleanup_complete();
410 }
411
412 // Cycle is complete
413 heap->heuristics()->record_success_concurrent();
414 heap->shenandoah_policy()->record_success_concurrent();
415 }
416
417 bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point) {
418 ShenandoahHeap* heap = ShenandoahHeap::heap();
419 if (heap->cancelled_gc()) {
420 assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting");
421 if (!in_graceful_shutdown()) {
422 assert (_degen_point == ShenandoahHeap::_degenerated_outside_cycle,
423 "Should not be set yet: %s", ShenandoahHeap::degen_point_to_string(_degen_point));
424 _degen_point = point;
425 }
426 return true;
|
296 }
297 os::naked_short_sleep(sleep);
298 }
299
300 // Wait for the actual stop(), can't leave run_service() earlier.
301 while (!should_terminate()) {
302 os::naked_short_sleep(ShenandoahControlIntervalMin);
303 }
304 }
305
306 void ShenandoahControlThread::service_concurrent_normal_cycle(GCCause::Cause cause) {
307 // Normal cycle goes via all concurrent phases. If allocation failure (af) happens during
308 // any of the concurrent phases, it first degrades to Degenerated GC and completes GC there.
309 // If second allocation failure happens during Degenerated GC cycle (for example, when GC
310 // tries to evac something and no memory is available), cycle degrades to Full GC.
311 //
312 // There are also a shortcut through the normal cycle: immediate garbage shortcut, when
313 // heuristics says there are no regions to compact, and all the collection comes from immediately
314 // reclaimable regions.
315 //
316 // ........................................................................................
317 //
318 // (immediate garbage shortcut) Concurrent GC
319 // /-----------------------------------\
320 // | |
321 // | |
322 // | |
323 // | v
324 // [START] ----> Conc Mark ----o---> Conc Evac-Update ---------> [END]
325 // | | ^
326 // | (af) | (af) |
327 // ..................|.....................|.......................|.......................
328 // | | |
329 // | | | Degenerated GC
330 // v v |
331 // STW Mark ---------> STW Evac-Update ------------->o
332 // | | ^
333 // | (af) | (af) |
334 // ..................|.....................|.......................|.......................
335 // | | |
336 // | v | Full GC
337 // \-------------------->o |
338 // | |
339 // v |
340 // Full GC ------------------/
341 //
342 ShenandoahHeap* heap = ShenandoahHeap::heap();
343
344 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_outside_cycle)) return;
345
346 GCIdMark gc_id_mark;
347 ShenandoahGCSession session(cause);
348
349 TraceCollectorStats tcs(heap->monitoring_support()->concurrent_collection_counters());
350
351 // Reset for upcoming marking
352 heap->entry_reset();
353
354 // Start initial mark under STW
355 heap->vmop_entry_init_mark();
356
357 // Continue concurrent mark
358 heap->entry_mark();
359 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_mark)) return;
360
377 ShenandoahHeapLocker locker(heap->lock());
378 heap->free_set()->log_status();
379 }
380
381 // Perform concurrent class unloading
382 if (heap->is_concurrent_weak_root_in_progress()) {
383 heap->entry_class_unloading();
384 }
385
386 // Processing strong roots
387 // This may be skipped if there is nothing to update/evacuate.
388 // If so, strong_root_in_progress would be unset.
389 if (heap->is_concurrent_strong_root_in_progress()) {
390 heap->entry_strong_roots();
391 }
392
393 // Continue the cycle with evacuation and optional update-refs.
394 // This may be skipped if there is nothing to evacuate.
395 // If so, evac_in_progress would be unset by collection set preparation code.
396 if (heap->is_evacuation_in_progress()) {
397 heap->vmop_entry_init_evac_update();
398
399 // Concurrently evacuate and update the refs
400 heap->entry_evac_update();
401 if (check_cancellation_or_degen(ShenandoahHeap::_degenerated_evac_update)) return;
402
403 heap->vmop_entry_final_evac_update();
404
405 // Update references freed up collection set, kick the cleanup to reclaim the space.
406 heap->entry_cleanup_complete();
407 }
408
409 // Cycle is complete
410 heap->heuristics()->record_success_concurrent();
411 heap->shenandoah_policy()->record_success_concurrent();
412 }
413
414 bool ShenandoahControlThread::check_cancellation_or_degen(ShenandoahHeap::ShenandoahDegenPoint point) {
415 ShenandoahHeap* heap = ShenandoahHeap::heap();
416 if (heap->cancelled_gc()) {
417 assert (is_alloc_failure_gc() || in_graceful_shutdown(), "Cancel GC either for alloc failure GC, or gracefully exiting");
418 if (!in_graceful_shutdown()) {
419 assert (_degen_point == ShenandoahHeap::_degenerated_outside_cycle,
420 "Should not be set yet: %s", ShenandoahHeap::degen_point_to_string(_degen_point));
421 _degen_point = point;
422 }
423 return true;
|