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