1 | /* |
2 | * Copyright (c) 2015, 2019, Oracle and/or its affiliates. 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 | #include "precompiled.hpp" |
25 | #include "classfile/classLoaderDataGraph.hpp" |
26 | #include "classfile/stringTable.hpp" |
27 | #include "classfile/systemDictionary.hpp" |
28 | #include "code/codeCache.hpp" |
29 | #include "compiler/oopMap.hpp" |
30 | #include "gc/shared/barrierSet.hpp" |
31 | #include "gc/shared/barrierSetNMethod.hpp" |
32 | #include "gc/shared/oopStorageParState.inline.hpp" |
33 | #include "gc/shared/suspendibleThreadSet.hpp" |
34 | #include "gc/z/zBarrierSetNMethod.hpp" |
35 | #include "gc/z/zGlobals.hpp" |
36 | #include "gc/z/zNMethod.hpp" |
37 | #include "gc/z/zOopClosures.inline.hpp" |
38 | #include "gc/z/zRootsIterator.hpp" |
39 | #include "gc/z/zStat.hpp" |
40 | #include "gc/z/zThreadLocalData.hpp" |
41 | #include "memory/resourceArea.hpp" |
42 | #include "memory/universe.hpp" |
43 | #include "prims/jvmtiExport.hpp" |
44 | #include "prims/resolvedMethodTable.hpp" |
45 | #include "runtime/atomic.hpp" |
46 | #include "runtime/jniHandles.hpp" |
47 | #include "runtime/thread.hpp" |
48 | #include "runtime/safepoint.hpp" |
49 | #include "runtime/synchronizer.hpp" |
50 | #include "services/management.hpp" |
51 | #include "utilities/debug.hpp" |
52 | #if INCLUDE_JFR |
53 | #include "jfr/jfr.hpp" |
54 | #endif |
55 | |
56 | static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup" ); |
57 | static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots" ); |
58 | static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown" ); |
59 | static const ZStatSubPhase ZSubPhasePauseRootsUniverse("Pause Roots Universe" ); |
60 | static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer" ); |
61 | static const ZStatSubPhase ZSubPhasePauseRootsManagement("Pause Roots Management" ); |
62 | static const ZStatSubPhase ZSubPhasePauseRootsJVMTIExport("Pause Roots JVMTIExport" ); |
63 | static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport" ); |
64 | static const ZStatSubPhase ZSubPhasePauseRootsSystemDictionary("Pause Roots SystemDictionary" ); |
65 | static const ZStatSubPhase ZSubPhasePauseRootsThreads("Pause Roots Threads" ); |
66 | static const ZStatSubPhase ZSubPhasePauseRootsCodeCache("Pause Roots CodeCache" ); |
67 | |
68 | static const ZStatSubPhase ZSubPhaseConcurrentRootsSetup("Concurrent Roots Setup" ); |
69 | static const ZStatSubPhase ZSubPhaseConcurrentRoots("Concurrent Roots" ); |
70 | static const ZStatSubPhase ZSubPhaseConcurrentRootsTeardown("Concurrent Roots Teardown" ); |
71 | static const ZStatSubPhase ZSubPhaseConcurrentRootsJNIHandles("Concurrent Roots JNIHandles" ); |
72 | static const ZStatSubPhase ZSubPhaseConcurrentRootsClassLoaderDataGraph("Concurrent Roots ClassLoaderDataGraph" ); |
73 | |
74 | static const ZStatSubPhase ZSubPhasePauseWeakRootsSetup("Pause Weak Roots Setup" ); |
75 | static const ZStatSubPhase ZSubPhasePauseWeakRoots("Pause Weak Roots" ); |
76 | static const ZStatSubPhase ZSubPhasePauseWeakRootsTeardown("Pause Weak Roots Teardown" ); |
77 | static const ZStatSubPhase ZSubPhasePauseWeakRootsJVMTIWeakExport("Pause Weak Roots JVMTIWeakExport" ); |
78 | static const ZStatSubPhase ZSubPhasePauseWeakRootsJFRWeak("Pause Weak Roots JFRWeak" ); |
79 | |
80 | static const ZStatSubPhase ZSubPhaseConcurrentWeakRoots("Concurrent Weak Roots" ); |
81 | static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsVMWeakHandles("Concurrent Weak Roots VMWeakHandles" ); |
82 | static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsJNIWeakHandles("Concurrent Weak Roots JNIWeakHandles" ); |
83 | static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsStringTable("Concurrent Weak Roots StringTable" ); |
84 | static const ZStatSubPhase ZSubPhaseConcurrentWeakRootsResolvedMethodTable("Concurrent Weak Roots ResolvedMethodTable" ); |
85 | |
86 | template <typename T, void (T::*F)(ZRootsIteratorClosure*)> |
87 | ZSerialOopsDo<T, F>::ZSerialOopsDo(T* iter) : |
88 | _iter(iter), |
89 | _claimed(false) {} |
90 | |
91 | template <typename T, void (T::*F)(ZRootsIteratorClosure*)> |
92 | void ZSerialOopsDo<T, F>::oops_do(ZRootsIteratorClosure* cl) { |
93 | if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { |
94 | (_iter->*F)(cl); |
95 | } |
96 | } |
97 | |
98 | template <typename T, void (T::*F)(ZRootsIteratorClosure*)> |
99 | ZParallelOopsDo<T, F>::ZParallelOopsDo(T* iter) : |
100 | _iter(iter), |
101 | _completed(false) {} |
102 | |
103 | template <typename T, void (T::*F)(ZRootsIteratorClosure*)> |
104 | void ZParallelOopsDo<T, F>::oops_do(ZRootsIteratorClosure* cl) { |
105 | if (!_completed) { |
106 | (_iter->*F)(cl); |
107 | if (!_completed) { |
108 | _completed = true; |
109 | } |
110 | } |
111 | } |
112 | |
113 | template <typename T, void (T::*F)(BoolObjectClosure*, ZRootsIteratorClosure*)> |
114 | ZSerialWeakOopsDo<T, F>::ZSerialWeakOopsDo(T* iter) : |
115 | _iter(iter), |
116 | _claimed(false) {} |
117 | |
118 | template <typename T, void (T::*F)(BoolObjectClosure*, ZRootsIteratorClosure*)> |
119 | void ZSerialWeakOopsDo<T, F>::weak_oops_do(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl) { |
120 | if (!_claimed && Atomic::cmpxchg(true, &_claimed, false) == false) { |
121 | (_iter->*F)(is_alive, cl); |
122 | } |
123 | } |
124 | |
125 | template <typename T, void (T::*F)(BoolObjectClosure*, ZRootsIteratorClosure*)> |
126 | ZParallelWeakOopsDo<T, F>::ZParallelWeakOopsDo(T* iter) : |
127 | _iter(iter), |
128 | _completed(false) {} |
129 | |
130 | template <typename T, void (T::*F)(BoolObjectClosure*, ZRootsIteratorClosure*)> |
131 | void ZParallelWeakOopsDo<T, F>::weak_oops_do(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl) { |
132 | if (!_completed) { |
133 | (_iter->*F)(is_alive, cl); |
134 | if (!_completed) { |
135 | _completed = true; |
136 | } |
137 | } |
138 | } |
139 | |
140 | class ZRootsIteratorCodeBlobClosure : public CodeBlobToOopClosure { |
141 | private: |
142 | BarrierSetNMethod* _bs; |
143 | |
144 | public: |
145 | ZRootsIteratorCodeBlobClosure(OopClosure* cl) : |
146 | CodeBlobToOopClosure(cl, true /* fix_relocations */), |
147 | _bs(BarrierSet::barrier_set()->barrier_set_nmethod()) {} |
148 | |
149 | virtual void do_code_blob(CodeBlob* cb) { |
150 | nmethod* const nm = cb->as_nmethod_or_null(); |
151 | if (nm != NULL && !nm->test_set_oops_do_mark()) { |
152 | CodeBlobToOopClosure::do_code_blob(cb); |
153 | _bs->disarm(nm); |
154 | } |
155 | } |
156 | }; |
157 | |
158 | class ZRootsIteratorThreadClosure : public ThreadClosure { |
159 | private: |
160 | ZRootsIteratorClosure* _cl; |
161 | |
162 | public: |
163 | ZRootsIteratorThreadClosure(ZRootsIteratorClosure* cl) : |
164 | _cl(cl) {} |
165 | |
166 | virtual void do_thread(Thread* thread) { |
167 | ZRootsIteratorCodeBlobClosure code_cl(_cl); |
168 | thread->oops_do(_cl, ClassUnloading ? &code_cl : NULL); |
169 | _cl->do_thread(thread); |
170 | } |
171 | }; |
172 | |
173 | ZRootsIterator::ZRootsIterator() : |
174 | _universe(this), |
175 | _object_synchronizer(this), |
176 | _management(this), |
177 | _jvmti_export(this), |
178 | _jvmti_weak_export(this), |
179 | _system_dictionary(this), |
180 | _threads(this), |
181 | _code_cache(this) { |
182 | assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint" ); |
183 | ZStatTimer timer(ZSubPhasePauseRootsSetup); |
184 | Threads::change_thread_claim_token(); |
185 | COMPILER2_PRESENT(DerivedPointerTable::clear()); |
186 | if (ClassUnloading) { |
187 | nmethod::oops_do_marking_prologue(); |
188 | } else { |
189 | ZNMethod::oops_do_begin(); |
190 | } |
191 | } |
192 | |
193 | ZRootsIterator::~ZRootsIterator() { |
194 | ZStatTimer timer(ZSubPhasePauseRootsTeardown); |
195 | ResourceMark rm; |
196 | if (ClassUnloading) { |
197 | nmethod::oops_do_marking_epilogue(); |
198 | } else { |
199 | ZNMethod::oops_do_end(); |
200 | } |
201 | JvmtiExport::gc_epilogue(); |
202 | |
203 | COMPILER2_PRESENT(DerivedPointerTable::update_pointers()); |
204 | Threads::assert_all_threads_claimed(); |
205 | } |
206 | |
207 | void ZRootsIterator::do_universe(ZRootsIteratorClosure* cl) { |
208 | ZStatTimer timer(ZSubPhasePauseRootsUniverse); |
209 | Universe::oops_do(cl); |
210 | } |
211 | |
212 | void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) { |
213 | ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer); |
214 | ObjectSynchronizer::oops_do(cl); |
215 | } |
216 | |
217 | void ZRootsIterator::do_management(ZRootsIteratorClosure* cl) { |
218 | ZStatTimer timer(ZSubPhasePauseRootsManagement); |
219 | Management::oops_do(cl); |
220 | } |
221 | |
222 | void ZRootsIterator::do_jvmti_export(ZRootsIteratorClosure* cl) { |
223 | ZStatTimer timer(ZSubPhasePauseRootsJVMTIExport); |
224 | JvmtiExport::oops_do(cl); |
225 | } |
226 | |
227 | void ZRootsIterator::do_jvmti_weak_export(ZRootsIteratorClosure* cl) { |
228 | ZStatTimer timer(ZSubPhasePauseRootsJVMTIWeakExport); |
229 | AlwaysTrueClosure always_alive; |
230 | JvmtiExport::weak_oops_do(&always_alive, cl); |
231 | } |
232 | |
233 | void ZRootsIterator::do_system_dictionary(ZRootsIteratorClosure* cl) { |
234 | ZStatTimer timer(ZSubPhasePauseRootsSystemDictionary); |
235 | SystemDictionary::oops_do(cl); |
236 | } |
237 | |
238 | void ZRootsIterator::do_threads(ZRootsIteratorClosure* cl) { |
239 | ZStatTimer timer(ZSubPhasePauseRootsThreads); |
240 | ResourceMark rm; |
241 | ZRootsIteratorThreadClosure thread_cl(cl); |
242 | Threads::possibly_parallel_threads_do(true, &thread_cl); |
243 | } |
244 | |
245 | void ZRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) { |
246 | ZStatTimer timer(ZSubPhasePauseRootsCodeCache); |
247 | ZNMethod::oops_do(cl); |
248 | } |
249 | |
250 | void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl, bool visit_jvmti_weak_export) { |
251 | ZStatTimer timer(ZSubPhasePauseRoots); |
252 | _universe.oops_do(cl); |
253 | _object_synchronizer.oops_do(cl); |
254 | _management.oops_do(cl); |
255 | _jvmti_export.oops_do(cl); |
256 | _system_dictionary.oops_do(cl); |
257 | _threads.oops_do(cl); |
258 | if (!ClassUnloading) { |
259 | _code_cache.oops_do(cl); |
260 | } |
261 | if (visit_jvmti_weak_export) { |
262 | _jvmti_weak_export.oops_do(cl); |
263 | } |
264 | } |
265 | |
266 | ZConcurrentRootsIterator::ZConcurrentRootsIterator(int cld_claim) : |
267 | _jni_handles_iter(JNIHandles::global_handles()), |
268 | _cld_claim(cld_claim), |
269 | _jni_handles(this), |
270 | _class_loader_data_graph(this) { |
271 | ZStatTimer timer(ZSubPhaseConcurrentRootsSetup); |
272 | } |
273 | |
274 | ZConcurrentRootsIterator::~ZConcurrentRootsIterator() { |
275 | ZStatTimer timer(ZSubPhaseConcurrentRootsTeardown); |
276 | } |
277 | |
278 | void ZConcurrentRootsIterator::do_jni_handles(ZRootsIteratorClosure* cl) { |
279 | ZStatTimer timer(ZSubPhaseConcurrentRootsJNIHandles); |
280 | _jni_handles_iter.oops_do(cl); |
281 | } |
282 | |
283 | void ZConcurrentRootsIterator::do_class_loader_data_graph(ZRootsIteratorClosure* cl) { |
284 | ZStatTimer timer(ZSubPhaseConcurrentRootsClassLoaderDataGraph); |
285 | CLDToOopClosure cld_cl(cl, _cld_claim); |
286 | ClassLoaderDataGraph::always_strong_cld_do(&cld_cl); |
287 | } |
288 | |
289 | void ZConcurrentRootsIterator::oops_do(ZRootsIteratorClosure* cl) { |
290 | ZStatTimer timer(ZSubPhaseConcurrentRoots); |
291 | _jni_handles.oops_do(cl); |
292 | _class_loader_data_graph.oops_do(cl); |
293 | } |
294 | |
295 | ZWeakRootsIterator::ZWeakRootsIterator() : |
296 | _jvmti_weak_export(this), |
297 | _jfr_weak(this) { |
298 | assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint" ); |
299 | ZStatTimer timer(ZSubPhasePauseWeakRootsSetup); |
300 | } |
301 | |
302 | ZWeakRootsIterator::~ZWeakRootsIterator() { |
303 | ZStatTimer timer(ZSubPhasePauseWeakRootsTeardown); |
304 | } |
305 | |
306 | void ZWeakRootsIterator::do_jvmti_weak_export(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl) { |
307 | ZStatTimer timer(ZSubPhasePauseWeakRootsJVMTIWeakExport); |
308 | JvmtiExport::weak_oops_do(is_alive, cl); |
309 | } |
310 | |
311 | void ZWeakRootsIterator::do_jfr_weak(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl) { |
312 | #if INCLUDE_JFR |
313 | ZStatTimer timer(ZSubPhasePauseWeakRootsJFRWeak); |
314 | Jfr::weak_oops_do(is_alive, cl); |
315 | #endif |
316 | } |
317 | |
318 | void ZWeakRootsIterator::weak_oops_do(BoolObjectClosure* is_alive, ZRootsIteratorClosure* cl) { |
319 | ZStatTimer timer(ZSubPhasePauseWeakRoots); |
320 | _jvmti_weak_export.weak_oops_do(is_alive, cl); |
321 | _jfr_weak.weak_oops_do(is_alive, cl); |
322 | } |
323 | |
324 | void ZWeakRootsIterator::oops_do(ZRootsIteratorClosure* cl) { |
325 | AlwaysTrueClosure always_alive; |
326 | weak_oops_do(&always_alive, cl); |
327 | } |
328 | |
329 | ZConcurrentWeakRootsIterator::ZConcurrentWeakRootsIterator() : |
330 | _vm_weak_handles_iter(SystemDictionary::vm_weak_oop_storage()), |
331 | _jni_weak_handles_iter(JNIHandles::weak_global_handles()), |
332 | _string_table_iter(StringTable::weak_storage()), |
333 | _resolved_method_table_iter(ResolvedMethodTable::weak_storage()), |
334 | _vm_weak_handles(this), |
335 | _jni_weak_handles(this), |
336 | _string_table(this), |
337 | _resolved_method_table(this) { |
338 | StringTable::reset_dead_counter(); |
339 | ResolvedMethodTable::reset_dead_counter(); |
340 | } |
341 | |
342 | ZConcurrentWeakRootsIterator::~ZConcurrentWeakRootsIterator() { |
343 | StringTable::finish_dead_counter(); |
344 | ResolvedMethodTable::finish_dead_counter(); |
345 | } |
346 | |
347 | void ZConcurrentWeakRootsIterator::do_vm_weak_handles(ZRootsIteratorClosure* cl) { |
348 | ZStatTimer timer(ZSubPhaseConcurrentWeakRootsVMWeakHandles); |
349 | _vm_weak_handles_iter.oops_do(cl); |
350 | } |
351 | |
352 | void ZConcurrentWeakRootsIterator::do_jni_weak_handles(ZRootsIteratorClosure* cl) { |
353 | ZStatTimer timer(ZSubPhaseConcurrentWeakRootsJNIWeakHandles); |
354 | _jni_weak_handles_iter.oops_do(cl); |
355 | } |
356 | |
357 | template <class Container> |
358 | class ZDeadCounterClosure : public ZRootsIteratorClosure { |
359 | private: |
360 | ZRootsIteratorClosure* const _cl; |
361 | size_t _ndead; |
362 | |
363 | public: |
364 | ZDeadCounterClosure(ZRootsIteratorClosure* cl) : |
365 | _cl(cl), |
366 | _ndead(0) {} |
367 | |
368 | ~ZDeadCounterClosure() { |
369 | Container::inc_dead_counter(_ndead); |
370 | } |
371 | |
372 | virtual void do_oop(oop* p) { |
373 | _cl->do_oop(p); |
374 | if (*p == NULL) { |
375 | _ndead++; |
376 | } |
377 | } |
378 | |
379 | virtual void do_oop(narrowOop* p) { |
380 | ShouldNotReachHere(); |
381 | } |
382 | }; |
383 | |
384 | void ZConcurrentWeakRootsIterator::do_string_table(ZRootsIteratorClosure* cl) { |
385 | ZStatTimer timer(ZSubPhaseConcurrentWeakRootsStringTable); |
386 | ZDeadCounterClosure<StringTable> counter_cl(cl); |
387 | _string_table_iter.oops_do(&counter_cl); |
388 | } |
389 | |
390 | void ZConcurrentWeakRootsIterator::do_resolved_method_table(ZRootsIteratorClosure* cl) { |
391 | ZStatTimer timer(ZSubPhaseConcurrentWeakRootsResolvedMethodTable); |
392 | ZDeadCounterClosure<ResolvedMethodTable> counter_cl(cl); |
393 | _resolved_method_table_iter.oops_do(&counter_cl); |
394 | } |
395 | |
396 | void ZConcurrentWeakRootsIterator::oops_do(ZRootsIteratorClosure* cl) { |
397 | ZStatTimer timer(ZSubPhaseConcurrentWeakRoots); |
398 | _vm_weak_handles.oops_do(cl); |
399 | _jni_weak_handles.oops_do(cl); |
400 | _string_table.oops_do(cl); |
401 | _resolved_method_table.oops_do(cl); |
402 | } |
403 | |
404 | ZThreadRootsIterator::ZThreadRootsIterator() : |
405 | _threads(this) { |
406 | assert(SafepointSynchronize::is_at_safepoint(), "Should be at safepoint" ); |
407 | ZStatTimer timer(ZSubPhasePauseRootsSetup); |
408 | Threads::change_thread_claim_token(); |
409 | } |
410 | |
411 | ZThreadRootsIterator::~ZThreadRootsIterator() { |
412 | ZStatTimer timer(ZSubPhasePauseRootsTeardown); |
413 | Threads::assert_all_threads_claimed(); |
414 | } |
415 | |
416 | void ZThreadRootsIterator::do_threads(ZRootsIteratorClosure* cl) { |
417 | ZStatTimer timer(ZSubPhasePauseRootsThreads); |
418 | ResourceMark rm; |
419 | Threads::possibly_parallel_oops_do(true, cl, NULL); |
420 | } |
421 | |
422 | void ZThreadRootsIterator::oops_do(ZRootsIteratorClosure* cl) { |
423 | ZStatTimer timer(ZSubPhasePauseRoots); |
424 | _threads.oops_do(cl); |
425 | } |
426 | |