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_oop_storage_roots(); 102 bool do_jvmti_roots(); 103 bool do_management_roots(); 104 bool do_string_table_roots(); 105 bool do_aot_loader_roots(); 106 107 bool do_roots(); 108 109 public: 110 ReferenceToRootClosure(RootCallback& callback) : _callback(callback), 111 _info(), 112 _complete(false) { 113 _info._high = NULL; 114 _info._low = NULL; 115 _info._context = NULL; 116 _info._system = OldObjectRoot::_system_undetermined; 117 _info._type = OldObjectRoot::_type_undetermined; 118 119 assert_locked_or_safepoint(Threads_lock); 120 do_roots(); 121 } 122 123 bool complete() const { 124 return _complete; 125 } 126 }; 127 128 bool ReferenceToRootClosure::do_cldg_roots() { 129 assert(!complete(), "invariant"); 130 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL); 131 CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_none); 132 ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); 133 return rlc.complete(); 134 } 135 136 bool ReferenceToRootClosure::do_object_synchronizer_roots() { 137 assert(!complete(), "invariant"); 138 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL); 139 ObjectSynchronizer::oops_do(&rlc); 140 return rlc.complete(); 141 } 142 143 bool ReferenceToRootClosure::do_universe_roots() { 144 assert(!complete(), "invariant"); 145 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL); 146 Universe::oops_do(&rlc); 147 return rlc.complete(); 148 } 149 150 bool ReferenceToRootClosure::do_oop_storage_roots() { 151 int i = 0; 152 for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) { 153 assert(!complete(), "invariant"); 154 OopStorage* oop_storage = *it; 155 OldObjectRoot::Type type = oop_storage == OopStorageSet::jni_global() ? 156 OldObjectRoot::_global_jni_handle : 157 OldObjectRoot::_global_oop_handle; 158 OldObjectRoot::System system = OldObjectRoot::System(OldObjectRoot::_strong_oop_storage_set_first + i); 159 ReferenceLocateClosure rlc(_callback, system, type, NULL); 160 oop_storage->oops_do(&rlc); 161 if (rlc.complete()) { 162 return true; 163 } 164 } 165 return false; 166 } 167 168 bool ReferenceToRootClosure::do_jvmti_roots() { 169 assert(!complete(), "invariant"); 170 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_jvmti, OldObjectRoot::_global_jni_handle, NULL); 171 JvmtiExport::oops_do(&rlc); 172 return rlc.complete(); 173 } 174 175 bool 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 182 bool ReferenceToRootClosure::do_aot_loader_roots() { 183 assert(!complete(), "invariant"); 184 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_aot, OldObjectRoot::_type_undetermined, NULL); 185 AOTLoader::oops_do(&rcl); 186 return rcl.complete(); 187 } 188 189 bool ReferenceToRootClosure::do_roots() { 190 assert(!complete(), "invariant"); 191 assert(OldObjectRoot::_system_undetermined == _info._system, "invariant"); 192 assert(OldObjectRoot::_type_undetermined == _info._type, "invariant"); 193 194 if (do_cldg_roots()) { 195 _complete = true; 196 return true; 197 } 198 199 if (do_object_synchronizer_roots()) { 200 _complete = true; 201 return true; 202 } 203 204 if (do_universe_roots()) { 205 _complete = true; 206 return true; 207 } 208 209 if (do_oop_storage_roots()) { 210 _complete = true; 211 return true; 212 } 213 214 if (do_jvmti_roots()) { 215 _complete = true; 216 return true; 217 } 218 219 if (do_management_roots()) { 220 _complete = true; 221 return true; 222 } 223 224 if (do_aot_loader_roots()) { 225 _complete = true; 226 return true; 227 } 228 229 return false; 230 } 231 232 class ReferenceToThreadRootClosure : public StackObj { 233 private: 234 RootCallback& _callback; 235 bool _complete; 236 237 bool do_java_threads_oops(JavaThread* jt); 238 bool do_thread_roots(JavaThread* jt); 239 bool do_thread_stack_fast(JavaThread* jt); 240 bool do_thread_stack_detailed(JavaThread* jt); 241 bool do_thread_jni_handles(JavaThread* jt); 242 bool do_thread_handle_area(JavaThread* jt); 243 244 public: 245 ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) { 246 assert_locked_or_safepoint(Threads_lock); 247 JfrJavaThreadIterator iter; 248 while (iter.has_next()) { 249 if (do_thread_roots(iter.next())) { 250 return; 251 } 252 } 253 } 254 255 bool complete() const { 256 return _complete; 257 } 258 }; 259 260 bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) { 261 assert(jt != NULL, "invariant"); 262 assert(!complete(), "invariant"); 263 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt); 264 jt->handle_area()->oops_do(&rcl); 265 return rcl.complete(); 266 } 267 268 bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) { 269 assert(jt != NULL, "invariant"); 270 assert(!complete(), "invariant"); 271 272 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt); 273 jt->active_handles()->oops_do(&rcl); 274 return rcl.complete(); 275 } 276 277 bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) { 278 assert(jt != NULL, "invariant"); 279 assert(!complete(), "invariant"); 280 281 if (_callback.entries() == 0) { 282 _complete = true; 283 return true; 284 } 285 286 RootCallbackInfo info; 287 info._high = NULL; 288 info._low = NULL; 289 info._context = jt; 290 info._system = OldObjectRoot::_threads; 291 info._type = OldObjectRoot::_stack_variable; 292 293 for (int i = 0; i < _callback.entries(); ++i) { 294 const address adr = _callback.at(i).addr<address>(); 295 if (jt->is_in_usable_stack(adr)) { 296 info._high = adr; 297 _complete = _callback.process(info); 298 if (_complete) { 299 return true; 300 } 301 } 302 } 303 assert(!complete(), "invariant"); 304 return false; 305 } 306 307 bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { 308 assert(jt != NULL, "invariant"); 309 assert(!complete(), "invariant"); 310 311 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt); 312 313 if (jt->has_last_Java_frame()) { 314 // traverse the registered growable array gc_array 315 // can't do this as it is not reachable from outside 316 317 // Traverse the monitor chunks 318 MonitorChunk* chunk = jt->monitor_chunks(); 319 for (; chunk != NULL; chunk = chunk->next()) { 320 chunk->oops_do(&rcl); 321 } 322 323 if (rcl.complete()) { 324 return true; 325 } 326 327 // Traverse the execution stack 328 for (StackFrameStream fst(jt); !fst.is_done(); fst.next()) { 329 fst.current()->oops_do(&rcl, NULL, fst.register_map()); 330 } 331 332 } // last java frame 333 334 if (rcl.complete()) { 335 return true; 336 } 337 338 GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = JvmtiDeferredUpdates::deferred_locals(jt); 339 if (list != NULL) { 340 for (int i = 0; i < list->length(); i++) { 341 list->at(i)->oops_do(&rcl); 342 } 343 } 344 345 if (rcl.complete()) { 346 return true; 347 } 348 349 // Traverse instance variables at the end since the GC may be moving things 350 // around using this function 351 /* 352 * // can't reach these oop* from the outside 353 f->do_oop((oop*) &_threadObj); 354 f->do_oop((oop*) &_vm_result); 355 f->do_oop((oop*) &_exception_oop); 356 f->do_oop((oop*) &_pending_async_exception); 357 */ 358 359 JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state(); 360 if (jvmti_thread_state != NULL) { 361 jvmti_thread_state->oops_do(&rcl, NULL); 362 } 363 364 return rcl.complete(); 365 } 366 367 bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) { 368 assert(jt != NULL, "invariant"); 369 assert(!complete(), "invariant"); 370 371 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt); 372 jt->oops_do(&rcl, NULL); 373 return rcl.complete(); 374 } 375 376 bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) { 377 assert(jt != NULL, "invariant"); 378 379 if (do_thread_stack_fast(jt)) { 380 _complete = true; 381 return true; 382 } 383 384 if (do_thread_jni_handles(jt)) { 385 _complete = true; 386 return true; 387 } 388 389 if (do_thread_handle_area(jt)) { 390 _complete = true; 391 return true; 392 } 393 394 if (do_thread_stack_detailed(jt)) { 395 _complete = true; 396 return true; 397 } 398 399 return false; 400 } 401 402 class RootResolverMarkScope : public MarkScope { 403 }; 404 405 void RootResolver::resolve(RootCallback& callback) { 406 RootResolverMarkScope mark_scope; 407 408 // thread local roots 409 ReferenceToThreadRootClosure rtrc(callback); 410 if (rtrc.complete()) { 411 return; 412 } 413 // system global roots 414 ReferenceToRootClosure rrc(callback); 415 }