< prev index next >

src/hotspot/share/prims/jvm.cpp

Print this page
*** 63,14 ***
  #include "oops/objArrayKlass.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/oop.inline.hpp"
  #include "prims/jvm_misc.hpp"
  #include "prims/jvmtiExport.hpp"
! #include "prims/jvmtiThreadState.hpp"
  #include "prims/stackwalk.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/atomic.hpp"
  #include "runtime/globals_extension.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/init.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/deoptimization.hpp"
--- 63,15 ---
  #include "oops/objArrayKlass.hpp"
  #include "oops/objArrayOop.inline.hpp"
  #include "oops/oop.inline.hpp"
  #include "prims/jvm_misc.hpp"
  #include "prims/jvmtiExport.hpp"
! #include "prims/jvmtiThreadState.inline.hpp"
  #include "prims/stackwalk.hpp"
  #include "runtime/arguments.hpp"
  #include "runtime/atomic.hpp"
+ #include "runtime/continuation.hpp"
  #include "runtime/globals_extension.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/init.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/deoptimization.hpp"

*** 527,16 ***
  JVM_END
  
  // java.lang.StackTraceElement //////////////////////////////////////////////
  
  
! JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject throwable))
!   Handle exception(THREAD, JNIHandles::resolve(throwable));
    objArrayOop st = objArrayOop(JNIHandles::resolve(elements));
    objArrayHandle stack_trace(THREAD, st);
    // Fill in the allocated stack trace
!   java_lang_Throwable::get_stack_trace_elements(exception, stack_trace, CHECK);
  JVM_END
  
  
  JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo))
    Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo));
--- 528,16 ---
  JVM_END
  
  // java.lang.StackTraceElement //////////////////////////////////////////////
  
  
! JVM_ENTRY(void, JVM_InitStackTraceElementArray(JNIEnv *env, jobjectArray elements, jobject backtrace, jint depth))
!   Handle backtraceh(THREAD, JNIHandles::resolve(backtrace));
    objArrayOop st = objArrayOop(JNIHandles::resolve(elements));
    objArrayHandle stack_trace(THREAD, st);
    // Fill in the allocated stack trace
!   java_lang_Throwable::get_stack_trace_elements(depth, backtraceh, stack_trace, CHECK);
  JVM_END
  
  
  JVM_ENTRY(void, JVM_InitStackTraceElement(JNIEnv* env, jobject element, jobject stackFrameInfo))
    Handle stack_frame_info(THREAD, JNIHandles::resolve_non_null(stackFrameInfo));

*** 547,18 ***
  
  // java.lang.StackWalker //////////////////////////////////////////////////////
  
  
  JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
!                                      jint skip_frames, jint frame_count, jint start_index,
!                                      jobjectArray frames))
    if (!thread->has_last_Java_frame()) {
      THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: no stack trace", NULL);
    }
  
    Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
! 
    // frames array is a Class<?>[] array when only getting caller reference,
    // and a StackFrameInfo[] array (or derivative) otherwise. It should never
    // be null.
    objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
    objArrayHandle frames_array_h(THREAD, fa);
--- 548,19 ---
  
  // java.lang.StackWalker //////////////////////////////////////////////////////
  
  
  JVM_ENTRY(jobject, JVM_CallStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
!                                      jint skip_frames, jobject contScope, jobject cont,
!                                      jint frame_count, jint start_index, jobjectArray frames))
    if (!thread->has_last_Java_frame()) {
      THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: no stack trace", NULL);
    }
  
    Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
!   Handle contScope_h(THREAD, JNIHandles::resolve(contScope));
+   Handle cont_h(THREAD, JNIHandles::resolve(cont));
    // frames array is a Class<?>[] array when only getting caller reference,
    // and a StackFrameInfo[] array (or derivative) otherwise. It should never
    // be null.
    objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
    objArrayHandle frames_array_h(THREAD, fa);

