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