diff -r 3054503bad7d -r caa25ab47aca src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Fri Sep 13 16:03:31 2019 -0700 +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Sat Sep 14 14:40:09 2019 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,32 +28,22 @@ #include "classfile/moduleEntry.hpp" #include "classfile/packageEntry.hpp" #include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" #include "jfr/jfr.hpp" #include "jfr/jni/jfrGetAllEventClasses.hpp" -#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" +#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp" #include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp" #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp" -#include "jfr/recorder/checkpoint/types/jfrTypeSetWriter.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp" -#include "jfr/recorder/storage/jfrBuffer.hpp" #include "jfr/utilities/jfrHashtable.hpp" #include "jfr/utilities/jfrTypes.hpp" +#include "jfr/writers/jfrTypeWriterHost.hpp" #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" -#include "memory/resourceArea.hpp" #include "utilities/accessFlags.hpp" -// incremented on each checkpoint -static u8 checkpoint_id = 0; - -// creates a unique id by combining a checkpoint relative symbol id (2^24) -// with the current checkpoint id (2^40) -#define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id))) - typedef const Klass* KlassPtr; typedef const PackageEntry* PkgPtr; typedef const ModuleEntry* ModPtr; @@ -63,57 +53,112 @@ typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr; typedef const JfrSymbolId::CStringEntry* CStringEntryPtr; -static traceid module_id(PkgPtr pkg) { - assert(pkg != NULL, "invariant"); - ModPtr module_entry = pkg->module(); - return module_entry != NULL && module_entry->is_named() ? TRACE_ID(module_entry) : 0; +static JfrCheckpointWriter* _writer = NULL; +static JfrCheckpointWriter* _leakp_writer = NULL; +static JfrArtifactSet* _artifacts = NULL; +static JfrArtifactClosure* _subsystem_callback = NULL; +static bool _class_unload = false; +static bool _flushpoint = false; + +// incremented on each rotation +static u8 checkpoint_id = 1; + +// creates a unique id by combining a checkpoint relative symbol id (2^24) +// with the current checkpoint id (2^40) +#define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id))) + +static traceid create_symbol_id(traceid artifact_id) { + return artifact_id != 0 ? CREATE_SYMBOL_ID(artifact_id) : 0; +} + +static bool current_epoch() { + return _class_unload; } -static traceid package_id(KlassPtr klass) { - assert(klass != NULL, "invariant"); - PkgPtr pkg_entry = klass->package(); - return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry); +static bool previous_epoch() { + return !current_epoch(); +} + +static bool is_complete() { + return !_artifacts->has_klass_entries() && current_epoch(); +} + +static traceid mark_symbol(KlassPtr klass, bool leakp) { + return klass != NULL ? create_symbol_id(_artifacts->mark(klass, leakp)) : 0; } -static traceid cld_id(CldPtr cld) { - assert(cld != NULL, "invariant"); - return cld->is_unsafe_anonymous() ? 0 : TRACE_ID(cld); +static traceid mark_symbol(Symbol* symbol, bool leakp) { + return symbol != NULL ? create_symbol_id(_artifacts->mark(symbol, leakp)) : 0; +} + +static traceid get_bootstrap_name(bool leakp) { + return create_symbol_id(_artifacts->bootstrap_name(leakp)); +} + +template +static traceid artifact_id(const T* ptr) { + assert(ptr != NULL, "invariant"); + return TRACE_ID(ptr); } -static void tag_leakp_klass_artifacts(KlassPtr k, bool class_unload) { - assert(k != NULL, "invariant"); - PkgPtr pkg = k->package(); - if (pkg != NULL) { - tag_leakp_artifact(pkg, class_unload); - ModPtr module = pkg->module(); - if (module != NULL) { - tag_leakp_artifact(module, class_unload); - } +static traceid package_id(KlassPtr klass, bool leakp) { + assert(klass != NULL, "invariant"); + PkgPtr pkg_entry = klass->package(); + if (pkg_entry == NULL) { + return 0; + } + if (leakp) { + SET_LEAKP(pkg_entry); } - CldPtr cld = k->class_loader_data(); - assert(cld != NULL, "invariant"); - if (!cld->is_unsafe_anonymous()) { - tag_leakp_artifact(cld, class_unload); + // package implicitly tagged already + return artifact_id(pkg_entry); +} + +static traceid module_id(PkgPtr pkg, bool leakp) { + assert(pkg != NULL, "invariant"); + ModPtr module_entry = pkg->module(); + if (module_entry == NULL || !module_entry->is_named()) { + return 0; } + if (leakp) { + SET_LEAKP(module_entry); + } else { + SET_TRANSIENT(module_entry); + } + return artifact_id(module_entry); } -class TagLeakpKlassArtifact { - bool _class_unload; - public: - TagLeakpKlassArtifact(bool class_unload) : _class_unload(class_unload) {} - bool operator()(KlassPtr klass) { - if (_class_unload) { - if (LEAKP_USED_THIS_EPOCH(klass)) { - tag_leakp_klass_artifacts(klass, _class_unload); - } - } else { - if (LEAKP_USED_PREV_EPOCH(klass)) { - tag_leakp_klass_artifacts(klass, _class_unload); - } - } - return true; +static traceid method_id(KlassPtr klass, MethodPtr method) { + assert(klass != NULL, "invariant"); + assert(method != NULL, "invariant"); + return METHOD_ID(klass, method); +} + +static traceid cld_id(CldPtr cld, bool leakp) { + assert(cld != NULL, "invariant"); + if (cld->is_unsafe_anonymous()) { + return 0; + } + if (leakp) { + SET_LEAKP(cld); + } else { + SET_TRANSIENT(cld); } -}; + return artifact_id(cld); +} + +template +static s4 get_flags(const T* ptr) { + assert(ptr != NULL, "invariant"); + return ptr->access_flags().get_flags(); +} + +template +static void set_serialized(const T* ptr) { + assert(ptr != NULL, "invariant"); + SET_SERIALIZED(ptr); + assert(IS_SERIALIZED(ptr), "invariant"); +} /* * In C++03, functions used as template parameters must have external linkage; @@ -123,11 +168,10 @@ * The weird naming is an effort to decrease the risk of name clashes. */ -int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) { +static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) { assert(writer != NULL, "invariant"); - assert(artifacts != NULL, "invariant"); - assert(k != NULL, "invariant"); - KlassPtr klass = (KlassPtr)k; + assert(_artifacts != NULL, "invariant"); + assert(klass != NULL, "invariant"); traceid pkg_id = 0; KlassPtr theklass = klass; if (theklass->is_objArray_klass()) { @@ -135,445 +179,167 @@ theklass = obj_arr_klass->bottom_klass(); } if (theklass->is_instance_klass()) { - pkg_id = package_id(theklass); + pkg_id = package_id(theklass, leakp); } else { assert(theklass->is_typeArray_klass(), "invariant"); } - const traceid symbol_id = artifacts->mark(klass); - assert(symbol_id > 0, "need to have an address for symbol!"); - writer->write(TRACE_ID(klass)); - writer->write(cld_id(klass->class_loader_data())); - writer->write((traceid)CREATE_SYMBOL_ID(symbol_id)); + writer->write(artifact_id(klass)); + writer->write(cld_id(klass->class_loader_data(), leakp)); + writer->write(mark_symbol(klass, leakp)); writer->write(pkg_id); - writer->write((s4)klass->access_flags().get_flags()); + writer->write(get_flags(klass)); return 1; } -typedef LeakPredicate LeakKlassPredicate; -typedef JfrPredicatedArtifactWriterImplHost LeakKlassWriterImpl; -typedef JfrArtifactWriterHost LeakKlassWriter; -typedef JfrArtifactWriterImplHost KlassWriterImpl; -typedef JfrArtifactWriterHost KlassWriter; +int write__klass(JfrCheckpointWriter* writer, const void* k) { + assert(k != NULL, "invariant"); + KlassPtr klass = (KlassPtr)k; + set_serialized(klass); + return write_klass(writer, klass, false); +} + +int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) { + assert(k != NULL, "invariant"); + KlassPtr klass = (KlassPtr)k; + return write_klass(writer, klass, true); +} + +static void do_implied(Klass* klass) { + assert(klass != NULL, "invariant"); + if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) { + if (_leakp_writer != NULL) { + SET_LEAKP(klass); + } + _subsystem_callback->do_artifact(klass); + } +} -int write__artifact__method(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) { - assert(writer != NULL, "invariant"); - assert(artifacts != NULL, "invariant"); - assert(m != NULL, "invariant"); - MethodPtr method = (MethodPtr)m; - const traceid method_name_symbol_id = artifacts->mark(method->name()); - assert(method_name_symbol_id > 0, "invariant"); - const traceid method_sig_symbol_id = artifacts->mark(method->signature()); - assert(method_sig_symbol_id > 0, "invariant"); - KlassPtr klass = method->method_holder(); +static void do_unloaded_klass(Klass* klass) { + assert(klass != NULL, "invariant"); + assert(_subsystem_callback != NULL, "invariant"); + if (IS_JDK_JFR_EVENT_SUBKLASS(klass)) { + JfrEventClasses::increment_unloaded_event_class(); + } + if (USED_THIS_EPOCH(klass)) { + ObjectSampleCheckpoint::on_klass_unload(klass); + _subsystem_callback->do_artifact(klass); + return; + } + do_implied(klass); +} + +static void do_klass(Klass* klass) { assert(klass != NULL, "invariant"); - assert(METHOD_USED_ANY_EPOCH(klass), "invariant"); - writer->write((u8)METHOD_ID(klass, method)); - writer->write((u8)TRACE_ID(klass)); - writer->write((u8)CREATE_SYMBOL_ID(method_name_symbol_id)); - writer->write((u8)CREATE_SYMBOL_ID(method_sig_symbol_id)); - writer->write((u2)method->access_flags().get_flags()); - writer->write(const_cast(method)->is_hidden() ? (u1)1 : (u1)0); - return 1; + assert(_subsystem_callback != NULL, "invariant"); + if (current_epoch()) { + if (USED_THIS_EPOCH(klass)) { + _subsystem_callback->do_artifact(klass); + return; + } + } else { + if (USED_PREV_EPOCH(klass)) { + _subsystem_callback->do_artifact(klass); + return; + } + } + do_implied(klass); +} + +static void do_klasses() { + if (_class_unload) { + ClassLoaderDataGraph::classes_unloading_do(&do_unloaded_klass); + return; + } + ClassLoaderDataGraph::classes_do(&do_klass); } -typedef JfrArtifactWriterImplHost MethodWriterImplTarget; -typedef JfrArtifactWriterHost MethodWriterImpl; +typedef SerializePredicate KlassPredicate; +typedef JfrPredicatedTypeWriterImplHost KlassWriterImpl; +typedef JfrTypeWriterHost KlassWriter; +typedef CompositeFunctor KlassWriterRegistration; +typedef JfrArtifactCallbackHost KlassCallback; + +typedef LeakPredicate LeakKlassPredicate; +typedef JfrPredicatedTypeWriterImplHost LeakKlassWriterImpl; +typedef JfrTypeWriterHost LeakKlassWriter; + +typedef CompositeFunctor CompositeKlassWriter; +typedef CompositeFunctor CompositeKlassWriterRegistration; +typedef JfrArtifactCallbackHost CompositeKlassCallback; -int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) { +static bool write_klasses() { + assert(!_artifacts->has_klass_entries(), "invariant"); + assert(_writer != NULL, "invariant"); + KlassArtifactRegistrator reg(_artifacts); + KlassWriter kw(_writer, _class_unload); + KlassWriterRegistration kwr(&kw, ®); + if (_leakp_writer == NULL) { + KlassCallback callback(&kwr); + _subsystem_callback = &callback; + do_klasses(); + } else { + LeakKlassWriter lkw(_leakp_writer, _artifacts, _class_unload); + CompositeKlassWriter ckw(&lkw, &kw); + CompositeKlassWriterRegistration ckwr(&ckw, ®); + CompositeKlassCallback callback(&ckwr); + _subsystem_callback = &callback; + do_klasses(); + } + if (is_complete()) { + return false; + } + _artifacts->tally(kw); + return true; +} + +template +static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) { + assert(callback != NULL, "invariant"); + assert(value != NULL, "invariant"); + if (USED_PREV_EPOCH(value)) { + callback->do_artifact(value); + assert(IS_NOT_SERIALIZED(value), "invariant"); + return; + } + if (IS_SERIALIZED(value)) { + CLEAR_SERIALIZED(value); + } + assert(IS_NOT_SERIALIZED(value), "invariant"); +} + +static int write_package(JfrCheckpointWriter* writer, PkgPtr pkg, bool leakp) { assert(writer != NULL, "invariant"); - assert(artifacts != NULL, "invariant"); - assert(p != NULL, "invariant"); - PkgPtr pkg = (PkgPtr)p; - Symbol* const pkg_name = pkg->name(); - const traceid package_name_symbol_id = pkg_name != NULL ? artifacts->mark(pkg_name) : 0; - assert(package_name_symbol_id > 0, "invariant"); - writer->write((traceid)TRACE_ID(pkg)); - writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id)); - writer->write(module_id(pkg)); + assert(_artifacts != NULL, "invariant"); + assert(pkg != NULL, "invariant"); + writer->write(artifact_id(pkg)); + writer->write(mark_symbol(pkg->name(), leakp)); + writer->write(module_id(pkg, leakp)); writer->write((bool)pkg->is_exported()); return 1; } -typedef LeakPredicate LeakPackagePredicate; -int _compare_pkg_ptr_(PkgPtr const& lhs, PkgPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; } -typedef UniquePredicate PackagePredicate; -typedef JfrPredicatedArtifactWriterImplHost LeakPackageWriterImpl; -typedef JfrPredicatedArtifactWriterImplHost PackageWriterImpl; -typedef JfrArtifactWriterHost LeakPackageWriter; -typedef JfrArtifactWriterHost PackageWriter; - -int write__artifact__module(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* m) { - assert( m != NULL, "invariant"); - ModPtr entry = (ModPtr)m; - Symbol* const module_name = entry->name(); - const traceid module_name_symbol_id = module_name != NULL ? artifacts->mark(module_name) : 0; - Symbol* const module_version = entry->version(); - const traceid module_version_symbol_id = module_version != NULL ? artifacts->mark(module_version) : 0; - Symbol* const module_location = entry->location(); - const traceid module_location_symbol_id = module_location != NULL ? artifacts->mark(module_location) : 0; - writer->write((traceid)TRACE_ID(entry)); - writer->write(module_name_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_name_symbol_id)); - writer->write(module_version_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_version_symbol_id)); - writer->write(module_location_symbol_id == 0 ? (traceid)0 : (traceid)CREATE_SYMBOL_ID(module_location_symbol_id)); - writer->write(cld_id(entry->loader_data())); - return 1; -} - -typedef LeakPredicate LeakModulePredicate; -int _compare_mod_ptr_(ModPtr const& lhs, ModPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; } -typedef UniquePredicate ModulePredicate; -typedef JfrPredicatedArtifactWriterImplHost LeakModuleWriterImpl; -typedef JfrPredicatedArtifactWriterImplHost ModuleWriterImpl; -typedef JfrArtifactWriterHost LeakModuleWriter; -typedef JfrArtifactWriterHost ModuleWriter; - -int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) { - assert(c != NULL, "invariant"); - CldPtr cld = (CldPtr)c; - assert(!cld->is_unsafe_anonymous(), "invariant"); - const traceid cld_id = TRACE_ID(cld); - // class loader type - const Klass* class_loader_klass = cld->class_loader_klass(); - if (class_loader_klass == NULL) { - // (primordial) boot class loader - writer->write(cld_id); // class loader instance id - writer->write((traceid)0); // class loader type id (absence of) - writer->write((traceid)CREATE_SYMBOL_ID(1)); // 1 maps to synthetic name -> "bootstrap" - } else { - Symbol* symbol_name = cld->name(); - const traceid symbol_name_id = symbol_name != NULL ? artifacts->mark(symbol_name) : 0; - writer->write(cld_id); // class loader instance id - writer->write(TRACE_ID(class_loader_klass)); // class loader type id - writer->write(symbol_name_id == 0 ? (traceid)0 : - (traceid)CREATE_SYMBOL_ID(symbol_name_id)); // class loader instance name - } - return 1; -} - -typedef LeakPredicate LeakCldPredicate; -int _compare_cld_ptr_(CldPtr const& lhs, CldPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; } -typedef UniquePredicate CldPredicate; -typedef JfrPredicatedArtifactWriterImplHost LeakCldWriterImpl; -typedef JfrPredicatedArtifactWriterImplHost CldWriterImpl; -typedef JfrArtifactWriterHost LeakCldWriter; -typedef JfrArtifactWriterHost CldWriter; - -typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr; - -static int write__artifact__symbol__entry__(JfrCheckpointWriter* writer, - SymbolEntryPtr entry) { - assert(writer != NULL, "invariant"); - assert(entry != NULL, "invariant"); - ResourceMark rm; - writer->write(CREATE_SYMBOL_ID(entry->id())); - writer->write(entry->value()->as_C_string()); - return 1; -} - -int write__artifact__symbol__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) { - assert(e != NULL, "invariant"); - return write__artifact__symbol__entry__(writer, (SymbolEntryPtr)e); -} - -typedef JfrArtifactWriterImplHost SymbolEntryWriterImpl; -typedef JfrArtifactWriterHost SymbolEntryWriter; - -typedef const JfrSymbolId::CStringEntry* CStringEntryPtr; - -static int write__artifact__cstring__entry__(JfrCheckpointWriter* writer, CStringEntryPtr entry) { - assert(writer != NULL, "invariant"); - assert(entry != NULL, "invariant"); - writer->write(CREATE_SYMBOL_ID(entry->id())); - writer->write(entry->value()); - return 1; -} - -int write__artifact__cstring__entry(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* e) { - assert(e != NULL, "invariant"); - return write__artifact__cstring__entry__(writer, (CStringEntryPtr)e); -} - -typedef JfrArtifactWriterImplHost CStringEntryWriterImpl; -typedef JfrArtifactWriterHost CStringEntryWriter; - -int write__artifact__klass__symbol(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) { - assert(writer != NULL, "invariant"); - assert(artifacts != NULL, "invaiant"); - assert(k != NULL, "invariant"); - const InstanceKlass* const ik = (const InstanceKlass*)k; - if (ik->is_unsafe_anonymous()) { - CStringEntryPtr entry = - artifacts->map_cstring(JfrSymbolId::unsafe_anonymous_klass_name_hash_code(ik)); - assert(entry != NULL, "invariant"); - return write__artifact__cstring__entry__(writer, entry); - } - - SymbolEntryPtr entry = artifacts->map_symbol(JfrSymbolId::regular_klass_name_hash_code(ik)); - return write__artifact__symbol__entry__(writer, entry); -} - -int _compare_traceid_(const traceid& lhs, const traceid& rhs) { - return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; +int write__package(JfrCheckpointWriter* writer, const void* p) { + assert(p != NULL, "invariant"); + PkgPtr pkg = (PkgPtr)p; + set_serialized(pkg); + return write_package(writer, pkg, false); } -template