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 }