--- /dev/null 2017-11-09 09:38:01.297999907 +0100 +++ new/src/hotspot/share/jfr/recorder/checkpoint/constant/jfrTagSet.cpp 2018-04-09 14:59:27.628208558 +0200 @@ -0,0 +1,1001 @@ +/* + * Copyright (c) 2016, 2018, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "classfile/classLoaderData.inline.hpp" +#include "classfile/javaClasses.inline.hpp" +#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/recorder/checkpoint/constant/jfrTagSet.hpp" +#include "jfr/recorder/checkpoint/constant/jfrTagSetUtils.hpp" +#include "jfr/recorder/checkpoint/constant/jfrTagSetWriter.hpp" +#include "jfr/recorder/checkpoint/constant/traceid/jfrTraceId.inline.hpp" +#include "jfr/recorder/storage/jfrBuffer.hpp" +#include "jfr/utilities/jfrHashtable.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" +// to get CONTENT_TYPE defines +#include "tracefiles/traceTypes.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; +typedef const ClassLoaderData* CldPtr; +typedef const Method* MethodPtr; +typedef const Symbol* SymbolPtr; +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 traceid package_id(KlassPtr klass) { + assert(klass != NULL, "invariant"); + PkgPtr pkg_entry = klass->package(); + return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry); +} + +static traceid cld_id(CldPtr cld) { + assert(cld != NULL, "invariant"); + return cld->is_anonymous() ? 0 : TRACE_ID(cld); +} + +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); + } + } + CldPtr cld = k->class_loader_data(); + assert(cld != NULL, "invariant"); + if (!cld->is_anonymous()) { + tag_leakp_artifact(cld, class_unload); + } +} + +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; + } +}; + +/* + * In C++03, functions used as template parameters must have external linkage; + * this restriction was removed in C++11. Change back to "static" and + * rename functions when C++11 becomes available. + * + * The weird naming is an effort to decrease the risk of name clashes. + */ + +int write__artifact__klass(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* k) { + assert(writer != NULL, "invariant"); + assert(artifacts != NULL, "invariant"); + assert(k != NULL, "invariant"); + KlassPtr klass = (KlassPtr)k; + traceid pkg_id = 0; + KlassPtr theklass = klass; + if (theklass->is_objArray_klass()) { + const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast(klass); + theklass = obj_arr_klass->bottom_klass(); + } + if (theklass->is_instance_klass()) { + pkg_id = package_id(theklass); + } 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(pkg_id); + writer->write((s4)klass->access_flags().get_flags()); + return 1; +} + +typedef LeakPredicate LeakKlassPredicate; +typedef JfrPredicatedArtifactWriterImplHost LeakKlassWriterImpl; +typedef JfrArtifactWriterHost LeakKlassWriter; +typedef JfrArtifactWriterImplHost KlassWriterImpl; +typedef JfrArtifactWriterHost KlassWriter; + +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(); + 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; +} + +typedef JfrArtifactWriterImplHost MethodWriterImplTarget; +typedef JfrArtifactWriterHost MethodWriterImpl; + +int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) { + 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)); + 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_anonymous(), "invariant"); + const traceid cld_id = TRACE_ID(cld); + // class loader type + const oop class_loader_oop = cld->class_loader(); + if (class_loader_oop == 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 -> "boot" + return 1; + } + assert(class_loader_oop != NULL, "invariant"); + KlassPtr class_loader_klass = class_loader_oop->klass(); + traceid symbol_name_id = 0; + const oop class_loader_name_oop = java_lang_ClassLoader::name(class_loader_oop); + if (class_loader_name_oop != NULL) { + const char* class_loader_instance_name = + java_lang_String::as_utf8_string(class_loader_name_oop); + if (class_loader_instance_name != NULL && class_loader_instance_name[0] != '\0') { + // tag the symbol as "anonymous" since its not really a Symbol* but a const char*, + // it will be handled correctly if it has the anonymous tag on insertion + symbol_name_id = artifacts->mark(class_loader_instance_name, + java_lang_String::hash_code(class_loader_name_oop)); + } + } + 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_anonymous()) { + CStringEntryPtr entry = + artifacts->map_cstring(JfrSymbolId::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; +} + +template