*** 566,12 ***
    int limit = start_index + frame_count;
    if (frames_array_h->length() < limit) {
      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL);
    }
  
!   oop result = StackWalk::walk(stackStream_h, mode, skip_frames, frame_count,
!                                start_index, frames_array_h, CHECK_NULL);
    return JNIHandles::make_local(THREAD, result);
  JVM_END
  
  
  JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,
--- 568,12 ---
    int limit = start_index + frame_count;
    if (frames_array_h->length() < limit) {
      THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers", NULL);
    }
  
!   oop result = StackWalk::walk(stackStream_h, mode, skip_frames, contScope_h, cont_h,
!                                frame_count, start_index, frames_array_h, CHECK_NULL);
    return JNIHandles::make_local(THREAD, result);
  JVM_END
  
  
  JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode, jlong anchor,

*** 588,11 ***
      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers");
    }
  
    Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
    return StackWalk::fetchNextBatch(stackStream_h, mode, anchor, frame_count,
!                                    start_index, frames_array_h, THREAD);
  JVM_END
  
  // java.lang.Object ///////////////////////////////////////////////
  
  
--- 590,20 ---
      THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "not enough space in buffers");
    }
  
    Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
    return StackWalk::fetchNextBatch(stackStream_h, mode, anchor, frame_count,
!                                   start_index, frames_array_h, THREAD);
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_SetStackWalkContinuation(JNIEnv *env, jobject stackStream, jlong anchor, jobjectArray frames, jobject cont))
+     objArrayOop fa = objArrayOop(JNIHandles::resolve_non_null(frames));
+     objArrayHandle frames_array_h(THREAD, fa);
+     Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
+     Handle cont_h(THREAD, JNIHandles::resolve_non_null(cont));
+ 
+     StackWalk::setContinuation(stackStream_h, anchor, frames_array_h, cont_h, THREAD);
  JVM_END
  
  // java.lang.Object ///////////////////////////////////////////////
  
  

*** 679,10 ***
--- 690,16 ---
    }
  
    return JNIHandles::make_local(THREAD, new_obj());
  JVM_END
  
+ // jdk.internal.vm.Continuation /////////////////////////////////////////////////////
+ 
+ JVM_ENTRY(void, JVM_RegisterContinuationMethods(JNIEnv *env, jclass cls))
+   CONT_RegisterNativeMethods(env, cls);
+ JVM_END
+ 
  // java.io.File ///////////////////////////////////////////////////////////////
  
  JVM_LEAF(char*, JVM_NativePath(char* path))
    return os::native_path(path);
  JVM_END

*** 3026,17 ***
    if (os::dont_yield()) return;
    HOTSPOT_THREAD_YIELD();
    os::naked_yield();
  JVM_END
  
- static void post_thread_sleep_event(EventThreadSleep* event, jlong millis) {
-   assert(event != NULL, "invariant");
-   assert(event->should_commit(), "invariant");
-   event->set_time(millis);
-   event->commit();
- }
- 
  JVM_ENTRY(void, JVM_Sleep(JNIEnv* env, jclass threadClass, jlong millis))
    if (millis < 0) {
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
    }
  
--- 3043,10 ---

*** 3047,40 ***
    // Save current thread state and restore it at the end of this block.
    // And set new thread state to SLEEPING.
    JavaThreadSleepState jtss(thread);
  
    HOTSPOT_THREAD_SLEEP_BEGIN(millis);
-   EventThreadSleep event;
  
    if (millis == 0) {
      os::naked_yield();
    } else {
      ThreadState old_state = thread->osthread()->get_state();
      thread->osthread()->set_state(SLEEPING);
      if (!thread->sleep(millis)) { // interrupted
        // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
        // us while we were sleeping. We do not overwrite those.
        if (!HAS_PENDING_EXCEPTION) {
-         if (event.should_commit()) {
-           post_thread_sleep_event(&event, millis);
-         }
          HOTSPOT_THREAD_SLEEP_END(1);
  
          // TODO-FIXME: THROW_MSG returns which means we will not call set_state()
          // to properly restore the thread state.  That's likely wrong.
          THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
        }
      }
      thread->osthread()->set_state(old_state);
    }
