Mon, 19 Aug 2019 10:11:31 +0200
8229401: Fix JFR code cache test failures
8223689: Add JFR Thread Sampling Support
8223690: Add JFR BiasedLock Event Support
8223691: Add JFR G1 Region Type Change Event Support
8223692: Add JFR G1 Heap Summary Event Support
Summary: Backport JFR from JDK11, additional fixes
Reviewed-by: neugens, apetushkov
Contributed-by: denghui.ddh@alibaba-inc.com
apetushkov@9858 | 1 | /* |
apetushkov@9858 | 2 | * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. |
apetushkov@9858 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
apetushkov@9858 | 4 | * |
apetushkov@9858 | 5 | * This code is free software; you can redistribute it and/or modify it |
apetushkov@9858 | 6 | * under the terms of the GNU General Public License version 2 only, as |
apetushkov@9858 | 7 | * published by the Free Software Foundation. |
apetushkov@9858 | 8 | * |
apetushkov@9858 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
apetushkov@9858 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
apetushkov@9858 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
apetushkov@9858 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
apetushkov@9858 | 13 | * accompanied this code). |
apetushkov@9858 | 14 | * |
apetushkov@9858 | 15 | * You should have received a copy of the GNU General Public License version |
apetushkov@9858 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
apetushkov@9858 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
apetushkov@9858 | 18 | * |
apetushkov@9858 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
apetushkov@9858 | 20 | * or visit www.oracle.com if you need additional information or have any |
apetushkov@9858 | 21 | * questions. |
apetushkov@9858 | 22 | * |
apetushkov@9858 | 23 | */ |
apetushkov@9858 | 24 | |
apetushkov@9858 | 25 | #ifndef SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP |
apetushkov@9858 | 26 | #define SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP |
apetushkov@9858 | 27 | |
apetushkov@9858 | 28 | #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" |
apetushkov@9858 | 29 | #include "jfr/utilities/jfrAllocation.hpp" |
apetushkov@9858 | 30 | #include "jfr/utilities/jfrHashtable.hpp" |
apetushkov@9858 | 31 | #include "oops/klass.hpp" |
apetushkov@9858 | 32 | #include "oops/method.hpp" |
apetushkov@9858 | 33 | #include "utilities/growableArray.hpp" |
apetushkov@9858 | 34 | |
apetushkov@9858 | 35 | // XXX is it correct? |
apetushkov@9858 | 36 | // external name (synthetic) for the primordial "bootstrap" class loader instance |
apetushkov@9858 | 37 | #define BOOTSTRAP_LOADER_NAME "<bootloader>" // XXX bootstrap |
apetushkov@9858 | 38 | #define BOOTSTRAP_LOADER_NAME_LEN 9 |
apetushkov@9858 | 39 | |
apetushkov@9858 | 40 | // Composite callback/functor building block |
apetushkov@9858 | 41 | template <typename T, typename Func1, typename Func2> |
apetushkov@9858 | 42 | class CompositeFunctor { |
apetushkov@9858 | 43 | private: |
apetushkov@9858 | 44 | Func1* _f; |
apetushkov@9858 | 45 | Func2* _g; |
apetushkov@9858 | 46 | public: |
apetushkov@9858 | 47 | CompositeFunctor(Func1* f, Func2* g) : _f(f), _g(g) { |
apetushkov@9858 | 48 | assert(f != NULL, "invariant"); |
apetushkov@9858 | 49 | assert(g != NULL, "invariant"); |
apetushkov@9858 | 50 | } |
apetushkov@9858 | 51 | bool operator()(T const& value) { |
apetushkov@9858 | 52 | return (*_f)(value) && (*_g)(value); |
apetushkov@9858 | 53 | } |
apetushkov@9858 | 54 | }; |
apetushkov@9858 | 55 | |
apetushkov@9858 | 56 | class JfrArtifactClosure { |
apetushkov@9858 | 57 | public: |
apetushkov@9858 | 58 | virtual void do_artifact(const void* artifact) = 0; |
apetushkov@9858 | 59 | }; |
apetushkov@9858 | 60 | |
apetushkov@9858 | 61 | template <typename T, typename Callback> |
apetushkov@9858 | 62 | class JfrArtifactCallbackHost : public JfrArtifactClosure { |
apetushkov@9858 | 63 | private: |
apetushkov@9858 | 64 | Callback* _callback; |
apetushkov@9858 | 65 | public: |
apetushkov@9858 | 66 | JfrArtifactCallbackHost(Callback* callback) : _callback(callback) {} |
apetushkov@9858 | 67 | void do_artifact(const void* artifact) { |
apetushkov@9858 | 68 | (*_callback)(reinterpret_cast<T const&>(artifact)); |
apetushkov@9858 | 69 | } |
apetushkov@9858 | 70 | }; |
apetushkov@9858 | 71 | |
apetushkov@9858 | 72 | template <typename FieldSelector, typename Letter> |
apetushkov@9858 | 73 | class KlassToFieldEnvelope { |
apetushkov@9858 | 74 | Letter* _letter; |
apetushkov@9858 | 75 | public: |
apetushkov@9858 | 76 | KlassToFieldEnvelope(Letter* letter) : _letter(letter) {} |
apetushkov@9858 | 77 | bool operator()(const Klass* klass) { |
apetushkov@9858 | 78 | typename FieldSelector::TypePtr t = FieldSelector::select(klass); |
apetushkov@9858 | 79 | return t != NULL ? (*_letter)(t) : true; |
apetushkov@9858 | 80 | } |
apetushkov@9858 | 81 | }; |
apetushkov@9858 | 82 | |
apetushkov@9858 | 83 | template <typename T> |
apetushkov@9858 | 84 | void tag_leakp_artifact(T const& value, bool class_unload) { |
apetushkov@9858 | 85 | assert(value != NULL, "invariant"); |
apetushkov@9858 | 86 | if (class_unload) { |
apetushkov@9858 | 87 | SET_LEAKP_USED_THIS_EPOCH(value); |
apetushkov@9858 | 88 | assert(LEAKP_USED_THIS_EPOCH(value), "invariant"); |
apetushkov@9858 | 89 | } else { |
apetushkov@9858 | 90 | SET_LEAKP_USED_PREV_EPOCH(value); |
apetushkov@9858 | 91 | assert(LEAKP_USED_PREV_EPOCH(value), "invariant"); |
apetushkov@9858 | 92 | } |
apetushkov@9858 | 93 | } |
apetushkov@9858 | 94 | |
apetushkov@9858 | 95 | template <typename T> |
apetushkov@9858 | 96 | class LeakpClearArtifact { |
apetushkov@9858 | 97 | bool _class_unload; |
apetushkov@9858 | 98 | public: |
apetushkov@9858 | 99 | LeakpClearArtifact(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 100 | bool operator()(T const& value) { |
apetushkov@9858 | 101 | if (_class_unload) { |
apetushkov@9858 | 102 | if (LEAKP_USED_THIS_EPOCH(value)) { |
apetushkov@9858 | 103 | LEAKP_UNUSE_THIS_EPOCH(value); |
apetushkov@9858 | 104 | } |
apetushkov@9858 | 105 | } else { |
apetushkov@9858 | 106 | if (LEAKP_USED_PREV_EPOCH(value)) { |
apetushkov@9858 | 107 | LEAKP_UNUSE_PREV_EPOCH(value); |
apetushkov@9858 | 108 | } |
apetushkov@9858 | 109 | } |
apetushkov@9858 | 110 | return true; |
apetushkov@9858 | 111 | } |
apetushkov@9858 | 112 | }; |
apetushkov@9858 | 113 | |
apetushkov@9858 | 114 | template <typename T> |
apetushkov@9858 | 115 | class ClearArtifact { |
apetushkov@9858 | 116 | bool _class_unload; |
apetushkov@9858 | 117 | public: |
apetushkov@9858 | 118 | ClearArtifact(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 119 | bool operator()(T const& value) { |
apetushkov@9858 | 120 | if (_class_unload) { |
apetushkov@9858 | 121 | if (LEAKP_USED_THIS_EPOCH(value)) { |
apetushkov@9858 | 122 | LEAKP_UNUSE_THIS_EPOCH(value); |
apetushkov@9858 | 123 | } |
apetushkov@9858 | 124 | if (USED_THIS_EPOCH(value)) { |
apetushkov@9858 | 125 | UNUSE_THIS_EPOCH(value); |
apetushkov@9858 | 126 | } |
apetushkov@9858 | 127 | if (METHOD_USED_THIS_EPOCH(value)) { |
apetushkov@9858 | 128 | UNUSE_METHOD_THIS_EPOCH(value); |
apetushkov@9858 | 129 | } |
apetushkov@9858 | 130 | } else { |
apetushkov@9858 | 131 | if (LEAKP_USED_PREV_EPOCH(value)) { |
apetushkov@9858 | 132 | LEAKP_UNUSE_PREV_EPOCH(value); |
apetushkov@9858 | 133 | } |
apetushkov@9858 | 134 | if (USED_PREV_EPOCH(value)) { |
apetushkov@9858 | 135 | UNUSE_PREV_EPOCH(value); |
apetushkov@9858 | 136 | } |
apetushkov@9858 | 137 | if (METHOD_USED_PREV_EPOCH(value)) { |
apetushkov@9858 | 138 | UNUSE_METHOD_PREV_EPOCH(value); |
apetushkov@9858 | 139 | } |
apetushkov@9858 | 140 | } |
apetushkov@9858 | 141 | return true; |
apetushkov@9858 | 142 | } |
apetushkov@9858 | 143 | }; |
apetushkov@9858 | 144 | |
apetushkov@9858 | 145 | template <> |
apetushkov@9858 | 146 | class ClearArtifact<const Method*> { |
apetushkov@9858 | 147 | bool _class_unload; |
apetushkov@9858 | 148 | public: |
apetushkov@9858 | 149 | ClearArtifact(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 150 | bool operator()(const Method* method) { |
apetushkov@9858 | 151 | if (_class_unload) { |
apetushkov@9858 | 152 | if (METHOD_FLAG_USED_THIS_EPOCH(method)) { |
apetushkov@9858 | 153 | CLEAR_METHOD_FLAG_USED_THIS_EPOCH(method); |
apetushkov@9858 | 154 | } |
apetushkov@9858 | 155 | } else { |
apetushkov@9858 | 156 | if (METHOD_FLAG_USED_PREV_EPOCH(method)) { |
apetushkov@9858 | 157 | CLEAR_METHOD_FLAG_USED_PREV_EPOCH(method); |
apetushkov@9858 | 158 | } |
apetushkov@9858 | 159 | } |
apetushkov@9858 | 160 | return true; |
apetushkov@9858 | 161 | } |
apetushkov@9858 | 162 | }; |
apetushkov@9858 | 163 | |
apetushkov@9858 | 164 | template <typename T> |
apetushkov@9858 | 165 | class LeakPredicate { |
apetushkov@9858 | 166 | bool _class_unload; |
apetushkov@9858 | 167 | public: |
apetushkov@9858 | 168 | LeakPredicate(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 169 | bool operator()(T const& value) { |
apetushkov@9858 | 170 | return _class_unload ? LEAKP_USED_THIS_EPOCH(value) : LEAKP_USED_PREV_EPOCH(value); |
apetushkov@9858 | 171 | } |
apetushkov@9858 | 172 | }; |
apetushkov@9858 | 173 | |
apetushkov@9858 | 174 | template <typename T> |
apetushkov@9858 | 175 | class UsedPredicate { |
apetushkov@9858 | 176 | bool _class_unload; |
apetushkov@9858 | 177 | public: |
apetushkov@9858 | 178 | UsedPredicate(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 179 | bool operator()(T const& value) { |
apetushkov@9858 | 180 | return _class_unload ? USED_THIS_EPOCH(value) : USED_PREV_EPOCH(value); |
apetushkov@9858 | 181 | } |
apetushkov@9858 | 182 | }; |
apetushkov@9858 | 183 | |
apetushkov@9858 | 184 | template <typename T, int compare(const T&, const T&)> |
apetushkov@9858 | 185 | class UniquePredicate { |
apetushkov@9858 | 186 | private: |
apetushkov@9858 | 187 | GrowableArray<T> _seen; |
apetushkov@9858 | 188 | public: |
apetushkov@9858 | 189 | UniquePredicate(bool) : _seen() {} |
apetushkov@9858 | 190 | bool operator()(T const& value) { |
apetushkov@9858 | 191 | bool not_unique; |
apetushkov@9858 | 192 | _seen.template find_sorted<T, compare>(value, not_unique); |
apetushkov@9858 | 193 | if (not_unique) { |
apetushkov@9858 | 194 | return false; |
apetushkov@9858 | 195 | } |
apetushkov@9858 | 196 | _seen.template insert_sorted<compare>(value); |
apetushkov@9858 | 197 | return true; |
apetushkov@9858 | 198 | } |
apetushkov@9858 | 199 | }; |
apetushkov@9858 | 200 | |
apetushkov@9858 | 201 | class MethodFlagPredicate { |
apetushkov@9858 | 202 | bool _class_unload; |
apetushkov@9858 | 203 | public: |
apetushkov@9858 | 204 | MethodFlagPredicate(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 205 | bool operator()(const Method* method) { |
apetushkov@9858 | 206 | return _class_unload ? METHOD_FLAG_USED_THIS_EPOCH(method) : METHOD_FLAG_USED_PREV_EPOCH(method); |
apetushkov@9858 | 207 | } |
apetushkov@9858 | 208 | }; |
apetushkov@9858 | 209 | |
apetushkov@9858 | 210 | template <bool leakp> |
apetushkov@9858 | 211 | class MethodUsedPredicate { |
apetushkov@9858 | 212 | bool _class_unload; |
apetushkov@9858 | 213 | public: |
apetushkov@9858 | 214 | MethodUsedPredicate(bool class_unload) : _class_unload(class_unload) {} |
apetushkov@9858 | 215 | bool operator()(const Klass* klass) { |
apetushkov@9858 | 216 | assert(ANY_USED(klass), "invariant"); |
apetushkov@9858 | 217 | if (_class_unload) { |
apetushkov@9858 | 218 | return leakp ? LEAKP_METHOD_USED_THIS_EPOCH(klass) : METHOD_USED_THIS_EPOCH(klass); |
apetushkov@9858 | 219 | } |
apetushkov@9858 | 220 | return leakp ? LEAKP_METHOD_USED_PREV_EPOCH(klass) : METHOD_USED_PREV_EPOCH(klass); |
apetushkov@9858 | 221 | } |
apetushkov@9858 | 222 | }; |
apetushkov@9858 | 223 | |
apetushkov@9858 | 224 | class JfrSymbolId : public JfrCHeapObj { |
apetushkov@9858 | 225 | template <typename, typename, template<typename, typename> class, typename, size_t> |
apetushkov@9858 | 226 | friend class HashTableHost; |
apetushkov@9858 | 227 | typedef HashTableHost<const Symbol*, traceid, Entry, JfrSymbolId> SymbolTable; |
apetushkov@9858 | 228 | typedef HashTableHost<const char*, traceid, Entry, JfrSymbolId> CStringTable; |
apetushkov@9858 | 229 | public: |
apetushkov@9858 | 230 | typedef SymbolTable::HashEntry SymbolEntry; |
apetushkov@9858 | 231 | typedef CStringTable::HashEntry CStringEntry; |
apetushkov@9858 | 232 | private: |
apetushkov@9858 | 233 | SymbolTable* _sym_table; |
apetushkov@9858 | 234 | CStringTable* _cstring_table; |
apetushkov@9858 | 235 | traceid _symbol_id_counter; |
apetushkov@9858 | 236 | |
apetushkov@9858 | 237 | // hashtable(s) callbacks |
apetushkov@9858 | 238 | void assign_id(SymbolEntry* entry); |
apetushkov@9858 | 239 | bool equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry); |
apetushkov@9858 | 240 | void assign_id(CStringEntry* entry); |
apetushkov@9858 | 241 | bool equals(const char* query, uintptr_t hash, const CStringEntry* entry); |
apetushkov@9858 | 242 | |
apetushkov@9858 | 243 | public: |
apetushkov@9858 | 244 | static bool is_anonymous_klass(const Klass* k); |
apetushkov@9858 | 245 | static const char* create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode); |
apetushkov@9858 | 246 | static uintptr_t anonymous_klass_name_hash_code(const InstanceKlass* ik); |
apetushkov@9858 | 247 | static uintptr_t regular_klass_name_hash_code(const Klass* k); |
apetushkov@9858 | 248 | |
apetushkov@9858 | 249 | JfrSymbolId(); |
apetushkov@9858 | 250 | ~JfrSymbolId(); |
apetushkov@9858 | 251 | |
apetushkov@9858 | 252 | void initialize(); |
apetushkov@9858 | 253 | void clear(); |
apetushkov@9858 | 254 | |
apetushkov@9858 | 255 | traceid mark_anonymous_klass_name(const Klass* k); |
apetushkov@9858 | 256 | traceid mark(const Symbol* sym, uintptr_t hash); |
apetushkov@9858 | 257 | traceid mark(const Klass* k); |
apetushkov@9858 | 258 | traceid mark(const Symbol* symbol); |
apetushkov@9858 | 259 | traceid mark(const char* str, uintptr_t hash); |
apetushkov@9858 | 260 | |
apetushkov@9858 | 261 | const SymbolEntry* map_symbol(const Symbol* symbol) const; |
apetushkov@9858 | 262 | const SymbolEntry* map_symbol(uintptr_t hash) const; |
apetushkov@9858 | 263 | const CStringEntry* map_cstring(uintptr_t hash) const; |
apetushkov@9858 | 264 | |
apetushkov@9858 | 265 | template <typename T> |
apetushkov@9858 | 266 | void symbol(T& functor, const Klass* k) { |
apetushkov@9858 | 267 | if (is_anonymous_klass(k)) { |
apetushkov@9858 | 268 | return; |
apetushkov@9858 | 269 | } |
apetushkov@9858 | 270 | functor(map_symbol(regular_klass_name_hash_code(k))); |
apetushkov@9858 | 271 | } |
apetushkov@9858 | 272 | |
apetushkov@9858 | 273 | template <typename T> |
apetushkov@9858 | 274 | void symbol(T& functor, const Method* method) { |
apetushkov@9858 | 275 | assert(method != NULL, "invariant"); |
apetushkov@9858 | 276 | functor(map_symbol((uintptr_t)method->name()->identity_hash())); |
apetushkov@9858 | 277 | functor(map_symbol((uintptr_t)method->signature()->identity_hash())); |
apetushkov@9858 | 278 | } |
apetushkov@9858 | 279 | |
apetushkov@9858 | 280 | template <typename T> |
apetushkov@9858 | 281 | void cstring(T& functor, const Klass* k) { |
apetushkov@9858 | 282 | if (!is_anonymous_klass(k)) { |
apetushkov@9858 | 283 | return; |
apetushkov@9858 | 284 | } |
apetushkov@9858 | 285 | functor(map_cstring(anonymous_klass_name_hash_code((const InstanceKlass*)k))); |
apetushkov@9858 | 286 | } |
apetushkov@9858 | 287 | |
apetushkov@9858 | 288 | template <typename T> |
apetushkov@9858 | 289 | void iterate_symbols(T& functor) { |
apetushkov@9858 | 290 | _sym_table->iterate_entry(functor); |
apetushkov@9858 | 291 | } |
apetushkov@9858 | 292 | |
apetushkov@9858 | 293 | template <typename T> |
apetushkov@9858 | 294 | void iterate_cstrings(T& functor) { |
apetushkov@9858 | 295 | _cstring_table->iterate_entry(functor); |
apetushkov@9858 | 296 | } |
apetushkov@9858 | 297 | |
apetushkov@9858 | 298 | bool has_entries() const { return has_symbol_entries() || has_cstring_entries(); } |
apetushkov@9858 | 299 | bool has_symbol_entries() const { return _sym_table->has_entries(); } |
apetushkov@9858 | 300 | bool has_cstring_entries() const { return _cstring_table->has_entries(); } |
apetushkov@9858 | 301 | }; |
apetushkov@9858 | 302 | |
apetushkov@9858 | 303 | /** |
apetushkov@9858 | 304 | * When processing a set of artifacts, there will be a need |
apetushkov@9858 | 305 | * to track transitive dependencies originating with each artifact. |
apetushkov@9858 | 306 | * These might or might not be explicitly "tagged" at that point. |
apetushkov@9858 | 307 | * With the introduction of "epochs" to allow for concurrent tagging, |
apetushkov@9858 | 308 | * we attempt to avoid "tagging" an artifact to indicate its use in a |
apetushkov@9858 | 309 | * previous epoch. This is mainly to reduce the risk for data races. |
apetushkov@9858 | 310 | * Instead, JfrArtifactSet is used to track transitive dependencies |
apetushkov@9858 | 311 | * during the write process itself. |
apetushkov@9858 | 312 | * |
apetushkov@9858 | 313 | * It can also provide opportunities for caching, as the ideal should |
apetushkov@9858 | 314 | * be to reduce the amount of iterations neccessary for locating artifacts |
apetushkov@9858 | 315 | * in the respective VM subsystems. |
apetushkov@9858 | 316 | */ |
apetushkov@9858 | 317 | class JfrArtifactSet : public JfrCHeapObj { |
apetushkov@9858 | 318 | private: |
apetushkov@9858 | 319 | JfrSymbolId* _symbol_id; |
apetushkov@9858 | 320 | GrowableArray<const Klass*>* _klass_list; |
apetushkov@9858 | 321 | bool _class_unload; |
apetushkov@9858 | 322 | |
apetushkov@9858 | 323 | public: |
apetushkov@9858 | 324 | JfrArtifactSet(bool class_unload); |
apetushkov@9858 | 325 | ~JfrArtifactSet(); |
apetushkov@9858 | 326 | |
apetushkov@9858 | 327 | // caller needs ResourceMark |
apetushkov@9858 | 328 | void initialize(bool class_unload); |
apetushkov@9858 | 329 | void clear(); |
apetushkov@9858 | 330 | |
apetushkov@9858 | 331 | traceid mark(const Symbol* sym, uintptr_t hash); |
apetushkov@9858 | 332 | traceid mark(const Klass* klass); |
apetushkov@9858 | 333 | traceid mark(const Symbol* symbol); |
apetushkov@9858 | 334 | traceid mark(const char* const str, uintptr_t hash); |
apetushkov@9858 | 335 | traceid mark_anonymous_klass_name(const Klass* klass); |
apetushkov@9858 | 336 | |
apetushkov@9858 | 337 | const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const; |
apetushkov@9858 | 338 | const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const; |
apetushkov@9858 | 339 | const JfrSymbolId::CStringEntry* map_cstring(uintptr_t hash) const; |
apetushkov@9858 | 340 | |
apetushkov@9858 | 341 | bool has_klass_entries() const; |
apetushkov@9858 | 342 | int entries() const; |
apetushkov@9858 | 343 | void register_klass(const Klass* k); |
apetushkov@9858 | 344 | |
apetushkov@9858 | 345 | template <typename Functor> |
apetushkov@9858 | 346 | void iterate_klasses(Functor& functor) const { |
apetushkov@9858 | 347 | for (int i = 0; i < _klass_list->length(); ++i) { |
apetushkov@9858 | 348 | if (!functor(_klass_list->at(i))) { |
apetushkov@9858 | 349 | break; |
apetushkov@9858 | 350 | } |
apetushkov@9858 | 351 | } |
apetushkov@9858 | 352 | } |
apetushkov@9858 | 353 | |
apetushkov@9858 | 354 | template <typename T> |
apetushkov@9858 | 355 | void iterate_symbols(T& functor) { |
apetushkov@9858 | 356 | _symbol_id->iterate_symbols(functor); |
apetushkov@9858 | 357 | } |
apetushkov@9858 | 358 | |
apetushkov@9858 | 359 | template <typename T> |
apetushkov@9858 | 360 | void iterate_cstrings(T& functor) { |
apetushkov@9858 | 361 | _symbol_id->iterate_cstrings(functor); |
apetushkov@9858 | 362 | } |
apetushkov@9858 | 363 | }; |
apetushkov@9858 | 364 | |
apetushkov@9858 | 365 | class KlassArtifactRegistrator { |
apetushkov@9858 | 366 | private: |
apetushkov@9858 | 367 | JfrArtifactSet* _artifacts; |
apetushkov@9858 | 368 | public: |
apetushkov@9858 | 369 | KlassArtifactRegistrator(JfrArtifactSet* artifacts) : |
apetushkov@9858 | 370 | _artifacts(artifacts) { |
apetushkov@9858 | 371 | assert(_artifacts != NULL, "invariant"); |
apetushkov@9858 | 372 | } |
apetushkov@9858 | 373 | |
apetushkov@9858 | 374 | bool operator()(const Klass* klass) { |
apetushkov@9858 | 375 | assert(klass != NULL, "invariant"); |
apetushkov@9858 | 376 | _artifacts->register_klass(klass); |
apetushkov@9858 | 377 | return true; |
apetushkov@9858 | 378 | } |
apetushkov@9858 | 379 | }; |
apetushkov@9858 | 380 | |
apetushkov@9858 | 381 | #endif // SHARE_VM_JFR_RECORDER_CHECKPOINT_TYPES_JFRTYPESETUTILS_HPP |