< 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
@@ -1637,11 +1637,11 @@
set_callee_target(NULL);
set_vm_result(NULL);
set_vm_result_2(NULL);
set_vframe_array_head(NULL);
set_vframe_array_last(NULL);
- set_deferred_locals(NULL);
+ set_deferred_updates(NULL);
set_deopt_mark(NULL);
set_deopt_compiled_method(NULL);
set_monitor_chunks(NULL);
_on_thread_list = false;
_thread_state = _thread_new;
@@ -1864,21 +1864,21 @@
old_array->set_unroll_block(NULL);
delete old_info;
delete old_array;
}
- GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = deferred_locals();
+ GrowableArray<jvmtiDeferredLocalVariableSet*>* deferred = JvmtiDeferredUpdates::deferred_locals(this);
if (deferred != NULL) {
// This can only happen if thread is destroyed before deoptimization occurs.
assert(deferred->length() != 0, "empty array!");
do {
jvmtiDeferredLocalVariableSet* dlv = deferred->at(0);
deferred->remove_at(0);
// individual jvmtiDeferredLocalVariableSet are CHeapObj's
delete dlv;
} while (deferred->length() != 0);
- delete deferred;
+ delete deferred_updates();
}
// All Java related clean up happens in exit
ThreadSafepointState::destroy(this);
if (_thread_stat != NULL) delete _thread_stat;
@@ -2382,10 +2382,15 @@
// so check for other async requests.
if (check_asyncs) {
check_and_handle_async_exceptions();
}
+ if (is_obj_deopt_suspend()) {
+ frame_anchor()->make_walkable(this);
+ wait_for_object_deoptimization();
+ }
+
JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
}
void JavaThread::send_thread_stop(oop java_throwable) {
ResourceMark rm;
@@ -2574,10 +2579,63 @@
if (state != _thread_in_native) {
SafepointMechanism::block_if_requested(this);
}
}
+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 (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();
+ }
+ // 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);
+
+ 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.
void JavaThread::verify_not_published() {
// Cannot create a ThreadsListHandle here and check !tlh.includes(this)
@@ -2603,10 +2661,14 @@
thread->java_suspend_self_with_safepoint_check();
} else {
SafepointMechanism::block_if_requested(thread);
}
+ if (thread->is_obj_deopt_suspend()) {
+ thread->wait_for_object_deoptimization();
+ }
+
JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(thread);)
}
// Slow path when the native==>VM/Java barriers detect a safepoint is in
// progress or when _suspend_flags is non-zero.
@@ -2980,11 +3042,11 @@
}
assert(vframe_array_head() == NULL, "deopt in progress at a safepoint!");
// If we have deferred set_locals there might be oops waiting to be
// written
- GrowableArray<jvmtiDeferredLocalVariableSet*>* list = deferred_locals();
+ GrowableArray<jvmtiDeferredLocalVariableSet*>* list = JvmtiDeferredUpdates::deferred_locals(this);
if (list != NULL) {
for (int i = 0; i < list->length(); i++) {
list->at(i)->oops_do(f);
}
}
@@ -4542,10 +4604,13 @@
// Maintain fast thread list
ThreadsSMRSupport::add_thread(p);
// Possible GC point.
Events::log(p, "Thread added: " INTPTR_FORMAT, p2i(p));
+
+ // Make new thread known to active EscapeBarrier
+ EscapeBarrier::thread_added(p);
}
void Threads::remove(JavaThread* p, bool is_daemon) {
// Reclaim the ObjectMonitors from the om_in_use_list and om_free_list of the moribund thread.
@@ -4575,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 >