提交 c6607dbc 编写于 作者: D Denghui Dong 提交者: D-D-H

[Backport] 8231081: TestMetadataRetention fails due to missing symbol id

Summary:

Test Plan: jdk/jfr

Reviewed-by: yuleil

Issue: https://github.com/alibaba/dragonwell8/issues/112
上级 09121154
...@@ -24,15 +24,18 @@ ...@@ -24,15 +24,18 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/javaClasses.hpp" #include "classfile/javaClasses.hpp"
#include "jfr/recorder/jfrRecorder.hpp" #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointManager.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp" #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp"
#include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp" #include "jfr/recorder/checkpoint/types/traceid/jfrTraceIdEpoch.hpp"
#include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/recorder/service/jfrOptionSet.hpp" #include "jfr/recorder/service/jfrOptionSet.hpp"
#include "jfr/recorder/storage/jfrMemorySpace.inline.hpp" #include "jfr/recorder/storage/jfrMemorySpace.inline.hpp"
#include "jfr/recorder/storage/jfrStorageUtils.inline.hpp" #include "jfr/recorder/storage/jfrStorageUtils.inline.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/utilities/jfrBigEndian.hpp" #include "jfr/utilities/jfrBigEndian.hpp"
#include "jfr/utilities/jfrTypes.hpp" #include "jfr/utilities/jfrTypes.hpp"
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
...@@ -80,7 +83,7 @@ JfrCheckpointManager::~JfrCheckpointManager() { ...@@ -80,7 +83,7 @@ JfrCheckpointManager::~JfrCheckpointManager() {
if (_lock != NULL) { if (_lock != NULL) {
delete _lock; delete _lock;
} }
JfrTypeManager::clear(); JfrTypeManager::destroy();
} }
static const size_t unlimited_mspace_size = 0; static const size_t unlimited_mspace_size = 0;
...@@ -332,6 +335,7 @@ size_t JfrCheckpointManager::write_epoch_transition_mspace() { ...@@ -332,6 +335,7 @@ size_t JfrCheckpointManager::write_epoch_transition_mspace() {
typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation; typedef DiscardOp<DefaultDiscarder<JfrBuffer> > DiscardOperation;
size_t JfrCheckpointManager::clear() { size_t JfrCheckpointManager::clear() {
JfrTypeSet::clear();
DiscardOperation discarder(mutexed); // mutexed discard mode DiscardOperation discarder(mutexed); // mutexed discard mode
process_free_list(discarder, _free_list_mspace); process_free_list(discarder, _free_list_mspace);
process_free_list(discarder, _epoch_transition_mspace); process_free_list(discarder, _epoch_transition_mspace);
...@@ -353,12 +357,35 @@ size_t JfrCheckpointManager::write_safepoint_types() { ...@@ -353,12 +357,35 @@ size_t JfrCheckpointManager::write_safepoint_types() {
} }
void JfrCheckpointManager::write_type_set() { void JfrCheckpointManager::write_type_set() {
JfrTypeManager::write_type_set(); assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
// can safepoint here
// TODO: CLDG lock does not exist in 11 - what shall we do?
// MutexLocker cld_lock(ClassLoaderDataGraph_lock);
MutexLocker package_table_lock(PackageTable_lock);
if (!LeakProfiler::is_running()) {
JfrCheckpointWriter writer(true, true, Thread::current());
JfrTypeSet::serialize(&writer, NULL, false);
return;
}
Thread* const t = Thread::current();
JfrCheckpointWriter leakp_writer(false, true, t);
JfrCheckpointWriter writer(false, true, t);
JfrTypeSet::serialize(&writer, &leakp_writer, false);
ObjectSampleCheckpoint::on_type_set(leakp_writer);
} }
void JfrCheckpointManager::write_type_set_for_unloaded_classes() { void JfrCheckpointManager::write_type_set_for_unloaded_classes() {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!"); assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
JfrTypeManager::write_type_set_for_unloaded_classes(); JfrCheckpointWriter writer(false, true, Thread::current());
const JfrCheckpointContext ctx = writer.context();
JfrTypeSet::serialize(&writer, NULL, true);
if (LeakProfiler::is_running()) {
ObjectSampleCheckpoint::on_type_set_unload(writer);
}
if (!JfrRecorder::is_recording()) {
// discard by rewind
writer.set_context(ctx);
}
} }
void JfrCheckpointManager::create_thread_blob(JavaThread* jt) { void JfrCheckpointManager::create_thread_blob(JavaThread* jt) {
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include "jfr/recorder/jfrRecorder.hpp" #include "jfr/recorder/jfrRecorder.hpp"
#include "jfr/recorder/checkpoint/types/jfrThreadGroup.hpp" #include "jfr/recorder/checkpoint/types/jfrThreadGroup.hpp"
#include "jfr/recorder/checkpoint/types/jfrThreadState.hpp" #include "jfr/recorder/checkpoint/types/jfrThreadState.hpp"
#include "jfr/recorder/checkpoint/types/jfrTypeSet.hpp"
#include "jfr/support/jfrThreadLocal.hpp" #include "jfr/support/jfrThreadLocal.hpp"
#include "jfr/writers/jfrJavaEventWriter.hpp" #include "jfr/writers/jfrJavaEventWriter.hpp"
#include "memory/metaspaceGCThresholdUpdater.hpp" #include "memory/metaspaceGCThresholdUpdater.hpp"
...@@ -292,30 +291,6 @@ void VMOperationTypeConstant::serialize(JfrCheckpointWriter& writer) { ...@@ -292,30 +291,6 @@ void VMOperationTypeConstant::serialize(JfrCheckpointWriter& writer) {
} }
} }
class TypeSetSerialization {
private:
JfrCheckpointWriter* _leakp_writer;
bool _class_unload;
public:
TypeSetSerialization(bool class_unload, JfrCheckpointWriter* leakp_writer = NULL) :
_leakp_writer(leakp_writer), _class_unload(class_unload) {}
void write(JfrCheckpointWriter& writer) {
JfrTypeSet::serialize(&writer, _leakp_writer, _class_unload);
}
};
void ClassUnloadTypeSet::serialize(JfrCheckpointWriter& writer) {
TypeSetSerialization type_set(true);
type_set.write(writer);
};
TypeSet::TypeSet(JfrCheckpointWriter* leakp_writer) : _leakp_writer(leakp_writer) {}
void TypeSet::serialize(JfrCheckpointWriter& writer) {
TypeSetSerialization type_set(false, _leakp_writer);
type_set.write(writer);
};
void ThreadStateConstant::serialize(JfrCheckpointWriter& writer) { void ThreadStateConstant::serialize(JfrCheckpointWriter& writer) {
JfrThreadState::serialize(writer); JfrThreadState::serialize(writer);
} }
......
...@@ -37,11 +37,6 @@ class JfrThreadGroupConstant : public JfrSerializer { ...@@ -37,11 +37,6 @@ class JfrThreadGroupConstant : public JfrSerializer {
void serialize(JfrCheckpointWriter& writer); void serialize(JfrCheckpointWriter& writer);
}; };
class ClassUnloadTypeSet : public JfrSerializer {
public:
void serialize(JfrCheckpointWriter& writer);
};
class FlagValueOriginConstant : public JfrSerializer { class FlagValueOriginConstant : public JfrSerializer {
public: public:
void serialize(JfrCheckpointWriter& writer); void serialize(JfrCheckpointWriter& writer);
...@@ -117,14 +112,6 @@ class VMOperationTypeConstant : public JfrSerializer { ...@@ -117,14 +112,6 @@ class VMOperationTypeConstant : public JfrSerializer {
void serialize(JfrCheckpointWriter& writer); void serialize(JfrCheckpointWriter& writer);
}; };
class TypeSet : public JfrSerializer {
private:
JfrCheckpointWriter* _leakp_writer;
public:
explicit TypeSet(JfrCheckpointWriter* leakp_writer = NULL);
void serialize(JfrCheckpointWriter& writer);
};
class ThreadStateConstant : public JfrSerializer { class ThreadStateConstant : public JfrSerializer {
public: public:
void serialize(JfrCheckpointWriter& writer); void serialize(JfrCheckpointWriter& writer);
......
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
*/ */
#include "precompiled.hpp" #include "precompiled.hpp"
#include "jfr/jfr.hpp"
#include "jfr/leakprofiler/leakProfiler.hpp"
#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
#include "jfr/metadata/jfrSerializer.hpp" #include "jfr/metadata/jfrSerializer.hpp"
#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
#include "jfr/recorder/checkpoint/types/jfrType.hpp" #include "jfr/recorder/checkpoint/types/jfrType.hpp"
...@@ -35,9 +32,9 @@ ...@@ -35,9 +32,9 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "runtime/handles.inline.hpp" #include "runtime/handles.inline.hpp"
#include "runtime/safepoint.hpp" #include "runtime/safepoint.hpp"
#include "runtime/semaphore.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "utilities/exceptions.hpp" #include "utilities/exceptions.hpp"
#include "runtime/semaphore.hpp"
class JfrSerializerRegistration : public JfrCHeapObj { class JfrSerializerRegistration : public JfrCHeapObj {
private: private:
...@@ -120,7 +117,7 @@ typedef StopOnNullIterator<const List> Iterator; ...@@ -120,7 +117,7 @@ typedef StopOnNullIterator<const List> Iterator;
static List types; static List types;
static List safepoint_types; static List safepoint_types;
void JfrTypeManager::clear() { void JfrTypeManager::destroy() {
SerializerRegistrationGuard guard; SerializerRegistrationGuard guard;
Iterator iter(types); Iterator iter(types);
JfrSerializerRegistration* registration; JfrSerializerRegistration* registration;
...@@ -152,38 +149,6 @@ void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) { ...@@ -152,38 +149,6 @@ void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) {
} }
} }
void JfrTypeManager::write_type_set() {
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
// can safepoint here
MutexLocker module_lock(PackageTable_lock);
if (!LeakProfiler::is_running()) {
JfrCheckpointWriter writer(true, true, Thread::current());
TypeSet set;
set.serialize(writer);
return;
}
JfrCheckpointWriter leakp_writer(false, true, Thread::current());
JfrCheckpointWriter writer(false, true, Thread::current());
TypeSet set(&leakp_writer);
set.serialize(writer);
ObjectSampleCheckpoint::on_type_set(leakp_writer);
}
void JfrTypeManager::write_type_set_for_unloaded_classes() {
assert(SafepointSynchronize::is_at_safepoint(), "invariant");
JfrCheckpointWriter writer(false, true, Thread::current());
const JfrCheckpointContext ctx = writer.context();
ClassUnloadTypeSet class_unload_set;
class_unload_set.serialize(writer);
if (LeakProfiler::is_running()) {
ObjectSampleCheckpoint::on_type_set_unload(writer);
}
if (!Jfr::is_recording()) {
// discard anything written
writer.set_context(ctx);
}
}
void JfrTypeManager::create_thread_blob(JavaThread* jt) { void JfrTypeManager::create_thread_blob(JavaThread* jt) {
assert(jt != NULL, "invariant"); assert(jt != NULL, "invariant");
ResourceMark rm(jt); ResourceMark rm(jt);
......
...@@ -32,11 +32,9 @@ class JfrCheckpointWriter; ...@@ -32,11 +32,9 @@ class JfrCheckpointWriter;
class JfrTypeManager : public AllStatic { class JfrTypeManager : public AllStatic {
public: public:
static bool initialize(); static bool initialize();
static void clear(); static void destroy();
static void write_types(JfrCheckpointWriter& writer); static void write_types(JfrCheckpointWriter& writer);
static void write_safepoint_types(JfrCheckpointWriter& writer); static void write_safepoint_types(JfrCheckpointWriter& writer);
static void write_type_set();
static void write_type_set_for_unloaded_classes();
static void create_thread_blob(JavaThread* jt); static void create_thread_blob(JavaThread* jt);
static void write_thread_checkpoint(JavaThread* jt); static void write_thread_checkpoint(JavaThread* jt);
}; };
......
...@@ -108,7 +108,6 @@ inline uintptr_t package_name_hash(const char *s) { ...@@ -108,7 +108,6 @@ inline uintptr_t package_name_hash(const char *s) {
return val; return val;
} }
/**
static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) { static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) {
assert(klass != NULL, "invariant"); assert(klass != NULL, "invariant");
char* klass_name = klass->name()->as_C_string(); // uses ResourceMark declared in JfrTypeSet::serialize() char* klass_name = klass->name()->as_C_string(); // uses ResourceMark declared in JfrTypeSet::serialize()
...@@ -118,7 +117,6 @@ static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) { ...@@ -118,7 +117,6 @@ static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) {
} }
return CREATE_PACKAGE_ID(artifacts->markPackage(pkg_name, package_name_hash(pkg_name))); return CREATE_PACKAGE_ID(artifacts->markPackage(pkg_name, package_name_hash(pkg_name)));
} }
*/
static traceid method_id(KlassPtr klass, MethodPtr method) { static traceid method_id(KlassPtr klass, MethodPtr method) {
assert(klass != NULL, "invariant"); assert(klass != NULL, "invariant");
...@@ -170,8 +168,7 @@ static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp) ...@@ -170,8 +168,7 @@ static int write_klass(JfrCheckpointWriter* writer, KlassPtr klass, bool leakp)
theklass = obj_arr_klass->bottom_klass(); theklass = obj_arr_klass->bottom_klass();
} }
if (theklass->oop_is_instance()) { if (theklass->oop_is_instance()) {
// pkg_id = package_id(theklass, _artifacts); pkg_id = package_id(theklass, _artifacts);
pkg_id = 0;
} else { } else {
assert(theklass->oop_is_typeArray(), "invariant"); assert(theklass->oop_is_typeArray(), "invariant");
} }
...@@ -206,9 +203,14 @@ int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) { ...@@ -206,9 +203,14 @@ int write__klass__leakp(JfrCheckpointWriter* writer, const void* k) {
return write_klass(writer, klass, true); return write_klass(writer, klass, true);
} }
static bool is_implied(const Klass* klass) {
assert(klass != NULL, "invariant");
return klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass();
}
static void do_implied(Klass* klass) { static void do_implied(Klass* klass) {
assert(klass != NULL, "invariant"); assert(klass != NULL, "invariant");
if (klass->is_subclass_of(SystemDictionary::ClassLoader_klass()) || klass == SystemDictionary::Object_klass()) { if (is_implied(klass)) {
if (_leakp_writer != NULL) { if (_leakp_writer != NULL) {
SET_LEAKP(klass); SET_LEAKP(klass);
} }
...@@ -261,6 +263,16 @@ typedef JfrTypeWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter; ...@@ -261,6 +263,16 @@ typedef JfrTypeWriterHost<KlassWriterImpl, TYPE_CLASS> KlassWriter;
typedef CompositeFunctor<KlassPtr, KlassWriter, KlassArtifactRegistrator> KlassWriterRegistration; typedef CompositeFunctor<KlassPtr, KlassWriter, KlassArtifactRegistrator> KlassWriterRegistration;
typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback; typedef JfrArtifactCallbackHost<KlassPtr, KlassWriterRegistration> KlassCallback;
template <>
class LeakPredicate<const Klass*> {
public:
LeakPredicate(bool class_unload) {}
bool operator()(const Klass* klass) {
assert(klass != NULL, "invariant");
return IS_LEAKP(klass) || is_implied(klass);
}
};
typedef LeakPredicate<KlassPtr> LeakKlassPredicate; typedef LeakPredicate<KlassPtr> LeakKlassPredicate;
typedef JfrPredicatedTypeWriterImplHost<KlassPtr, LeakKlassPredicate, write__klass__leakp> LeakKlassWriterImpl; typedef JfrPredicatedTypeWriterImplHost<KlassPtr, LeakKlassPredicate, write__klass__leakp> LeakKlassWriterImpl;
typedef JfrTypeWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter; typedef JfrTypeWriterHost<LeakKlassWriterImpl, TYPE_CLASS> LeakKlassWriter;
...@@ -308,7 +320,6 @@ int write__artifact__package(JfrCheckpointWriter* writer, const void* p) { ...@@ -308,7 +320,6 @@ int write__artifact__package(JfrCheckpointWriter* writer, const void* p) {
return 1; return 1;
} }
/**
typedef JfrTypeWriterImplHost<CStringEntryPtr, write__artifact__package> PackageEntryWriterImpl; typedef JfrTypeWriterImplHost<CStringEntryPtr, write__artifact__package> PackageEntryWriterImpl;
typedef JfrTypeWriterHost<PackageEntryWriterImpl, TYPE_PACKAGE> PackageEntryWriter; typedef JfrTypeWriterHost<PackageEntryWriterImpl, TYPE_PACKAGE> PackageEntryWriter;
...@@ -318,7 +329,6 @@ void write_packages() { ...@@ -318,7 +329,6 @@ void write_packages() {
PackageEntryWriter pw(_writer, _class_unload); PackageEntryWriter pw(_writer, _class_unload);
_artifacts->iterate_packages(pw); _artifacts->iterate_packages(pw);
} }
*/
template <typename T> template <typename T>
static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) { static void do_previous_epoch_artifact(JfrArtifactClosure* callback, T* value) {
...@@ -657,6 +667,12 @@ static void write_symbols() { ...@@ -657,6 +667,12 @@ static void write_symbols() {
_artifacts->tally(sw); _artifacts->tally(sw);
} }
static bool clear_artifacts = false;
void JfrTypeSet::clear() {
clear_artifacts = true;
}
typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits; typedef Wrapper<KlassPtr, ClearArtifact> ClearKlassBits;
typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag; typedef Wrapper<MethodPtr, ClearArtifact> ClearMethodFlag;
typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, false> ClearKlassAndMethods; typedef MethodIteratorHost<ClearMethodFlag, ClearKlassBits, false> ClearKlassAndMethods;
...@@ -668,7 +684,7 @@ static size_t teardown() { ...@@ -668,7 +684,7 @@ static size_t teardown() {
assert(_writer != NULL, "invariant"); assert(_writer != NULL, "invariant");
ClearKlassAndMethods clear(_writer); ClearKlassAndMethods clear(_writer);
_artifacts->iterate_klasses(clear); _artifacts->iterate_klasses(clear);
_artifacts->clear(); JfrTypeSet::clear();
++checkpoint_id; ++checkpoint_id;
} }
return total_count; return total_count;
...@@ -681,8 +697,9 @@ static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer ...@@ -681,8 +697,9 @@ static void setup(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer
if (_artifacts == NULL) { if (_artifacts == NULL) {
_artifacts = new JfrArtifactSet(class_unload); _artifacts = new JfrArtifactSet(class_unload);
} else { } else {
_artifacts->initialize(class_unload); _artifacts->initialize(class_unload, clear_artifacts);
} }
clear_artifacts = false;
assert(_artifacts != NULL, "invariant"); assert(_artifacts != NULL, "invariant");
assert(!_artifacts->has_klass_entries(), "invariant"); assert(!_artifacts->has_klass_entries(), "invariant");
} }
...@@ -699,7 +716,7 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l ...@@ -699,7 +716,7 @@ size_t JfrTypeSet::serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* l
if (!write_klasses()) { if (!write_klasses()) {
return 0; return 0;
} }
// write_packages(); write_packages();
write_classloaders(); write_classloaders();
write_methods(); write_methods();
write_symbols(); write_symbols();
......
...@@ -31,6 +31,7 @@ class JfrCheckpointWriter; ...@@ -31,6 +31,7 @@ class JfrCheckpointWriter;
class JfrTypeSet : AllStatic { class JfrTypeSet : AllStatic {
public: public:
static void clear();
static size_t serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload); static size_t serialize(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer, bool class_unload);
}; };
......
...@@ -36,6 +36,8 @@ JfrSymbolId::JfrSymbolId() : ...@@ -36,6 +36,8 @@ JfrSymbolId::JfrSymbolId() :
_pkg_table(new CStringTable(this)), _pkg_table(new CStringTable(this)),
_sym_list(NULL), _sym_list(NULL),
_cstring_list(NULL), _cstring_list(NULL),
_sym_query(NULL),
_cstring_query(NULL),
_symbol_id_counter(1), _symbol_id_counter(1),
_class_unload(false) { _class_unload(false) {
assert(_sym_table != NULL, "invariant"); assert(_sym_table != NULL, "invariant");
...@@ -74,9 +76,11 @@ void JfrSymbolId::clear() { ...@@ -74,9 +76,11 @@ void JfrSymbolId::clear() {
assert(!_pkg_table->has_entries(), "invariant"); assert(!_pkg_table->has_entries(), "invariant");
_sym_list = NULL; _sym_list = NULL;
_cstring_list = NULL;
_symbol_id_counter = 1; _symbol_id_counter = 1;
_sym_query = NULL;
_cstring_query = NULL;
assert(bootstrap != NULL, "invariant"); assert(bootstrap != NULL, "invariant");
bootstrap->reset(); bootstrap->reset();
_cstring_list = bootstrap; _cstring_list = bootstrap;
...@@ -96,10 +100,10 @@ void JfrSymbolId::on_link(const SymbolEntry* entry) { ...@@ -96,10 +100,10 @@ void JfrSymbolId::on_link(const SymbolEntry* entry) {
} }
bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) { bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) {
// query might be NULL
assert(entry != NULL, "invariant"); assert(entry != NULL, "invariant");
assert(entry->hash() == hash, "invariant"); assert(entry->hash() == hash, "invariant");
return true; assert(_sym_query != NULL, "invariant");
return _sym_query == entry->literal();
} }
void JfrSymbolId::on_unlink(const SymbolEntry* entry) { void JfrSymbolId::on_unlink(const SymbolEntry* entry) {
...@@ -107,18 +111,36 @@ void JfrSymbolId::on_unlink(const SymbolEntry* entry) { ...@@ -107,18 +111,36 @@ void JfrSymbolId::on_unlink(const SymbolEntry* entry) {
const_cast<Symbol*>(entry->literal())->decrement_refcount(); const_cast<Symbol*>(entry->literal())->decrement_refcount();
} }
static const char* resource_to_cstring(const char* resource_str) {
assert(resource_str != NULL, "invariant");
const size_t length = strlen(resource_str);
char* const c_string = JfrCHeapObj::new_array<char>(length + 1);
assert(c_string != NULL, "invariant");
strncpy(c_string, resource_str, length + 1);
return c_string;
}
void JfrSymbolId::on_link(const CStringEntry* entry) { void JfrSymbolId::on_link(const CStringEntry* entry) {
assert(entry != NULL, "invariant"); assert(entry != NULL, "invariant");
assert(entry->id() == 0, "invariant"); assert(entry->id() == 0, "invariant");
entry->set_id(++_symbol_id_counter); entry->set_id(++_symbol_id_counter);
const_cast<CStringEntry*>(entry)->set_literal(resource_to_cstring(entry->literal()));
entry->set_list_next(_cstring_list); entry->set_list_next(_cstring_list);
_cstring_list = entry; _cstring_list = entry;
} }
static bool string_compare(const char* query, const char* candidate) {
assert(query != NULL, "invariant");
assert(candidate != NULL, "invariant");
const size_t length = strlen(query);
return strncmp(query, candidate, length) == 0;
}
bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) { bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) {
assert(entry != NULL, "invariant"); assert(entry != NULL, "invariant");
assert(entry->hash() == hash, "invariant"); assert(entry->hash() == hash, "invariant");
return true; assert(_cstring_query != NULL, "invariant");
return string_compare(_cstring_query, entry->literal());
} }
void JfrSymbolId::on_unlink(const CStringEntry* entry) { void JfrSymbolId::on_unlink(const CStringEntry* entry) {
...@@ -139,16 +161,10 @@ traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { ...@@ -139,16 +161,10 @@ traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) {
return mark((uintptr_t)((Symbol*)symbol)->identity_hash(), symbol, leakp); return mark((uintptr_t)((Symbol*)symbol)->identity_hash(), symbol, leakp);
} }
static unsigned int last_symbol_hash = 0;
static traceid last_symbol_id = 0;
traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) {
assert(data != NULL, "invariant"); assert(data != NULL, "invariant");
assert(_sym_table != NULL, "invariant"); assert(_sym_table != NULL, "invariant");
if (hash == last_symbol_hash) { _sym_query = data;
assert(last_symbol_id != 0, "invariant");
return last_symbol_id;
}
const SymbolEntry& entry = _sym_table->lookup_put(hash, data); const SymbolEntry& entry = _sym_table->lookup_put(hash, data);
if (_class_unload) { if (_class_unload) {
entry.set_unloading(); entry.set_unloading();
...@@ -156,39 +172,24 @@ traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { ...@@ -156,39 +172,24 @@ traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) {
if (leakp) { if (leakp) {
entry.set_leakp(); entry.set_leakp();
} }
last_symbol_hash = hash; return entry.id();
last_symbol_id = entry.id();
return last_symbol_id;
} }
static unsigned int last_cstring_hash_for_pkg = 0;
static traceid last_cstring_id_for_pkg = 0;
static unsigned int last_cstring_hash = 0;
static traceid last_cstring_id = 0;
traceid JfrSymbolId::markPackage(const char* name, uintptr_t hash) { traceid JfrSymbolId::markPackage(const char* name, uintptr_t hash) {
assert(name != NULL, "invariant"); assert(name != NULL, "invariant");
assert(_pkg_table != NULL, "invariant"); assert(_pkg_table != NULL, "invariant");
if (hash == last_cstring_hash_for_pkg) { _cstring_query = name;
assert(last_cstring_id_for_pkg != 0, "invariant");
return last_cstring_id_for_pkg;
}
const CStringEntry& entry = _pkg_table->lookup_put(hash, name); const CStringEntry& entry = _pkg_table->lookup_put(hash, name);
if (_class_unload) { if (_class_unload) {
entry.set_unloading(); entry.set_unloading();
} }
last_cstring_hash_for_pkg = hash; return entry.id();
last_cstring_id_for_pkg = entry.id();
return last_cstring_id_for_pkg;
} }
traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) {
assert(str != NULL, "invariant"); assert(str != NULL, "invariant");
assert(_cstring_table != NULL, "invariant"); assert(_cstring_table != NULL, "invariant");
if (hash == last_cstring_hash) { _cstring_query = str;
assert(last_cstring_id != 0, "invariant");
return last_cstring_id;
}
const CStringEntry& entry = _cstring_table->lookup_put(hash, str); const CStringEntry& entry = _cstring_table->lookup_put(hash, str);
if (_class_unload) { if (_class_unload) {
entry.set_unloading(); entry.set_unloading();
...@@ -196,9 +197,7 @@ traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { ...@@ -196,9 +197,7 @@ traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) {
if (leakp) { if (leakp) {
entry.set_leakp(); entry.set_leakp();
} }
last_cstring_hash = hash; return entry.id();
last_cstring_id = entry.id();
return last_cstring_id;
} }
/* /*
...@@ -228,7 +227,7 @@ static const char* create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, ...@@ -228,7 +227,7 @@ static const char* create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik,
sprintf(hash_buf, "/" UINTX_FORMAT, hash); sprintf(hash_buf, "/" UINTX_FORMAT, hash);
const size_t hash_len = strlen(hash_buf); const size_t hash_len = strlen(hash_buf);
const size_t result_len = ik->name()->utf8_length(); const size_t result_len = ik->name()->utf8_length();
anonymous_symbol = JfrCHeapObj::new_array<char>(result_len + hash_len + 1); anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1);
assert(strlen(anonymous_symbol) == result_len, "invariant"); assert(strlen(anonymous_symbol) == result_len, "invariant");
strcpy(anonymous_symbol + result_len, hash_buf); strcpy(anonymous_symbol + result_len, hash_buf);
...@@ -241,21 +240,12 @@ bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { ...@@ -241,21 +240,12 @@ bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) {
return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous(); return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous();
} }
static unsigned int last_anonymous_hash = 0;
static traceid last_anonymous_id = 0;
traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) { traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) {
assert(ik != NULL, "invariant"); assert(ik != NULL, "invariant");
assert(ik->is_anonymous(), "invariant"); assert(ik->is_anonymous(), "invariant");
const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik);
if (hash == last_anonymous_hash) { const char* const anonymous_klass_symbol = create_unsafe_anonymous_klass_symbol(ik, hash);
assert(last_anonymous_id != 0, "invariant"); return mark(hash, anonymous_klass_symbol, leakp);
return last_anonymous_id;
}
last_anonymous_hash = hash;
const CStringEntry* const entry = _cstring_table->lookup_only(hash);
last_anonymous_id = entry != NULL ? entry->id() : mark(hash, create_unsafe_anonymous_klass_symbol(ik, hash), leakp);
return last_anonymous_id;
} }
traceid JfrSymbolId::mark(const Klass* k, bool leakp) { traceid JfrSymbolId::mark(const Klass* k, bool leakp) {
...@@ -275,13 +265,6 @@ traceid JfrSymbolId::mark(const Klass* k, bool leakp) { ...@@ -275,13 +265,6 @@ traceid JfrSymbolId::mark(const Klass* k, bool leakp) {
return symbol_id; return symbol_id;
} }
static void reset_symbol_caches() {
last_anonymous_hash = 0;
last_symbol_hash = 0;
last_cstring_hash = 0;
last_cstring_hash_for_pkg = 0;
}
JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
_klass_list(NULL), _klass_list(NULL),
_total_count(0) { _total_count(0) {
...@@ -291,8 +274,11 @@ JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId() ...@@ -291,8 +274,11 @@ JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()
static const size_t initial_class_list_size = 200; static const size_t initial_class_list_size = 200;
void JfrArtifactSet::initialize(bool class_unload) { void JfrArtifactSet::initialize(bool class_unload, bool clear /* false */) {
assert(_symbol_id != NULL, "invariant"); assert(_symbol_id != NULL, "invariant");
if (clear) {
_symbol_id->clear();
}
_symbol_id->set_class_unload(class_unload); _symbol_id->set_class_unload(class_unload);
_total_count = 0; _total_count = 0;
// resource allocation // resource allocation
...@@ -300,13 +286,8 @@ void JfrArtifactSet::initialize(bool class_unload) { ...@@ -300,13 +286,8 @@ void JfrArtifactSet::initialize(bool class_unload) {
} }
JfrArtifactSet::~JfrArtifactSet() { JfrArtifactSet::~JfrArtifactSet() {
clear();
delete _symbol_id;
}
void JfrArtifactSet::clear() {
reset_symbol_caches();
_symbol_id->clear(); _symbol_id->clear();
delete _symbol_id;
// _klass_list will be cleared by a ResourceMark // _klass_list will be cleared by a ResourceMark
} }
......
...@@ -228,6 +228,8 @@ class JfrSymbolId : public JfrCHeapObj { ...@@ -228,6 +228,8 @@ class JfrSymbolId : public JfrCHeapObj {
CStringTable* _pkg_table; CStringTable* _pkg_table;
const SymbolEntry* _sym_list; const SymbolEntry* _sym_list;
const CStringEntry* _cstring_list; const CStringEntry* _cstring_list;
const Symbol* _sym_query;
const char* _cstring_query;
traceid _symbol_id_counter; traceid _symbol_id_counter;
bool _class_unload; bool _class_unload;
...@@ -313,9 +315,7 @@ class JfrArtifactSet : public JfrCHeapObj { ...@@ -313,9 +315,7 @@ class JfrArtifactSet : public JfrCHeapObj {
~JfrArtifactSet(); ~JfrArtifactSet();
// caller needs ResourceMark // caller needs ResourceMark
void initialize(bool class_unload); void initialize(bool class_unload, bool clear = false);
void clear();
traceid mark(uintptr_t hash, const Symbol* sym, bool leakp); traceid mark(uintptr_t hash, const Symbol* sym, bool leakp);
traceid mark(const Klass* klass, bool leakp); traceid mark(const Klass* klass, bool leakp);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册