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. |
43 | inline MetadataVisitingOopIterateClosure::MetadataVisitingOopIterateClosure(ReferenceDiscoverer* rd) : |
44 | ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_strong, rd) {} |
45 | |
46 | inline void ClaimMetadataVisitingOopIterateClosure::do_cld(ClassLoaderData* cld) { |
47 | cld->oops_do(this, _claim); |
48 | } |
49 | |
50 | inline 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(). |
58 | template <typename T> |
59 | void 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 | |
112 | template <typename T, typename Receiver, typename Base, typename OopClosureType> |
113 | static typename EnableIf<IsSame<Receiver, Base>::value, void>::type |
114 | call_do_oop(void (Receiver::*)(T*), void (Base::*)(T*), OopClosureType* closure, T* p) { |
115 | closure->do_oop(p); |
116 | } |
117 | |
118 | template <typename T, typename Receiver, typename Base, typename OopClosureType> |
119 | static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type |
120 | call_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 | |
126 | template <typename OopClosureType, typename T> |
127 | inline 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 | |
131 | template <typename OopClosureType, typename T> |
132 | inline 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 | |
140 | template <typename Receiver, typename Base, typename OopClosureType> |
141 | static typename EnableIf<IsSame<Receiver, Base>::value, bool>::type |
142 | call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) { |
143 | return closure->do_metadata(); |
144 | } |
145 | |
146 | template <typename Receiver, typename Base, typename OopClosureType> |
147 | static typename EnableIf<!IsSame<Receiver, Base>::value, bool>::type |
148 | call_do_metadata(bool (Receiver::*)(), bool (Base::*)(), OopClosureType* closure) { |
149 | return closure->OopClosureType::do_metadata(); |
150 | } |
151 | |
152 | template <typename OopClosureType> |
153 | inline 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 | |
159 | template <typename Receiver, typename Base, typename OopClosureType> |
160 | static typename EnableIf<IsSame<Receiver, Base>::value, void>::type |
161 | call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) { |
162 | closure->do_klass(k); |
163 | } |
164 | |
165 | template <typename Receiver, typename Base, typename OopClosureType> |
166 | static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type |
167 | call_do_klass(void (Receiver::*)(Klass*), void (Base::*)(Klass*), OopClosureType* closure, Klass* k) { |
168 | closure->OopClosureType::do_klass(k); |
169 | } |
170 | |
171 | template <typename OopClosureType> |
172 | inline 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 | |
178 | template <typename Receiver, typename Base, typename OopClosureType> |
179 | static typename EnableIf<IsSame<Receiver, Base>::value, void>::type |
180 | call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) { |
181 | closure->do_cld(cld); |
182 | } |
183 | |
184 | template <typename Receiver, typename Base, typename OopClosureType> |
185 | static typename EnableIf<!IsSame<Receiver, Base>::value, void>::type |
186 | call_do_cld(void (Receiver::*)(ClassLoaderData*), void (Base::*)(ClassLoaderData*), OopClosureType* closure, ClassLoaderData* cld) { |
187 | closure->OopClosureType::do_cld(cld); |
188 | } |
189 | |
190 | template <typename OopClosureType> |
191 | void 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 | |
230 | template <typename OopClosureType> |
231 | class OopOopIterateDispatch : public AllStatic { |
232 | private: |
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; |
282 | public: |
283 | |
284 | static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) { |
285 | return _table._function[klass->id()]; |
286 | } |
287 | }; |
288 | |
289 | template <typename OopClosureType> |
290 | typename OopOopIterateDispatch<OopClosureType>::Table OopOopIterateDispatch<OopClosureType>::_table; |
291 | |
292 | |
293 | template <typename OopClosureType> |
294 | class OopOopIterateBoundedDispatch { |
295 | private: |
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; |
342 | public: |
343 | |
344 | static void (*function(Klass* klass))(OopClosureType*, oop, Klass*, MemRegion) { |
345 | return _table._function[klass->id()]; |
346 | } |
347 | }; |
348 | |
349 | template <typename OopClosureType> |
350 | typename OopOopIterateBoundedDispatch<OopClosureType>::Table OopOopIterateBoundedDispatch<OopClosureType>::_table; |
351 | |
352 | |
353 | template <typename OopClosureType> |
354 | class OopOopIterateBackwardsDispatch { |
355 | private: |
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; |
402 | public: |
403 | |
404 | static void (*function(Klass* klass))(OopClosureType*, oop, Klass*) { |
405 | return _table._function[klass->id()]; |
406 | } |
407 | }; |
408 | |
409 | template <typename OopClosureType> |
410 | typename OopOopIterateBackwardsDispatch<OopClosureType>::Table OopOopIterateBackwardsDispatch<OopClosureType>::_table; |
411 | |
412 | |
413 | template <typename OopClosureType> |
414 | void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass) { |
415 | OopOopIterateDispatch<OopClosureType>::function(klass)(cl, obj, klass); |
416 | } |
417 | |
418 | template <typename OopClosureType> |
419 | void OopIteratorClosureDispatch::oop_oop_iterate(OopClosureType* cl, oop obj, Klass* klass, MemRegion mr) { |
420 | OopOopIterateBoundedDispatch<OopClosureType>::function(klass)(cl, obj, klass, mr); |
421 | } |
422 | |
423 | template <typename OopClosureType> |
424 | void 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 | |