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