1028 ShenandoahHeap* heap = ShenandoahHeap::heap();
1029 ShenandoahTraversalGC* traversal_gc = heap->traversal_gc();
1030 ShenandoahPushWorkerQueuesScope scope(_workers,
1031 traversal_gc->task_queues(),
1032 ergo_workers,
1033 /* do_check = */ false);
1034 uint nworkers = _workers->active_workers();
1035 traversal_gc->task_queues()->reserve(nworkers);
1036 ShenandoahTaskTerminator terminator(nworkers, traversal_gc->task_queues());
1037 ShenandoahTraversalRefProcTaskProxy proc_task_proxy(task, &terminator);
1038 _workers->run_task(&proc_task_proxy);
1039 }
1040 };
1041
1042 void ShenandoahTraversalGC::weak_refs_work_doit() {
1043 ReferenceProcessor* rp = _heap->ref_processor();
1044
1045 ShenandoahPhaseTimings::Phase phase_process = ShenandoahPhaseTimings::weakrefs_process;
1046
1047 shenandoah_assert_rp_isalive_not_installed();
1048 ShenandoahForwardedIsAliveClosure is_alive;
1049 ReferenceProcessorIsAliveMutator fix_isalive(rp, &is_alive);
1050
1051 WorkGang* workers = _heap->workers();
1052 uint nworkers = workers->active_workers();
1053
1054 rp->setup_policy(_heap->soft_ref_policy()->should_clear_all_soft_refs());
1055 rp->set_active_mt_degree(nworkers);
1056
1057 assert(task_queues()->is_empty(), "Should be empty");
1058
1059 // complete_gc and keep_alive closures instantiated here are only needed for
1060 // single-threaded path in RP. They share the queue 0 for tracking work, which
1061 // simplifies implementation. Since RP may decide to call complete_gc several
1062 // times, we need to be able to reuse the terminator.
1063 uint serial_worker_id = 0;
1064 ShenandoahTaskTerminator terminator(1, task_queues());
1065 ShenandoahTraversalSingleThreadedDrainMarkingStackClosure complete_gc(serial_worker_id, &terminator, /* reset_terminator = */ true);
1066 ShenandoahPushWorkerQueuesScope scope(workers, task_queues(), 1, /* do_check = */ false);
1067
1068 ShenandoahTraversalRefProcTaskExecutor executor(workers);
|
1028 ShenandoahHeap* heap = ShenandoahHeap::heap();
1029 ShenandoahTraversalGC* traversal_gc = heap->traversal_gc();
1030 ShenandoahPushWorkerQueuesScope scope(_workers,
1031 traversal_gc->task_queues(),
1032 ergo_workers,
1033 /* do_check = */ false);
1034 uint nworkers = _workers->active_workers();
1035 traversal_gc->task_queues()->reserve(nworkers);
1036 ShenandoahTaskTerminator terminator(nworkers, traversal_gc->task_queues());
1037 ShenandoahTraversalRefProcTaskProxy proc_task_proxy(task, &terminator);
1038 _workers->run_task(&proc_task_proxy);
1039 }
1040 };
1041
1042 void ShenandoahTraversalGC::weak_refs_work_doit() {
1043 ReferenceProcessor* rp = _heap->ref_processor();
1044
1045 ShenandoahPhaseTimings::Phase phase_process = ShenandoahPhaseTimings::weakrefs_process;
1046
1047 shenandoah_assert_rp_isalive_not_installed();
1048 ShenandoahForwardedIsAliveNoCSetCheckClosure is_alive;
1049 ReferenceProcessorIsAliveMutator fix_isalive(rp, &is_alive);
1050
1051 WorkGang* workers = _heap->workers();
1052 uint nworkers = workers->active_workers();
1053
1054 rp->setup_policy(_heap->soft_ref_policy()->should_clear_all_soft_refs());
1055 rp->set_active_mt_degree(nworkers);
1056
1057 assert(task_queues()->is_empty(), "Should be empty");
1058
1059 // complete_gc and keep_alive closures instantiated here are only needed for
1060 // single-threaded path in RP. They share the queue 0 for tracking work, which
1061 // simplifies implementation. Since RP may decide to call complete_gc several
1062 // times, we need to be able to reuse the terminator.
1063 uint serial_worker_id = 0;
1064 ShenandoahTaskTerminator terminator(1, task_queues());
1065 ShenandoahTraversalSingleThreadedDrainMarkingStackClosure complete_gc(serial_worker_id, &terminator, /* reset_terminator = */ true);
1066 ShenandoahPushWorkerQueuesScope scope(workers, task_queues(), 1, /* do_check = */ false);
1067
1068 ShenandoahTraversalRefProcTaskExecutor executor(workers);
|