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 // Weak reference processing
93 ShenandoahHeap* const heap = ShenandoahHeap::heap();
94 ShenandoahReferenceProcessor* rp = heap->ref_processor();
95 rp->reset_thread_locals();
96 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs());
97
98 // Init mark, do not expect forwarded pointers in roots
99 if (ShenandoahVerify) {
100 assert(Thread::current()->is_VM_thread(), "Must be");
101 heap->verifier()->verify_roots_no_forwarded();
102 }
103
104 start_mark();
105
106 uint nworkers = heap->workers()->active_workers();
107 task_queues()->reserve(nworkers);
108
109 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
110
111 {
112 // Mark
113 StrongRootsScope scope(nworkers);
114 ShenandoahSTWMarkTask task(this);
115 heap->workers()->run_task(&task);
116
117 assert(task_queues()->is_empty(), "Should be empty");
118 }
119
120 heap->mark_complete_marking_context();
121 end_mark();
122
123 assert(task_queues()->is_empty(), "Should be empty");
124 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
125 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
126 }
127
128 void ShenandoahSTWMark::mark_roots(uint worker_id) {
129 ShenandoahInitMarkRootsClosure init_mark(task_queues()->queue(worker_id));
130 _root_scanner.roots_do(&init_mark, worker_id);
131 }
132
133 void ShenandoahSTWMark::finish_mark(uint worker_id) {
134 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark;
135 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id);
136 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->ref_processor();
137 StringDedup::Requests requests;
138
139 mark_loop(worker_id, &_terminator, rp,
140 false /* not cancellable */,
141 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests);
142 }
143
|
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/shenandoahGeneration.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<GenerationMode 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
49 public:
50 ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q);
51
52 void do_oop(narrowOop* p) { do_oop_work(p); }
53 void do_oop(oop* p) { do_oop_work(p); }
54 };
55
56 template<GenerationMode GENERATION>
57 ShenandoahInitMarkRootsClosure<GENERATION>::ShenandoahInitMarkRootsClosure(ShenandoahObjToScanQueue* q) :
58 _queue(q),
59 _mark_context(ShenandoahHeap::heap()->marking_context()) {
60 }
61
62 template <GenerationMode GENERATION>
63 template <class T>
64 void ShenandoahInitMarkRootsClosure<GENERATION>::do_oop_work(T* p) {
65 // Only called from STW mark, should not be used to bootstrap old generation marking.
66 ShenandoahMark::mark_through_ref<T, GENERATION>(p, _queue, nullptr, _mark_context, false);
67 }
68
69 class ShenandoahSTWMarkTask : public WorkerTask {
70 private:
71 ShenandoahSTWMark* const _mark;
72
73 public:
74 ShenandoahSTWMarkTask(ShenandoahSTWMark* mark);
75 void work(uint worker_id);
76 };
77
78 ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) :
79 WorkerTask("Shenandoah STW mark"),
80 _mark(mark) {
81 }
82
83 void ShenandoahSTWMarkTask::work(uint worker_id) {
84 ShenandoahParallelWorkerSession worker_session(worker_id);
85 _mark->mark_roots(worker_id);
86 _mark->finish_mark(worker_id);
87 }
88
89 ShenandoahSTWMark::ShenandoahSTWMark(ShenandoahGeneration* generation, bool full_gc) :
90 ShenandoahMark(generation),
91 _root_scanner(full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark),
92 _terminator(ShenandoahHeap::heap()->workers()->active_workers(), task_queues()),
93 _full_gc(full_gc) {
94 assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a Shenandoah safepoint");
95 }
96
97 void ShenandoahSTWMark::mark() {
98 // Weak reference processing
99 ShenandoahHeap* const heap = ShenandoahHeap::heap();
100 ShenandoahReferenceProcessor* rp = heap->active_generation()->ref_processor();
101 rp->reset_thread_locals();
102 rp->set_soft_reference_policy(heap->soft_ref_policy()->should_clear_all_soft_refs());
103
104 // Init mark, do not expect forwarded pointers in roots
105 if (ShenandoahVerify) {
106 assert(Thread::current()->is_VM_thread(), "Must be");
107 heap->verifier()->verify_roots_no_forwarded();
108 }
109
110 start_mark();
111
112 uint nworkers = heap->workers()->active_workers();
113 task_queues()->reserve(nworkers);
114
115 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
116
117 {
118 // Mark
119 if (_generation->generation_mode() == YOUNG) {
120 // But only scan the remembered set for young generation.
121 _generation->scan_remembered_set(false /* is_concurrent */);
122 }
123
124 StrongRootsScope scope(nworkers);
125 ShenandoahSTWMarkTask task(this);
126 heap->workers()->run_task(&task);
127
128 assert(task_queues()->is_empty(), "Should be empty");
129 }
130
131 _generation->set_mark_complete();
132 end_mark();
133
134 assert(task_queues()->is_empty(), "Should be empty");
135 TASKQUEUE_STATS_ONLY(task_queues()->print_taskqueue_stats());
136 TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
137 }
138
139 void ShenandoahSTWMark::mark_roots(uint worker_id) {
140 switch (_generation->generation_mode()) {
141 case GLOBAL: {
142 ShenandoahInitMarkRootsClosure<GLOBAL> init_mark(task_queues()->queue(worker_id));
143 _root_scanner.roots_do(&init_mark, worker_id);
144 break;
145 }
146 case YOUNG: {
147 ShenandoahInitMarkRootsClosure<YOUNG> init_mark(task_queues()->queue(worker_id));
148 _root_scanner.roots_do(&init_mark, worker_id);
149 break;
150 }
151 default:
152 ShouldNotReachHere();
153 }
154 }
155
156 void ShenandoahSTWMark::finish_mark(uint worker_id) {
157 ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark;
158 ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id);
159 ShenandoahReferenceProcessor* rp = ShenandoahHeap::heap()->active_generation()->ref_processor();
160 StringDedup::Requests requests;
161
162 mark_loop(_generation->generation_mode(),
163 worker_id, &_terminator, rp,
164 false /* not cancellable */,
165 ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests);
166 }
167
|