Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/hotspot/share/memory/metaspaceClosure.hpp
41144 views
1
/*
2
* Copyright (c) 2017, 2021, 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 "metaprogramming/enableIf.hpp"
31
#include "oops/array.hpp"
32
#include "utilities/globalDefinitions.hpp"
33
#include "utilities/growableArray.hpp"
34
#include "utilities/hashtable.inline.hpp"
35
#include "utilities/macros.hpp"
36
#include <type_traits>
37
38
// The metadata hierarchy is separate from the oop hierarchy
39
class MetaspaceObj; // no C++ vtable
40
//class Array; // no C++ vtable
41
class Annotations; // no C++ vtable
42
class ConstantPoolCache; // no C++ vtable
43
class ConstMethod; // no C++ vtable
44
class MethodCounters; // no C++ vtable
45
class Symbol; // no C++ vtable
46
class Metadata; // has C++ vtable (so do all subclasses)
47
class ConstantPool;
48
class MethodData;
49
class Method;
50
class Klass;
51
class InstanceKlass;
52
class InstanceMirrorKlass;
53
class InstanceClassLoaderKlass;
54
class InstanceRefKlass;
55
class ArrayKlass;
56
class ObjArrayKlass;
57
class TypeArrayKlass;
58
59
// class MetaspaceClosure --
60
//
61
// This class is used for iterating the objects in the HotSpot Metaspaces. It
62
// provides an API to walk all the reachable objects starting from a set of
63
// root references (such as all Klass'es in the SystemDictionary).
64
//
65
// Currently it is used for compacting the CDS archive by eliminate temporary
66
// objects allocated during archive creation time. See ArchiveBuilder for an example.
67
//
68
// To support MetaspaceClosure, each subclass of MetaspaceObj must provide
69
// a method of the type void metaspace_pointers_do(MetaspaceClosure*). This method
70
// should call MetaspaceClosure::push() on every pointer fields of this
71
// class that points to a MetaspaceObj. See Annotations::metaspace_pointers_do()
72
// for an example.
73
class MetaspaceClosure {
74
public:
75
enum Writability {
76
_writable,
77
_not_writable,
78
_default
79
};
80
81
enum SpecialRef {
82
_method_entry_ref
83
};
84
85
// class MetaspaceClosure::Ref --
86
//
87
// MetaspaceClosure can be viewed as a very simple type of copying garbage
88
// collector. For it to function properly, it requires each subclass of
89
// MetaspaceObj to provide two methods:
90
//
91
// size_t size(); -- to determine how much data to copy
92
// void metaspace_pointers_do(MetaspaceClosure*); -- to locate all the embedded pointers
93
//
94
// Calling these methods would be trivial if these two were virtual methods.
95
// However, to save space, MetaspaceObj has NO vtable. The vtable is introduced
96
// only in the Metadata class.
97
//
98
// To work around the lack of a vtable, we use the Ref class with templates
99
// (see MSORef, OtherArrayRef, MSOArrayRef, and MSOPointerArrayRef)
100
// so that we can statically discover the type of a object. The use of Ref
101
// depends on the fact that:
102
//
103
// [1] We don't use polymorphic pointers for MetaspaceObj's that are not subclasses
104
// of Metadata. I.e., we don't do this:
105
// class Klass {
106
// MetaspaceObj *_obj;
107
// Array<int>* foo() { return (Array<int>*)_obj; }
108
// Symbol* bar() { return (Symbol*) _obj; }
109
//
110
// [2] All Array<T> dimensions are statically declared.
111
class Ref : public CHeapObj<mtMetaspace> {
112
Writability _writability;
113
bool _keep_after_pushing;
114
Ref* _next;
115
void* _user_data;
116
NONCOPYABLE(Ref);
117
118
protected:
119
virtual void** mpp() const = 0;
120
Ref(Writability w) : _writability(w), _keep_after_pushing(false), _next(NULL), _user_data(NULL) {}
121
public:
122
virtual bool not_null() const = 0;
123
virtual int size() const = 0;
124
virtual void metaspace_pointers_do(MetaspaceClosure *it) const = 0;
125
virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const = 0;
126
virtual MetaspaceObj::Type msotype() const = 0;
127
virtual bool is_read_only_by_default() const = 0;
128
virtual ~Ref() {}
129
130
address obj() const {
131
// In some rare cases (see CPSlot in constantPool.hpp) we store some flags in the lowest
132
// 2 bits of a MetaspaceObj pointer. Unmask these when manipulating the pointer.
133
uintx p = (uintx)*mpp();
134
return (address)(p & (~FLAG_MASK));
135
}
136
137
address* addr() const {
138
return (address*)mpp();
139
}
140
141
void update(address new_loc) const;
142
143
Writability writability() const { return _writability; };
144
void set_keep_after_pushing() { _keep_after_pushing = true; }
145
bool keep_after_pushing() { return _keep_after_pushing; }
146
void set_user_data(void* data) { _user_data = data; }
147
void* user_data() { return _user_data; }
148
void set_next(Ref* n) { _next = n; }
149
Ref* next() const { return _next; }
150
151
private:
152
static const uintx FLAG_MASK = 0x03;
153
154
int flag_bits() const {
155
uintx p = (uintx)*mpp();
156
return (int)(p & FLAG_MASK);
157
}
158
};
159
160
private:
161
// MSORef -- iterate an instance of MetaspaceObj
162
template <class T> class MSORef : public Ref {
163
T** _mpp;
164
T* dereference() const {
165
return *_mpp;
166
}
167
protected:
168
virtual void** mpp() const {
169
return (void**)_mpp;
170
}
171
172
public:
173
MSORef(T** mpp, Writability w) : Ref(w), _mpp(mpp) {}
174
175
virtual bool is_read_only_by_default() const { return T::is_read_only_by_default(); }
176
virtual bool not_null() const { return dereference() != NULL; }
177
virtual int size() const { return dereference()->size(); }
178
virtual MetaspaceObj::Type msotype() const { return dereference()->type(); }
179
180
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
181
dereference()->metaspace_pointers_do(it);
182
}
183
virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
184
((T*)new_loc)->metaspace_pointers_do(it);
185
}
186
};
187
188
// abstract base class for MSOArrayRef, MSOPointerArrayRef and OtherArrayRef
189
template <class T> class ArrayRef : public Ref {
190
Array<T>** _mpp;
191
protected:
192
Array<T>* dereference() const {
193
return *_mpp;
194
}
195
virtual void** mpp() const {
196
return (void**)_mpp;
197
}
198
199
ArrayRef(Array<T>** mpp, Writability w) : Ref(w), _mpp(mpp) {}
200
201
// all Arrays are read-only by default
202
virtual bool is_read_only_by_default() const { return true; }
203
virtual bool not_null() const { return dereference() != NULL; }
204
virtual int size() const { return dereference()->size(); }
205
virtual MetaspaceObj::Type msotype() const { return MetaspaceObj::array_type(sizeof(T)); }
206
};
207
208
// OtherArrayRef -- iterate an instance of Array<T>, where T is NOT a subtype of MetaspaceObj.
209
// T can be a primitive type, such as int, or a structure. However, we do not scan
210
// the fields inside T, so you should not embed any pointers inside T.
211
template <class T> class OtherArrayRef : public ArrayRef<T> {
212
public:
213
OtherArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
214
215
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
216
Array<T>* array = ArrayRef<T>::dereference();
217
log_trace(cds)("Iter(OtherArray): %p [%d]", array, array->length());
218
}
219
virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
220
Array<T>* array = (Array<T>*)new_loc;
221
log_trace(cds)("Iter(OtherArray): %p [%d]", array, array->length());
222
}
223
};
224
225
// MSOArrayRef -- iterate an instance of Array<T>, where T is a subtype of MetaspaceObj.
226
// We recursively call T::metaspace_pointers_do() for each element in this array.
227
template <class T> class MSOArrayRef : public ArrayRef<T> {
228
public:
229
MSOArrayRef(Array<T>** mpp, Writability w) : ArrayRef<T>(mpp, w) {}
230
231
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
232
metaspace_pointers_do_at_impl(it, ArrayRef<T>::dereference());
233
}
234
virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
235
metaspace_pointers_do_at_impl(it, (Array<T>*)new_loc);
236
}
237
private:
238
void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T>* array) const {
239
log_trace(cds)("Iter(MSOArray): %p [%d]", array, array->length());
240
for (int i = 0; i < array->length(); i++) {
241
T* elm = array->adr_at(i);
242
elm->metaspace_pointers_do(it);
243
}
244
}
245
};
246
247
// MSOPointerArrayRef -- iterate an instance of Array<T*>, where T is a subtype of MetaspaceObj.
248
// We recursively call MetaspaceClosure::push() for each pointer in this array.
249
template <class T> class MSOPointerArrayRef : public ArrayRef<T*> {
250
public:
251
MSOPointerArrayRef(Array<T*>** mpp, Writability w) : ArrayRef<T*>(mpp, w) {}
252
253
virtual void metaspace_pointers_do(MetaspaceClosure *it) const {
254
metaspace_pointers_do_at_impl(it, ArrayRef<T*>::dereference());
255
}
256
virtual void metaspace_pointers_do_at(MetaspaceClosure *it, address new_loc) const {
257
metaspace_pointers_do_at_impl(it, (Array<T*>*)new_loc);
258
}
259
private:
260
void metaspace_pointers_do_at_impl(MetaspaceClosure *it, Array<T*>* array) const {
261
log_trace(cds)("Iter(MSOPointerArray): %p [%d]", array, array->length());
262
for (int i = 0; i < array->length(); i++) {
263
T** mpp = array->adr_at(i);
264
it->push(mpp);
265
}
266
}
267
};
268
269
// Normally, chains of references like a->b->c->d are iterated recursively. However,
270
// if recursion is too deep, we save the Refs in _pending_refs, and push them later in
271
// MetaspaceClosure::finish(). This avoids overflowing the C stack.
272
static const int MAX_NEST_LEVEL = 5;
273
Ref* _pending_refs;
274
int _nest_level;
275
Ref* _enclosing_ref;
276
277
void push_impl(Ref* ref);
278
void do_push(Ref* ref);
279
280
public:
281
MetaspaceClosure(): _pending_refs(NULL), _nest_level(0), _enclosing_ref(NULL) {}
282
~MetaspaceClosure();
283
284
void finish();
285
286
// enclosing_ref() is used to compute the offset of a field in a C++ class. For example
287
// class Foo { intx scala; Bar* ptr; }
288
// Foo *f = 0x100;
289
// when the f->ptr field is iterated with do_ref() on 64-bit platforms, we will have
290
// do_ref(Ref* r) {
291
// r->addr() == 0x108; // == &f->ptr;
292
// enclosing_ref()->obj() == 0x100; // == foo
293
// So we know that we are iterating upon a field at offset 8 of the object at 0x100.
294
//
295
// Note that if we have stack overflow, do_pending_ref(r) will be called first and
296
// do_ref(r) will be called later, for the same r. In this case, enclosing_ref() is valid only
297
// when do_pending_ref(r) is called, and will return NULL when do_ref(r) is called.
298
Ref* enclosing_ref() const {
299
return _enclosing_ref;
300
}
301
302
// This is called when a reference is placed in _pending_refs. Override this
303
// function if you're using enclosing_ref(). See notes above.
304
virtual void do_pending_ref(Ref* ref) {}
305
306
// returns true if we want to keep iterating the pointers embedded inside <ref>
307
virtual bool do_ref(Ref* ref, bool read_only) = 0;
308
309
private:
310
template <class REF_TYPE, typename T>
311
void push_with_ref(T** mpp, Writability w) {
312
push_impl(new REF_TYPE(mpp, w));
313
}
314
315
public:
316
// When MetaspaceClosure::push(...) is called, pick the correct Ref subtype to handle it:
317
//
318
// MetaspaceClosure* it = ...;
319
// Klass* o = ...; it->push(&o); => MSORef
320
// Array<int>* a1 = ...; it->push(&a1); => OtherArrayRef
321
// Array<Annotation>* a2 = ...; it->push(&a2); => MSOArrayRef
322
// Array<Klass*>* a3 = ...; it->push(&a3); => MSOPointerArrayRef
323
// Array<Array<Klass*>*>* a4 = ...; it->push(&a4); => MSOPointerArrayRef
324
// Array<Annotation*>* a5 = ...; it->push(&a5); => MSOPointerArrayRef
325
//
326
// Note that the following will fail to compile (to prevent you from adding new fields
327
// into the MetaspaceObj subtypes that cannot be properly copied by CDS):
328
//
329
// Hashtable* h = ...; it->push(&h); => Hashtable is not a subclass of MetaspaceObj
330
// Array<Hashtable*>* a6 = ...; it->push(&a6); => Hashtable is not a subclass of MetaspaceObj
331
// Array<int*>* a7 = ...; it->push(&a7); => int is not a subclass of MetaspaceObj
332
333
template <typename T>
334
void push(T** mpp, Writability w = _default) {
335
static_assert(std::is_base_of<MetaspaceObj, T>::value, "Do not push pointers of arbitrary types");
336
push_with_ref<MSORef<T>>(mpp, w);
337
}
338
339
template <typename T, ENABLE_IF(!std::is_base_of<MetaspaceObj, T>::value)>
340
void push(Array<T>** mpp, Writability w = _default) {
341
push_with_ref<OtherArrayRef<T>>(mpp, w);
342
}
343
344
template <typename T, ENABLE_IF(std::is_base_of<MetaspaceObj, T>::value)>
345
void push(Array<T>** mpp, Writability w = _default) {
346
push_with_ref<MSOArrayRef<T>>(mpp, w);
347
}
348
349
template <typename T>
350
void push(Array<T*>** mpp, Writability w = _default) {
351
static_assert(std::is_base_of<MetaspaceObj, T>::value, "Do not push Arrays of arbitrary pointer types");
352
push_with_ref<MSOPointerArrayRef<T>>(mpp, w);
353
}
354
355
#if 0
356
// Enable this block if you're changing the push(...) methods, to test for types that should be
357
// disallowed. Each of the following "push" calls should result in a compile-time error.
358
void test_disallowed_types(MetaspaceClosure* it) {
359
Hashtable<bool, mtInternal>* h = NULL;
360
it->push(&h);
361
362
Array<Hashtable<bool, mtInternal>*>* a6 = NULL;
363
it->push(&a6);
364
365
Array<int*>* a7 = NULL;
366
it->push(&a7);
367
}
368
#endif
369
370
template <class T> void push_method_entry(T** mpp, intptr_t* p) {
371
Ref* ref = new MSORef<T>(mpp, _default);
372
push_special(_method_entry_ref, ref, (intptr_t*)p);
373
if (!ref->keep_after_pushing()) {
374
delete ref;
375
}
376
}
377
378
// This is for tagging special pointers that are not a reference to MetaspaceObj. It's currently
379
// used to mark the method entry points in Method/ConstMethod.
380
virtual void push_special(SpecialRef type, Ref* obj, intptr_t* p) {
381
assert(type == _method_entry_ref, "only special type allowed for now");
382
}
383
};
384
385
// This is a special MetaspaceClosure that visits each unique MetaspaceObj once.
386
class UniqueMetaspaceClosure : public MetaspaceClosure {
387
static const int INITIAL_TABLE_SIZE = 15889;
388
static const int MAX_TABLE_SIZE = 1000000;
389
390
// Do not override. Returns true if we are discovering ref->obj() for the first time.
391
virtual bool do_ref(Ref* ref, bool read_only);
392
393
public:
394
// Gets called the first time we discover an object.
395
virtual bool do_unique_ref(Ref* ref, bool read_only) = 0;
396
UniqueMetaspaceClosure() : _has_been_visited(INITIAL_TABLE_SIZE) {}
397
398
private:
399
KVHashtable<address, bool, mtInternal> _has_been_visited;
400
};
401
402
#endif // SHARE_MEMORY_METASPACECLOSURE_HPP
403
404