-   if (event.should_commit()) {
-     post_thread_sleep_event(&event, millis);
-   }
    HOTSPOT_THREAD_SLEEP_END(0);
  JVM_END
  
! JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
    oop jthread = thread->threadObj();
    assert(jthread != NULL, "no current thread!");
    return JNIHandles::make_local(THREAD, jthread);
  JVM_END
  
--- 3057,33 ---
    // Save current thread state and restore it at the end of this block.
    // And set new thread state to SLEEPING.
    JavaThreadSleepState jtss(thread);
  
    HOTSPOT_THREAD_SLEEP_BEGIN(millis);
  
    if (millis == 0) {
      os::naked_yield();
    } else {
      ThreadState old_state = thread->osthread()->get_state();
      thread->osthread()->set_state(SLEEPING);
      if (!thread->sleep(millis)) { // interrupted
        // An asynchronous exception (e.g., ThreadDeathException) could have been thrown on
        // us while we were sleeping. We do not overwrite those.
        if (!HAS_PENDING_EXCEPTION) {
          HOTSPOT_THREAD_SLEEP_END(1);
  
          // TODO-FIXME: THROW_MSG returns which means we will not call set_state()
          // to properly restore the thread state.  That's likely wrong.
          THROW_MSG(vmSymbols::java_lang_InterruptedException(), "sleep interrupted");
        }
      }
      thread->osthread()->set_state(old_state);
    }
    HOTSPOT_THREAD_SLEEP_END(0);
  JVM_END
  
! JVM_ENTRY(jobject, JVM_CurrentThread0(JNIEnv* env, jclass threadClass))
    oop jthread = thread->threadObj();
    assert(jthread != NULL, "no current thread!");
    return JNIHandles::make_local(THREAD, jthread);
  JVM_END
  

*** 3092,10 ***
--- 3095,38 ---
      // jthread refers to a live JavaThread.
      receiver->interrupt();
    }
  JVM_END
  
+ JVM_ENTRY(jobject, JVM_ScopeLocalCache(JNIEnv* env, jclass threadClass))
+   oop theCache = thread->scopeLocalCache();
+   if (theCache) {
+     arrayOop objs = arrayOop(theCache);
+     assert(objs->length() == ScopeLocalCacheSize * 2, "wrong length");
+   }
+   return JNIHandles::make_local(THREAD, theCache);
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_SetScopeLocalCache(JNIEnv* env, jclass threadClass,
+                                    jobject theCache))
+   arrayOop objs = arrayOop(JNIHandles::resolve(theCache));
+   if (objs != NULL) {
+     assert(objs->length() == ScopeLocalCacheSize * 2, "wrong length");
+   }
+   thread->set_scopeLocalCache(objs);
+ JVM_END
+ 
+ JVM_ENTRY(jobject, JVM_CurrentThread(JNIEnv* env, jclass threadClass))
+   oop theThread = thread->vthread();
+   assert (theThread != (oop)NULL, "no current thread!");
+   return JNIHandles::make_local(THREAD, theThread);
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_SetCurrentThread(JNIEnv* env, jclass threadClass,
+                                      jobject theThread))
+   thread->set_vthread(JNIHandles::resolve(theThread));
+ JVM_END
  
  // Return true iff the current thread has locked the object passed in
  
  JVM_ENTRY(jboolean, JVM_HoldsLock(JNIEnv* env, jclass threadClass, jobject obj))
    if (obj == NULL) {

*** 3103,10 ***
--- 3134,14 ---
    }
    Handle h_obj(THREAD, JNIHandles::resolve(obj));
    return ObjectSynchronizer::current_thread_holds_lock(thread, h_obj);
  JVM_END
  
