src/hotspot/share/memory/metaspaceClosure.hpp
changeset 47216 71c04702a3d5
parent 47103 a993ec29ec75
child 52631 3009ca99de32
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     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