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