1 /*
   2  * Copyright (c) 2017, 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 #ifndef SHARE_VM_MEMORY_METASPACE_ITERATOR_HPP
  26 #define SHARE_VM_MEMORY_METASPACE_ITERATOR_HPP
  27 
  28 #include "logging/log.hpp"
  29 #include "memory/allocation.hpp"
  30 #include "oops/array.hpp"
  31 #include "utilities/growableArray.hpp"
  32 #include "utilities/resourceHash.hpp"
  33 
  34 // The metadata hierarchy is separate from the oop hierarchy
  35   class MetaspaceObj;        // no C++ vtable
  36 //class   Array;             // no C++ vtable
  37   class   Annotations;       // no C++ vtable
  38   class   ConstantPoolCache; // no C++ vtable
  39   class   ConstMethod;       // no C++ vtable
  40   class   MethodCounters;    // no C++ vtable
  41   class   Symbol;            // no C++ vtable
  42   class   Metadata;          // has C++ vtable (so do all subclasses)
  43   class     ConstantPool;
  44   class     MethodData;
  45   class     Method;
  46   class     Klass;
  47   class       InstanceKlass;
  48   class         InstanceMirrorKlass;
  49   class         InstanceClassLoaderKlass;
  50   class         InstanceRefKlass;
  51   class       ArrayKlass;
  52   class         ObjArrayKlass;
  53   class         TypeArrayKlass;
  54 
  55 // class MetaspaceClosure --
  56 //
  57 // This class is used for iterating the objects in the HotSpot Metaspaces. It
  58 // provides an API to walk all the reachable objects starting from a set of
  59 // root references (such as all Klass'es in the SystemDictionary).
  60 //
  61 // Currently it is used for compacting the CDS archive by eliminate temporary
  62 // objects allocated during archive creation time. See ArchiveCompactor in
  63 // metaspaceShared.cpp for an example.
  64 //
  65 // To support MetaspaceClosure, each subclass of MetaspaceObj must provide
  66 // a method of the type void metaspace_pointers_do(MetaspaceClosure*). This method
  67 // should call MetaspaceClosure::push() on every pointer fields of this
  68 // class that points to a MetaspaceObj. See Annotations::metaspace_pointers_do()
  69 // for an example.
  70 class MetaspaceClosure {
  71 public:
  72   enum Writability {
  73     _writable,
  74     _not_writable,
  75     _default
  76   };
  77 
  78   // class MetaspaceClosure::Ref --
  79   //
  80   // MetaspaceClosure can be viewed as a very simple type of copying garbage
  81   // collector. For it to function properly, it requires each subclass of
  82   // MetaspaceObj to provide two methods:
  83   //
  84   //  size_t size();                                 -- to determine how much data to copy
  85   //  void metaspace_pointers_do(MetaspaceClosure*); -- to locate all the embedded pointers
  86   //
  87   // Calling these methods would be trivial if these two were virtual methods.
  88   // However, to save space, MetaspaceObj has NO vtable. The vtable is introduced
  89   // only in the Metadata class.
  90   //
  91   // To work around the lack of a vtable, we use Ref class with templates
  92   // (see ObjectRef, PrimitiveArrayRef and PointerArrayRef)
  93   // so that we can statically discover the type of a object. The use of Ref
  94   // depends on the fact that:
  95   //
  96   // [1] We don't use polymorphic pointers for MetaspaceObj's that are not subclasses
  97   //     of Metadata. I.e., we don't do this:
  98   //     class Klass {
  99   //         MetaspaceObj *_obj;
 100   //         Array<int>* foo() { return (Array<int>*)_obj; }
 101   //         Symbol*     bar() { return (Symbol*)    _obj; }
 102   //
 103   // [2] All Array<T> dimensions are statically declared.
 104   class Ref {
 105   protected:
 106     virtual void** mpp() const = 0;
 107   public:
 108     virtual bool not_null() const = 0;
 109     virtual int size() const = 0;
 110     virtual void metaspace_pointers_do(MetaspaceClosure *it) const = 0;
 111     virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const = 0;
 112     virtual MetaspaceObj::Type msotype() const = 0;
 113     virtual bool is_read_only_by_default() const = 0;
 114 
 115     address obj() const {
 116       // In some rare cases (see CPSlot in constantPool.hpp) we store some flags in the lowest
 117       // 2 bits of a MetaspaceObj pointer. Unmask these when manipulating the pointer.
 118       uintx p = (uintx)*mpp();
 119       return (address)(p & (~FLAG_MASK));
 120     }
 121 
 122     void update(address new_loc) const;
 123 
 124   private:
 125     static const uintx FLAG_MASK = 0x03;
 126 
 127     int flag_bits() const {
 128       uintx p = (uintx)*mpp();
 129       return (int)(p & FLAG_MASK);
 130     }
 131   };
 132 
 133 private:
 134   // -------------------------------------------------- ObjectRef
 135   template <class T> class ObjectRef : public Ref {
 136     T** _mpp;
 137     T* dereference() const {
 138       return *_mpp;
 139     }
 140   protected:
 141     virtual void** mpp() const {
 142       return (void**)_mpp;
 143     }
 144 
 145   public:
 146     ObjectRef(T** mpp) : _mpp(mpp) {}
 147 
 148     virtual bool is_read_only_by_default() const { return T::is_read_only_by_default(); }
 149     virtual bool not_null()                const { return dereference() != NULL; }
 150     virtual int size()                     const { return dereference()->size(); }
 151     virtual MetaspaceObj::Type msotype()   const { return dereference()->type(); }
 152 
 153     virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
 154       dereference()->metaspace_pointers_do(it);
 155     }
 156     virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
 157       ((T*)new_loc)->metaspace_pointers_do(it);
 158     }
 159   };
 160 
 161   // -------------------------------------------------- PrimitiveArrayRef
 162   template <class T> class PrimitiveArrayRef : public Ref {
 163     Array<T>** _mpp;
 164     Array<T>* dereference() const {
 165       return *_mpp;
 166     }
 167   protected:
 168     virtual void** mpp() const {
 169       return (void**)_mpp;
 170     }
 171 
 172   public:
 173     PrimitiveArrayRef(Array<T>** mpp) : _mpp(mpp) {}
 174 
 175     // all Arrays are read-only by default
 176     virtual bool is_read_only_by_default() const { return true; }
 177     virtual bool not_null()                const { return dereference() != NULL;  }
 178     virtual int size()                     const { return dereference()->size(); }
 179     virtual MetaspaceObj::Type msotype()   const { return MetaspaceObj::array_type(sizeof(T)); }
 180 
 181     virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
 182       Array<T>* array = dereference();
 183       log_trace(cds)("Iter(PrimitiveArray): %p [%d]", array, array->length());
 184     }
 185     virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
 186       Array<T>* array = (Array<T>*)new_loc;
 187       log_trace(cds)("Iter(PrimitiveArray): %p [%d]", array, array->length());
 188     }
 189   };
 190 
 191   // -------------------------------------------------- PointerArrayRef
 192   template <class T> class PointerArrayRef : public Ref {
 193     Array<T*>** _mpp;
 194     Array<T*>* dereference() const {
 195       return *_mpp;
 196     }
 197   protected:
 198     virtual void** mpp() const {
 199       return (void**)_mpp;
 200     }
 201 
 202   public:
 203     PointerArrayRef(Array<T*>** mpp) : _mpp(mpp) {}
 204 
 205     // all Arrays are read-only by default
 206     virtual bool is_read_only_by_default() const { return true; }
 207     virtual bool not_null()                const { return dereference() != NULL; }
 208     virtual int size()                     const { return dereference()->size(); }
 209     virtual MetaspaceObj::Type msotype()   const { return MetaspaceObj::array_type(sizeof(T*)); }
 210 
 211     virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
 212       metaspace_pointers_do_at_impl(it, dereference());
 213     }
 214     virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
 215       metaspace_pointers_do_at_impl(it, (Array<T*>*)new_loc);
 216     }
 217   private:
 218     void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T*>* array) const {
 219       log_trace(cds)("Iter(ObjectArray): %p [%d]", array, array->length());
 220       for (int i = 0; i < array->length(); i++) {
 221         T** mpp = array->adr_at(i);
 222         it->push(mpp);
 223       }
 224     }
 225   };
 226 
 227   void push_impl(Ref* ref, Writability w);
 228 
 229 public:
 230   // returns true if we want to keep iterating the pointers embedded inside <ref>
 231   virtual bool do_ref(Ref* ref, bool read_only) = 0;
 232 
 233   // When you do:
 234   //     void MyType::metaspace_pointers_do(MetaspaceClosure* it) {
 235   //       it->push(_my_field)
 236   //
 237   // C++ will try to match the "most specific" template function. This one will
 238   // will be matched if possible (if mpp is an Array<> of any pointer type).
 239   template <typename T> void push(Array<T*>** mpp, Writability w = _default) {
 240     PointerArrayRef<T> ref(mpp);
 241     push_impl(&ref, w);
 242   }
 243 
 244   // If the above function doesn't match (mpp is an Array<>, but T is not a pointer type), then
 245   // this is the second choice.
 246   template <typename T> void push(Array<T>** mpp, Writability w = _default) {
 247     PrimitiveArrayRef<T> ref(mpp);
 248     push_impl(&ref, w);
 249   }
 250 
 251   // If the above function doesn't match (mpp is not an Array<> type), then
 252   // this will be matched by default.
 253   template <class T> void push(T** mpp, Writability w = _default) {
 254     ObjectRef<T> ref(mpp);
 255     push_impl(&ref, w);
 256   }
 257 };
 258 
 259 // This is a special MetaspaceClosure that visits each unique MetaspaceObj once.
 260 class UniqueMetaspaceClosure : public MetaspaceClosure {
 261   // Do not override. Returns true if we are discovering ref->obj() for the first time.
 262   virtual bool do_ref(Ref* ref, bool read_only);
 263 
 264 public:
 265   // Gets called the first time we discover an object.
 266   virtual void do_unique_ref(Ref* ref, bool read_only) = 0;
 267 private:
 268   static unsigned my_hash(const address& a) {
 269     return primitive_hash<address>(a);
 270   }
 271   static bool my_equals(const address& a0, const address& a1) {
 272     return primitive_equals<address>(a0, a1);
 273   }
 274   ResourceHashtable<
 275       address, bool,
 276       UniqueMetaspaceClosure::my_hash,   // solaris compiler doesn't like: primitive_hash<address>
 277       UniqueMetaspaceClosure::my_equals, // solaris compiler doesn't like: primitive_equals<address>
 278       15889,                             // prime number
 279       ResourceObj::C_HEAP> _has_been_visited;
 280 };
 281 
 282 #endif // SHARE_VM_MEMORY_METASPACE_ITERATOR_HPP