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