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