< prev index next >

src/hotspot/share/prims/jvmtiEnvThreadState.cpp

Print this page
@@ -25,10 +25,11 @@
  #include "precompiled.hpp"
  #include "interpreter/interpreter.hpp"
  #include "jvmtifiles/jvmtiEnv.hpp"
  #include "memory/resourceArea.hpp"
  #include "prims/jvmtiEnvThreadState.hpp"
+ #include "prims/jvmtiThreadState.inline.hpp"
  #include "prims/jvmtiEventController.inline.hpp"
  #include "prims/jvmtiImpl.hpp"
  #include "runtime/handles.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"

@@ -124,13 +125,13 @@
  //
  // Instances of JvmtiEnvThreadState hang off of each JvmtiThreadState,
  // one per JvmtiEnv.
  //
  
- JvmtiEnvThreadState::JvmtiEnvThreadState(JavaThread *thread, JvmtiEnvBase *env) :
+ JvmtiEnvThreadState::JvmtiEnvThreadState(JvmtiThreadState* state, JvmtiEnvBase *env) :
    _event_enable() {
-   _thread                 = thread;
+   _state                  = state;
    _env                    = (JvmtiEnv*)env;
    _next                   = NULL;
    _frame_pops             = NULL;
    _current_bci            = 0;
    _current_method_id      = NULL;

@@ -142,10 +143,32 @@
  JvmtiEnvThreadState::~JvmtiEnvThreadState()   {
    delete _frame_pops;
    _frame_pops = NULL;
  }
  
+ bool JvmtiEnvThreadState::is_virtual() {
+   return _state->is_virtual();
+ }
+ 
+ // Use _thread_saved if cthread is detached from JavaThread (_thread == NULL).
+ JavaThread* JvmtiEnvThreadState::get_thread_or_saved() {
+   return _state->get_thread_or_saved();
+ }
+ 
+ JavaThread* JvmtiEnvThreadState::get_thread() {
+   return _state->get_thread();
+ }
+ 
+ void* JvmtiEnvThreadState::get_agent_thread_local_storage_data() {
+   return _agent_thread_local_storage_data;
+ }
+ 
+ void JvmtiEnvThreadState::set_agent_thread_local_storage_data (void *data) {
+   _agent_thread_local_storage_data = data;
+ }
+ 
+ 
  // Given that a new (potential) event has come in,
  // maintain the current JVMTI location on a per-thread per-env basis
  // and use it to filter out duplicate events:
  // - instruction rewrites
  // - breakpoint followed by single step

@@ -191,12 +214,12 @@
  
  JvmtiFramePops* JvmtiEnvThreadState::get_frame_pops() {
  #ifdef ASSERT
    Thread *current = Thread::current();
  #endif
-   assert(get_thread()->is_handshake_safe_for(current),
-          "frame pop data only accessible from same thread or direct handshake");
+   assert(get_thread() == NULL || get_thread()->is_handshake_safe_for(current),
+          "frame pop data only accessible from same or detached thread or direct handshake");
    if (_frame_pops == NULL) {
      _frame_pops = new JvmtiFramePops();
      assert(_frame_pops != NULL, "_frame_pops != NULL");
    }
    return _frame_pops;

@@ -209,41 +232,79 @@
  
  void JvmtiEnvThreadState::set_frame_pop(int frame_number) {
  #ifdef ASSERT
    Thread *current = Thread::current();
  #endif
-   assert(get_thread()->is_handshake_safe_for(current),
-          "frame pop data only accessible from same thread or direct handshake");
+   assert(get_thread() == NULL || get_thread()->is_handshake_safe_for(current),
+          "frame pop data only accessible from same or detached thread or direct handshake");
    JvmtiFramePop fpop(frame_number);
    JvmtiEventController::set_frame_pop(this, fpop);
  }
  
  
  void JvmtiEnvThreadState::clear_frame_pop(int frame_number) {
  #ifdef ASSERT
    Thread *current = Thread::current();
  #endif
-   assert(get_thread()->is_handshake_safe_for(current),
-          "frame pop data only accessible from same thread or direct handshake");
+   assert(get_thread() == NULL || get_thread()->is_handshake_safe_for(current),
+          "frame pop data only accessible from same or detached thread or direct handshake");
    JvmtiFramePop fpop(frame_number);
    JvmtiEventController::clear_frame_pop(this, fpop);
  }
  
  
  bool JvmtiEnvThreadState::is_frame_pop(int cur_frame_number) {
  #ifdef ASSERT
    Thread *current = Thread::current();
  #endif
-   assert(get_thread()->is_handshake_safe_for(current),
-          "frame pop data only accessible from same thread or direct handshake");
-   if (!get_thread()->is_interp_only_mode() || _frame_pops == NULL) {
+   assert(get_thread() == NULL || get_thread()->is_handshake_safe_for(current),
+          "frame pop data only accessible from same or detached thread or direct handshake");
+   if (!jvmti_thread_state()->is_interp_only_mode() || _frame_pops == NULL) {
      return false;
    }
    JvmtiFramePop fp(cur_frame_number);
    return get_frame_pops()->contains(fp);
  }
  
+ class VM_VThreadGetCurrentLocation : public VM_Operation {
+  private:
+    Handle _vthread_h;
+    jmethodID _method_id;
+    int _bci;
+    bool _completed;
+ 
+  public:
+   VM_VThreadGetCurrentLocation(Handle vthread_h)
+     : _vthread_h(vthread_h),
+       _method_id(NULL),
+       _bci(0),
+       _completed(false)
+   {}
+ 
+   VMOp_Type type() const { return VMOp_VThreadGetCurrentLocation; }
+   void doit() {
+     if (!JvmtiEnvBase::is_vthread_alive(_vthread_h())) {
+       return; // _completed remains false
+     }
+     ResourceMark rm;
+     javaVFrame* jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h());
+ 
+     if (jvf != NULL) { // TBD: jvf can be NULL, most likely, when vthread is exiting
+       Method* method = jvf->method();
+       _method_id = method->jmethod_id();
+       _bci = jvf->bci();
+     }
+     _completed = true;
+   }
+   void get_current_location(jmethodID *method_id, int *bci) {
+     *method_id = _method_id;
+     *bci = _bci;
+   }
+   bool completed() {
+     return _completed;
+   }
+ };
  
  class GetCurrentLocationClosure : public HandshakeClosure {
   private:
     jmethodID _method_id;
     int _bci;

@@ -306,21 +367,41 @@
    // to detect any duplicate events.
  
    if (enabled) {
      // If enabling breakpoint, no need to reset.
      // Can't do anything if empty stack.
-     if (event_type == JVMTI_EVENT_SINGLE_STEP && _thread->has_last_Java_frame()) {
+ 
+     JavaThread* thread = get_thread_or_saved();
+ 
+     oop thread_oop = jvmti_thread_state()->get_thread_oop();
+ 
+     // Check for an unmounted virual thread case.
+     if (thread == NULL && event_type == JVMTI_EVENT_SINGLE_STEP && is_virtual()) {
+       jmethodID method_id;
+       int bci;
+       JavaThread* cur_thread = JavaThread::current();
+       HandleMark hm(cur_thread);
+       VM_VThreadGetCurrentLocation op(Handle(cur_thread, thread_oop));
+       VMThread::execute(&op);
+       // do nothing if virtual thread has been already terminated
+       if (op.completed()) {
+         op.get_current_location(&method_id, &bci);
+         set_current_location(method_id, bci);
+       }
+       return;
+     }
+     if (event_type == JVMTI_EVENT_SINGLE_STEP && thread->has_last_Java_frame()) {
        jmethodID method_id;
        int bci;
        // The java thread stack may not be walkable for a running thread
        // so get current location with direct handshake.
        GetCurrentLocationClosure op;
        Thread *current = Thread::current();
-       if (_thread->is_handshake_safe_for(current)) {
-         op.do_thread(_thread);
+       if (thread->is_handshake_safe_for(current)) {
+         op.do_thread(thread);
        } else {
-         Handshake::execute(&op, _thread);
+         Handshake::execute(&op, thread);
          guarantee(op.completed(), "Handshake failed. Target thread is not alive?");
        }
        op.get_current_location(&method_id, &bci);
        set_current_location(method_id, bci);
      }
< prev index next >