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