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