< prev index next > src/hotspot/share/prims/jvmtiEnvBase.cpp
Print this page
}
jint
JvmtiEnvBase::get_vthread_state(oop thread_oop, JavaThread* java_thread) {
jint state = 0;
+ bool is_mon_responsible = java_lang_VirtualThread::recheckInterval(thread_oop) > 0;
bool ext_suspended = JvmtiVTSuspender::is_vthread_suspended(thread_oop);
jint interrupted = java_lang_Thread::interrupted(thread_oop);
if (java_thread != nullptr) {
// If virtual thread is blocked on a monitor enter the BLOCKED_ON_MONITOR_ENTER bit
oop ct_oop = java_lang_VirtualThread::carrier_thread(thread_oop);
jint filtered_bits = JVMTI_THREAD_STATE_SUSPENDED | JVMTI_THREAD_STATE_INTERRUPTED;
// This call can trigger a safepoint, so thread_oop must not be used after it.
state = get_thread_state_base(ct_oop, java_thread) & ~filtered_bits;
+ } else if (is_mon_responsible) {
+ state = (jint) JavaThreadStatus::BLOCKED_ON_MONITOR_ENTER;
} else {
int vt_state = java_lang_VirtualThread::state(thread_oop);
state = (jint)java_lang_VirtualThread::map_state_to_thread_status(vt_state);
}
// Ensure the thread has not exited after retrieving suspended/interrupted values.
return err;
}
jvmtiError
! JvmtiEnvBase::get_owned_monitors(JavaThread* calling_thread, JavaThread* java_thread, javaVFrame* jvf,
! GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list) {
jvmtiError err = JVMTI_ERROR_NONE;
Thread *current_thread = Thread::current();
! assert(java_thread->is_handshake_safe_for(current_thread),
"call by myself or at handshake");
int depth = 0;
for ( ; jvf != nullptr; jvf = jvf->java_sender()) {
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
// Add locked objects for this frame into list.
! err = get_locked_objects_in_frame(calling_thread, java_thread, jvf, owned_monitors_list, depth - 1);
if (err != JVMTI_ERROR_NONE) {
return err;
}
}
}
// Get off stack monitors. (e.g. acquired via jni MonitorEnter).
JvmtiMonitorClosure jmc(calling_thread, owned_monitors_list, this);
! ObjectSynchronizer::owned_monitors_iterate(&jmc, java_thread);
err = jmc.error();
return err;
}
// Save JNI local handles for any objects that this frame owns.
jvmtiError
! JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* java_thread,
! javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list, jint stack_depth) {
jvmtiError err = JVMTI_ERROR_NONE;
Thread* current_thread = Thread::current();
ResourceMark rm(current_thread);
HandleMark hm(current_thread);
return err;
}
jvmtiError
! JvmtiEnvBase::get_owned_monitors(JavaThread* calling_thread, JavaThread* carrier, javaVFrame* jvf,
! GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list, oop vthread) {
jvmtiError err = JVMTI_ERROR_NONE;
Thread *current_thread = Thread::current();
! assert(carrier == nullptr || carrier->is_handshake_safe_for(current_thread),
"call by myself or at handshake");
int depth = 0;
for ( ; jvf != nullptr; jvf = jvf->java_sender()) {
if (MaxJavaStackTraceDepth == 0 || depth++ < MaxJavaStackTraceDepth) { // check for stack too deep
// Add locked objects for this frame into list.
! err = get_locked_objects_in_frame(calling_thread, carrier, jvf, owned_monitors_list, depth - 1, vthread);
if (err != JVMTI_ERROR_NONE) {
return err;
}
}
}
+ if (carrier == nullptr) {
+ // vthread gets pinned if monitors are acquired via jni MonitorEnter
+ // so nothing else to do for unmounted case.
+ return err;
+ }
+
// Get off stack monitors. (e.g. acquired via jni MonitorEnter).
JvmtiMonitorClosure jmc(calling_thread, owned_monitors_list, this);
! ObjectSynchronizer::owned_monitors_iterate(&jmc, carrier);
err = jmc.error();
return err;
}
// Save JNI local handles for any objects that this frame owns.
jvmtiError
! JvmtiEnvBase::get_locked_objects_in_frame(JavaThread* calling_thread, JavaThread* target,
! javaVFrame *jvf, GrowableArray<jvmtiMonitorStackDepthInfo*>* owned_monitors_list,
+ jint stack_depth, oop vthread) {
jvmtiError err = JVMTI_ERROR_NONE;
Thread* current_thread = Thread::current();
ResourceMark rm(current_thread);
HandleMark hm(current_thread);
{
// The ObjectMonitor* can't be async deflated since we are either
// at a safepoint or the calling thread is operating on itself so
// it cannot leave the underlying wait() call.
// Save object of current wait() call (if any) for later comparison.
! ObjectMonitor *mon = java_thread->current_waiting_monitor();
! if (mon != nullptr) {
! wait_obj = mon->object();
}
}
oop pending_obj = nullptr;
{
// The ObjectMonitor* can't be async deflated since we are either
// at a safepoint or the calling thread is operating on itself so
// it cannot leave the underlying enter() call.
// Save object of current enter() call (if any) for later comparison.
! ObjectMonitor *mon = java_thread->current_pending_monitor();
! if (mon != nullptr) {
! pending_obj = mon->object();
}
}
for (int i = 0; i < mons->length(); i++) {
MonitorInfo *mi = mons->at(i);
{
// The ObjectMonitor* can't be async deflated since we are either
// at a safepoint or the calling thread is operating on itself so
// it cannot leave the underlying wait() call.
// Save object of current wait() call (if any) for later comparison.
! if (target != nullptr) {
! ObjectMonitor *mon = target->current_waiting_monitor();
! if (mon != nullptr) wait_obj = mon->object();
}
}
oop pending_obj = nullptr;
{
// The ObjectMonitor* can't be async deflated since we are either
// at a safepoint or the calling thread is operating on itself so
// it cannot leave the underlying enter() call.
// Save object of current enter() call (if any) for later comparison.
! if (target != nullptr) {
! ObjectMonitor *mon = target->current_pending_monitor();
! if (mon != nullptr) pending_obj = mon->object();
+ } else {
+ assert(vthread != nullptr, "no vthread oop");
+ oop oopCont = java_lang_VirtualThread::continuation(vthread);
+ assert(oopCont != nullptr, "vthread with no continuation");
+ stackChunkOop chunk = jdk_internal_vm_Continuation::tail(oopCont);
+ assert(chunk != nullptr, "unmounted vthread should have a chunk");
+ ObjectMonitor *mon = chunk->objectMonitor();
+ if (mon != nullptr) pending_obj = mon->object();
}
}
for (int i = 0; i < mons->length(); i++) {
MonitorInfo *mi = mons->at(i);
}
}
void
GetOwnedMonitorInfoClosure::do_vthread(Handle target_h) {
- assert(_target_jt != nullptr, "sanity check");
Thread* current = Thread::current();
ResourceMark rm(current); // vframes are resource allocated
HandleMark hm(current);
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(target_h());
! if (!_target_jt->is_exiting() && _target_jt->threadObj() != nullptr) {
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread,
_target_jt,
jvf,
! _owned_monitors_list);
}
}
void
GetCurrentContendedMonitorClosure::do_thread(Thread *target) {
}
}
void
GetOwnedMonitorInfoClosure::do_vthread(Handle target_h) {
Thread* current = Thread::current();
ResourceMark rm(current); // vframes are resource allocated
HandleMark hm(current);
javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(target_h());
! if (_target_jt == nullptr || (!_target_jt->is_exiting() && _target_jt->threadObj() != nullptr)) {
_result = ((JvmtiEnvBase *)_env)->get_owned_monitors(_calling_thread,
_target_jt,
jvf,
! _owned_monitors_list,
+ target_h());
}
}
void
GetCurrentContendedMonitorClosure::do_thread(Thread *target) {
}
void
GetCurrentContendedMonitorClosure::do_vthread(Handle target_h) {
if (_target_jt == nullptr) {
+ oop cont = java_lang_VirtualThread::continuation(target_h());
+ assert(cont != nullptr, "vthread with no continuation");
+ stackChunkOop chunk = jdk_internal_vm_Continuation::tail(cont);
+ assert(chunk != nullptr, "unmounted vthread should have a chunk");
+ if (chunk->objectMonitor() != nullptr) {
+ *_owned_monitor_ptr = JNIHandles::make_local(_calling_thread, chunk->objectMonitor()->object());
+ }
_result = JVMTI_ERROR_NONE; // target virtual thread is unmounted
return;
}
// mounted virtual thread case
do_thread(_target_jt);
_result = ((JvmtiEnvBase*)_env)->get_frame_location(target_h(), _depth,
_method_ptr, _location_ptr);
}
void
+
VirtualThreadGetThreadClosure::do_thread(Thread *target) {
assert(target->is_Java_thread(), "just checking");
JavaThread *jt = JavaThread::cast(target);
oop carrier_thread = java_lang_VirtualThread::carrier_thread(_vthread_h());
*_carrier_thread_ptr = (jthread)JNIHandles::make_local(jt, carrier_thread);
< prev index next >