< prev index next >
src/hotspot/share/runtime/thread.cpp
Print this page
rev 60137 : 8227745: Enable Escape Analysis for Better Performance in the Presence of JVMTI Agents
Reviewed-by: mdoerr, goetz
rev 60138 : 8227745: delta webrev.5 -> webrev.6
@@ -2382,11 +2382,11 @@
// so check for other async requests.
if (check_asyncs) {
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();
}
JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
@@ -2584,30 +2584,56 @@
void JavaThread::wait_for_object_deoptimization() {
assert(!has_last_Java_frame() || frame_anchor()->walkable(), "should have walkable stack");
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()) {
+ if (EscapeBarrier::deoptimizing_objects_for_all_threads() ||
+ (is_obj_deopt_suspend() && !should_spin_wait)) {
ml.wait();
}
- if (handle_special_suspend_equivalent_condition()) {
- MutexUnlocker mu(EscapeBarrier_lock, Monitor::_no_safepoint_check_flag);
- java_suspend_self();
+ should_spin_wait = should_spin_wait && is_obj_deopt_suspend();
+ }
+ // 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());
+
+ 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
// Verify the JavaThread has not yet been published in the Threads::list, and
// hence doesn't need protection from concurrent access at this stage.
@@ -2635,11 +2661,11 @@
thread->java_suspend_self_with_safepoint_check();
} else {
SafepointMechanism::block_if_requested(thread);
}
- if (thread->is_ea_obj_deopt_suspend()) {
+ if (thread->is_obj_deopt_suspend()) {
thread->wait_for_object_deoptimization();
}
JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(thread);)
}
@@ -4614,10 +4640,13 @@
// Make sure that safepoint code disregard this thread. This is needed since
// the thread might mess around with locks after this point. This can cause it
// 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
Events::log(p, "Thread exited: " INTPTR_FORMAT, p2i(p));
}
< prev index next >