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