1/*
2 * Copyright (c) 2014, 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
25#include "precompiled.hpp"
26#include "aot/aotLoader.hpp"
27#include "classfile/classLoaderDataGraph.hpp"
28#include "classfile/stringTable.hpp"
29#include "gc/shared/strongRootsScope.hpp"
30#include "jfr/leakprofiler/utilities/unifiedOop.hpp"
31#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
32#include "memory/iterator.hpp"
33#include "memory/universe.hpp"
34#include "oops/klass.hpp"
35#include "oops/markOop.hpp"
36#include "oops/oop.hpp"
37#include "prims/jvmtiThreadState.hpp"
38#include "runtime/frame.inline.hpp"
39#include "runtime/mutexLocker.hpp"
40#include "runtime/threadSMR.inline.hpp"
41#include "runtime/vframe_hp.hpp"
42#include "services/management.hpp"
43#include "utilities/growableArray.hpp"
44#if INCLUDE_JVMCI
45#include "jvmci/jvmci.hpp"
46#endif
47
48class ReferenceLocateClosure : public OopClosure {
49 protected:
50 RootCallback& _callback;
51 RootCallbackInfo _info;
52 bool _complete;
53
54 void do_oop_shared(const void* ref);
55
56 public:
57 ReferenceLocateClosure(RootCallback& callback,
58 OldObjectRoot::System system,
59 OldObjectRoot::Type type,
60 const void* context) : _callback(callback),
61 _info(),
62 _complete(false) {
63 _info._high = NULL;
64 _info._low = NULL;
65 _info._system = system;
66 _info._type = type;
67 _info._context = context;
68 }
69
70 virtual void do_oop(oop* ref);
71 virtual void do_oop(narrowOop* ref);
72
73 bool complete() const {
74 return _complete;
75 }
76};
77
78void ReferenceLocateClosure::do_oop_shared(const void* ref) {
79 assert(ref != NULL, "invariant");
80 if (!_complete) {
81 _info._high = ref;
82 _complete = _callback.process(_info);
83 }
84}
85
86void ReferenceLocateClosure::do_oop(oop* ref) {
87 do_oop_shared(ref);
88}
89
90void ReferenceLocateClosure::do_oop(narrowOop* ref) {
91 do_oop_shared(ref);
92}
93
94class ReferenceToRootClosure : public StackObj {
95 private:
96 RootCallback& _callback;
97 RootCallbackInfo _info;
98 bool _complete;
99
100 bool do_cldg_roots();
101 bool do_object_synchronizer_roots();
102 bool do_universe_roots();
103 bool do_jni_handle_roots();
104 bool do_jvmti_roots();
105 bool do_system_dictionary_roots();
106 bool do_management_roots();
107 bool do_string_table_roots();
108 bool do_aot_loader_roots();
109 JVMCI_ONLY(bool do_jvmci_roots();)
110
111 bool do_roots();
112
113 public:
114 ReferenceToRootClosure(RootCallback& callback) : _callback(callback),
115 _info(),
116 _complete(false) {
117 _info._high = NULL;
118 _info._low = NULL;
119 _info._context = NULL;
120 _info._system = OldObjectRoot::_system_undetermined;
121 _info._type = OldObjectRoot::_type_undetermined;
122
123 assert_locked_or_safepoint(Threads_lock);
124 do_roots();
125 }
126
127 bool complete() const {
128 return _complete;
129 }
130};
131
132bool ReferenceToRootClosure::do_cldg_roots() {
133 assert(!complete(), "invariant");
134 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
135 CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_none);
136 ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
137 return rlc.complete();
138}
139
140bool ReferenceToRootClosure::do_object_synchronizer_roots() {
141 assert(!complete(), "invariant");
142 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL);
143 ObjectSynchronizer::oops_do(&rlc);
144 return rlc.complete();
145}
146
147bool ReferenceToRootClosure::do_universe_roots() {
148 assert(!complete(), "invariant");
149 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL);
150 Universe::oops_do(&rlc);
151 return rlc.complete();
152}
153
154bool ReferenceToRootClosure::do_jni_handle_roots() {
155 assert(!complete(), "invariant");
156 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_global_jni_handles, OldObjectRoot::_global_jni_handle, NULL);
157 JNIHandles::oops_do(&rlc);
158 return rlc.complete();
159}
160
161bool ReferenceToRootClosure::do_jvmti_roots() {
162 assert(!complete(), "invariant");
163 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_jvmti, OldObjectRoot::_global_jni_handle, NULL);
164 JvmtiExport::oops_do(&rlc);
165 return rlc.complete();
166}
167
168bool ReferenceToRootClosure::do_system_dictionary_roots() {
169 assert(!complete(), "invariant");
170 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_system_dictionary, OldObjectRoot::_type_undetermined, NULL);
171 SystemDictionary::oops_do(&rlc);
172 return rlc.complete();
173}
174
175bool ReferenceToRootClosure::do_management_roots() {
176 assert(!complete(), "invariant");
177 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_management, OldObjectRoot::_type_undetermined, NULL);
178 Management::oops_do(&rlc);
179 return rlc.complete();
180}
181
182bool ReferenceToRootClosure::do_string_table_roots() {
183 assert(!complete(), "invariant");
184 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_string_table, OldObjectRoot::_type_undetermined, NULL);
185 StringTable::oops_do(&rlc);
186 return rlc.complete();
187}
188
189bool ReferenceToRootClosure::do_aot_loader_roots() {
190 assert(!complete(), "invariant");
191 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_aot, OldObjectRoot::_type_undetermined, NULL);
192 AOTLoader::oops_do(&rcl);
193 return rcl.complete();
194}
195
196#if INCLUDE_JVMCI
197bool ReferenceToRootClosure::do_jvmci_roots() {
198 assert(!complete(), "invariant");
199 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_jvmci, OldObjectRoot::_type_undetermined, NULL);
200 JVMCI::oops_do(&rcl);
201 return rcl.complete();
202}
203#endif
204
205bool ReferenceToRootClosure::do_roots() {
206 assert(!complete(), "invariant");
207 assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
208 assert(OldObjectRoot::_type_undetermined == _info._type, "invariant");
209
210 if (do_cldg_roots()) {
211 _complete = true;
212 return true;
213 }
214
215 if (do_object_synchronizer_roots()) {
216 _complete = true;
217 return true;
218 }
219
220 if (do_universe_roots()) {
221 _complete = true;
222 return true;
223 }
224
225 if (do_jni_handle_roots()) {
226 _complete = true;
227 return true;
228 }
229
230 if (do_jvmti_roots()) {
231 _complete = true;
232 return true;
233 }
234
235 if (do_system_dictionary_roots()) {
236 _complete = true;
237 return true;
238 }
239
240 if (do_management_roots()) {
241 _complete = true;
242 return true;
243 }
244
245 if (do_string_table_roots()) {
246 _complete = true;
247 return true;
248 }
249
250 if (do_aot_loader_roots()) {
251 _complete = true;
252 return true;
253 }
254
255#if INCLUDE_JVMCI
256 if (do_jvmci_roots()) {
257 _complete = true;
258 return true;
259 }
260#endif
261
262 return false;
263}
264
265class ReferenceToThreadRootClosure : public StackObj {
266 private:
267 RootCallback& _callback;
268 bool _complete;
269
270 bool do_java_threads_oops(JavaThread* jt);
271 bool do_thread_roots(JavaThread* jt);
272 bool do_thread_stack_fast(JavaThread* jt);
273 bool do_thread_stack_detailed(JavaThread* jt);
274 bool do_thread_jni_handles(JavaThread* jt);
275 bool do_thread_handle_area(JavaThread* jt);
276
277 public:
278 ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) {
279 assert_locked_or_safepoint(Threads_lock);
280 for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
281 if (do_thread_roots(jt)) {
282 return;
283 }
284 }
285 }
286
287 bool complete() const {
288 return _complete;
289 }
290};
291
292bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) {
293 assert(jt != NULL, "invariant");
294 assert(!complete(), "invariant");
295 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt);
296 jt->handle_area()->oops_do(&rcl);
297 return rcl.complete();
298}
299
300bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) {
301 assert(jt != NULL, "invariant");
302 assert(!complete(), "invariant");
303
304 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt);
305 jt->active_handles()->oops_do(&rcl);
306 return rcl.complete();
307}
308
309bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) {
310 assert(jt != NULL, "invariant");
311 assert(!complete(), "invariant");
312
313 if (_callback.entries() == 0) {
314 _complete = true;
315 return true;
316 }
317
318 RootCallbackInfo info;
319 info._high = NULL;
320 info._low = NULL;
321 info._context = jt;
322 info._system = OldObjectRoot::_threads;
323 info._type = OldObjectRoot::_stack_variable;
324
325 for (int i = 0; i < _callback.entries(); ++i) {
326 const address adr = (address)_callback.at(i);
327 if (jt->is_in_usable_stack(adr)) {
328 info._high = adr;
329 _complete = _callback.process(info);
330 if (_complete) {
331 return true;
332 }
333 }
334 }
335 assert(!complete(), "invariant");
336 return false;
337}
338
339bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) {
340 assert(jt != NULL, "invariant");
341 assert(!complete(), "invariant");
342
343 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt);
344
345 if (jt->has_last_Java_frame()) {
346 // traverse the registered growable array gc_array
347 // can't do this as it is not reachable from outside
348
349 // Traverse the monitor chunks
350 MonitorChunk* chunk = jt->monitor_chunks();
351 for (; chunk != NULL; chunk = chunk->next()) {
352 chunk->oops_do(&rcl);
353 }
354
355 if (rcl.complete()) {
356 return true;
357 }
358
359 // Traverse the execution stack
360 for (StackFrameStream fst(jt); !fst.is_done(); fst.next()) {
361 fst.current()->oops_do(&rcl, NULL, fst.register_map());
362 }
363
364 } // last java frame
365
366 if (rcl.complete()) {
367 return true;
368 }
369
370 GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = jt->deferred_locals();
371 if (list != NULL) {
372 for (int i = 0; i < list->length(); i++) {
373 list->at(i)->oops_do(&rcl);
374 }
375 }
376
377 if (rcl.complete()) {
378 return true;
379 }
380
381 // Traverse instance variables at the end since the GC may be moving things
382 // around using this function
383 /*
384 * // can't reach these oop* from the outside
385 f->do_oop((oop*) &_threadObj);
386 f->do_oop((oop*) &_vm_result);
387 f->do_oop((oop*) &_exception_oop);
388 f->do_oop((oop*) &_pending_async_exception);
389 */
390
391 JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state();
392 if (jvmti_thread_state != NULL) {
393 jvmti_thread_state->oops_do(&rcl);
394 }
395
396 return rcl.complete();
397}
398
399bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) {
400 assert(jt != NULL, "invariant");
401 assert(!complete(), "invariant");
402
403 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt);
404 jt->oops_do(&rcl, NULL);
405 return rcl.complete();
406}
407
408bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) {
409 assert(jt != NULL, "invariant");
410
411 if (do_thread_stack_fast(jt)) {
412 _complete = true;
413 return true;
414 }
415
416 if (do_thread_jni_handles(jt)) {
417 _complete = true;
418 return true;
419 }
420
421 if (do_thread_handle_area(jt)) {
422 _complete = true;
423 return true;
424 }
425
426 if (do_thread_stack_detailed(jt)) {
427 _complete = true;
428 return true;
429 }
430
431 return false;
432}
433
434class RootResolverMarkScope : public MarkScope {
435};
436
437void RootResolver::resolve(RootCallback& callback) {
438 RootResolverMarkScope mark_scope;
439
440 // thread local roots
441 ReferenceToThreadRootClosure rtrc(callback);
442 if (rtrc.complete()) {
443 return;
444 }
445 // system global roots
446 ReferenceToRootClosure rrc(callback);
447}
448