--- /dev/null 2019-02-13 16:01:02.292000000 +0300 +++ new/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp 2019-02-15 19:03:15.421507863 +0300 @@ -0,0 +1,901 @@ +/* + * 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.hpp" +// XXX #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/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 "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; +// XXX typedef const PackageEntry* PkgPtr; +typedef const ClassLoaderData* CldPtr; +typedef const Method* MethodPtr; +typedef const Symbol* SymbolPtr; +typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr; +typedef const JfrSymbolId::CStringEntry* CStringEntryPtr; + +// XXX +// 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"); + // XXX + // PkgPtr pkg = k->package(); + // if (pkg != NULL) { + // tag_leakp_artifact(pkg, 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->oop_is_objArray()) { + const ObjArrayKlass* obj_arr_klass = ObjArrayKlass::cast((Klass*)klass); + theklass = obj_arr_klass->bottom_klass(); + } + if (theklass->oop_is_instance()) { + pkg_id = 0; // XXX package_id(theklass); + } else { + assert(theklass->oop_is_typeArray(), "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; + +// XXX +// 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((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__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 Klass* class_loader_klass = cld->class_loader() != NULL ? cld->class_loader()->klass() : NULL; + 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 = class_loader_klass->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_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