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