--- old/src/share/vm/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp 2021-07-05 14:05:59.665147100 +0000 +++ new/src/share/vm/jfr/recorder/stacktrace/jfrStackTraceRepository.cpp 2021-07-05 14:05:59.601146148 +0000 @@ -83,26 +83,42 @@ } static JfrStackTraceRepository* _instance = NULL; +static JfrStackTraceRepository* _leak_profiler_instance = NULL; +static traceid _next_id = 0; JfrStackTraceRepository& JfrStackTraceRepository::instance() { + assert(_instance != NULL, "invariant"); return *_instance; } +JfrStackTraceRepository& JfrStackTraceRepository::leak_profiler_instance() { + assert(_leak_profiler_instance != NULL, "invariant"); + return *_leak_profiler_instance; +} + JfrStackTraceRepository* JfrStackTraceRepository::create() { assert(_instance == NULL, "invariant"); + assert(_leak_profiler_instance == NULL, "invariant"); + _leak_profiler_instance = new JfrStackTraceRepository(); + if (_leak_profiler_instance == NULL) { + return NULL; + } _instance = new JfrStackTraceRepository(); return _instance; } void JfrStackTraceRepository::destroy() { - assert(_instance != NULL, "invarinat"); + assert(_instance != NULL, "invariant"); delete _instance; _instance = NULL; + delete _leak_profiler_instance; + _leak_profiler_instance = NULL; } -JfrStackTraceRepository::JfrStackTraceRepository() : _next_id(0), _entries(0) { +JfrStackTraceRepository::JfrStackTraceRepository() : _entries(0) { memset(_table, 0, sizeof(_table)); } + class JfrFrameType : public JfrSerializer { public: void serialize(JfrCheckpointWriter& writer) { @@ -122,22 +138,22 @@ return JfrSerializer::register_serializer(TYPE_FRAMETYPE, false, true, new JfrFrameType()); } -size_t JfrStackTraceRepository::clear() { +size_t JfrStackTraceRepository::clear(JfrStackTraceRepository& repo) { MutexLockerEx lock(JfrStacktrace_lock, Mutex::_no_safepoint_check_flag); - if (_entries == 0) { + if (repo._entries == 0) { return 0; } for (u4 i = 0; i < TABLE_SIZE; ++i) { - JfrStackTraceRepository::StackTrace* stacktrace = _table[i]; + JfrStackTraceRepository::StackTrace* stacktrace = repo._table[i]; while (stacktrace != NULL) { JfrStackTraceRepository::StackTrace* next = stacktrace->next(); delete stacktrace; stacktrace = next; } } - memset(_table, 0, sizeof(_table)); - const size_t processed = _entries; - _entries = 0; + memset(repo._table, 0, sizeof(repo._table)); + const size_t processed = repo._entries; + repo._entries = 0; return processed; } @@ -163,16 +179,39 @@ return id; } -traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) { - traceid tid = instance().add_trace(stacktrace); +traceid JfrStackTraceRepository::add(JfrStackTraceRepository& repo, const JfrStackTrace& stacktrace) { + traceid tid = repo.add_trace(stacktrace); if (tid == 0) { stacktrace.resolve_linenos(); - tid = instance().add_trace(stacktrace); + tid = repo.add_trace(stacktrace); } assert(tid != 0, "invariant"); return tid; } +traceid JfrStackTraceRepository::add(const JfrStackTrace& stacktrace) { + return add(instance(), stacktrace); +} + +void JfrStackTraceRepository::record_for_leak_profiler(JavaThread* thread, JfrStackTrace* stacktrace, int skip /* 0 */) { + //assert(stacktrace != NULL, "invariant"); + //assert(stacktrace->hash() != 0, "invariant"); + //const traceid stacktrace_id = JfrStackTraceRepository::add_for_leak_profiler(stacktrace, thread); + //thread->jfr_thread_local()->set_cached_stack_trace_id(stacktrace_id, stacktrace->hash()); + //return stacktrace_id; + + assert(thread != NULL, "invariant"); + JfrThreadLocal* const tl = thread->jfr_thread_local(); + assert(tl != NULL, "invariant"); + assert(!tl->has_cached_stack_trace(), "invariant"); + const unsigned int hash = stacktrace->hash(); + if (hash != 0) { + traceid t = add(leak_profiler_instance(), *stacktrace); + //tty->print_cr("jfrStackTraceRepository.cpp | Add stack traceid %ld", t); + tl->set_cached_stack_trace_id(t, hash); + } +} + traceid JfrStackTraceRepository::record(Thread* thread, int skip /* 0 */) { assert(thread == Thread::current(), "invariant"); JfrThreadLocal* const tl = thread->jfr_thread_local(); @@ -198,11 +237,11 @@ return stacktrace.record_safe(thread, skip) ? add(stacktrace) : 0; } -traceid JfrStackTraceRepository::add(const JfrStackTrace* stacktrace, JavaThread* thread) { +traceid JfrStackTraceRepository::add_for_leak_profiler(const JfrStackTrace* stacktrace, JavaThread* thread) { assert(stacktrace != NULL, "invariant"); assert(thread != NULL, "invariant"); assert(stacktrace->hash() != 0, "invariant"); - return add(*stacktrace); + return add(leak_profiler_instance(), *stacktrace); } bool JfrStackTraceRepository::fill_stacktrace_for(JavaThread* thread, JfrStackTrace* stacktrace, int skip) { @@ -247,9 +286,9 @@ return _entries > 0 ? write_impl(sw, clear) : 0; } -traceid JfrStackTraceRepository::write(JfrCheckpointWriter& writer, traceid id, unsigned int hash) { +traceid JfrStackTraceRepository::write_for_leak_profiler(JfrCheckpointWriter& writer, traceid id, unsigned int hash) { assert(JfrStacktrace_lock->owned_by_self(), "invariant"); - const StackTrace* const trace = resolve_entry(hash, id); + const StackTrace* const trace = lookup_for_leak_profiler(hash, id); assert(trace != NULL, "invariant"); assert(trace->hash() == hash, "invariant"); assert(trace->id() == id, "invariant"); @@ -309,6 +348,15 @@ write_stacktrace(cpw, _id, _reached_root, _nr_of_frames, _frames); } +void JfrStackTraceRepository::clear_leak_profiler() { + clear(leak_profiler_instance()); +} + +size_t JfrStackTraceRepository::clear() { + clear_leak_profiler(); + return clear(instance()); +} + // JfrStackFrame bool JfrStackFrame::equals(const JfrStackFrame& rhs) const { @@ -332,9 +380,9 @@ } // invariant is that the entry to be resolved actually exists in the table -const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::resolve_entry(unsigned int hash, traceid id) const { +const JfrStackTraceRepository::StackTrace* JfrStackTraceRepository::lookup_for_leak_profiler(unsigned int hash, traceid id) { const size_t index = (hash % TABLE_SIZE); - const StackTrace* trace = _table[index]; + const StackTrace* trace = leak_profiler_instance()._table[index]; while (trace != NULL && trace->id() != id) { trace = trace->next(); }