1 /* 2 * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 26 #include "precompiled.hpp" 27 28 #include "gc/shared/strongRootsScope.hpp" 29 #include "gc/shared/taskTerminator.hpp" 30 #include "gc/shared/workerThread.hpp" 31 #include "gc/shenandoah/shenandoahClosures.inline.hpp" 32 #include "gc/shenandoah/shenandoahGenerationType.hpp" 33 #include "gc/shenandoah/shenandoahMark.inline.hpp" 34 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" 35 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" 36 #include "gc/shenandoah/shenandoahSTWMark.hpp" 37 #include "gc/shenandoah/shenandoahVerifier.hpp" 38 39 class ShenandoahSTWMarkTask : public WorkerTask { 40 private: 41 ShenandoahSTWMark* const _mark; 42 43 public: 44 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark); 45 void work(uint worker_id); 46 }; 47 48 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) : 49 WorkerTask("Shenandoah STW mark"), 50 _mark(mark) { 51 } 52 53 void ShenandoahSTWMarkTask::work(uint worker_id) { 54 ShenandoahParallelWorkerSession worker_session(worker_id); 55 _mark->mark_roots(worker_id); 56 _mark->finish_mark(worker_id); 57 } 58 59 ShenandoahSTWMark::ShenandoahSTWMark(bool full_gc) : 60 ShenandoahMark(), 61 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark), 62 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), ShenandoahHeap::heap()->marking_context()->task_queues()), 63 _full_gc(full_gc) { 64 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint"); 65 } 66 67 void ShenandoahSTWMark::mark() { 68 ShenandoahHeap* const heap = ShenandoahHeap::heap(); 69 70 // Arm all nmethods. Even though this is STW mark, some marking code 71 // piggybacks on nmethod barriers for special instances. 72 ShenandoahCodeRoots::arm_nmethods_for_mark(); 73 74 // Weak reference processing 75 ShenandoahReferenceProcessor* rp = heap->ref_processor(); 76 rp->reset_thread_locals(); 77 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs()); 78 79 // Init mark, do not expect forwarded pointers in roots 80 if (ShenandoahVerify) { 81 assert(Thread::current()->is_VM_thread(), "Must be"); 82 heap->verifier()->verify_roots_no_forwarded(); 83 } 84 85 start_mark(); 86 87 uint nworkers = heap->workers()->active_workers(); 88 task_queues()->reserve(nworkers); 89 90 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); 91 92 { 93 // Mark 94 StrongRootsScope scope(nworkers); 95 ShenandoahSTWMarkTask task(this); 96 heap->workers()->run_task(&task); 97 98 assert(task_queues()->is_empty(), "Should be empty"); 99 } 100 101 heap->mark_complete_marking_context(); 102 end_mark(); 103 104 // Mark is finished, can disarm the nmethods now. 105 ShenandoahCodeRoots::disarm_nmethods(); 106 107 assert(task_queues()->is_empty(), "Should be empty"); 108 TASKQUEUE_STATS_ONLY(task_queues()->print_and_reset_taskqueue_stats("")); 109 } 110 111 void ShenandoahSTWMark::mark_roots(uint worker_id) { 112 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor(); 113 ShenandoahMarkRefsClosure<NON_GEN> cl(task_queues()->queue(worker_id), rp); 114 _root_scanner.roots_do(&cl, worker_id); 115 } 116 117 void ShenandoahSTWMark::finish_mark(uint worker_id) { 118 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark; 119 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id); 120 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor(); 121 StringDedup::Requests requests; 122 123 mark_loop(worker_id, &_terminator, rp, NON_GEN, false /* not cancellable */, 124 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests); 125 }