1 /*
2 * Copyright (c) 1997, 2024, 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_ITERATOR_HPP
26 #define SHARE_MEMORY_ITERATOR_HPP
27
28 #include "memory/allocation.hpp"
29 #include "memory/memRegion.hpp"
30 #include "oops/oopsHierarchy.hpp"
31
32 class CodeBlob;
33 class nmethod;
34 class ReferenceDiscoverer;
35 class DataLayout;
36 class KlassClosure;
37 class ClassLoaderData;
38 class Symbol;
39 class Metadata;
40 class Thread;
41
42 // The following classes are C++ `closures` for iterating over objects, roots and spaces
43
44 class Closure : public StackObj { };
45
46 // Thread iterator
47 class ThreadClosure {
48 public:
49 virtual void do_thread(Thread* thread) = 0;
50 };
51
52 // OopClosure is used for iterating through references to Java objects.
53 class OopClosure : public Closure {
54 public:
55 virtual void do_oop(oop* o) = 0;
56 virtual void do_oop(narrowOop* o) = 0;
57 };
58
59 class DoNothingClosure : public OopClosure {
60 public:
61 virtual void do_oop(oop* p) {}
62 virtual void do_oop(narrowOop* p) {}
63 };
64 extern DoNothingClosure do_nothing_cl;
65
66 // OopIterateClosure adds extra code to be run during oop iterations.
67 // This is needed by the GC and is extracted to a separate type to not
68 // pollute the OopClosure interface.
69 class OopIterateClosure : public OopClosure {
70 private:
71 ReferenceDiscoverer* _ref_discoverer;
72
73 protected:
74 OopIterateClosure(ReferenceDiscoverer* rd) : _ref_discoverer(rd) { }
75 OopIterateClosure() : _ref_discoverer(nullptr) { }
76 ~OopIterateClosure() { }
77
78 void set_ref_discoverer_internal(ReferenceDiscoverer* rd) { _ref_discoverer = rd; }
79
80 public:
81 ReferenceDiscoverer* ref_discoverer() const { return _ref_discoverer; }
82
83 // Iteration of InstanceRefKlasses differ depending on the closure,
84 // the below enum describes the different alternatives.
85 enum ReferenceIterationMode {
86 DO_DISCOVERY, // Apply closure and discover references
87 DO_FIELDS, // Apply closure to all fields
88 DO_FIELDS_EXCEPT_REFERENT // Apply closure to all fields except the referent field
89 };
90
91 // The default iteration mode is to do discovery.
92 virtual ReferenceIterationMode reference_iteration_mode() { return DO_DISCOVERY; }
93
94 // If the do_metadata functions return "true",
95 // we invoke the following when running oop_iterate():
96 //
97 // 1) do_klass on the header klass pointer.
98 // 2) do_klass on the klass pointer in the mirrors.
99 // 3) do_cld on the class loader data in class loaders.
100 //
101 // Used to determine metadata liveness for class unloading GCs.
102
103 virtual bool do_metadata() = 0;
104 virtual void do_klass(Klass* k) = 0;
105 virtual void do_cld(ClassLoaderData* cld) = 0;
106
107 // Class redefinition needs to get notified about methods from stackChunkOops
108 virtual void do_method(Method* m) = 0;
109 // The code cache unloading needs to get notified about methods from stackChunkOops
110 virtual void do_nmethod(nmethod* nm) = 0;
111 };
112
113 // An OopIterateClosure that can be used when there's no need to visit the Metadata.
114 class BasicOopIterateClosure : public OopIterateClosure {
115 public:
116 BasicOopIterateClosure(ReferenceDiscoverer* rd = nullptr) : OopIterateClosure(rd) {}
117
118 virtual bool do_metadata() { return false; }
119 virtual void do_klass(Klass* k) { ShouldNotReachHere(); }
120 virtual void do_cld(ClassLoaderData* cld) { ShouldNotReachHere(); }
121 virtual void do_method(Method* m) { ShouldNotReachHere(); }
122 virtual void do_nmethod(nmethod* nm) { ShouldNotReachHere(); }
123 };
124
125 // Interface for applying an OopClosure to a set of oops.
126 class OopIterator {
127 public:
128 virtual void oops_do(OopClosure* cl) = 0;
129 };
130
131 enum class derived_base : intptr_t;
132 enum class derived_pointer : intptr_t;
133 class DerivedOopClosure : public Closure {
134 public:
135 enum { SkipNull = true };
136 virtual void do_derived_oop(derived_base* base, derived_pointer* derived) = 0;
137 };
138
139 class KlassClosure : public Closure {
140 public:
141 virtual void do_klass(Klass* k) = 0;
142 };
143
144 class CLDClosure : public Closure {
145 public:
146 virtual void do_cld(ClassLoaderData* cld) = 0;
147 };
148
149 class MetadataClosure : public Closure {
150 public:
151 virtual void do_metadata(Metadata* md) = 0;
152 };
153
154
155 class CLDToOopClosure : public CLDClosure {
156 OopClosure* _oop_closure;
157 int _cld_claim;
158
159 public:
160 CLDToOopClosure(OopClosure* oop_closure,
161 int cld_claim) :
162 _oop_closure(oop_closure),
163 _cld_claim(cld_claim) {}
164
165 void do_cld(ClassLoaderData* cld);
166 };
167
168 template <int claim>
169 class ClaimingCLDToOopClosure : public CLDToOopClosure {
170 public:
171 ClaimingCLDToOopClosure(OopClosure* cl) : CLDToOopClosure(cl, claim) {}
172 };
173
174 class ClaimMetadataVisitingOopIterateClosure : public OopIterateClosure {
175 protected:
176 const int _claim;
177
178 public:
179 ClaimMetadataVisitingOopIterateClosure(int claim, ReferenceDiscoverer* rd = nullptr) :
180 OopIterateClosure(rd),
181 _claim(claim) { }
182
183 virtual bool do_metadata() { return true; }
184 virtual void do_klass(Klass* k);
185 virtual void do_cld(ClassLoaderData* cld);
186 virtual void do_method(Method* m);
187 virtual void do_nmethod(nmethod* nm);
188 };
189
190 // The base class for all concurrent marking closures,
191 // that participates in class unloading.
192 // It's used to proxy through the metadata to the oops defined in them.
193 class MetadataVisitingOopIterateClosure: public ClaimMetadataVisitingOopIterateClosure {
194 public:
195 MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd = nullptr);
196 };
197
198 // ObjectClosure is used for iterating through an object space
199
200 class ObjectClosure : public Closure {
201 public:
202 // Called for each object.
203 virtual void do_object(oop obj) = 0;
204 };
205
206 class BoolObjectClosure : public Closure {
207 public:
208 virtual bool do_object_b(oop obj) = 0;
209 };
210
211 class OopFieldClosure {
212 public:
213 virtual void do_field(oop base, oop* p) = 0;
214 };
215
216 class AlwaysTrueClosure: public BoolObjectClosure {
217 public:
218 bool do_object_b(oop p) { return true; }
219 };
220
221 class AlwaysFalseClosure : public BoolObjectClosure {
222 public:
223 bool do_object_b(oop p) { return false; }
224 };
225
226 // Applies an oop closure to all ref fields in objects iterated over in an
227 // object iteration.
228 class ObjectToOopClosure: public ObjectClosure {
229 OopIterateClosure* _cl;
230 public:
231 void do_object(oop obj);
232 ObjectToOopClosure(OopIterateClosure* cl) : _cl(cl) {}
233 };
234
235 // NMethodClosure is used for iterating through nmethods
236 // in the code cache or on thread stacks
237
238 class NMethodClosure : public Closure {
239 public:
240 virtual void do_nmethod(nmethod* n) = 0;
241 };
242
243 // Applies an oop closure to all ref fields in nmethods
244 // iterated over in an object iteration.
245 class NMethodToOopClosure : public NMethodClosure {
246 protected:
247 OopClosure* _cl;
248 bool _fix_relocations;
249 public:
250 // If fix_relocations(), then cl must copy objects to their new location immediately to avoid
251 // patching nmethods with the old locations.
252 NMethodToOopClosure(OopClosure* cl, bool fix_relocations) : _cl(cl), _fix_relocations(fix_relocations) {}
253 void do_nmethod(nmethod* nm) override;
254
255 const static bool FixRelocations = true;
256 };
257
258 class MarkingNMethodClosure : public NMethodClosure {
259 OopClosure* _cl;
260
261 public:
262 MarkingNMethodClosure(OopClosure* cl) : _cl(cl) {}
263
264 // Called for each nmethod.
265 virtual void do_nmethod(nmethod* nm);
266 };
267
268 // MonitorClosure is used for iterating over monitors in the monitors cache
269
270 class ObjectMonitor;
271
272 class MonitorClosure : public StackObj {
273 public:
274 // called for each monitor in cache
275 virtual void do_monitor(ObjectMonitor* m) = 0;
276 };
277
278 // A closure that is applied without any arguments.
279 class VoidClosure : public StackObj {
280 public:
281 virtual void do_void() = 0;
282 };
283
284
285 // YieldClosure is intended for use by iteration loops
286 // to incrementalize their work, allowing interleaving
287 // of an interruptible task so as to allow other
288 // threads to run (which may not otherwise be able to access
289 // exclusive resources, for instance). Additionally, the
290 // closure also allows for aborting an ongoing iteration
291 // by means of checking the return value from the polling
292 // call.
293 class YieldClosure : public StackObj {
294 public:
295 virtual bool should_return() = 0;
296
297 // Yield on a fine-grain level. The check in case of not yielding should be very fast.
298 virtual bool should_return_fine_grain() { return false; }
299 };
300
301 class SymbolClosure : public StackObj {
302 public:
303 virtual void do_symbol(Symbol**) = 0;
304 };
305
306 template <typename E>
307 class CompareClosure : public Closure {
308 public:
309 virtual int do_compare(const E&, const E&) = 0;
310 };
311
312 class OopIteratorClosureDispatch {
313 public:
314 template <typename OopClosureType> static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass);
315 template <typename OopClosureType> static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr);
316 template <typename OopClosureType> static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass);
317 };
318
319 #endif // SHARE_MEMORY_ITERATOR_HPP
--- EOF ---