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