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/shenandoahOopClosures.inline.hpp" 35 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp" 36 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" 37 #include "gc/shenandoah/shenandoahSTWMark.hpp" 38 #include "gc/shenandoah/shenandoahVerifier.hpp" 39 40 template<ShenandoahGenerationType GENERATION> 41 class ShenandoahInitMarkRootsClosure : public OopClosure { 42 private: 43 ShenandoahObjToScanQueue* const _queue; 44 ShenandoahMarkingContext* const _mark_context; 45 46 template <class T> 47 inline void do_oop_work(T* p); 48 public: 49 ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q); 50 51 void do_oop(narrowOop* p) { do_oop_work(p); } 52 void do_oop(oop* p) { do_oop_work(p); } 53 }; 54 55 template <ShenandoahGenerationType GENERATION> 56 ShenandoahInitMarkRootsClosure<GENERATION>::ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q) : 57 _queue(q), 58 _mark_context(ShenandoahHeap::heap()->marking_context()) { 59 } 60 61 template <ShenandoahGenerationType GENERATION> 62 template <class T> 63 void ShenandoahInitMarkRootsClosure<GENERATION>::do_oop_work(T* p) { 64 ShenandoahMark::mark_through_ref<T, GENERATION>(p, _queue, _mark_context, false); 65 } 66 67 class ShenandoahSTWMarkTask : public WorkerTask { 68 private: 69 ShenandoahSTWMark* const _mark; 70 71 public: 72 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark); 73 void work(uint worker_id); 74 }; 75 76 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) : 77 WorkerTask("Shenandoah STW mark"), 78 _mark(mark) { 79 } 80 81 void ShenandoahSTWMarkTask::work(uint worker_id) { 82 ShenandoahParallelWorkerSession worker_session(worker_id); 83 _mark->mark_roots(worker_id); 84 _mark->finish_mark(worker_id); 85 } 86 87 ShenandoahSTWMark::ShenandoahSTWMark(bool full_gc) : 88 ShenandoahMark(), 89 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark), 90 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), ShenandoahHeap::heap()->marking_context()->task_queues()), 91 _full_gc(full_gc) { 92 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint"); 93 } 94 95 void ShenandoahSTWMark::mark() { 96 ShenandoahHeap* const heap = ShenandoahHeap::heap(); 97 98 // Arm all nmethods. Even though this is STW mark, some marking code 99 // piggybacks on nmethod barriers for special instances. 100 ShenandoahCodeRoots::arm_nmethods_for_mark(); 101 102 // Weak reference processing 103 ShenandoahReferenceProcessor* rp = heap->ref_processor(); 104 rp->reset_thread_locals(); 105 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs()); 106 107 // Init mark, do not expect forwarded pointers in roots 108 if (ShenandoahVerify) { 109 assert(Thread::current()->is_VM_thread(), "Must be"); 110 heap->verifier()->verify_roots_no_forwarded(); 111 } 112 113 start_mark(); 114 115 uint nworkers = heap->workers()->active_workers(); 116 task_queues()->reserve(nworkers); 117 118 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); 119 120 { 121 // Mark 122 StrongRootsScope scope(nworkers); 123 ShenandoahSTWMarkTask task(this); 124 heap->workers()->run_task(&task); 125 126 assert(task_queues()->is_empty(), "Should be empty"); 127 } 128 129 heap->mark_complete_marking_context(); 130 end_mark(); 131 132 // Mark is finished, can disarm the nmethods now. 133 ShenandoahCodeRoots::disarm_nmethods(); 134 135 assert(task_queues()->is_empty(), "Should be empty"); 136 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats()); 137 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats()); 138 } 139 140 void ShenandoahSTWMark::mark_roots(uint worker_id) { 141 ShenandoahInitMarkRootsClosure<NON_GEN> init_mark(task_queues()->queue(worker_id)); 142 _root_scanner.roots_do(&init_mark, worker_id); 143 } 144 145 void ShenandoahSTWMark::finish_mark(uint worker_id) { 146 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark; 147 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id); 148 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor(); 149 StringDedup::Requests requests; 150 151 mark_loop(worker_id, &_terminator, rp, NON_GEN, false /* not cancellable */, 152 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests); 153 }