1 /*
  2  * Copyright (c) 2014, 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_INLINE_HPP
 26 #define SHARE_MEMORY_ITERATOR_INLINE_HPP
 27 
 28 #include "memory/iterator.hpp"
 29 
 30 #include "cds/aotLinkedClassBulkLoader.hpp"
 31 #include "classfile/classLoaderData.hpp"
 32 #include "code/nmethod.hpp"
 33 #include "oops/access.inline.hpp"
 34 #include "oops/compressedOops.inline.hpp"
 35 #include "oops/klass.hpp"
 36 #include "oops/flatArrayKlass.inline.hpp"
 37 #include "oops/instanceKlass.inline.hpp"
 38 #include "oops/instanceMirrorKlass.inline.hpp"
 39 #include "oops/instanceClassLoaderKlass.inline.hpp"
 40 #include "oops/instanceRefKlass.inline.hpp"
 41 #include "oops/instanceStackChunkKlass.inline.hpp"
 42 #include "oops/objArrayKlass.inline.hpp"
 43 #include "oops/typeArrayKlass.inline.hpp"
 44 #include "oops/refArrayKlass.inline.hpp"
 45 #include "utilities/debug.hpp"
 46 
 47 // Defaults to strong claiming.
 48 inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) :
 49     ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {}
 50 
 51 inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
 52   cld->oops_do(this, _claim);
 53 }
 54 
 55 inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) {
 56   ClassLoaderData* cld = k->class_loader_data();
 57   if (cld != nullptr) {
 58     ClaimMetadataVisitingOopIterateClosure::do_cld(cld);
 59   } else {
 60     assert(AOTLinkedClassBulkLoader::is_pending_aot_linked_class(k), "sanity");
 61   }
 62 }
 63 
 64 inline void ClaimMetadataVisitingOopIterateClosure::do_nmethod(nmethod* nm) {
 65   nm->follow_nmethod(this);
 66 }
 67 
 68 inline void ClaimMetadataVisitingOopIterateClosure::do_method(Method* m) {
 69   // Mark interpreted frames for class redefinition
 70   m->record_gc_epoch();
 71 }
 72 
 73 // Dispatch table implementation for *Klass::oop_oop_iterate
 74 //
 75 // It allows for a single call to do a multi-dispatch to an optimized version
 76 //   of oop_oop_iterate that statically know all these types:
 77 //   - OopClosureType    : static type give at call site
 78 //   - Klass*            : dynamic to static type through Klass::kind() -> table index
 79 //   - UseCompressedOops : dynamic to static value determined once
 80 //
 81 // when users call obj->oop_iterate(&cl).
 82 //
 83 // oopDesc::oop_iterate() calls OopOopIterateDispatch::function(klass)(cl, obj, klass),
 84 //   which dispatches to an optimized version of
 85 //   [Instance, ObjArry, etc]Klass::oop_oop_iterate(oop, OopClosureType)
 86 //
 87 // OopClosureType :
 88 //   If OopClosureType has an implementation of do_oop (and do_metadata et.al.),
 89 //   then the static type of OopClosureType will be used to allow inlining of
 90 //   do_oop (even though do_oop is virtual). Otherwise, a virtual call will be
 91 //   used when calling do_oop.
 92 //
 93 // Klass* :
 94 //   A table mapping from *Klass::Kind to function is setup. This happens once
 95 //   when the program starts, when the static _table instance is initialized for
 96 //   the OopOopIterateDispatch specialized with the OopClosureType.
 97 //
 98 // UseCompressedOops :
 99 //   Initially the table is populated with an init function, and not the actual
100 //   oop_oop_iterate function. This is done, so that the first time we dispatch
101 //   through the init function we check what the value of UseCompressedOops
102 //   became, and use that to determine if we should install an optimized
103 //   narrowOop version or optimized oop version of oop_oop_iterate. The appropriate
104 //   oop_oop_iterate function replaces the init function in the table, and
105 //   succeeding calls will jump directly to oop_oop_iterate.
106 
107 
108 template <typename OopClosureType>
109 class OopOopIterateDispatch : public AllStatic {
110 private:
111   typedef void (*FunctionType)(OopClosureType*, oop, Klass*);
112 
113   class Table {
114   private:
115     template <typename KlassType, typename T>
116     static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* k) {
117       ((KlassType*)k)->KlassType::template oop_oop_iterate<T>(obj, cl);
118     }
119 
120     template <typename KlassType>
121     static void init(OopClosureType* cl, oop obj, Klass* k) {
122       OopOopIterateDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
123     }
124 
125     template <typename KlassType>
126     void set_init_function() {
127       _function[KlassType::Kind] = &init<KlassType>;
128     }
129 
130     template <typename KlassType>
131     void set_resolve_function() {
132       // Size requirement to prevent word tearing
133       // when functions pointers are updated.
134       STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*));
135       if (UseCompressedOops) {
136         _function[KlassType::Kind] = &oop_oop_iterate<KlassType, narrowOop>;
137       } else {
138         _function[KlassType::Kind] = &oop_oop_iterate<KlassType, oop>;
139       }
140     }
141 
142     template <typename KlassType>
143     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
144       set_resolve_function<KlassType>();
145       _function[KlassType::Kind](cl, obj, k);
146     }
147 
148   public:
149     FunctionType _function[Klass::KLASS_KIND_COUNT];
150 
151     Table(){
152       set_init_function<InstanceKlass>();
153       set_init_function<InlineKlass>();
154       set_init_function<InstanceRefKlass>();
155       set_init_function<InstanceMirrorKlass>();
156       set_init_function<InstanceClassLoaderKlass>();
157       set_init_function<InstanceStackChunkKlass>();
158       set_init_function<ObjArrayKlass>();
159       set_init_function<TypeArrayKlass>();
160       set_init_function<FlatArrayKlass>();
161       set_init_function<RefArrayKlass>();
162     }
163   };
164 
165   static Table _table;
166 public:
167 
168   static FunctionType function(Klass* klass) {
169     return _table._function[klass->kind()];
170   }
171 };
172 
173 template <typename OopClosureType>
174 typename OopOopIterateDispatch<OopClosureType>::Table OopOopIterateDispatch<OopClosureType>::_table;
175 
176 
177 template <typename OopClosureType>
178 class OopOopIterateBoundedDispatch {
179 private:
180   typedef void (*FunctionType)(OopClosureType*, oop, Klass*, MemRegion);
181 
182   class Table {
183   private:
184     template <typename KlassType, typename T>
185     static void oop_oop_iterate_bounded(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
186       ((KlassType*)k)->KlassType::template oop_oop_iterate_bounded<T>(obj, cl, mr);
187     }
188 
189     template <typename KlassType>
190     static void init(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
191       OopOopIterateBoundedDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k, mr);
192     }
193 
194     template <typename KlassType>
195     void set_init_function() {
196       _function[KlassType::Kind] = &init<KlassType>;
197     }
198 
199     template <typename KlassType>
200     void set_resolve_function() {
201       if (UseCompressedOops) {
202         _function[KlassType::Kind] = &oop_oop_iterate_bounded<KlassType, narrowOop>;
203       } else {
204         _function[KlassType::Kind] = &oop_oop_iterate_bounded<KlassType, oop>;
205       }
206     }
207 
208     template <typename KlassType>
209     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
210       set_resolve_function<KlassType>();
211       _function[KlassType::Kind](cl, obj, k, mr);
212     }
213 
214   public:
215     FunctionType _function[Klass::KLASS_KIND_COUNT];
216 
217     Table(){
218       set_init_function<InstanceKlass>();
219       set_init_function<InlineKlass>();
220       set_init_function<InstanceRefKlass>();
221       set_init_function<InstanceMirrorKlass>();
222       set_init_function<InstanceClassLoaderKlass>();
223       set_init_function<InstanceStackChunkKlass>();
224       set_init_function<ObjArrayKlass>();
225       set_init_function<TypeArrayKlass>();
226       set_init_function<FlatArrayKlass>();
227       set_init_function<RefArrayKlass>();
228     }
229   };
230 
231   static Table _table;
232 public:
233 
234   static FunctionType function(Klass* klass) {
235     return _table._function[klass->kind()];
236   }
237 };
238 
239 template <typename OopClosureType>
240 typename OopOopIterateBoundedDispatch<OopClosureType>::Table OopOopIterateBoundedDispatch<OopClosureType>::_table;
241 
242 
243 template <typename OopClosureType>
244 class OopOopIterateBackwardsDispatch {
245 private:
246   typedef void (*FunctionType)(OopClosureType*, oop, Klass*);
247 
248   class Table {
249   private:
250     template <typename KlassType, typename T>
251     static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* k) {
252       ((KlassType*)k)->KlassType::template oop_oop_iterate_reverse<T>(obj, cl);
253     }
254 
255     template <typename KlassType>
256     static void init(OopClosureType* cl, oop obj, Klass* k) {
257       OopOopIterateBackwardsDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
258     }
259 
260     template <typename KlassType>
261     void set_init_function() {
262       _function[KlassType::Kind] = &init<KlassType>;
263     }
264 
265     template <typename KlassType>
266     void set_resolve_function() {
267       if (UseCompressedOops) {
268         _function[KlassType::Kind] = &oop_oop_iterate_backwards<KlassType, narrowOop>;
269       } else {
270         _function[KlassType::Kind] = &oop_oop_iterate_backwards<KlassType, oop>;
271       }
272     }
273 
274     template <typename KlassType>
275     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
276       set_resolve_function<KlassType>();
277       _function[KlassType::Kind](cl, obj, k);
278     }
279 
280   public:
281     FunctionType _function[Klass::KLASS_KIND_COUNT];
282 
283     Table(){
284       set_init_function<InstanceKlass>();
285       set_init_function<InlineKlass>();
286       set_init_function<InstanceRefKlass>();
287       set_init_function<InstanceMirrorKlass>();
288       set_init_function<InstanceClassLoaderKlass>();
289       set_init_function<InstanceStackChunkKlass>();
290       set_init_function<ObjArrayKlass>();
291       set_init_function<TypeArrayKlass>();
292       set_init_function<FlatArrayKlass>();
293       set_init_function<RefArrayKlass>();
294     }
295   };
296 
297   static Table _table;
298 public:
299 
300   static FunctionType function(Klass* klass) {
301     return _table._function[klass->kind()];
302   }
303 };
304 
305 template <typename OopClosureType>
306 typename OopOopIterateBackwardsDispatch<OopClosureType>::Table OopOopIterateBackwardsDispatch<OopClosureType>::_table;
307 
308 
309 template <typename OopClosureType>
310 void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) {
311   OopOopIterateDispatch<OopClosureType>::function(klass)(cl, obj, klass);
312 }
313 
314 template <typename OopClosureType>
315 void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) {
316   OopOopIterateBoundedDispatch<OopClosureType>::function(klass)(cl, obj, klass, mr);
317 }
318 
319 template <typename OopClosureType>
320 void OopIteratorClosureDispatch::oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass) {
321   OopOopIterateBackwardsDispatch<OopClosureType>::function(klass)(cl, obj, klass);
322 }
323 
324 #endif // SHARE_MEMORY_ITERATOR_INLINE_HPP