+ JVM_ENTRY(jobject, JVM_GetStackTrace(JNIEnv *env, jobject jthread))
+   oop trace = java_lang_Thread::async_get_stack_trace(JNIHandles::resolve(jthread), THREAD);
+   return JNIHandles::make_local(THREAD, trace);
+ JVM_END
  
  JVM_ENTRY(void, JVM_DumpAllStacks(JNIEnv* env, jclass))
    VM_PrintThreads op;
    VMThread::execute(&op);
    if (JvmtiExport::should_post_data_dump()) {

*** 3849,5 ***
--- 3884,80 ---
  JVM_END
  
  JVM_ENTRY_NO_ENV(jint, JVM_FindSignal(const char *name))
    return os::get_signal_number(name);
  JVM_END
+ 
+ JVM_ENTRY(void, JVM_VirtualThreadMountBegin(JNIEnv* env, jobject vthread, jboolean first_mount))
+ #if INCLUDE_JVMTI
+   JvmtiVTMTDisabler::start_VTMT(vthread, 0);
+ #else
+   fatal("Should only be called with JVMTI enabled");
+ #endif
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_VirtualThreadMountEnd(JNIEnv* env, jobject vthread, jboolean first_mount))
+ #if INCLUDE_JVMTI
+   oop vt = JNIHandles::resolve(vthread);
+ 
+   thread->rebind_to_jvmti_thread_state_of(vt);
+ 
+   assert(thread->is_in_VTMT(), "VTMT sanity check");
+   JvmtiVTMTDisabler::finish_VTMT(vthread, 0);
+ 
+   if (first_mount) {
+     // thread start
+     if (JvmtiExport::can_support_virtual_threads()) {
+       if (JvmtiExport::should_post_vthread_start()) {
+         JvmtiExport::post_vthread_start(vthread);
+       }
+     } else { // compatibility for vthread unaware agents: legacy thread_start
+       if (JvmtiExport::should_post_thread_life()) {
+         JvmtiExport::post_thread_start(thread);
+       }
+     }
+   }
+   if (JvmtiExport::should_post_vthread_mount()) {
+     JvmtiExport::post_vthread_mount(vthread);
+   }
+ #else
+   fatal("Should only be called with JVMTI enabled");
+ #endif
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_VirtualThreadUnmountBegin(JNIEnv* env, jobject vthread, jboolean last_unmount))
+ #if INCLUDE_JVMTI
+   HandleMark hm(thread);
+   Handle ct(thread, thread->threadObj());
+ 
+   if (JvmtiExport::should_post_vthread_unmount()) {
+     JvmtiExport::post_vthread_unmount(vthread);
+   }
+   if (last_unmount) {
+     if (JvmtiExport::can_support_virtual_threads()) {
+       if (JvmtiExport::should_post_vthread_end()) {
+         JvmtiExport::post_vthread_end(vthread);
+       }
+     } else { // compatibility for vthread unaware agents: legacy thread_end
+       if (JvmtiExport::should_post_thread_life()) {
+         JvmtiExport::post_thread_end(thread);
+       }
+     }
+     thread->set_mounted_vthread(NULL);
+   }
+ 
+   assert(!thread->is_in_VTMT(), "VTMT sanity check");
+   JvmtiVTMTDisabler::start_VTMT(vthread, 1);
+   thread->rebind_to_jvmti_thread_state_of(ct());
+ #else
+   fatal("Should only be called with JVMTI enabled");
+ #endif
+ JVM_END
+ 
+ JVM_ENTRY(void, JVM_VirtualThreadUnmountEnd(JNIEnv* env, jobject vthread, jboolean last_unmount))
+ #if INCLUDE_JVMTI
+   assert(thread->is_in_VTMT(), "VTMT sanity check");
+   JvmtiVTMTDisabler::finish_VTMT(vthread, 1);
+ #else
+   fatal("Should only be called with JVMTI enabled");
+ #endif
+ JVM_END
< prev index next >