1/*
2 * Copyright (c) 2017, 2019, 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_MEMORY_METASPACECLOSURE_HPP
26#define SHARE_MEMORY_METASPACECLOSURE_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/hashtable.inline.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.
70class MetaspaceClosure {
71public:
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 : public CHeapObj<mtInternal> {
105 Writability _writability;
106 Ref* _next;
107 // Noncopyable.
108 Ref(const Ref&);
109 Ref& operator=(const Ref&);
110 protected:
111 virtual void** mpp() const = 0;
112 Ref(Writability w) : _writability(w), _next(NULL) {}
113 public:
114 virtual bool not_null() const = 0;
115 virtual int size() const = 0;
116 virtual void metaspace_pointers_do(MetaspaceClosure *it) const = 0;
117 virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const = 0;
118 virtual MetaspaceObj::Type msotype() const = 0;
119 virtual bool is_read_only_by_default() const = 0;
120 virtual ~Ref() {}
121
122 address obj() const {
123 // In some rare cases (see CPSlot in constantPool.hpp) we store some flags in the lowest
124 // 2 bits of a MetaspaceObj pointer. Unmask these when manipulating the pointer.
125 uintx p = (uintx)*mpp();
126 return (address)(p & (~FLAG_MASK));
127 }
128
129 address* addr() const {
130 return (address*)mpp();
131 }
132
133 void update(address new_loc) const;
134
135 Writability writability() const { return _writability; };
136 void set_next(Ref* n) { _next = n; }
137 Ref* next() const { return _next; }
138
139 private:
140 static const uintx FLAG_MASK = 0x03;
141
142 int flag_bits() const {
143 uintx p = (uintx)*mpp();
144 return (int)(p & FLAG_MASK);
145 }
146 };
147
148private:
149 // -------------------------------------------------- ObjectRef
150 template <class T> class ObjectRef : public Ref {
151 T** _mpp;
152 T* dereference() const {
153 return *_mpp;
154 }
155 protected:
156 virtual void** mpp() const {
157 return (void**)_mpp;
158 }
159
160 public:
161 ObjectRef(T** mpp, Writability w) : Ref(w), _mpp(mpp) {}
162
163 virtual bool is_read_only_by_default() const { return T::is_read_only_by_default(); }
164 virtual bool not_null() const { return dereference() != NULL; }
165 virtual int size() const { return dereference()->size(); }
166 virtual MetaspaceObj::Type msotype() const { return dereference()->type(); }
167
168 virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
169 dereference()->metaspace_pointers_do(it);
170 }
171 virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
172 ((T*)new_loc)->metaspace_pointers_do(it);
173 }
174 };
175
176 // -------------------------------------------------- PrimitiveArrayRef
177 template <class T> class PrimitiveArrayRef : public Ref {
178 Array<T>** _mpp;
179 Array<T>* dereference() const {
180 return *_mpp;
181 }
182 protected:
183 virtual void** mpp() const {
184 return (void**)_mpp;
185 }
186
187 public:
188 PrimitiveArrayRef(Array<T>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
189
190 // all Arrays are read-only by default
191 virtual bool is_read_only_by_default() const { return true; }
192 virtual bool not_null() const { return dereference() != NULL; }
193 virtual int size() const { return dereference()->size(); }
194 virtual MetaspaceObj::Type msotype() const { return MetaspaceObj::array_type(sizeof(T)); }
195
196 virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
197 Array<T>* array = dereference();
198 log_trace(cds)("Iter(PrimitiveArray): %p [%d]", array, array->length());
199 }
200 virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
201 Array<T>* array = (Array<T>*)new_loc;
202 log_trace(cds)("Iter(PrimitiveArray): %p [%d]", array, array->length());
203 }
204 };
205
206 // -------------------------------------------------- PointerArrayRef
207 template <class T> class PointerArrayRef : public Ref {
208 Array<T*>** _mpp;
209 Array<T*>* dereference() const {
210 return *_mpp;
211 }
212 protected:
213 virtual void** mpp() const {
214 return (void**)_mpp;
215 }
216
217 public:
218 PointerArrayRef(Array<T*>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
219
220 // all Arrays are read-only by default
221 virtual bool is_read_only_by_default() const { return true; }
222 virtual bool not_null() const { return dereference() != NULL; }
223 virtual int size() const { return dereference()->size(); }
224 virtual MetaspaceObj::Type msotype() const { return MetaspaceObj::array_type(sizeof(T*)); }
225
226 virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
227 metaspace_pointers_do_at_impl(it, dereference());
228 }
229 virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
230 metaspace_pointers_do_at_impl(it, (Array<T*>*)new_loc);
231 }
232 private:
233 void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T*>* array) const {
234 log_trace(cds)("Iter(ObjectArray): %p [%d]", array, array->length());
235 for (int i = 0; i < array->length(); i++) {
236 T** mpp = array->adr_at(i);
237 it->push(mpp);
238 }
239 }
240 };
241
242 // If recursion is too deep, save the Refs in _pending_refs, and push them later using
243 // MetaspaceClosure::finish()
244 static const int MAX_NEST_LEVEL = 5;
245 Ref* _pending_refs;
246 int _nest_level;
247
248 void push_impl(Ref* ref);
249 void do_push(Ref* ref);
250
251public:
252 MetaspaceClosure(): _pending_refs(NULL), _nest_level(0) {}
253 ~MetaspaceClosure();
254
255 void finish();
256
257 // returns true if we want to keep iterating the pointers embedded inside <ref>
258 virtual bool do_ref(Ref* ref, bool read_only) = 0;
259
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.
284class 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
291public:
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
296private:
297 KVHashtable<address, bool, mtInternal> _has_been_visited;
298};
299
300#endif // SHARE_MEMORY_METASPACECLOSURE_HPP
301