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