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: 260 // When you do: 261 // void MyType::metaspace_pointers_do(MetaspaceClosure* it) { 262 // it->push(_my_field) 263 // 264 // C++ will try to match the "most specific" template function. This one will 265 // will be matched if possible (if mpp is an Array<> of any pointer type). 266 template <typename T> void push(Array<T*>** mpp, Writability w = _default) { 267 push_impl(new PointerArrayRef<T>(mpp, w)); 268 } 269 270 // If the above function doesn't match (mpp is an Array<>, but T is not a pointer type), then 271 // this is the second choice. 272 template <typename T> void push(Array<T>** mpp, Writability w = _default) { 273 push_impl(new PrimitiveArrayRef<T>(mpp, w)); 274 } 275 276 // If the above function doesn't match (mpp is not an Array<> type), then 277 // this will be matched by default. 278 template <class T> void push(T** mpp, Writability w = _default) { 279 push_impl(new ObjectRef<T>(mpp, w)); 280 } 281 }; 282 283 // This is a special MetaspaceClosure that visits each unique MetaspaceObj once. 284 class UniqueMetaspaceClosure : public MetaspaceClosure { 285 static const int INITIAL_TABLE_SIZE = 15889; 286 static const int MAX_TABLE_SIZE = 1000000; 287 288 // Do not override. Returns true if we are discovering ref->obj() for the first time. 289 virtual bool do_ref(Ref* ref, bool read_only); 290 291 public: 292 // Gets called the first time we discover an object. 293 virtual bool do_unique_ref(Ref* ref, bool read_only) = 0; 294 UniqueMetaspaceClosure() : _has_been_visited(INITIAL_TABLE_SIZE) {} 295 296 private: 297 KVHashtable<address, bool, mtInternal> _has_been_visited; 298 }; 299 | 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 enum SpecialRef { 79 _method_entry_ref 80 }; 81 82 // class MetaspaceClosure::Ref -- 83 // 84 // MetaspaceClosure can be viewed as a very simple type of copying garbage 85 // collector. For it to function properly, it requires each subclass of 86 // MetaspaceObj to provide two methods: 87 // 88 // size_t size(); -- to determine how much data to copy 89 // void metaspace_pointers_do(MetaspaceClosure*); -- to locate all the embedded pointers 90 // 91 // Calling these methods would be trivial if these two were virtual methods. 92 // However, to save space, MetaspaceObj has NO vtable. The vtable is introduced 93 // only in the Metadata class. 94 // 95 // To work around the lack of a vtable, we use Ref class with templates 96 // (see ObjectRef, PrimitiveArrayRef and PointerArrayRef) 97 // so that we can statically discover the type of a object. The use of Ref 98 // depends on the fact that: 99 // 100 // [1] We don't use polymorphic pointers for MetaspaceObj's that are not subclasses 101 // of Metadata. I.e., we don't do this: 264 // When you do: 265 // void MyType::metaspace_pointers_do(MetaspaceClosure* it) { 266 // it->push(_my_field) 267 // 268 // C++ will try to match the "most specific" template function. This one will 269 // will be matched if possible (if mpp is an Array<> of any pointer type). 270 template <typename T> void push(Array<T*>** mpp, Writability w = _default) { 271 push_impl(new PointerArrayRef<T>(mpp, w)); 272 } 273 274 // If the above function doesn't match (mpp is an Array<>, but T is not a pointer type), then 275 // this is the second choice. 276 template <typename T> void push(Array<T>** mpp, Writability w = _default) { 277 push_impl(new PrimitiveArrayRef<T>(mpp, w)); 278 } 279 280 // If the above function doesn't match (mpp is not an Array<> type), then 281 // this will be matched by default. 282 template <class T> void push(T** mpp, Writability w = _default) { 283 push_impl(new ObjectRef<T>(mpp, w)); 284 } 285 286 template <class T> void push_method_entry(T** mpp, intptr_t* p) { 287 push_special(_method_entry_ref, new ObjectRef<T>(mpp, _default), (intptr_t*)p); 288 } 289 290 // This is for tagging special pointers that are not a reference to MetaspaceObj. It's currently 291 // used to mark the method entry points in Method/ConstMethod. 292 virtual void push_special(SpecialRef type, Ref* obj, intptr_t* p) { 293 assert(type == _method_entry_ref, "only special type allowed for now"); 294 } 295 }; 296 297 // This is a special MetaspaceClosure that visits each unique MetaspaceObj once. 298 class UniqueMetaspaceClosure : public MetaspaceClosure { 299 static const int INITIAL_TABLE_SIZE = 15889; 300 static const int MAX_TABLE_SIZE = 1000000; 301 302 // Do not override. Returns true if we are discovering ref->obj() for the first time. 303 virtual bool do_ref(Ref* ref, bool read_only); 304 305 public: 306 // Gets called the first time we discover an object. 307 virtual bool do_unique_ref(Ref* ref, bool read_only) = 0; 308 UniqueMetaspaceClosure() : _has_been_visited(INITIAL_TABLE_SIZE) {} 309 310 private: 311 KVHashtable<address, bool, mtInternal> _has_been_visited; 312 }; 313 |