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