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