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