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