1 /*
   2  * Copyright (c) 2019, Red Hat, Inc. All rights reserved.
   3  *
   4  * This code is free software; you can redistribute it and/or modify it
   5  * under the terms of the GNU General Public License version 2 only, as
   6  * published by the Free Software Foundation.
   7  *
   8  * This code is distributed in the hope that it will be useful, but WITHOUT
   9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  11  * version 2 for more details (a copy is included in the LICENSE file that
  12  * accompanied this code).
  13  *
  14  * You should have received a copy of the GNU General Public License version
  15  * 2 along with this work; if not, write to the Free Software Foundation,
  16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  17  *
  18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  19  * or visit www.oracle.com if you need additional information or have any
  20  * questions.
  21  *
  22  */
  23 
  24 
  25 #include "precompiled.hpp"
  26 
  27 
  28 #include "classfile/classLoaderDataGraph.hpp"
  29 #include "classfile/systemDictionary.hpp"
  30 #include "code/codeCache.hpp"
  31 #include "gc/shenandoah/shenandoahAsserts.hpp"
  32 #include "gc/shenandoah/shenandoahHeap.hpp"
  33 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
  34 #include "gc/shenandoah/shenandoahRootVerifier.hpp"
  35 #include "gc/shenandoah/shenandoahStringDedup.hpp"
  36 #include "gc/shenandoah/shenandoahUtils.hpp"
  37 #include "gc/shared/weakProcessor.inline.hpp"
  38 #include "memory/universe.hpp"
  39 #include "runtime/thread.hpp"
  40 #include "services/management.hpp"
  41 #include "utilities/debug.hpp"
  42 
  43 // Check for overflow of number of root types.
  44 STATIC_ASSERT((static_cast<uint>(ShenandoahRootVerifier::AllRoots) + 1) > static_cast<uint>(ShenandoahRootVerifier::AllRoots));
  45 
  46 ShenandoahRootVerifier::ShenandoahRootVerifier(RootTypes types) : _types(types) {
  47 }
  48 
  49 void ShenandoahRootVerifier::excludes(RootTypes types) {
  50   _types = static_cast<ShenandoahRootVerifier::RootTypes>(static_cast<uint>(_types) & (~static_cast<uint>(types)));
  51 }
  52 
  53 bool ShenandoahRootVerifier::verify(RootTypes type) const {
  54   return (_types & type) != 0;
  55 }
  56 
  57 ShenandoahRootVerifier::RootTypes ShenandoahRootVerifier::combine(RootTypes t1, RootTypes t2) {
  58   return static_cast<ShenandoahRootVerifier::RootTypes>(static_cast<uint>(t1) | static_cast<uint>(t2));
  59 }
  60 
  61 void ShenandoahRootVerifier::oops_do(OopClosure* oops) {
  62   CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
  63   if (verify(CodeRoots)) {
  64     shenandoah_assert_locked_or_safepoint(CodeCache_lock);
  65     CodeCache::blobs_do(&blobs);
  66   }
  67 
  68   if (verify(CLDGRoots)) {
  69     shenandoah_assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
  70     CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
  71     ClassLoaderDataGraph::cld_do(&clds);
  72   }
  73 
  74   if (verify(SerialRoots)) {
  75     shenandoah_assert_safepoint();
  76     Universe::oops_do(oops);
  77     Management::oops_do(oops);
  78     JvmtiExport::oops_do(oops);
  79     ObjectSynchronizer::oops_do(oops);
  80     SystemDictionary::oops_do(oops);
  81   }
  82 
  83   if (verify(JNIHandleRoots)) {
  84     shenandoah_assert_safepoint();
  85     JNIHandles::oops_do(oops);
  86   }
  87 
  88   if (verify(WeakRoots)) {
  89     shenandoah_assert_safepoint();
  90     AlwaysTrueClosure always_true;
  91     WeakProcessor::weak_oops_do(&always_true, oops);
  92   }
  93 
  94   if (ShenandoahStringDedup::is_enabled() && verify(StringDedupRoots)) {
  95     shenandoah_assert_safepoint();
  96     ShenandoahStringDedup::oops_do_slow(oops);
  97   }
  98 
  99   if (verify(ThreadRoots)) {
 100     shenandoah_assert_safepoint();
 101     // Do thread roots the last. This allows verification code to find
 102     // any broken objects from those special roots first, not the accidental
 103     // dangling reference from the thread root.
 104     Threads::possibly_parallel_oops_do(false, oops, &blobs);
 105   }
 106 }
 107 
 108 void ShenandoahRootVerifier::roots_do(OopClosure* oops) {
 109   shenandoah_assert_safepoint();
 110 
 111   CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
 112   CodeCache::blobs_do(&blobs);
 113 
 114   CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
 115   ClassLoaderDataGraph::cld_do(&clds);
 116 
 117   Universe::oops_do(oops);
 118   Management::oops_do(oops);
 119   JvmtiExport::oops_do(oops);
 120   JNIHandles::oops_do(oops);
 121   ObjectSynchronizer::oops_do(oops);
 122   SystemDictionary::oops_do(oops);
 123 
 124   AlwaysTrueClosure always_true;
 125   WeakProcessor::weak_oops_do(&always_true, oops);
 126 
 127   if (ShenandoahStringDedup::is_enabled()) {
 128     ShenandoahStringDedup::oops_do_slow(oops);
 129   }
 130 
 131   // Do thread roots the last. This allows verification code to find
 132   // any broken objects from those special roots first, not the accidental
 133   // dangling reference from the thread root.
 134   Threads::possibly_parallel_oops_do(false, oops, &blobs);
 135 }
 136 
 137 void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) {
 138   shenandoah_assert_safepoint();
 139 
 140   CodeBlobToOopClosure blobs(oops, !CodeBlobToOopClosure::FixRelocations);
 141 
 142   CLDToOopClosure clds(oops, ClassLoaderData::_claim_none);
 143   ClassLoaderDataGraph::roots_cld_do(&clds, NULL);
 144 
 145   Universe::oops_do(oops);
 146   Management::oops_do(oops);
 147   JvmtiExport::oops_do(oops);
 148   JNIHandles::oops_do(oops);
 149   ObjectSynchronizer::oops_do(oops);
 150   SystemDictionary::oops_do(oops);
 151 
 152   // Do thread roots the last. This allows verification code to find
 153   // any broken objects from those special roots first, not the accidental
 154   // dangling reference from the thread root.
 155   Threads::possibly_parallel_oops_do(false, oops, &blobs);
 156 }