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