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