src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp

Mon, 19 Aug 2019 10:11:31 +0200

author
neugens
date
Mon, 19 Aug 2019 10:11:31 +0200
changeset 9861
a248d0be1309
parent 9858
b985cbb00e68
child 9926
d20a5f399218
permissions
-rw-r--r--

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

mercurial