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