1 /*
  2  * Copyright (c) 2014, 2020, 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 "oops/access.inline.hpp"
 32 #include "oops/compressedOops.inline.hpp"
 33 #include "oops/klass.hpp"
 34 #include "oops/flatArrayKlass.inline.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/objArrayKlass.inline.hpp"
 40 #include "oops/typeArrayKlass.inline.hpp"
 41 #include "utilities/debug.hpp"
 42 
 43 // Defaults to strong claiming.
 44 inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) :
 45     ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {}
 46 
 47 inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) {
 48   cld->oops_do(this, _claim);
 49 }
 50 
 51 inline void ClaimMetadataVisitingOopIterateClosure::do_klass(Klass* k) {
 52   ClassLoaderData* cld = k->class_loader_data();
 53   ClaimMetadataVisitingOopIterateClosure::do_cld(cld);
 54 }
 55 
 56 // Implementation of the non-virtual do_oop dispatch.
 57 //
 58 // The same implementation is used for do_metadata, do_klass, and do_cld.
 59 //
 60 // Preconditions:
 61 //  - Base has a pure virtual do_oop
 62 //  - Only one of the classes in the inheritance chain from OopClosureType to
 63 //    Base implements do_oop.
 64 //
 65 // Given the preconditions:
 66 //  - If &OopClosureType::do_oop is resolved to &Base::do_oop, then there is no
 67 //    implementation of do_oop between Base and OopClosureType. However, there
 68 //    must be one implementation in one of the subclasses of OopClosureType.
 69 //    In this case we take the virtual call.
 70 //
 71 //  - Conversely, if &OopClosureType::do_oop is not resolved to &Base::do_oop,
 72 //    then we've found the one and only concrete implementation. In this case we
 73 //    take a non-virtual call.
 74 //
 75 // Because of this it's clear when we should call the virtual call and
 76 //   when the non-virtual call should be made.
 77 //
 78 // The way we find if &OopClosureType::do_oop is resolved to &Base::do_oop is to
 79 //   check if the resulting type of the class of a member-function pointer to
 80 //   &OopClosureType::do_oop is equal to the type of the class of a
 81 //   &Base::do_oop member-function pointer. Template parameter deduction is used
 82 //   to find these types, and then the IsSame trait is used to check if they are
 83 //   equal. Finally, SFINAE is used to select the appropriate implementation.
 84 //
 85 // Template parameters:
 86 //   T              - narrowOop or oop
 87 //   Receiver       - the resolved type of the class of the
 88 //                    &OopClosureType::do_oop member-function pointer. That is,
 89 //                    the klass with the do_oop member function.
 90 //   Base           - klass with the pure virtual do_oop member function.
 91 //   OopClosureType - The dynamic closure type
 92 //
 93 // Parameters:
 94 //   closure - The closure to call
 95 //   p       - The oop (or narrowOop) field to pass to the closure
 96 
 97 template <typename T, typename Receiver, typename Base, typename OopClosureType>
 98 static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
 99 call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
100   closure->do_oop(p);
101 }
102 
103 template <typename T, typename Receiver, typename Base, typename OopClosureType>
104 static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
105 call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) {
106   // Sanity check
107   STATIC_ASSERT((!IsSame<OopClosureType, OopIterateClosure>::value));
108   closure->OopClosureType::do_oop(p);
109 }
110 
111 template <typename OopClosureType, typename T>
112 inline void Devirtualizer::do_oop(OopClosureType* closure, T* p) {
113   call_do_oop<T>(&OopClosureType::do_oop, &OopClosure::do_oop, closure, p);
114 }
115 
116 // Implementation of the non-virtual do_metadata dispatch.
117 
118 template <typename Receiver, typename Base, typename OopClosureType>
119 static typename EnableIf<IsSame<Receiver, Base>::value, bool>::type
120 call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
121   return closure->do_metadata();
122 }
123 
124 template <typename Receiver, typename Base, typename OopClosureType>
125 static typename EnableIf<!IsSame<Receiver, Base>::value, bool>::type
126 call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) {
127   return closure->OopClosureType::do_metadata();
128 }
129 
130 template <typename OopClosureType>
131 inline bool Devirtualizer::do_metadata(OopClosureType* closure) {
132   return call_do_metadata(&OopClosureType::do_metadata, &OopIterateClosure::do_metadata, closure);
133 }
134 
135 // Implementation of the non-virtual do_klass dispatch.
136 
137 template <typename Receiver, typename Base, typename OopClosureType>
138 static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
139 call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
140   closure->do_klass(k);
141 }
142 
143 template <typename Receiver, typename Base, typename OopClosureType>
144 static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
145 call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) {
146   closure->OopClosureType::do_klass(k);
147 }
148 
149 template <typename OopClosureType>
150 inline void Devirtualizer::do_klass(OopClosureType* closure, Klass* k) {
151   call_do_klass(&OopClosureType::do_klass, &OopIterateClosure::do_klass, closure, k);
152 }
153 
154 // Implementation of the non-virtual do_cld dispatch.
155 
156 template <typename Receiver, typename Base, typename OopClosureType>
157 static typename EnableIf<IsSame<Receiver, Base>::value, void>::type
158 call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
159   closure->do_cld(cld);
160 }
161 
162 template <typename Receiver, typename Base, typename OopClosureType>
163 static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type
164 call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) {
165   closure->OopClosureType::do_cld(cld);
166 }
167 
168 template <typename OopClosureType>
169 void Devirtualizer::do_cld(OopClosureType* closure, ClassLoaderData* cld) {
170   call_do_cld(&OopClosureType::do_cld, &OopIterateClosure::do_cld, closure, cld);
171 }
172 
173 // Dispatch table implementation for *Klass::oop_oop_iterate
174 //
175 // It allows for a single call to do a multi-dispatch to an optimized version
176 //   of oop_oop_iterate that statically know all these types:
177 //   - OopClosureType    : static type give at call site
178 //   - Klass*            : dynamic to static type through Klass::id() -> table index
179 //   - UseCompressedOops : dynamic to static value determined once
180 //
181 // when users call obj->oop_iterate(&cl).
182 //
183 // oopDesc::oop_iterate() calls OopOopIterateDispatch::function(klass)(cl, obj, klass),
184 //   which dispatches to an optimized version of
185 //   [Instance, ObjArry, etc]Klass::oop_oop_iterate(oop, OopClosureType)
186 //
187 // OopClosureType :
188 //   If OopClosureType has an implementation of do_oop (and do_metadata et.al.),
189 //   then the static type of OopClosureType will be used to allow inlining of
190 //   do_oop (even though do_oop is virtual). Otherwise, a virtual call will be
191 //   used when calling do_oop.
192 //
193 // Klass* :
194 //   A table mapping from *Klass::ID to function is setup. This happens once
195 //   when the program starts, when the static _table instance is initialized for
196 //   the OopOopIterateDispatch specialized with the OopClosureType.
197 //
198 // UseCompressedOops :
199 //   Initially the table is populated with an init function, and not the actual
200 //   oop_oop_iterate function. This is done, so that the first time we dispatch
201 //   through the init function we check what the value of UseCompressedOops
202 //   became, and use that to determine if we should install an optimized
203 //   narrowOop version or optimized oop version of oop_oop_iterate. The appropriate
204 //   oop_oop_iterate function replaces the init function in the table, and
205 //   succeeding calls will jump directly to oop_oop_iterate.
206 
207 
208 template <typename OopClosureType>
209 class OopOopIterateDispatch : public AllStatic {
210 private:
211   typedef void (*FunctionType)(OopClosureType*, oop, Klass*);
212 
213   class Table {
214   private:
215     template <typename KlassType, typename T>
216     static void oop_oop_iterate(OopClosureType* cl, oop obj, Klass* k) {
217       ((KlassType*)k)->KlassType::template oop_oop_iterate<T>(obj, cl);
218     }
219 
220     template <typename KlassType>
221     static void init(OopClosureType* cl, oop obj, Klass* k) {
222       OopOopIterateDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
223     }
224 
225     template <typename KlassType>
226     void set_init_function() {
227       _function[KlassType::ID] = &init<KlassType>;
228     }
229 
230     template <typename KlassType>
231     void set_resolve_function() {
232       // Size requirement to prevent word tearing
233       // when functions pointers are updated.
234       STATIC_ASSERT(sizeof(_function[0]) == sizeof(void*));
235       if (UseCompressedOops) {
236         _function[KlassType::ID] = &oop_oop_iterate<KlassType, narrowOop>;
237       } else {
238         _function[KlassType::ID] = &oop_oop_iterate<KlassType, oop>;
239       }
240     }
241 
242     template <typename KlassType>
243     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
244       set_resolve_function<KlassType>();
245       _function[KlassType::ID](cl, obj, k);
246     }
247 
248   public:
249     FunctionType _function[KLASS_ID_COUNT];
250 
251     Table(){
252       set_init_function<InstanceKlass>();
253       set_init_function<InstanceRefKlass>();
254       set_init_function<InstanceMirrorKlass>();
255       set_init_function<InstanceClassLoaderKlass>();
256       set_init_function<ObjArrayKlass>();
257       set_init_function<TypeArrayKlass>();
258       set_init_function<FlatArrayKlass>();
259     }
260   };
261 
262   static Table _table;
263 public:
264 
265   static FunctionType function(Klass* klass) {
266     return _table._function[klass->id()];
267   }
268 };
269 
270 template <typename OopClosureType>
271 typename OopOopIterateDispatch<OopClosureType>::Table OopOopIterateDispatch<OopClosureType>::_table;
272 
273 
274 template <typename OopClosureType>
275 class OopOopIterateBoundedDispatch {
276 private:
277   typedef void (*FunctionType)(OopClosureType*, oop, Klass*, MemRegion);
278 
279   class Table {
280   private:
281     template <typename KlassType, typename T>
282     static void oop_oop_iterate_bounded(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
283       ((KlassType*)k)->KlassType::template oop_oop_iterate_bounded<T>(obj, cl, mr);
284     }
285 
286     template <typename KlassType>
287     static void init(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
288       OopOopIterateBoundedDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k, mr);
289     }
290 
291     template <typename KlassType>
292     void set_init_function() {
293       _function[KlassType::ID] = &init<KlassType>;
294     }
295 
296     template <typename KlassType>
297     void set_resolve_function() {
298       if (UseCompressedOops) {
299         _function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, narrowOop>;
300       } else {
301         _function[KlassType::ID] = &oop_oop_iterate_bounded<KlassType, oop>;
302       }
303     }
304 
305     template <typename KlassType>
306     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k, MemRegion mr) {
307       set_resolve_function<KlassType>();
308       _function[KlassType::ID](cl, obj, k, mr);
309     }
310 
311   public:
312     FunctionType _function[KLASS_ID_COUNT];
313 
314     Table(){
315       set_init_function<InstanceKlass>();
316       set_init_function<InstanceRefKlass>();
317       set_init_function<InstanceMirrorKlass>();
318       set_init_function<InstanceClassLoaderKlass>();
319       set_init_function<ObjArrayKlass>();
320       set_init_function<TypeArrayKlass>();
321       set_init_function<FlatArrayKlass>();
322     }
323   };
324 
325   static Table _table;
326 public:
327 
328   static FunctionType function(Klass* klass) {
329     return _table._function[klass->id()];
330   }
331 };
332 
333 template <typename OopClosureType>
334 typename OopOopIterateBoundedDispatch<OopClosureType>::Table OopOopIterateBoundedDispatch<OopClosureType>::_table;
335 
336 
337 template <typename OopClosureType>
338 class OopOopIterateBackwardsDispatch {
339 private:
340   typedef void (*FunctionType)(OopClosureType*, oop, Klass*);
341 
342   class Table {
343   private:
344     template <typename KlassType, typename T>
345     static void oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* k) {
346       ((KlassType*)k)->KlassType::template oop_oop_iterate_reverse<T>(obj, cl);
347     }
348 
349     template <typename KlassType>
350     static void init(OopClosureType* cl, oop obj, Klass* k) {
351       OopOopIterateBackwardsDispatch<OopClosureType>::_table.set_resolve_function_and_execute<KlassType>(cl, obj, k);
352     }
353 
354     template <typename KlassType>
355     void set_init_function() {
356       _function[KlassType::ID] = &init<KlassType>;
357     }
358 
359     template <typename KlassType>
360     void set_resolve_function() {
361       if (UseCompressedOops) {
362         _function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, narrowOop>;
363       } else {
364         _function[KlassType::ID] = &oop_oop_iterate_backwards<KlassType, oop>;
365       }
366     }
367 
368     template <typename KlassType>
369     void set_resolve_function_and_execute(OopClosureType* cl, oop obj, Klass* k) {
370       set_resolve_function<KlassType>();
371       _function[KlassType::ID](cl, obj, k);
372     }
373 
374   public:
375     FunctionType _function[KLASS_ID_COUNT];
376 
377     Table(){
378       set_init_function<InstanceKlass>();
379       set_init_function<InstanceRefKlass>();
380       set_init_function<InstanceMirrorKlass>();
381       set_init_function<InstanceClassLoaderKlass>();
382       set_init_function<ObjArrayKlass>();
383       set_init_function<TypeArrayKlass>();
384       set_init_function<FlatArrayKlass>();
385     }
386   };
387 
388   static Table _table;
389 public:
390 
391   static FunctionType function(Klass* klass) {
392     return _table._function[klass->id()];
393   }
394 };
395 
396 template <typename OopClosureType>
397 typename OopOopIterateBackwardsDispatch<OopClosureType>::Table OopOopIterateBackwardsDispatch<OopClosureType>::_table;
398 
399 
400 template <typename OopClosureType>
401 void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) {
402   OopOopIterateDispatch<OopClosureType>::function(klass)(cl, obj, klass);
403 }
404 
405 template <typename OopClosureType>
406 void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) {
407   OopOopIterateBoundedDispatch<OopClosureType>::function(klass)(cl, obj, klass, mr);
408 }
409 
410 template <typename OopClosureType>
411 void OopIteratorClosureDispatch::oop_oop_iterate_backwards(OopClosureType* cl, oop obj, Klass* klass) {
412   OopOopIterateBackwardsDispatch<OopClosureType>::function(klass)(cl, obj, klass);
413 }
414 
415 #endif // SHARE_MEMORY_ITERATOR_INLINE_HPP