--- old/src/hotspot/share/runtime/thread.cpp 2020-07-12 22:24:43.535389488 +0200 +++ new/src/hotspot/share/runtime/thread.cpp 2020-07-12 22:24:43.107388672 +0200 @@ -2384,7 +2384,7 @@ check_and_handle_async_exceptions(); } - if (is_ea_obj_deopt_suspend()) { + if (is_obj_deopt_suspend()) { frame_anchor()->make_walkable(this); wait_for_object_deoptimization(); } @@ -2586,26 +2586,52 @@ assert(this == Thread::current(), "invariant"); JavaThreadState state = thread_state(); + bool should_spin_wait = true; do { set_thread_state(_thread_blocked); set_suspend_equivalent(); - MonitorLocker ml(this, EscapeBarrier_lock, Monitor::_no_safepoint_check_flag); - if (is_ea_obj_deopt_suspend()) { - ml.wait(); + { + MonitorLocker ml(this, EscapeBarrier_lock, Monitor::_no_safepoint_check_flag); + if (EscapeBarrier::deoptimizing_objects_for_all_threads() || + (is_obj_deopt_suspend() && !should_spin_wait)) { + ml.wait(); + } + should_spin_wait = should_spin_wait && is_obj_deopt_suspend(); } - if (handle_special_suspend_equivalent_condition()) { - MutexUnlocker mu(EscapeBarrier_lock, Monitor::_no_safepoint_check_flag); - java_suspend_self(); + // Single deoptimization is typically very short. Microbenchmarks + // showed 5% better performance when spinning + if (should_spin_wait) { + // Inspired by HandshakeSpinYield + const jlong max_spin_time_ns = 100 /* us */ * (NANOUNITS / MICROUNITS); + const int free_cpus = os::active_processor_count() - 1; + jlong spin_time_ns = (5 /* us */ * (NANOUNITS / MICROUNITS)) * free_cpus; // zero on UP + spin_time_ns = spin_time_ns > max_spin_time_ns ? max_spin_time_ns : spin_time_ns; + jlong spin_start = os::javaTimeNanos(); + while (is_obj_deopt_suspend()) { + os::naked_yield(); + if ((os::javaTimeNanos() - spin_start) > spin_time_ns) { + should_spin_wait = false; + break; + } + } } set_thread_state_fence(state); - } while (is_ea_obj_deopt_suspend()); - // Since we are not using a regular thread-state transition helper here, - // we must manually emit the instruction barrier after leaving a safe state. - OrderAccess::cross_modify_fence(); - if (state != _thread_in_native) { - SafepointMechanism::block_if_requested(this); - } + if (handle_special_suspend_equivalent_condition()) { + java_suspend_self_with_safepoint_check(); + } + + // Since we are not using a regular thread-state transition helper here, + // we must manually emit the instruction barrier after leaving a safe state. + OrderAccess::cross_modify_fence(); + if (state != _thread_in_native) { + SafepointMechanism::block_if_requested(this); + } + + // Check for another deopt suspend _after_ checking for safepont/handshake, + // or otherwise a stale value can be seen if the flag was changed with a + // handshake while the current thread was _thread_blocked above. + } while (is_obj_deopt_suspend()); } #ifdef ASSERT @@ -2637,7 +2663,7 @@ SafepointMechanism::block_if_requested(thread); } - if (thread->is_ea_obj_deopt_suspend()) { + if (thread->is_obj_deopt_suspend()) { thread->wait_for_object_deoptimization(); } @@ -4616,6 +4642,9 @@ // to do callbacks into the safepoint code. However, the safepoint code is not aware // of this thread since it is removed from the queue. p->set_terminated_value(); + + // Notify threads waiting in EscapeBarriers + EscapeBarrier::thread_removed(p); } // unlock Threads_lock // Since Events::log uses a lock, we grab it outside the Threads_lock