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
|
1 /*
2 * Copyright (c) 2021, 2022, Red Hat, Inc. All rights reserved.
3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 only, as
8 * published by the Free Software Foundation.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 *
24 */
25
26
27 #include "precompiled.hpp"
28
29 #include "gc/shared/strongRootsScope.hpp"
30 #include "gc/shared/taskTerminator.hpp"
31 #include "gc/shared/workerThread.hpp"
32 #include "gc/shenandoah/shenandoahClosures.inline.hpp"
33 #include "gc/shenandoah/shenandoahGeneration.hpp"
34 #include "gc/shenandoah/shenandoahGenerationType.hpp"
35 #include "gc/shenandoah/shenandoahMark.inline.hpp"
36 #include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
37 #include "gc/shenandoah/shenandoahReferenceProcessor.hpp"
38 #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp"
39 #include "gc/shenandoah/shenandoahSTWMark.hpp"
40 #include "gc/shenandoah/shenandoahVerifier.hpp"
41
42 template<ShenandoahGenerationType GENERATION>
43 class ShenandoahInitMarkRootsClosure : public OopClosure {
44 private:
45 ShenandoahObjToScanQueue* const _queue;
46 ShenandoahMarkingContext* const _mark_context;
47
48 template <class T>
49 inline void do_oop_work(T* p);
50
51 public:
52 ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q);
53
54 void do_oop(narrowOop* p) { do_oop_work(p); }
55 void do_oop(oop* p) { do_oop_work(p); }
56 };
57
58 template <ShenandoahGenerationType GENERATION>
59 ShenandoahInitMarkRootsClosure<GENERATION>::ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q) :
60 _queue(q),
61 _mark_context(ShenandoahHeap::heap()->marking_context()) {
62 }
63
64 template <ShenandoahGenerationType GENERATION>
65 template <class T>
66 void ShenandoahInitMarkRootsClosure<GENERATION>::do_oop_work(T* p) {
67 // Only called from STW mark, should not be used to bootstrap old generation marking.
68 ShenandoahMark::mark_through_ref<T, GENERATION>(p, _queue, nullptr, _mark_context, false);
69 }
70
71 class ShenandoahSTWMarkTask : public WorkerTask {
72 private:
73 ShenandoahSTWMark* const _mark;
74
75 public:
76 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark);
77 void work(uint worker_id);
78 };
79
80 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) :
81 WorkerTask("Shenandoah STW mark"),
82 _mark(mark) {
83 }
84
85 void ShenandoahSTWMarkTask::work(uint worker_id) {
86 ShenandoahParallelWorkerSession worker_session(worker_id);
87 _mark->mark_roots(worker_id);
88 _mark->finish_mark(worker_id);
89 }
90
91 ShenandoahSTWMark::ShenandoahSTWMark(ShenandoahGeneration* generation, bool full_gc) :
92 ShenandoahMark(generation),
93 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark),
94 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), task_queues()),
95 _full_gc(full_gc) {
96 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint");
97 }
98
99 void ShenandoahSTWMark::mark() {
100 ShenandoahHeap* const heap = ShenandoahHeap::heap();
101
102 // Arm all nmethods. Even though this is STW mark, some marking code
103 // piggybacks on nmethod barriers for special instances.
104 ShenandoahCodeRoots::arm_nmethods_for_mark();
105
106 // Weak reference processing
107 ShenandoahReferenceProcessor* rp = heap->gc_generation()->ref_processor();
108 shenandoah_assert_generations_reconciled();
109 rp->reset_thread_locals();
110 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs());
111
112 // Init mark, do not expect forwarded pointers in roots
113 if (ShenandoahVerify) {
114 assert(Thread::current()->is_VM_thread(), "Must be");
115 heap->verifier()->verify_roots_no_forwarded();
116 }
117
118 start_mark();
119
120 uint nworkers = heap->workers()->active_workers();
121 task_queues()->reserve(nworkers);
122
123 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
124
125 {
126 // Mark
127 if (_generation->is_young()) {
128 // But only scan the remembered set for young generation.
129 _generation->scan_remembered_set(false /* is_concurrent */);
130 }
131
132 StrongRootsScope scope(nworkers);
133 ShenandoahSTWMarkTask task(this);
134 heap->workers()->run_task(&task);
135
136 assert(task_queues()->is_empty(), "Should be empty");
137 }
138
139 _generation->set_mark_complete();
140 end_mark();
141
142 // Mark is finished, can disarm the nmethods now.
143 ShenandoahCodeRoots::disarm_nmethods();
144
145 assert(task_queues()->is_empty(), "Should be empty");
146 TASKQUEUE_STATS_ONLY(task_queues()->print_and_reset_taskqueue_stats(""));
147 }
148
149 void ShenandoahSTWMark::mark_roots(uint worker_id) {
150 switch (_generation->type()) {
151 case NON_GEN: {
152 ShenandoahInitMarkRootsClosure<NON_GEN> init_mark(task_queues()->queue(worker_id));
153 _root_scanner.roots_do(&init_mark, worker_id);
154 break;
155 }
156 case GLOBAL: {
157 ShenandoahInitMarkRootsClosure<GLOBAL> init_mark(task_queues()->queue(worker_id));
158 _root_scanner.roots_do(&init_mark, worker_id);
159 break;
160 }
161 case YOUNG: {
162 ShenandoahInitMarkRootsClosure<YOUNG> init_mark(task_queues()->queue(worker_id));
163 _root_scanner.roots_do(&init_mark, worker_id);
164 break;
165 }
166 case OLD:
167 default:
168 ShouldNotReachHere();
169 }
170 }
171
172 void ShenandoahSTWMark::finish_mark(uint worker_id) {
173 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark;
174 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id);
175 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->gc_generation()->ref_processor();
176 shenandoah_assert_generations_reconciled();
177 StringDedup::Requests requests;
178
179 mark_loop(worker_id, &_terminator, rp,
180 _generation->type(), false /* not cancellable */,
181 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests);
182 }
|