Thu, 15 Nov 2018 11:10:04 +0100
8210024: JFR calls virtual is_Java_thread from ~Thread()
Reviewed-by: kbarrett, dholmes, dcubed, egahlin
1.1 --- a/src/share/vm/jfr/jfr.cpp Wed Dec 05 16:40:12 2018 +0100 1.2 +++ b/src/share/vm/jfr/jfr.cpp Thu Nov 15 11:10:04 2018 +0100 1.3 @@ -63,13 +63,17 @@ 1.4 } 1.5 } 1.6 1.7 -void Jfr::on_thread_exit(JavaThread* thread) { 1.8 - JfrThreadLocal::on_exit(thread); 1.9 +void Jfr::on_thread_start(Thread* t) { 1.10 + JfrThreadLocal::on_start(t); 1.11 } 1.12 1.13 -void Jfr::on_thread_destruct(Thread* thread) { 1.14 - if (JfrRecorder::is_created()) { 1.15 - JfrThreadLocal::on_destruct(thread); 1.16 +void Jfr::on_thread_exit(Thread* t) { 1.17 + JfrThreadLocal::on_exit(t); 1.18 +} 1.19 + 1.20 +void Jfr::on_java_thread_dismantle(JavaThread* jt) { 1.21 + if (JfrRecorder::is_recording()) { 1.22 + JfrCheckpointManager::write_thread_checkpoint(jt); 1.23 } 1.24 } 1.25
2.1 --- a/src/share/vm/jfr/jfr.hpp Wed Dec 05 16:40:12 2018 +0100 2.2 +++ b/src/share/vm/jfr/jfr.hpp Thu Nov 15 11:10:04 2018 +0100 2.3 @@ -46,8 +46,9 @@ 2.4 static void on_vm_init(); 2.5 static void on_vm_start(); 2.6 static void on_unloading_classes(); 2.7 - static void on_thread_exit(JavaThread* thread); 2.8 - static void on_thread_destruct(Thread* thread); 2.9 + static void on_thread_start(Thread* thread); 2.10 + static void on_thread_exit(Thread* thread); 2.11 + static void on_java_thread_dismantle(JavaThread* jt); 2.12 static void on_vm_shutdown(bool exception_handler = false); 2.13 static bool on_flight_recorder_option(const JavaVMOption** option, char* delimiter); 2.14 static bool on_start_flight_recording_option(const JavaVMOption** option, char* delimiter);
3.1 --- a/src/share/vm/jfr/support/jfrThreadLocal.cpp Wed Dec 05 16:40:12 2018 +0100 3.2 +++ b/src/share/vm/jfr/support/jfrThreadLocal.cpp Thu Nov 15 11:10:04 2018 +0100 3.3 @@ -23,6 +23,7 @@ 3.4 */ 3.5 3.6 #include "precompiled.hpp" 3.7 +#include "jfr/jfrEvents.hpp" 3.8 #include "jfr/jni/jfrJavaSupport.hpp" 3.9 #include "jfr/periodic/jfrThreadCPULoadEvent.hpp" 3.10 #include "jfr/recorder/jfrRecorder.hpp" 3.11 @@ -35,6 +36,7 @@ 3.12 #include "memory/allocation.inline.hpp" 3.13 #include "runtime/os.hpp" 3.14 #include "runtime/thread.inline.hpp" 3.15 +#include "utilities/sizes.hpp" 3.16 3.17 /* This data structure is per thread and only accessed by the thread itself, no locking required */ 3.18 JfrThreadLocal::JfrThreadLocal() : 3.19 @@ -73,53 +75,76 @@ 3.20 return _thread_cp; 3.21 } 3.22 3.23 -void JfrThreadLocal::set_dead() { 3.24 - assert(!is_dead(), "invariant"); 3.25 - _dead = true; 3.26 +static void send_java_thread_start_event(JavaThread* jt) { 3.27 + EventThreadStart event; 3.28 + event.set_thread(jt->jfr_thread_local()->thread_id()); 3.29 + event.commit(); 3.30 } 3.31 3.32 -void JfrThreadLocal::on_exit(JavaThread* thread) { 3.33 +void JfrThreadLocal::on_start(Thread* t) { 3.34 + assert(t != NULL, "invariant"); 3.35 + assert(Thread::current() == t, "invariant"); 3.36 if (JfrRecorder::is_recording()) { 3.37 - JfrCheckpointManager::write_thread_checkpoint(thread); 3.38 - JfrThreadCPULoadEvent::send_event_for_thread(thread); 3.39 + if (t->is_Java_thread()) { 3.40 + send_java_thread_start_event((JavaThread*)t); 3.41 + } 3.42 } 3.43 - thread->jfr_thread_local()->set_dead(); 3.44 } 3.45 3.46 -void JfrThreadLocal::on_destruct(Thread* thread) { 3.47 - JfrThreadLocal* const tl = thread->jfr_thread_local(); 3.48 +static void send_java_thread_end_events(traceid id, JavaThread* jt) { 3.49 + assert(jt != NULL, "invariant"); 3.50 + assert(Thread::current() == jt, "invariant"); 3.51 + assert(jt->jfr_thread_local()->trace_id() == id, "invariant"); 3.52 + EventThreadEnd event; 3.53 + event.set_thread(id); 3.54 + event.commit(); 3.55 + JfrThreadCPULoadEvent::send_event_for_thread(jt); 3.56 +} 3.57 + 3.58 +void JfrThreadLocal::release(JfrThreadLocal* tl, Thread* t) { 3.59 + assert(tl != NULL, "invariant"); 3.60 + assert(t != NULL, "invariant"); 3.61 + assert(Thread::current() == t, "invariant"); 3.62 + assert(!tl->is_dead(), "invariant"); 3.63 + assert(tl->shelved_buffer() == NULL, "invariant"); 3.64 if (tl->has_native_buffer()) { 3.65 - release(tl->native_buffer(), thread); 3.66 + JfrStorage::release_thread_local(tl->native_buffer(), t); 3.67 } 3.68 if (tl->has_java_buffer()) { 3.69 - release(tl->java_buffer(), thread); 3.70 + JfrStorage::release_thread_local(tl->java_buffer(), t); 3.71 } 3.72 - assert(tl->shelved_buffer() == NULL, "invariant"); 3.73 - if (thread->jfr_thread_local()->has_java_event_writer()) { 3.74 + if (tl->has_java_event_writer()) { 3.75 + assert(t->is_Java_thread(), "invariant"); 3.76 JfrJavaSupport::destroy_global_jni_handle(tl->java_event_writer()); 3.77 } 3.78 - destroy_stackframes(thread); 3.79 + if (tl->_stackframes != NULL) { 3.80 + FREE_C_HEAP_ARRAY(JfrStackFrame, tl->_stackframes, mtTracing); 3.81 + } 3.82 + tl->_dead = true; 3.83 } 3.84 3.85 -JfrBuffer* JfrThreadLocal::acquire(Thread* thread, size_t size) { 3.86 - return JfrStorage::acquire_thread_local(thread, size); 3.87 -} 3.88 - 3.89 -void JfrThreadLocal::release(JfrBuffer* buffer, Thread* thread) { 3.90 - assert(buffer != NULL, "invariant"); 3.91 - JfrStorage::release_thread_local(buffer, thread); 3.92 +void JfrThreadLocal::on_exit(Thread* t) { 3.93 + assert(t != NULL, "invariant"); 3.94 + JfrThreadLocal * const tl = t->jfr_thread_local(); 3.95 + assert(!tl->is_dead(), "invariant"); 3.96 + if (JfrRecorder::is_recording()) { 3.97 + if (t->is_Java_thread()) { 3.98 + send_java_thread_end_events(tl->thread_id(), (JavaThread*)t); 3.99 + } 3.100 + } 3.101 + release(tl, Thread::current()); // because it could be that Thread::current() != t 3.102 } 3.103 3.104 JfrBuffer* JfrThreadLocal::install_native_buffer() const { 3.105 assert(!has_native_buffer(), "invariant"); 3.106 - _native_buffer = acquire(Thread::current()); 3.107 + _native_buffer = JfrStorage::acquire_thread_local(Thread::current()); 3.108 return _native_buffer; 3.109 } 3.110 3.111 JfrBuffer* JfrThreadLocal::install_java_buffer() const { 3.112 assert(!has_java_buffer(), "invariant"); 3.113 assert(!has_java_event_writer(), "invariant"); 3.114 - _java_buffer = acquire(Thread::current()); 3.115 + _java_buffer = JfrStorage::acquire_thread_local(Thread::current()); 3.116 return _java_buffer; 3.117 } 3.118 3.119 @@ -131,11 +156,10 @@ 3.120 return _stackframes; 3.121 } 3.122 3.123 -void JfrThreadLocal::destroy_stackframes(Thread* thread) { 3.124 - assert(thread != NULL, "invariant"); 3.125 - JfrStackFrame* frames = thread->jfr_thread_local()->stackframes(); 3.126 - if (frames != NULL) { 3.127 - FREE_C_HEAP_ARRAY(JfrStackFrame, frames, mtTracing); 3.128 - thread->jfr_thread_local()->set_stackframes(NULL); 3.129 - } 3.130 +ByteSize JfrThreadLocal::trace_id_offset() { 3.131 + return in_ByteSize(offset_of(JfrThreadLocal, _trace_id)); 3.132 } 3.133 + 3.134 +ByteSize JfrThreadLocal::java_event_writer_offset() { 3.135 + return in_ByteSize(offset_of(JfrThreadLocal, _java_event_writer)); 3.136 +}
4.1 --- a/src/share/vm/jfr/support/jfrThreadLocal.hpp Wed Dec 05 16:40:12 2018 +0100 4.2 +++ b/src/share/vm/jfr/support/jfrThreadLocal.hpp Thu Nov 15 11:10:04 2018 +0100 4.3 @@ -27,11 +27,11 @@ 4.4 4.5 #include "jfr/recorder/checkpoint/jfrCheckpointBlob.hpp" 4.6 #include "jfr/utilities/jfrTypes.hpp" 4.7 -#include "utilities/sizes.hpp" 4.8 4.9 class JavaThread; 4.10 class JfrBuffer; 4.11 class JfrStackFrame; 4.12 +class Thread; 4.13 4.14 class JfrThreadLocal { 4.15 private: 4.16 @@ -56,7 +56,7 @@ 4.17 JfrBuffer* install_java_buffer() const; 4.18 JfrStackFrame* install_stackframes() const; 4.19 4.20 - void set_dead(); 4.21 + static void release(JfrThreadLocal* tl, Thread* t); 4.22 4.23 public: 4.24 JfrThreadLocal(); 4.25 @@ -213,20 +213,12 @@ 4.26 void set_thread_checkpoint(const JfrCheckpointBlobHandle& handle); 4.27 const JfrCheckpointBlobHandle& thread_checkpoint() const; 4.28 4.29 - static JfrBuffer* acquire(Thread* t, size_t size = 0); 4.30 - static void release(JfrBuffer* buffer, Thread* t); 4.31 - static void destroy_stackframes(Thread* t); 4.32 - static void on_exit(JavaThread* t); 4.33 - static void on_destruct(Thread* t); 4.34 + static void on_start(Thread* t); 4.35 + static void on_exit(Thread* t); 4.36 4.37 // Code generation 4.38 - static ByteSize trace_id_offset() { 4.39 - return in_ByteSize(offset_of(JfrThreadLocal, _trace_id)); 4.40 - } 4.41 - 4.42 - static ByteSize java_event_writer_offset() { 4.43 - return in_ByteSize(offset_of(JfrThreadLocal, _java_event_writer)); 4.44 - } 4.45 + static ByteSize trace_id_offset(); 4.46 + static ByteSize java_event_writer_offset(); 4.47 }; 4.48 4.49 #endif // SHARE_VM_JFR_SUPPORT_JFRTHREADLOCAL_HPP
5.1 --- a/src/share/vm/runtime/thread.cpp Wed Dec 05 16:40:12 2018 +0100 5.2 +++ b/src/share/vm/runtime/thread.cpp Thu Nov 15 11:10:04 2018 +0100 5.3 @@ -33,7 +33,6 @@ 5.4 #include "interpreter/linkResolver.hpp" 5.5 #include "interpreter/oopMapCache.hpp" 5.6 #include "jfr/jfrEvents.hpp" 5.7 -#include "jfr/support/jfrThreadId.hpp" 5.8 #include "jvmtifiles/jvmtiEnv.hpp" 5.9 #include "memory/gcLocker.inline.hpp" 5.10 #include "memory/metaspaceShared.hpp" 5.11 @@ -345,8 +344,6 @@ 5.12 // Reclaim the objectmonitors from the omFreeList of the moribund thread. 5.13 ObjectSynchronizer::omFlush (this) ; 5.14 5.15 - JFR_ONLY(Jfr::on_thread_destruct(this);) 5.16 - 5.17 // stack_base can be NULL if the thread is never started or exited before 5.18 // record_stack_base_and_size called. Although, we would like to ensure 5.19 // that all started threads do call record_stack_base_and_size(), there is 5.20 @@ -1215,6 +1212,7 @@ 5.21 } 5.22 5.23 NamedThread::~NamedThread() { 5.24 + JFR_ONLY(Jfr::on_thread_exit(this);) 5.25 if (_name != NULL) { 5.26 FREE_C_HEAP_ARRAY(char, _name, mtThread); 5.27 _name = NULL; 5.28 @@ -1672,11 +1670,7 @@ 5.29 JvmtiExport::post_thread_start(this); 5.30 } 5.31 5.32 - EventThreadStart event; 5.33 - if (event.should_commit()) { 5.34 - event.set_thread(JFR_THREAD_ID(this)); 5.35 - event.commit(); 5.36 - } 5.37 + JFR_ONLY(Jfr::on_thread_start(this);) 5.38 5.39 // We call another function to do the rest so we are sure that the stack addresses used 5.40 // from there will be lower than the stack base just computed 5.41 @@ -1803,17 +1797,7 @@ 5.42 } 5.43 } 5.44 } 5.45 - 5.46 - // Called before the java thread exit since we want to read info 5.47 - // from java_lang_Thread object 5.48 - EventThreadEnd event; 5.49 - if (event.should_commit()) { 5.50 - event.set_thread(JFR_THREAD_ID(this)); 5.51 - event.commit(); 5.52 - } 5.53 - 5.54 - // Call after last event on thread 5.55 - JFR_ONLY(Jfr::on_thread_exit(this);) 5.56 + JFR_ONLY(Jfr::on_java_thread_dismantle(this);) 5.57 5.58 // Call Thread.exit(). We try 3 times in case we got another Thread.stop during 5.59 // the execution of the method. If that is not enough, then we don't really care. Thread.stop 5.60 @@ -1890,6 +1874,7 @@ 5.61 // These things needs to be done while we are still a Java Thread. Make sure that thread 5.62 // is in a consistent state, in case GC happens 5.63 assert(_privileged_stack_top == NULL, "must be NULL when we get here"); 5.64 + JFR_ONLY(Jfr::on_thread_exit(this);) 5.65 5.66 if (active_handles() != NULL) { 5.67 JNIHandleBlock* block = active_handles();