src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp

Tue, 02 Jun 2020 14:29:43 +0800

author
ddong
date
Tue, 02 Jun 2020 14:29:43 +0800
changeset 9941
45c8de52649c
parent 9858
b985cbb00e68
child 9949
fb74ae591209
permissions
-rw-r--r--

8246310: Clean commented-out code about ModuleEntry andPackageEntry in JFR
Reviewed-by: adinn

apetushkov@9858 1 /*
apetushkov@9858 2 * Copyright (c) 2016, 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 #include "precompiled.hpp"
apetushkov@9858 26 #include "classfile/classLoaderData.inline.hpp"
apetushkov@9858 27 #include "classfile/javaClasses.hpp"
apetushkov@9858 28 #include "classfile/symbolTable.hpp"
apetushkov@9858 29 #include "classfile/systemDictionary.hpp"
apetushkov@9858 30 #include "jfr/jfr.hpp"
apetushkov@9858 31 #include "jfr/jni/jfrGetAllEventClasses.hpp"
apetushkov@9858 32 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
apetushkov@9858 33 #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
apetushkov@9858 34 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
apetushkov@9858 35 #include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp"
apetushkov@9858 36 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
apetushkov@9858 37 #include "jfr/recorder/storage/jfrBuffer.hpp"
apetushkov@9858 38 #include "jfr/utilities/jfrHashtable.hpp"
apetushkov@9858 39 #include "jfr/utilities/jfrTypes.hpp"
apetushkov@9858 40 #include "memory/iterator.hpp"
apetushkov@9858 41 #include "memory/resourceArea.hpp"
apetushkov@9858 42 #include "oops/instanceKlass.hpp"
apetushkov@9858 43 #include "oops/objArrayKlass.hpp"
apetushkov@9858 44 #include "oops/oop.inline.hpp"
apetushkov@9858 45 #include "memory/resourceArea.hpp"
apetushkov@9858 46 #include "utilities/accessFlags.hpp"
apetushkov@9858 47
apetushkov@9858 48 // incremented on each checkpoint
apetushkov@9858 49 static u8 checkpoint_id = 0;
apetushkov@9858 50
apetushkov@9858 51 // creates a unique id by combining a checkpoint relative symbol id (2^24)
apetushkov@9858 52 // with the current checkpoint id (2^40)
apetushkov@9858 53 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
apetushkov@9858 54
apetushkov@9858 55 typedef const Klass* KlassPtr;
apetushkov@9858 56 typedef const ClassLoaderData* CldPtr;
apetushkov@9858 57 typedef const Method* MethodPtr;
apetushkov@9858 58 typedef const Symbol* SymbolPtr;
apetushkov@9858 59 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
apetushkov@9858 60 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
apetushkov@9858 61
apetushkov@9858 62 static traceid cld_id(CldPtr cld) {
apetushkov@9858 63 assert(cld != NULL, "invariant");
apetushkov@9858 64 return cld->is_anonymous() ? 0 : TRACE_ID(cld);
apetushkov@9858 65 }
apetushkov@9858 66
apetushkov@9858 67 static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) {
apetushkov@9858 68 assert(k != NULL, "invariant");
apetushkov@9858 69 CldPtr cld = k->class_loader_data();
apetushkov@9858 70 assert(cld != NULL, "invariant");
apetushkov@9858 71 if (!cld->is_anonymous()) {
apetushkov@9858 72 tag_leakp_artifact(cld, class_unload);
apetushkov@9858 73 }
apetushkov@9858 74 }
apetushkov@9858 75
apetushkov@9858 76 class TagLeakpKlassArtifact {
apetushkov@9858 77 bool _class_unload;
apetushkov@9858 78 public:
apetushkov@9858 79 TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {}
apetushkov@9858 80 bool operator()(KlassPtr klass) {
apetushkov@9858 81 if (_class_unload) {
apetushkov@9858 82 if (LEAKP_USED_THIS_EPOCH(klass)) {
apetushkov@9858 83 tag_leakp_klass_artifacts(klass, _class_unload);
apetushkov@9858 84 }
apetushkov@9858 85 } else {
apetushkov@9858 86 if (LEAKP_USED_PREV_EPOCH(klass)) {
apetushkov@9858 87 tag_leakp_klass_artifacts(klass, _class_unload);
apetushkov@9858 88 }
apetushkov@9858 89 }
apetushkov@9858 90 return true;
apetushkov@9858 91 }
apetushkov@9858 92 };
apetushkov@9858 93
apetushkov@9858 94 /*
apetushkov@9858 95 * In C++03, functions used as template parameters must have external linkage;
apetushkov@9858 96 * this restriction was removed in C++11. Change back to "static" and
apetushkov@9858 97 * rename functions when C++11 becomes available.
apetushkov@9858 98 *
apetushkov@9858 99 * The weird naming is an effort to decrease the risk of name clashes.
apetushkov@9858 100 */
apetushkov@9858 101
apetushkov@9858 102 int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
apetushkov@9858 103 assert(writer != NULL, "invariant");
apetushkov@9858 104 assert(artifacts != NULL, "invariant");
apetushkov@9858 105 assert(k != NULL, "invariant");
apetushkov@9858 106 KlassPtr klass = (KlassPtr)k;
apetushkov@9858 107 traceid pkg_id = 0;
apetushkov@9858 108 KlassPtr theklass = klass;
apetushkov@9858 109 if (theklass->oop_is_objArray()) {
apetushkov@9858 110 const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast((Klass*)klass);
apetushkov@9858 111 theklass = obj_arr_klass->bottom_klass();
apetushkov@9858 112 }
apetushkov@9858 113 if (theklass->oop_is_instance()) {
ddong@9941 114 pkg_id = 0;
apetushkov@9858 115 } else {
apetushkov@9858 116 assert(theklass->oop_is_typeArray(), "invariant");
apetushkov@9858 117 }
apetushkov@9858 118 const traceid symbol_id = artifacts->mark(klass);
apetushkov@9858 119 assert(symbol_id > 0, "need to have an address for symbol!");
apetushkov@9858 120 writer->write(TRACE_ID(klass));
apetushkov@9858 121 writer->write(cld_id(klass->class_loader_data()));
apetushkov@9858 122 writer->write((traceid)CREATE_SYMBOL_ID(symbol_id));
apetushkov@9858 123 writer->write(pkg_id);
apetushkov@9858 124 writer->write((s4)klass->access_flags().get_flags());
apetushkov@9858 125 return 1;
apetushkov@9858 126 }
apetushkov@9858 127
apetushkov@9858 128 typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
apetushkov@9858 129 typedef JfrPredicatedArtifactWriterImplHost<KlassPtr, LeakKlassPredicate, write__artifact__klass> LeakKlassWriterImpl;
apetushkov@9858 130 typedef JfrArtifactWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
apetushkov@9858 131 typedef JfrArtifactWriterImplHost<KlassPtr, write__artifact__klass> KlassWriterImpl;
apetushkov@9858 132 typedef JfrArtifactWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
apetushkov@9858 133
apetushkov@9858 134 int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) {
apetushkov@9858 135 assert(writer != NULL, "invariant");
apetushkov@9858 136 assert(artifacts != NULL, "invariant");
apetushkov@9858 137 assert(m != NULL, "invariant");
apetushkov@9858 138 MethodPtr method = (MethodPtr)m;
apetushkov@9858 139 const traceid method_name_symbol_id = artifacts->mark(method->name());
apetushkov@9858 140 assert(method_name_symbol_id > 0, "invariant");
apetushkov@9858 141 const traceid method_sig_symbol_id = artifacts->mark(method->signature());
apetushkov@9858 142 assert(method_sig_symbol_id > 0, "invariant");
apetushkov@9858 143 KlassPtr klass = method->method_holder();
apetushkov@9858 144 assert(klass != NULL, "invariant");
apetushkov@9858 145 assert(METHOD_USED_ANY_EPOCH(klass), "invariant");
apetushkov@9858 146 writer->write((u8)METHOD_ID(klass, method));
apetushkov@9858 147 writer->write((u8)TRACE_ID(klass));
apetushkov@9858 148 writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id));
apetushkov@9858 149 writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id));
apetushkov@9858 150 writer->write((u2)method->access_flags().get_flags());
apetushkov@9858 151 writer->write(const_cast<Method*>(method)->is_hidden() ? (u1)1 : (u1)0);
apetushkov@9858 152 return 1;
apetushkov@9858 153 }
apetushkov@9858 154
apetushkov@9858 155 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
apetushkov@9858 156 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
apetushkov@9858 157
apetushkov@9858 158 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
apetushkov@9858 159 assert(c != NULL, "invariant");
apetushkov@9858 160 CldPtr cld = (CldPtr)c;
apetushkov@9858 161 assert(!cld->is_anonymous(), "invariant");
apetushkov@9858 162 const traceid cld_id = TRACE_ID(cld);
apetushkov@9858 163 // class loader type
apetushkov@9858 164 const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
apetushkov@9858 165 if (class_loader_klass == NULL) {
apetushkov@9858 166 // (primordial) boot class loader
apetushkov@9858 167 writer->write(cld_id); // class loader instance id
apetushkov@9858 168 writer->write((traceid)0); // class loader type id (absence of)
apetushkov@9858 169 writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap"
apetushkov@9858 170 } else {
apetushkov@9858 171 Symbol* symbol_name = class_loader_klass->name();
apetushkov@9858 172 const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0;
apetushkov@9858 173 writer->write(cld_id); // class loader instance id
apetushkov@9858 174 writer->write(TRACE_ID(class_loader_klass)); // class loader type id
apetushkov@9858 175 writer->write(symbol_name_id == 0 ? (traceid)0 :
apetushkov@9858 176 (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name
apetushkov@9858 177 }
apetushkov@9858 178 return 1;
apetushkov@9858 179 }
apetushkov@9858 180
apetushkov@9858 181 typedef LeakPredicate<CldPtr> LeakCldPredicate;
apetushkov@9858 182 int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; }
apetushkov@9858 183 typedef UniquePredicate<CldPtr, _compare_cld_ptr_> CldPredicate;
apetushkov@9858 184 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, LeakCldPredicate, write__artifact__classloader> LeakCldWriterImpl;
apetushkov@9858 185 typedef JfrPredicatedArtifactWriterImplHost<CldPtr, CldPredicate, write__artifact__classloader> CldWriterImpl;
apetushkov@9858 186 typedef JfrArtifactWriterHost<LeakCldWriterImpl, TYPE_CLASSLOADER> LeakCldWriter;
apetushkov@9858 187 typedef JfrArtifactWriterHost<CldWriterImpl, TYPE_CLASSLOADER> CldWriter;
apetushkov@9858 188
apetushkov@9858 189 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
apetushkov@9858 190
apetushkov@9858 191 static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer,
apetushkov@9858 192 SymbolEntryPtr entry) {
apetushkov@9858 193 assert(writer != NULL, "invariant");
apetushkov@9858 194 assert(entry != NULL, "invariant");
apetushkov@9858 195 ResourceMark rm;
apetushkov@9858 196 writer->write(CREATE_SYMBOL_ID(entry->id()));
apetushkov@9858 197 writer->write(entry->value()->as_C_string());
apetushkov@9858 198 return 1;
apetushkov@9858 199 }
apetushkov@9858 200
apetushkov@9858 201 int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
apetushkov@9858 202 assert(e != NULL, "invariant");
apetushkov@9858 203 return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e);
apetushkov@9858 204 }
apetushkov@9858 205
apetushkov@9858 206 typedef JfrArtifactWriterImplHost<SymbolEntryPtr, write__artifact__symbol__entry> SymbolEntryWriterImpl;
apetushkov@9858 207 typedef JfrArtifactWriterHost<SymbolEntryWriterImpl, TYPE_SYMBOL> SymbolEntryWriter;
apetushkov@9858 208
apetushkov@9858 209 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
apetushkov@9858 210
apetushkov@9858 211 static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) {
apetushkov@9858 212 assert(writer != NULL, "invariant");
apetushkov@9858 213 assert(entry != NULL, "invariant");
apetushkov@9858 214 writer->write(CREATE_SYMBOL_ID(entry->id()));
apetushkov@9858 215 writer->write(entry->value());
apetushkov@9858 216 return 1;
apetushkov@9858 217 }
apetushkov@9858 218
apetushkov@9858 219 int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) {
apetushkov@9858 220 assert(e != NULL, "invariant");
apetushkov@9858 221 return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e);
apetushkov@9858 222 }
apetushkov@9858 223
apetushkov@9858 224 typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__cstring__entry> CStringEntryWriterImpl;
apetushkov@9858 225 typedef JfrArtifactWriterHost<CStringEntryWriterImpl, TYPE_SYMBOL> CStringEntryWriter;
apetushkov@9858 226
apetushkov@9858 227 int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) {
apetushkov@9858 228 assert(writer != NULL, "invariant");
apetushkov@9858 229 assert(artifacts != NULL, "invaiant");
apetushkov@9858 230 assert(k != NULL, "invariant");
apetushkov@9858 231 const InstanceKlass* const ik = (const InstanceKlass*)k;
apetushkov@9858 232 if (ik->is_anonymous()) {
apetushkov@9858 233 CStringEntryPtr entry =
apetushkov@9858 234 artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
apetushkov@9858 235 assert(entry != NULL, "invariant");
apetushkov@9858 236 return write__artifact__cstring__entry__(writer, entry);
apetushkov@9858 237 }
apetushkov@9858 238
apetushkov@9858 239 SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik));
apetushkov@9858 240 return write__artifact__symbol__entry__(writer, entry);
apetushkov@9858 241 }
apetushkov@9858 242
apetushkov@9858 243 int _compare_traceid_(const traceid& lhs, const traceid& rhs) {
apetushkov@9858 244 return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0;
apetushkov@9858 245 }
apetushkov@9858 246
apetushkov@9858 247 template <template <typename> class Predicate>
apetushkov@9858 248 class KlassSymbolWriterImpl {
apetushkov@9858 249 private:
apetushkov@9858 250 JfrCheckpointWriter* _writer;
apetushkov@9858 251 JfrArtifactSet* _artifacts;
apetushkov@9858 252 Predicate<KlassPtr> _predicate;
apetushkov@9858 253 MethodUsedPredicate<true> _method_used_predicate;
apetushkov@9858 254 MethodFlagPredicate _method_flag_predicate;
apetushkov@9858 255 UniquePredicate<traceid, _compare_traceid_> _unique_predicate;
apetushkov@9858 256
apetushkov@9858 257 int klass_symbols(KlassPtr klass);
apetushkov@9858 258 int class_loader_symbols(CldPtr cld);
apetushkov@9858 259 int method_symbols(KlassPtr klass);
apetushkov@9858 260
apetushkov@9858 261 public:
apetushkov@9858 262 typedef KlassPtr Type;
apetushkov@9858 263 KlassSymbolWriterImpl(JfrCheckpointWriter* writer,
apetushkov@9858 264 JfrArtifactSet* artifacts,
apetushkov@9858 265 bool class_unload) : _writer(writer),
apetushkov@9858 266 _artifacts(artifacts),
apetushkov@9858 267 _predicate(class_unload),
apetushkov@9858 268 _method_used_predicate(class_unload),
apetushkov@9858 269 _method_flag_predicate(class_unload),
apetushkov@9858 270 _unique_predicate(class_unload) {}
apetushkov@9858 271
apetushkov@9858 272 int operator()(KlassPtr klass) {
apetushkov@9858 273 assert(klass != NULL, "invariant");
apetushkov@9858 274 int count = 0;
apetushkov@9858 275 if (_predicate(klass)) {
apetushkov@9858 276 count += klass_symbols(klass);
apetushkov@9858 277 CldPtr cld = klass->class_loader_data();
apetushkov@9858 278 assert(cld != NULL, "invariant");
apetushkov@9858 279 if (!cld->is_anonymous()) {
apetushkov@9858 280 count += class_loader_symbols(cld);
apetushkov@9858 281 }
apetushkov@9858 282 if (_method_used_predicate(klass)) {
apetushkov@9858 283 count += method_symbols(klass);
apetushkov@9858 284 }
apetushkov@9858 285 }
apetushkov@9858 286 return count;
apetushkov@9858 287 }
apetushkov@9858 288 };
apetushkov@9858 289
apetushkov@9858 290 template <template <typename> class Predicate>
apetushkov@9858 291 int KlassSymbolWriterImpl<Predicate>::klass_symbols(KlassPtr klass) {
apetushkov@9858 292 assert(klass != NULL, "invariant");
apetushkov@9858 293 assert(_predicate(klass), "invariant");
apetushkov@9858 294 const InstanceKlass* const ik = (const InstanceKlass*)klass;
apetushkov@9858 295 if (ik->is_anonymous()) {
apetushkov@9858 296 CStringEntryPtr entry =
apetushkov@9858 297 this->_artifacts->map_cstring(JfrSymbolId::anonymous_klass_name_hash_code(ik));
apetushkov@9858 298 assert(entry != NULL, "invariant");
apetushkov@9858 299 return _unique_predicate(entry->id()) ? write__artifact__cstring__entry__(this->_writer, entry) : 0;
apetushkov@9858 300 }
apetushkov@9858 301 SymbolEntryPtr entry = this->_artifacts->map_symbol(ik->name());
apetushkov@9858 302 assert(entry != NULL, "invariant");
apetushkov@9858 303 return _unique_predicate(entry->id()) ? write__artifact__symbol__entry__(this->_writer, entry) : 0;
apetushkov@9858 304 }
apetushkov@9858 305
apetushkov@9858 306 template <template <typename> class Predicate>
apetushkov@9858 307 int KlassSymbolWriterImpl<Predicate>::class_loader_symbols(CldPtr cld) {
apetushkov@9858 308 assert(cld != NULL, "invariant");
apetushkov@9858 309 assert(!cld->is_anonymous(), "invariant");
apetushkov@9858 310 int count = 0;
apetushkov@9858 311 // class loader type
apetushkov@9858 312 const Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL;
apetushkov@9858 313 if (class_loader_klass == NULL) {
apetushkov@9858 314 // (primordial) boot class loader
apetushkov@9858 315 CStringEntryPtr entry = this->_artifacts->map_cstring(0);
apetushkov@9858 316 assert(entry != NULL, "invariant");
apetushkov@9858 317 assert(strncmp(entry->literal(),
apetushkov@9858 318 BOOTSTRAP_LOADER_NAME,
apetushkov@9858 319 BOOTSTRAP_LOADER_NAME_LEN) == 0, "invariant");
apetushkov@9858 320 if (_unique_predicate(entry->id())) {
apetushkov@9858 321 count += write__artifact__cstring__entry__(this->_writer, entry);
apetushkov@9858 322 }
apetushkov@9858 323 } else {
apetushkov@9858 324 const Symbol* class_loader_name = class_loader_klass->name()/* XXX TODO cld->name()*/;
apetushkov@9858 325 if (class_loader_name != NULL) {
apetushkov@9858 326 SymbolEntryPtr entry = this->_artifacts->map_symbol(class_loader_name);
apetushkov@9858 327 assert(entry != NULL, "invariant");
apetushkov@9858 328 if (_unique_predicate(entry->id())) {
apetushkov@9858 329 count += write__artifact__symbol__entry__(this->_writer, entry);
apetushkov@9858 330 }
apetushkov@9858 331 }
apetushkov@9858 332 }
apetushkov@9858 333 return count;
apetushkov@9858 334 }
apetushkov@9858 335
apetushkov@9858 336 template <template <typename> class Predicate>
apetushkov@9858 337 int KlassSymbolWriterImpl<Predicate>::method_symbols(KlassPtr klass) {
apetushkov@9858 338 assert(_predicate(klass), "invariant");
apetushkov@9858 339 assert(_method_used_predicate(klass), "invariant");
apetushkov@9858 340 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
apetushkov@9858 341 int count = 0;
apetushkov@9858 342 const InstanceKlass* const ik = InstanceKlass::cast((Klass*)klass);
apetushkov@9858 343 const int len = ik->methods()->length();
apetushkov@9858 344 for (int i = 0; i < len; ++i) {
apetushkov@9858 345 MethodPtr method = ik->methods()->at(i);
apetushkov@9858 346 if (_method_flag_predicate(method)) {
apetushkov@9858 347 SymbolEntryPtr entry = this->_artifacts->map_symbol(method->name());
apetushkov@9858 348 assert(entry != NULL, "invariant");
apetushkov@9858 349 if (_unique_predicate(entry->id())) {
apetushkov@9858 350 count += write__artifact__symbol__entry__(this->_writer, entry);
apetushkov@9858 351 }
apetushkov@9858 352 entry = this->_artifacts->map_symbol(method->signature());
apetushkov@9858 353 assert(entry != NULL, "invariant");
apetushkov@9858 354 if (_unique_predicate(entry->id())) {
apetushkov@9858 355 count += write__artifact__symbol__entry__(this->_writer, entry);
apetushkov@9858 356 }
apetushkov@9858 357 }
apetushkov@9858 358 }
apetushkov@9858 359 return count;
apetushkov@9858 360 }
apetushkov@9858 361
apetushkov@9858 362 typedef KlassSymbolWriterImpl<LeakPredicate> LeakKlassSymbolWriterImpl;
apetushkov@9858 363 typedef JfrArtifactWriterHost<LeakKlassSymbolWriterImpl, TYPE_SYMBOL> LeakKlassSymbolWriter;
apetushkov@9858 364
apetushkov@9858 365 class ClearKlassAndMethods {
apetushkov@9858 366 private:
apetushkov@9858 367 ClearArtifact<KlassPtr> _clear_klass_tag_bits;
apetushkov@9858 368 ClearArtifact<MethodPtr> _clear_method_flag;
apetushkov@9858 369 MethodUsedPredicate<false> _method_used_predicate;
apetushkov@9858 370
apetushkov@9858 371 public:
apetushkov@9858 372 ClearKlassAndMethods(bool class_unload) : _clear_klass_tag_bits(class_unload),
apetushkov@9858 373 _clear_method_flag(class_unload),
apetushkov@9858 374 _method_used_predicate(class_unload) {}
apetushkov@9858 375 bool operator()(KlassPtr klass) {
apetushkov@9858 376 if (_method_used_predicate(klass)) {
apetushkov@9858 377 const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
apetushkov@9858 378 const int len = ik->methods()->length();
apetushkov@9858 379 for (int i = 0; i < len; ++i) {
apetushkov@9858 380 MethodPtr method = ik->methods()->at(i);
apetushkov@9858 381 _clear_method_flag(method);
apetushkov@9858 382 }
apetushkov@9858 383 }
apetushkov@9858 384 _clear_klass_tag_bits(klass);
apetushkov@9858 385 return true;
apetushkov@9858 386 }
apetushkov@9858 387 };
apetushkov@9858 388
apetushkov@9858 389 typedef CompositeFunctor<KlassPtr,
apetushkov@9858 390 TagLeakpKlassArtifact,
apetushkov@9858 391 LeakKlassWriter> LeakpKlassArtifactTagging;
apetushkov@9858 392
apetushkov@9858 393 typedef CompositeFunctor<KlassPtr,
apetushkov@9858 394 LeakpKlassArtifactTagging,
apetushkov@9858 395 KlassWriter> CompositeKlassWriter;
apetushkov@9858 396
apetushkov@9858 397 typedef CompositeFunctor<KlassPtr,
apetushkov@9858 398 CompositeKlassWriter,
apetushkov@9858 399 KlassArtifactRegistrator> CompositeKlassWriterRegistration;
apetushkov@9858 400
apetushkov@9858 401 typedef CompositeFunctor<KlassPtr,
apetushkov@9858 402 KlassWriter,
apetushkov@9858 403 KlassArtifactRegistrator> KlassWriterRegistration;
apetushkov@9858 404
apetushkov@9858 405 typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
apetushkov@9858 406 typedef JfrArtifactCallbackHost<KlassPtr, CompositeKlassWriterRegistration> CompositeKlassCallback;
apetushkov@9858 407
apetushkov@9858 408 /*
apetushkov@9858 409 * Composite operation
apetushkov@9858 410 *
apetushkov@9858 411 * TagLeakpKlassArtifact ->
apetushkov@9858 412 * LeakpPredicate ->
apetushkov@9858 413 * LeakpKlassWriter ->
apetushkov@9858 414 * KlassPredicate ->
apetushkov@9858 415 * KlassWriter ->
apetushkov@9858 416 * KlassWriterRegistration
apetushkov@9858 417 */
apetushkov@9858 418 void JfrTypeSet::write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
apetushkov@9858 419 assert(!_artifacts->has_klass_entries(), "invariant");
apetushkov@9858 420 KlassArtifactRegistrator reg(_artifacts);
apetushkov@9858 421 KlassWriter kw(writer, _artifacts, _class_unload);
apetushkov@9858 422 KlassWriterRegistration kwr(&kw, &reg);
apetushkov@9858 423 if (leakp_writer == NULL) {
apetushkov@9858 424 KlassCallback callback(&kwr);
apetushkov@9858 425 _subsystem_callback = &callback;
apetushkov@9858 426 do_klasses();
apetushkov@9858 427 return;
apetushkov@9858 428 }
apetushkov@9858 429 TagLeakpKlassArtifact tagging(_class_unload);
apetushkov@9858 430 LeakKlassWriter lkw(leakp_writer, _artifacts, _class_unload);
apetushkov@9858 431 LeakpKlassArtifactTagging lpkat(&tagging, &lkw);
apetushkov@9858 432 CompositeKlassWriter ckw(&lpkat, &kw);
apetushkov@9858 433 CompositeKlassWriterRegistration ckwr(&ckw, &reg);
apetushkov@9858 434 CompositeKlassCallback callback(&ckwr);
apetushkov@9858 435 _subsystem_callback = &callback;
apetushkov@9858 436 do_klasses();
apetushkov@9858 437 }
apetushkov@9858 438
apetushkov@9858 439 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
apetushkov@9858 440 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
apetushkov@9858 441 typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
apetushkov@9858 442 typedef JfrArtifactCallbackHost<CldPtr, CldWriterWithClear> CldCallback;
apetushkov@9858 443 typedef JfrArtifactCallbackHost<CldPtr, CompositeCldWriterWithClear> CompositeCldCallback;
apetushkov@9858 444
apetushkov@9858 445 class CldFieldSelector {
apetushkov@9858 446 public:
apetushkov@9858 447 typedef CldPtr TypePtr;
apetushkov@9858 448 static TypePtr select(KlassPtr klass) {
apetushkov@9858 449 assert(klass != NULL, "invariant");
apetushkov@9858 450 CldPtr cld = klass->class_loader_data();
apetushkov@9858 451 return cld->is_anonymous() ? NULL : cld;
apetushkov@9858 452 }
apetushkov@9858 453 };
apetushkov@9858 454
apetushkov@9858 455 typedef KlassToFieldEnvelope<CldFieldSelector, CldWriterWithClear> KlassCldWriterWithClear;
apetushkov@9858 456 typedef KlassToFieldEnvelope<CldFieldSelector, CompositeCldWriterWithClear> KlassCompositeCldWriterWithClear;
apetushkov@9858 457
apetushkov@9858 458 /*
apetushkov@9858 459 * Composite operation
apetushkov@9858 460 *
apetushkov@9858 461 * LeakpClassLoaderWriter ->
apetushkov@9858 462 * ClassLoaderWriter ->
apetushkov@9858 463 * ClearArtifact<ClassLoaderData>
apetushkov@9858 464 */
apetushkov@9858 465 void JfrTypeSet::write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
apetushkov@9858 466 assert(_artifacts->has_klass_entries(), "invariant");
apetushkov@9858 467 ClearArtifact<CldPtr> clear(_class_unload);
apetushkov@9858 468 CldWriter cldw(writer, _artifacts, _class_unload);
apetushkov@9858 469 if (leakp_writer == NULL) {
apetushkov@9858 470 CldWriterWithClear cldwwc(&cldw, &clear);
apetushkov@9858 471 KlassCldWriterWithClear kcldwwc(&cldwwc);
apetushkov@9858 472 _artifacts->iterate_klasses(kcldwwc);
apetushkov@9858 473 CldCallback callback(&cldwwc);
apetushkov@9858 474 _subsystem_callback = &callback;
apetushkov@9858 475 do_class_loaders();
apetushkov@9858 476 return;
apetushkov@9858 477 }
apetushkov@9858 478 LeakCldWriter lcldw(leakp_writer, _artifacts, _class_unload);
apetushkov@9858 479 CompositeCldWriter ccldw(&lcldw, &cldw);
apetushkov@9858 480 CompositeCldWriterWithClear ccldwwc(&ccldw, &clear);
apetushkov@9858 481 KlassCompositeCldWriterWithClear kcclwwc(&ccldwwc);
apetushkov@9858 482 _artifacts->iterate_klasses(kcclwwc);
apetushkov@9858 483 CompositeCldCallback callback(&ccldwwc);
apetushkov@9858 484 _subsystem_callback = &callback;
apetushkov@9858 485 do_class_loaders();
apetushkov@9858 486 }
apetushkov@9858 487
apetushkov@9858 488 template <bool predicate_bool, typename MethodFunctor>
apetushkov@9858 489 class MethodIteratorHost {
apetushkov@9858 490 private:
apetushkov@9858 491 MethodFunctor _method_functor;
apetushkov@9858 492 MethodUsedPredicate<predicate_bool> _method_used_predicate;
apetushkov@9858 493 MethodFlagPredicate _method_flag_predicate;
apetushkov@9858 494
apetushkov@9858 495 public:
apetushkov@9858 496 MethodIteratorHost(JfrCheckpointWriter* writer,
apetushkov@9858 497 JfrArtifactSet* artifacts,
apetushkov@9858 498 bool class_unload,
apetushkov@9858 499 bool skip_header = false) :
apetushkov@9858 500 _method_functor(writer, artifacts, class_unload, skip_header),
apetushkov@9858 501 _method_used_predicate(class_unload),
apetushkov@9858 502 _method_flag_predicate(class_unload) {}
apetushkov@9858 503
apetushkov@9858 504 bool operator()(KlassPtr klass) {
apetushkov@9858 505 if (_method_used_predicate(klass)) {
apetushkov@9858 506 assert(METHOD_AND_CLASS_USED_ANY_EPOCH(klass), "invariant");
apetushkov@9858 507 const InstanceKlass* ik = InstanceKlass::cast((Klass*)klass);
apetushkov@9858 508 const int len = ik->methods()->length();
apetushkov@9858 509 for (int i = 0; i < len; ++i) {
apetushkov@9858 510 MethodPtr method = ik->methods()->at(i);
apetushkov@9858 511 if (_method_flag_predicate(method)) {
apetushkov@9858 512 _method_functor(method);
apetushkov@9858 513 }
apetushkov@9858 514 }
apetushkov@9858 515 }
apetushkov@9858 516 return true;
apetushkov@9858 517 }
apetushkov@9858 518
apetushkov@9858 519 int count() const { return _method_functor.count(); }
apetushkov@9858 520 void add(int count) { _method_functor.add(count); }
apetushkov@9858 521 };
apetushkov@9858 522
apetushkov@9858 523 typedef MethodIteratorHost<true /*leakp */, MethodWriterImpl> LeakMethodWriter;
apetushkov@9858 524 typedef MethodIteratorHost<false, MethodWriterImpl> MethodWriter;
apetushkov@9858 525 typedef CompositeFunctor<KlassPtr, LeakMethodWriter, MethodWriter> CompositeMethodWriter;
apetushkov@9858 526
apetushkov@9858 527 /*
apetushkov@9858 528 * Composite operation
apetushkov@9858 529 *
apetushkov@9858 530 * LeakpMethodWriter ->
apetushkov@9858 531 * MethodWriter
apetushkov@9858 532 */
apetushkov@9858 533 void JfrTypeSet::write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
apetushkov@9858 534 assert(_artifacts->has_klass_entries(), "invariant");
apetushkov@9858 535 MethodWriter mw(writer, _artifacts, _class_unload);
apetushkov@9858 536 if (leakp_writer == NULL) {
apetushkov@9858 537 _artifacts->iterate_klasses(mw);
apetushkov@9858 538 return;
apetushkov@9858 539 }
apetushkov@9858 540 LeakMethodWriter lpmw(leakp_writer, _artifacts, _class_unload);
apetushkov@9858 541 CompositeMethodWriter cmw(&lpmw, &mw);
apetushkov@9858 542 _artifacts->iterate_klasses(cmw);
apetushkov@9858 543 }
apetushkov@9858 544 static void write_symbols_leakp(JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
apetushkov@9858 545 assert(leakp_writer != NULL, "invariant");
apetushkov@9858 546 assert(artifacts != NULL, "invariant");
apetushkov@9858 547 LeakKlassSymbolWriter lpksw(leakp_writer, artifacts, class_unload);
apetushkov@9858 548 artifacts->iterate_klasses(lpksw);
apetushkov@9858 549 }
apetushkov@9858 550 static void write_symbols(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, JfrArtifactSet* artifacts, bool class_unload) {
apetushkov@9858 551 assert(writer != NULL, "invariant");
apetushkov@9858 552 assert(artifacts != NULL, "invariant");
apetushkov@9858 553 if (leakp_writer != NULL) {
apetushkov@9858 554 write_symbols_leakp(leakp_writer, artifacts, class_unload);
apetushkov@9858 555 }
apetushkov@9858 556 // iterate all registered symbols
apetushkov@9858 557 SymbolEntryWriter symbol_writer(writer, artifacts, class_unload);
apetushkov@9858 558 artifacts->iterate_symbols(symbol_writer);
apetushkov@9858 559 CStringEntryWriter cstring_writer(writer, artifacts, class_unload, true); // skip header
apetushkov@9858 560 artifacts->iterate_cstrings(cstring_writer);
apetushkov@9858 561 symbol_writer.add(cstring_writer.count());
apetushkov@9858 562 }
apetushkov@9858 563
apetushkov@9858 564 bool JfrTypeSet::_class_unload = false;
apetushkov@9858 565 JfrArtifactSet* JfrTypeSet::_artifacts = NULL;
apetushkov@9858 566 JfrArtifactClosure* JfrTypeSet::_subsystem_callback = NULL;
apetushkov@9858 567
apetushkov@9858 568 void JfrTypeSet::write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
apetushkov@9858 569 assert(writer != NULL, "invariant");
apetushkov@9858 570 assert(_artifacts->has_klass_entries(), "invariant");
apetushkov@9858 571 write_symbols(writer, leakp_writer, _artifacts, _class_unload);
apetushkov@9858 572 }
apetushkov@9858 573
apetushkov@9858 574 void JfrTypeSet::do_unloaded_klass(Klass* klass) {
apetushkov@9858 575 assert(klass != NULL, "invariant");
apetushkov@9858 576 assert(_subsystem_callback != NULL, "invariant");
apetushkov@9858 577 if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) {
apetushkov@9858 578 JfrEventClasses::increment_unloaded_event_class();
apetushkov@9858 579 }
apetushkov@9858 580 if (USED_THIS_EPOCH(klass)) { // includes leakp subset
apetushkov@9858 581 _subsystem_callback->do_artifact(klass);
apetushkov@9858 582 return;
apetushkov@9858 583 }
apetushkov@9858 584 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
apetushkov@9858 585 SET_LEAKP_USED_THIS_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
apetushkov@9858 586 _subsystem_callback->do_artifact(klass);
apetushkov@9858 587 }
apetushkov@9858 588 }
apetushkov@9858 589
apetushkov@9858 590 void JfrTypeSet::do_klass(Klass* klass) {
apetushkov@9858 591 assert(klass != NULL, "invariant");
apetushkov@9858 592 assert(_subsystem_callback != NULL, "invariant");
apetushkov@9858 593 if (USED_PREV_EPOCH(klass)) { // includes leakp subset
apetushkov@9858 594 _subsystem_callback->do_artifact(klass);
apetushkov@9858 595 return;
apetushkov@9858 596 }
apetushkov@9858 597 if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) {
apetushkov@9858 598 SET_LEAKP_USED_PREV_EPOCH(klass); // tag leakp "safe byte" for subset inclusion
apetushkov@9858 599 _subsystem_callback->do_artifact(klass);
apetushkov@9858 600 }
apetushkov@9858 601 }
apetushkov@9858 602
apetushkov@9858 603 void JfrTypeSet::do_klasses() {
apetushkov@9858 604 if (_class_unload) {
apetushkov@9858 605 ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass);
apetushkov@9858 606 return;
apetushkov@9858 607 }
apetushkov@9858 608 ClassLoaderDataGraph::classes_do(&do_klass);
apetushkov@9858 609 }
apetushkov@9858 610
apetushkov@9858 611 void JfrTypeSet::do_unloaded_class_loader_data(ClassLoaderData* cld) {
apetushkov@9858 612 assert(_subsystem_callback != NULL, "invariant");
apetushkov@9858 613 if (ANY_USED_THIS_EPOCH(cld)) { // includes leakp subset
apetushkov@9858 614 _subsystem_callback->do_artifact(cld);
apetushkov@9858 615 }
apetushkov@9858 616 }
apetushkov@9858 617
apetushkov@9858 618 void JfrTypeSet::do_class_loader_data(ClassLoaderData* cld) {
apetushkov@9858 619 assert(_subsystem_callback != NULL, "invariant");
apetushkov@9858 620 if (ANY_USED_PREV_EPOCH(cld)) { // includes leakp subset
apetushkov@9858 621 _subsystem_callback->do_artifact(cld);
apetushkov@9858 622 }
apetushkov@9858 623 }
apetushkov@9858 624
apetushkov@9858 625 class CLDCallback : public CLDClosure {
apetushkov@9858 626 private:
apetushkov@9858 627 bool _class_unload;
apetushkov@9858 628 public:
apetushkov@9858 629 CLDCallback(bool class_unload) : _class_unload(class_unload) {}
apetushkov@9858 630 void do_cld(ClassLoaderData* cld) {
apetushkov@9858 631 assert(cld != NULL, "invariant");
apetushkov@9858 632 if (cld->is_anonymous()) {
apetushkov@9858 633 return;
apetushkov@9858 634 }
apetushkov@9858 635 if (_class_unload) {
apetushkov@9858 636 JfrTypeSet::do_unloaded_class_loader_data(cld);
apetushkov@9858 637 return;
apetushkov@9858 638 }
apetushkov@9858 639 JfrTypeSet::do_class_loader_data(cld);
apetushkov@9858 640 }
apetushkov@9858 641 };
apetushkov@9858 642
apetushkov@9858 643 void JfrTypeSet::do_class_loaders() {
apetushkov@9858 644 CLDCallback cld_cb(_class_unload);
apetushkov@9858 645 if (_class_unload) {
apetushkov@9858 646 ClassLoaderDataGraph::cld_unloading_do(&cld_cb);
apetushkov@9858 647 return;
apetushkov@9858 648 }
apetushkov@9858 649 ClassLoaderDataGraph::cld_do(&cld_cb);
apetushkov@9858 650 }
apetushkov@9858 651
apetushkov@9858 652 static void clear_artifacts(JfrArtifactSet* artifacts,
apetushkov@9858 653 bool class_unload) {
apetushkov@9858 654 assert(artifacts != NULL, "invariant");
apetushkov@9858 655 assert(artifacts->has_klass_entries(), "invariant");
apetushkov@9858 656
apetushkov@9858 657 // untag
apetushkov@9858 658 ClearKlassAndMethods clear(class_unload);
apetushkov@9858 659 artifacts->iterate_klasses(clear);
apetushkov@9858 660 artifacts->clear();
apetushkov@9858 661 }
apetushkov@9858 662
apetushkov@9858 663 /**
apetushkov@9858 664 * Write all "tagged" (in-use) constant artifacts and their dependencies.
apetushkov@9858 665 */
apetushkov@9858 666 void JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload) {
apetushkov@9858 667 assert(writer != NULL, "invariant");
apetushkov@9858 668 ResourceMark rm;
apetushkov@9858 669 // initialization begin
apetushkov@9858 670 _class_unload = class_unload;
apetushkov@9858 671 ++checkpoint_id;
apetushkov@9858 672 if (_artifacts == NULL) {
apetushkov@9858 673 _artifacts = new JfrArtifactSet(class_unload);
apetushkov@9858 674 _subsystem_callback = NULL;
apetushkov@9858 675 } else {
apetushkov@9858 676 _artifacts->initialize(class_unload);
apetushkov@9858 677 _subsystem_callback = NULL;
apetushkov@9858 678 }
apetushkov@9858 679 assert(_artifacts != NULL, "invariant");
apetushkov@9858 680 assert(!_artifacts->has_klass_entries(), "invariant");
apetushkov@9858 681 assert(_subsystem_callback == NULL, "invariant");
apetushkov@9858 682 // initialization complete
apetushkov@9858 683
apetushkov@9858 684 // write order is important because an individual write step
apetushkov@9858 685 // might tag an artifact to be written in a subsequent step
apetushkov@9858 686 write_klass_constants(writer, leakp_writer);
apetushkov@9858 687 if (_artifacts->has_klass_entries()) {
apetushkov@9858 688 write_class_loader_constants(writer, leakp_writer);
apetushkov@9858 689 write_method_constants(writer, leakp_writer);
apetushkov@9858 690 write_symbol_constants(writer, leakp_writer);
apetushkov@9858 691 clear_artifacts(_artifacts, class_unload);
apetushkov@9858 692 }
apetushkov@9858 693 }

mercurial