# HG changeset patch # User rehn # Date 1553175607 -3600 # Thu Mar 21 14:40:07 2019 +0100 # Node ID 9f22efac97ddbe3cd01e31fb70cfc5df6dace83e # Parent ed40b61fed963d90b5b27b48b1121520ead6a25f [mq]: 8220774-handshakealot-v3 diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -371,6 +371,10 @@ "Generate a lot of safepoints. This works with " \ "GuaranteedSafepointInterval") \ \ + diagnostic(bool, HandshakeALot, false, \ + "Generate a lot of handshakes. This works with " \ + "GuaranteedSafepointInterval") \ + \ product_pd(bool, BackgroundCompilation, \ "A thread requesting compilation is not blocked during " \ "compilation") \ diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -2948,6 +2948,14 @@ } } +#ifdef ASSERT +void JavaThread::verify_states_for_handshake() { + // This checks that the thread has a correct frame state during a handshake. + assert((!has_last_Java_frame() && java_call_counter() == 0) || + (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); +} +#endif + void JavaThread::nmethods_do(CodeBlobClosure* cf) { assert((!has_last_Java_frame() && java_call_counter() == 0) || (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -1868,6 +1868,9 @@ // RedefineClasses Support void metadata_do(MetadataClosure* f); + // Debug method asserting thread states are correct during a handshake operation. + DEBUG_ONLY(void verify_states_for_handshake();) + // Misc. operations char* name() const { return (char*)get_thread_name(); } void print_on(outputStream* st, bool print_extended_info) const; diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -434,22 +434,35 @@ static VM_None safepointALot_op("SafepointALot"); static VM_Cleanup cleanup_op; -VM_Operation* VMThread::no_op_safepoint(bool check_time) { +class HandshakeALotTC : public ThreadClosure { + public: + virtual void do_thread(Thread* thread) { +#ifdef ASSERT + assert(thread->is_Java_thread(), "must be"); + JavaThread* jt = (JavaThread*)thread; + jt->verify_states_for_handshake(); +#endif + } +}; + +VM_Operation* VMThread::no_op_safepoint() { + // Must check for handshakes first, since ops returns. + if (HandshakeALot) { + HandshakeALotTC haltc; + Handshake::execute(&haltc); + } + // Check for a true cleanup first, trying to keep stats correct. + long interval_ms = SafepointTracing::time_since_last_safepoint_ms(); + bool max_time_exceeded = GuaranteedSafepointInterval != 0 && + (interval_ms >= GuaranteedSafepointInterval); + if (max_time_exceeded && SafepointSynchronize::is_cleanup_needed()) { + return &cleanup_op; + } if (SafepointALot) { return &safepointALot_op; } - if (!SafepointSynchronize::is_cleanup_needed()) { - return NULL; - } - if (check_time) { - long interval_ms = SafepointTracing::time_since_last_safepoint_ms(); - bool max_time_exceeded = GuaranteedSafepointInterval != 0 && - (interval_ms > GuaranteedSafepointInterval); - if (!max_time_exceeded) { - return NULL; - } - } - return &cleanup_op; + // Nothing to be done. + return NULL; } void VMThread::loop() { @@ -491,19 +504,22 @@ exit(-1); } - if (timedout && (_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) { - MutexUnlockerEx mul(VMOperationQueue_lock, - Mutex::_no_safepoint_check_flag); - // Force a safepoint since we have not had one for at least - // 'GuaranteedSafepointInterval' milliseconds. This will run all - // the clean-up processing that needs to be done regularly at a - // safepoint - SafepointSynchronize::begin(); - #ifdef ASSERT - if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); - #endif - SafepointSynchronize::end(); - _cur_vm_operation = NULL; + { + // Have to unlock VMOperationQueue_lock just in case no_op_safepoint() + // has to do a handshake. + MutexUnlockerEx mul(VMOperationQueue_lock, Mutex::_no_safepoint_check_flag); + if (timedout && (_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) { + // Force a safepoint since we have not had one for at least + // 'GuaranteedSafepointInterval' milliseconds and we need to clean + // something. This will run all the clean-up processing that needs + // to be done at a safepoint. + SafepointSynchronize::begin(); + #ifdef ASSERT + if (GCALotAtAllSafepoints) InterfaceSupport::check_gc_alot(); + #endif + SafepointSynchronize::end(); + _cur_vm_operation = NULL; + } } _cur_vm_operation = _vm_queue->remove_next(); @@ -618,7 +634,7 @@ // // We want to make sure that we get to a safepoint regularly. // - if ((_cur_vm_operation = VMThread::no_op_safepoint(false)) != NULL) { + if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) { HandleMark hm(VMThread::vm_thread()); SafepointSynchronize::begin(); SafepointSynchronize::end(); diff --git a/src/hotspot/share/runtime/vmThread.hpp b/src/hotspot/share/runtime/vmThread.hpp --- a/src/hotspot/share/runtime/vmThread.hpp +++ b/src/hotspot/share/runtime/vmThread.hpp @@ -123,7 +123,7 @@ static VMOperationTimeoutTask* _timeout_task; - static VM_Operation* no_op_safepoint(bool check_time); + static VM_Operation* no_op_safepoint(); void evaluate_operation(VM_Operation* op); # HG changeset patch # User rehn # Date 1553183749 -3600 # Thu Mar 21 16:55:49 2019 +0100 # Node ID 65d817296a44213af3fc94307f81999c7af58875 # Parent 9f22efac97ddbe3cd01e31fb70cfc5df6dace83e [mq]: 8220774-handshakealot-v4 diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -2952,13 +2952,17 @@ void JavaThread::verify_states_for_handshake() { // This checks that the thread has a correct frame state during a handshake. assert((!has_last_Java_frame() && java_call_counter() == 0) || - (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); + (has_last_Java_frame() && java_call_counter() > 0), + "unexpected frame info: has_last_frame=%d, java_call_counter=%d", + has_last_Java_frame(), java_call_counter()); } #endif void JavaThread::nmethods_do(CodeBlobClosure* cf) { assert((!has_last_Java_frame() && java_call_counter() == 0) || - (has_last_Java_frame() && java_call_counter() > 0), "wrong java_sp info!"); + (has_last_Java_frame() && java_call_counter() > 0), + "unexpected frame info: has_last_frame=%d, java_call_counter=%d", + has_last_Java_frame(), java_call_counter()); if (has_last_Java_frame()) { // Traverse the execution stack diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -446,12 +446,12 @@ }; VM_Operation* VMThread::no_op_safepoint() { - // Must check for handshakes first, since ops returns. + // Check for handshakes first since we may need to return a VMop. if (HandshakeALot) { HandshakeALotTC haltc; Handshake::execute(&haltc); } - // Check for a true cleanup first, trying to keep stats correct. + // Check for a cleanup before SafepointALot to keep stats correct. long interval_ms = SafepointTracing::time_since_last_safepoint_ms(); bool max_time_exceeded = GuaranteedSafepointInterval != 0 && (interval_ms >= GuaranteedSafepointInterval); @@ -631,9 +631,8 @@ VMOperationRequest_lock->notify_all(); } - // - // We want to make sure that we get to a safepoint regularly. - // + // We want to make sure that we get to a safepoint regularly + // even when executing VMops that don't require safepoints. if ((_cur_vm_operation = VMThread::no_op_safepoint()) != NULL) { HandleMark hm(VMThread::vm_thread()); SafepointSynchronize::begin();