1 /*
2 * Copyright (c) 2019, 2020, 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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
25 #define SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP
26
27 #include "gc/shenandoah/shenandoahClosures.hpp"
28
29 #include "gc/shared/barrierSetNMethod.hpp"
30 #include "gc/shenandoah/shenandoahAsserts.hpp"
31 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
32 #include "gc/shenandoah/shenandoahEvacOOMHandler.inline.hpp"
33 #include "gc/shenandoah/shenandoahMarkingContext.inline.hpp"
34 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
35 #include "gc/shenandoah/shenandoahNMethod.inline.hpp"
36 #include "memory/iterator.inline.hpp"
37 #include "oops/compressedOops.inline.hpp"
38 #include "runtime/atomic.hpp"
39 #include "runtime/javaThread.hpp"
40
41 ShenandoahForwardedIsAliveClosure::ShenandoahForwardedIsAliveClosure() :
42 _mark_context(ShenandoahHeap::heap()->marking_context()) {
43 }
44
45 bool ShenandoahForwardedIsAliveClosure::do_object_b(oop obj) {
46 if (CompressedOops::is_null(obj)) {
47 return false;
48 }
49 obj = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
50 shenandoah_assert_not_forwarded_if(nullptr, obj, ShenandoahHeap::heap()->is_concurrent_mark_in_progress());
51 return _mark_context->is_marked(obj);
52 }
53
54 ShenandoahIsAliveClosure::ShenandoahIsAliveClosure() :
55 _mark_context(ShenandoahHeap::heap()->marking_context()) {
56 }
57
58 bool ShenandoahIsAliveClosure::do_object_b(oop obj) {
59 if (CompressedOops::is_null(obj)) {
60 return false;
61 }
62 shenandoah_assert_not_forwarded(nullptr, obj);
63 return _mark_context->is_marked(obj);
64 }
65
66 BoolObjectClosure* ShenandoahIsAliveSelector::is_alive_closure() {
67 return ShenandoahHeap::heap()->has_forwarded_objects() ?
68 reinterpret_cast<BoolObjectClosure*>(&_fwd_alive_cl) :
69 reinterpret_cast<BoolObjectClosure*>(&_alive_cl);
70 }
71
72 void ShenandoahOopClosureBase::do_nmethod(nmethod* nm) {
73 nm->run_nmethod_entry_barrier();
74 }
75
76 ShenandoahKeepAliveClosure::ShenandoahKeepAliveClosure() :
77 _bs(ShenandoahBarrierSet::barrier_set()) {
78 }
79
80 void ShenandoahKeepAliveClosure::do_oop(oop* p) {
81 do_oop_work(p);
82 }
83
84 void ShenandoahKeepAliveClosure::do_oop(narrowOop* p) {
85 do_oop_work(p);
86 }
87
88 template <typename T>
89 void ShenandoahKeepAliveClosure::do_oop_work(T* p) {
90 assert(ShenandoahHeap::heap()->is_concurrent_mark_in_progress(), "Only for concurrent marking phase");
91 assert(!ShenandoahHeap::heap()->has_forwarded_objects(), "Not expected");
92
93 T o = RawAccess<>::oop_load(p);
94 if (!CompressedOops::is_null(o)) {
95 oop obj = CompressedOops::decode_not_null(o);
96 _bs->enqueue(obj);
97 }
98 }
99
100 ShenandoahUpdateRefsClosure::ShenandoahUpdateRefsClosure() :
101 _heap(ShenandoahHeap::heap()) {
102 }
103
104 template <class T>
105 void ShenandoahUpdateRefsClosure::do_oop_work(T* p) {
106 _heap->update_with_forwarded(p);
107 }
108
109 void ShenandoahUpdateRefsClosure::do_oop(oop* p) { do_oop_work(p); }
110 void ShenandoahUpdateRefsClosure::do_oop(narrowOop* p) { do_oop_work(p); }
111
112 template <bool concurrent, bool stable_thread>
113 ShenandoahEvacuateUpdateRootClosureBase<concurrent, stable_thread>::ShenandoahEvacuateUpdateRootClosureBase() :
114 _heap(ShenandoahHeap::heap()), _thread(stable_thread ? Thread::current() : nullptr) {
115 }
116
117 template <bool concurrent, bool stable_thread>
118 void ShenandoahEvacuateUpdateRootClosureBase<concurrent, stable_thread>::do_oop(oop* p) {
119 if (concurrent) {
120 ShenandoahEvacOOMScope scope;
121 do_oop_work(p);
122 } else {
123 do_oop_work(p);
124 }
125 }
126
127 template <bool concurrent, bool stable_thread>
128 void ShenandoahEvacuateUpdateRootClosureBase<concurrent, stable_thread>::do_oop(narrowOop* p) {
129 if (concurrent) {
130 ShenandoahEvacOOMScope scope;
131 do_oop_work(p);
132 } else {
133 do_oop_work(p);
134 }
135 }
136
137 template <bool atomic, bool stable_thread>
138 template <class T>
139 void ShenandoahEvacuateUpdateRootClosureBase<atomic, stable_thread>::do_oop_work(T* p) {
140 assert(_heap->is_concurrent_weak_root_in_progress() ||
141 _heap->is_concurrent_strong_root_in_progress(),
142 "Only do this in root processing phase");
143
144 T o = RawAccess<>::oop_load(p);
145 if (!CompressedOops::is_null(o)) {
146 oop obj = CompressedOops::decode_not_null(o);
147 if (_heap->in_collection_set(obj)) {
148 assert(_heap->is_evacuation_in_progress(), "Only do this when evacuation is in progress");
149 shenandoah_assert_marked(p, obj);
150 oop resolved = ShenandoahBarrierSet::resolve_forwarded_not_null(obj);
151 if (resolved == obj) {
152 Thread* thr = stable_thread ? _thread : Thread::current();
153 assert(thr == Thread::current(), "Wrong thread");
154
155 resolved = _heap->evacuate_object(obj, thr);
156 }
157 if (atomic) {
158 ShenandoahHeap::atomic_update_oop(resolved, p, o);
159 } else {
160 RawAccess<IS_NOT_NULL | MO_UNORDERED>::oop_store(p, resolved);
161 }
162 }
163 }
164 }
165
166 template <bool CONCURRENT, typename IsAlive, typename KeepAlive>
167 ShenandoahCleanUpdateWeakOopsClosure<CONCURRENT, IsAlive, KeepAlive>::ShenandoahCleanUpdateWeakOopsClosure(IsAlive* is_alive, KeepAlive* keep_alive) :
168 _is_alive(is_alive), _keep_alive(keep_alive) {
169 if (!CONCURRENT) {
170 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint");
171 }
172 }
173
174 template <bool CONCURRENT, typename IsAlive, typename KeepAlive>
175 void ShenandoahCleanUpdateWeakOopsClosure<CONCURRENT, IsAlive, KeepAlive>::do_oop(oop* p) {
176 oop obj = RawAccess<>::oop_load(p);
177 if (!CompressedOops::is_null(obj)) {
178 if (_is_alive->do_object_b(obj)) {
179 _keep_alive->do_oop(p);
180 } else {
181 if (CONCURRENT) {
182 ShenandoahHeap::atomic_clear_oop(p, obj);
183 } else {
184 RawAccess<IS_NOT_NULL>::oop_store(p, oop());
185 }
186 }
187 }
188 }
189
190 template <bool CONCURRENT, typename IsAlive, typename KeepAlive>
191 void ShenandoahCleanUpdateWeakOopsClosure<CONCURRENT, IsAlive, KeepAlive>::do_oop(narrowOop* p) {
192 ShouldNotReachHere();
193 }
194
195 ShenandoahCodeBlobAndDisarmClosure::ShenandoahCodeBlobAndDisarmClosure(OopClosure* cl) :
196 CodeBlobToOopClosure(cl, true /* fix_relocations */),
197 _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {
198 }
199
200 void ShenandoahCodeBlobAndDisarmClosure::do_code_blob(CodeBlob* cb) {
201 nmethod* const nm = cb->as_nmethod_or_null();
202 if (nm != nullptr) {
203 assert(!ShenandoahNMethod::gc_data(nm)->is_unregistered(), "Should not be here");
204 CodeBlobToOopClosure::do_code_blob(cb);
205 _bs->disarm(nm);
206 }
207 }
208
209 #ifdef ASSERT
210 template <class T>
211 void ShenandoahAssertNotForwardedClosure::do_oop_work(T* p) {
212 T o = RawAccess<>::oop_load(p);
213 if (!CompressedOops::is_null(o)) {
214 oop obj = CompressedOops::decode_not_null(o);
215 shenandoah_assert_not_forwarded(p, obj);
216 }
217 }
218
219 void ShenandoahAssertNotForwardedClosure::do_oop(narrowOop* p) { do_oop_work(p); }
220 void ShenandoahAssertNotForwardedClosure::do_oop(oop* p) { do_oop_work(p); }
221 #endif
222
223 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHCLOSURES_INLINE_HPP