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