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