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 "classfile/stringTable.hpp" 27 //#include "gc_interface/strongRootsScope.hpp" 28 #include "jfr/leakprofiler/utilities/unifiedOop.hpp" 29 #include "jfr/leakprofiler/checkpoint/rootResolver.hpp" 30 #include "memory/iterator.hpp" 31 #include "oops/klass.hpp" 32 #include "oops/markOop.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/vframe_hp.hpp" 39 #include "services/management.hpp" 40 #include "utilities/growableArray.hpp" 41 42 class ReferenceLocateClosure : public OopClosure { 43 protected: 44 RootCallback& _callback; 45 RootCallbackInfo _info; 46 bool _complete; 47 48 void do_oop_shared(const void* ref); 49 50 public: 51 ReferenceLocateClosure(RootCallback& callback, 52 OldObjectRoot::System system, 53 OldObjectRoot::Type type, 54 const void* context) : _callback(callback), 55 _info(), 56 _complete(false) { 57 _info._high = NULL; 58 _info._low = NULL; 59 _info._system = system; 60 _info._type = type; 61 _info._context = context; 62 } 63 64 virtual void do_oop(oop* ref); 65 virtual void do_oop(narrowOop* ref); 66 67 bool complete() const { 68 return _complete; 69 } 70 }; 71 72 void ReferenceLocateClosure::do_oop_shared(const void* ref) { 73 assert(ref != NULL, "invariant"); 74 if (!_complete) { 75 _info._high = ref; 76 _complete = _callback.process(_info); 77 } 78 } 79 80 void ReferenceLocateClosure::do_oop(oop* ref) { 81 do_oop_shared(ref); 82 } 83 84 void ReferenceLocateClosure::do_oop(narrowOop* ref) { 85 do_oop_shared(ref); 86 } 87 88 class ReferenceToRootClosure : public StackObj { 89 private: 90 RootCallback& _callback; 91 RootCallbackInfo _info; 92 bool _complete; 93 94 bool do_cldg_roots(); 95 bool do_object_synchronizer_roots(); 96 bool do_universe_roots(); 97 bool do_jni_handle_roots(); 98 bool do_jvmti_roots(); 99 bool do_system_dictionary_roots(); 100 bool do_management_roots(); 101 bool do_string_table_roots(); 102 // bool do_aot_loader_roots(); 103 104 bool do_roots(); 105 106 public: 107 ReferenceToRootClosure(RootCallback& callback) : _callback(callback), 108 _info(), 109 _complete(false) { 110 _info._high = NULL; 111 _info._low = NULL; 112 _info._context = NULL; 113 _info._system = OldObjectRoot::_system_undetermined; 114 _info._type = OldObjectRoot::_type_undetermined; 115 116 assert_locked_or_safepoint(Threads_lock); 117 do_roots(); 118 } 119 120 bool complete() const { 121 return _complete; 122 } 123 }; 124 125 bool ReferenceToRootClosure::do_cldg_roots() { 126 assert(!complete(), "invariant"); 127 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL); 128 CLDToOopClosure cldt_closure(&rlc); 129 ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); 130 return rlc.complete(); 131 } 132 133 bool ReferenceToRootClosure::do_object_synchronizer_roots() { 134 assert(!complete(), "invariant"); 135 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL); 136 ObjectSynchronizer::oops_do(&rlc); 137 return rlc.complete(); 138 } 139 140 bool ReferenceToRootClosure::do_universe_roots() { 141 assert(!complete(), "invariant"); 142 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL); 143 Universe::oops_do(&rlc); 144 return rlc.complete(); 145 } 146 147 bool ReferenceToRootClosure::do_jni_handle_roots() { 148 assert(!complete(), "invariant"); 149 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_global_jni_handles, OldObjectRoot::_global_jni_handle, NULL); 150 JNIHandles::oops_do(&rlc); 151 return rlc.complete(); 152 } 153 154 bool ReferenceToRootClosure::do_jvmti_roots() { 155 assert(!complete(), "invariant"); 156 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_jvmti, OldObjectRoot::_global_jni_handle, NULL); 157 JvmtiExport::oops_do(&rlc); 158 return rlc.complete(); 159 } 160 161 bool ReferenceToRootClosure::do_system_dictionary_roots() { 162 assert(!complete(), "invariant"); 163 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_system_dictionary, OldObjectRoot::_type_undetermined, NULL); 164 SystemDictionary::oops_do(&rlc); 165 return rlc.complete(); 166 } 167 168 bool ReferenceToRootClosure::do_management_roots() { 169 assert(!complete(), "invariant"); 170 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_management, OldObjectRoot::_type_undetermined, NULL); 171 Management::oops_do(&rlc); 172 return rlc.complete(); 173 } 174 175 bool ReferenceToRootClosure::do_string_table_roots() { 176 assert(!complete(), "invariant"); 177 ReferenceLocateClosure rlc(_callback, OldObjectRoot::_string_table, OldObjectRoot::_type_undetermined, NULL); 178 StringTable::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_jni_handle_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_system_dictionary_roots()) { 220 _complete = true; 221 return true; 222 } 223 224 if (do_management_roots()) { 225 _complete = true; 226 return true; 227 } 228 229 if (do_string_table_roots()) { 230 _complete = true; 231 return true; 232 } 233 234 // if (do_aot_loader_roots()) { 235 // _complete = true; 236 // return true; 237 // } 238 239 return false; 240 } 241 242 class ReferenceToThreadRootClosure : public StackObj { 243 private: 244 RootCallback& _callback; 245 bool _complete; 246 247 bool do_java_threads_oops(JavaThread* jt); 248 bool do_thread_roots(JavaThread* jt); 249 bool do_thread_stack_fast(JavaThread* jt); 250 bool do_thread_stack_detailed(JavaThread* jt); 251 bool do_thread_jni_handles(JavaThread* jt); 252 bool do_thread_handle_area(JavaThread* jt); 253 254 public: 255 ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) { 256 assert_locked_or_safepoint(Threads_lock); 257 for (JavaThread *thread = Threads::first(); thread != NULL; thread = thread->next()) { 258 if (do_thread_roots(thread)) { 259 return; 260 } 261 } 262 } 263 264 bool complete() const { 265 return _complete; 266 } 267 }; 268 269 bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) { 270 assert(jt != NULL, "invariant"); 271 assert(!complete(), "invariant"); 272 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt); 273 jt->handle_area()->oops_do(&rcl); 274 return rcl.complete(); 275 } 276 277 bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) { 278 assert(jt != NULL, "invariant"); 279 assert(!complete(), "invariant"); 280 281 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt); 282 jt->active_handles()->oops_do(&rcl); 283 return rcl.complete(); 284 } 285 286 bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) { 287 assert(jt != NULL, "invariant"); 288 assert(!complete(), "invariant"); 289 290 if (_callback.entries() == 0) { 291 _complete = true; 292 return true; 293 } 294 295 RootCallbackInfo info; 296 info._high = NULL; 297 info._low = NULL; 298 info._context = jt; 299 info._system = OldObjectRoot::_threads; 300 info._type = OldObjectRoot::_stack_variable; 301 302 for (int i = 0; i < _callback.entries(); ++i) { 303 const address adr = (address)_callback.at(i); 304 if (jt->is_in_usable_stack(adr)) { 305 info._high = adr; 306 _complete = _callback.process(info); 307 if (_complete) { 308 return true; 309 } 310 } 311 } 312 assert(!complete(), "invariant"); 313 return false; 314 } 315 316 bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) { 317 assert(jt != NULL, "invariant"); 318 assert(!complete(), "invariant"); 319 320 ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt); 321 322 if (jt->has_last_Java_frame()) { 323 PrivilegedElement* const pelem = jt->privileged_stack_top(); 324 if (pelem != NULL) { 325 pelem->oops_do(&rcl); 326 if (rcl.complete()) { 327 return true; 328 } 329 } 330 331 // traverse the registered growable array gc_array 332 // can't do this as it is not reachable from outside 333 334 // Traverse the monitor chunks 335 MonitorChunk* chunk = jt->monitor_chunks(); 336 for (; chunk != NULL; chunk = chunk->next()) { 337 chunk->oops_do(&rcl); 338 } 339 340 if (rcl.complete()) { 341 return true; 342 } 343 344 // Traverse the execution stack 345 for (StackFrameStream fst(jt); !fst.is_done(); fst.next()) { 346 // XXX set CLDClosure to NULL 347 fst.current()->oops_do(&rcl, NULL, 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); 380 } 381 382 return rcl.complete(); 383 } 384 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, NULL); 391 return rcl.complete(); 392 } 393 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 MarkingCodeBlobClosure::MarkScope { 421 }; 422 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 }