< prev index next >

src/hotspot/share/prims/jvmtiEventController.cpp

Print this page
*** 21,10 ***
--- 21,11 ---
   * questions.
   *
   */
  
  #include "precompiled.hpp"
+ #include "classfile/javaClasses.hpp"
  #include "interpreter/interpreter.hpp"
  #include "jvmtifiles/jvmtiEnv.hpp"
  #include "logging/log.hpp"
  #include "memory/resourceArea.hpp"
  #include "prims/jvmtiEventController.hpp"

*** 86,21 ***
  static const jlong  GARBAGE_COLLECTION_FINISH_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  OBJECT_FREE_BIT = (((jlong)1) << (JVMTI_EVENT_OBJECT_FREE - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  RESOURCE_EXHAUSTED_BIT = (((jlong)1) << (JVMTI_EVENT_RESOURCE_EXHAUSTED - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  VM_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_VM_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  SAMPLED_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_SAMPLED_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL));
  
  // bits for extension events
  static const jlong  CLASS_UNLOAD_BIT = (((jlong)1) << (EXT_EVENT_CLASS_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL));
  
  
  static const jlong  MONITOR_BITS = MONITOR_CONTENDED_ENTER_BIT | MONITOR_CONTENDED_ENTERED_BIT |
                            MONITOR_WAIT_BIT | MONITOR_WAITED_BIT;
  static const jlong  EXCEPTION_BITS = EXCEPTION_THROW_BIT | EXCEPTION_CATCH_BIT;
  static const jlong  INTERP_EVENT_BITS =  SINGLE_STEP_BIT | METHOD_ENTRY_BIT | METHOD_EXIT_BIT |
                                  FRAME_POP_BIT | FIELD_ACCESS_BIT | FIELD_MODIFICATION_BIT;
! static const jlong  THREAD_FILTERED_EVENT_BITS = INTERP_EVENT_BITS | EXCEPTION_BITS | MONITOR_BITS |
                                          BREAKPOINT_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT | THREAD_END_BIT |
                                          SAMPLED_OBJECT_ALLOC_BIT;
  static const jlong  NEED_THREAD_LIFE_EVENTS = THREAD_FILTERED_EVENT_BITS | THREAD_START_BIT;
  static const jlong  EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT |
                                 VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
--- 87,26 ---
  static const jlong  GARBAGE_COLLECTION_FINISH_BIT = (((jlong)1) << (JVMTI_EVENT_GARBAGE_COLLECTION_FINISH - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  OBJECT_FREE_BIT = (((jlong)1) << (JVMTI_EVENT_OBJECT_FREE - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  RESOURCE_EXHAUSTED_BIT = (((jlong)1) << (JVMTI_EVENT_RESOURCE_EXHAUSTED - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  VM_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_VM_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL));
  static const jlong  SAMPLED_OBJECT_ALLOC_BIT = (((jlong)1) << (JVMTI_EVENT_SAMPLED_OBJECT_ALLOC - TOTAL_MIN_EVENT_TYPE_VAL));
+ static const jlong  VTHREAD_START_BIT = (((jlong)1) << (JVMTI_EVENT_VIRTUAL_THREAD_START - TOTAL_MIN_EVENT_TYPE_VAL));
+ static const jlong  VTHREAD_END_BIT = (((jlong)1) << (JVMTI_EVENT_VIRTUAL_THREAD_END - TOTAL_MIN_EVENT_TYPE_VAL));
  
  // bits for extension events
  static const jlong  CLASS_UNLOAD_BIT = (((jlong)1) << (EXT_EVENT_CLASS_UNLOAD - TOTAL_MIN_EVENT_TYPE_VAL));
+ static const jlong  VTHREAD_MOUNT_BIT = (((jlong)1) << (EXT_EVENT_VIRTUAL_THREAD_MOUNT - TOTAL_MIN_EVENT_TYPE_VAL));
+ static const jlong  VTHREAD_UNMOUNT_BIT = (((jlong)1) << (EXT_EVENT_VIRTUAL_THREAD_UNMOUNT - TOTAL_MIN_EVENT_TYPE_VAL));
  
  
+ static const jlong  VTHREAD_BITS = VTHREAD_START_BIT | VTHREAD_END_BIT | VTHREAD_MOUNT_BIT | VTHREAD_UNMOUNT_BIT;
  static const jlong  MONITOR_BITS = MONITOR_CONTENDED_ENTER_BIT | MONITOR_CONTENDED_ENTERED_BIT |
                            MONITOR_WAIT_BIT | MONITOR_WAITED_BIT;
  static const jlong  EXCEPTION_BITS = EXCEPTION_THROW_BIT | EXCEPTION_CATCH_BIT;
  static const jlong  INTERP_EVENT_BITS =  SINGLE_STEP_BIT | METHOD_ENTRY_BIT | METHOD_EXIT_BIT |
                                  FRAME_POP_BIT | FIELD_ACCESS_BIT | FIELD_MODIFICATION_BIT;
! static const jlong  THREAD_FILTERED_EVENT_BITS = INTERP_EVENT_BITS | EXCEPTION_BITS | MONITOR_BITS | VTHREAD_BITS |
                                          BREAKPOINT_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT | THREAD_END_BIT |
                                          SAMPLED_OBJECT_ALLOC_BIT;
  static const jlong  NEED_THREAD_LIFE_EVENTS = THREAD_FILTERED_EVENT_BITS | THREAD_START_BIT;
  static const jlong  EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT | CLASS_LOAD_BIT | CLASS_PREPARE_BIT |
                                 VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |

*** 202,15 ***
    EnterInterpOnlyModeClosure() : HandshakeClosure("EnterInterpOnlyMode"), _completed(false) { }
    void do_thread(Thread* th) {
      JavaThread* jt = JavaThread::cast(th);
      JvmtiThreadState* state = jt->jvmti_thread_state();
  
!     // Set up the current stack depth for later tracking
-     state->invalidate_cur_stack_depth();
- 
      state->enter_interp_only_mode();
  
      if (jt->has_last_Java_frame()) {
        // If running in fullspeed mode, single stepping is implemented
        // as follows: first, the interpreter does not dispatch to
        // compiled code for threads that have single stepping enabled;
        // second, we deoptimize all compiled java frames on the thread's stack when
--- 208,18 ---
    EnterInterpOnlyModeClosure() : HandshakeClosure("EnterInterpOnlyMode"), _completed(false) { }
    void do_thread(Thread* th) {
      JavaThread* jt = JavaThread::cast(th);
      JvmtiThreadState* state = jt->jvmti_thread_state();
  
!     // invalidate_cur_stack_depth is called in enter_interp_only_mode
      state->enter_interp_only_mode();
  
+     if (state->get_thread() != NULL) {
+       // TODO LOOM: find out why the other place where this is called is insufficient 
+       Continuation::set_cont_fastpath_thread_state(state->get_thread());
+     }
+ 
      if (jt->has_last_Java_frame()) {
        // If running in fullspeed mode, single stepping is implemented
        // as follows: first, the interpreter does not dispatch to
        // compiled code for threads that have single stepping enabled;
        // second, we deoptimize all compiled java frames on the thread's stack when

*** 277,11 ***
    static jlong recompute_env_enabled(JvmtiEnvBase* env);
    static jlong recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state);
    static jlong recompute_thread_enabled(JvmtiThreadState *state);
    static void event_init();
  
!   static void set_user_enabled(JvmtiEnvBase *env, JavaThread *thread,
                          jvmtiEvent event_type, bool enabled);
    static void set_event_callbacks(JvmtiEnvBase *env,
                                    const jvmtiEventCallbacks* callbacks,
                                    jint size_of_callbacks);
  
--- 286,11 ---
    static jlong recompute_env_enabled(JvmtiEnvBase* env);
    static jlong recompute_env_thread_enabled(JvmtiEnvThreadState* ets, JvmtiThreadState* state);
    static jlong recompute_thread_enabled(JvmtiThreadState *state);
    static void event_init();
  
!   static void set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, oop thread_oop,
                          jvmtiEvent event_type, bool enabled);
    static void set_event_callbacks(JvmtiEnvBase *env,
                                    const jvmtiEventCallbacks* callbacks,
                                    jint size_of_callbacks);
  

*** 337,15 ***
  }
  
  
  void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) {
    EC_TRACE(("[%s] # Entering interpreter only mode",
!             JvmtiTrace::safe_get_thread_name(state->get_thread())));
    EnterInterpOnlyModeClosure hs;
    JavaThread *target = state->get_thread();
    Thread *current = Thread::current();
!   if (target->is_handshake_safe_for(current)) {
      hs.do_thread(target);
    } else {
      Handshake::execute(&hs, target);
      guarantee(hs.completed(), "Handshake failed: Target thread is not alive?");
    }
--- 346,22 ---
  }
  
  
  void JvmtiEventControllerPrivate::enter_interp_only_mode(JvmtiThreadState *state) {
    EC_TRACE(("[%s] # Entering interpreter only mode",
!             JvmtiTrace::safe_get_thread_name(state->get_thread_or_saved())));
    EnterInterpOnlyModeClosure hs;
    JavaThread *target = state->get_thread();
    Thread *current = Thread::current();
! 
+   // TBD: This is TMP workaround. We need a proper synchronization here.
+   if (target == NULL) {
+     state->enter_interp_only_mode(); // increment _saved_interp_only_mode
+     return;
+   }
+ 
+ if (target->is_handshake_safe_for(current)) {
      hs.do_thread(target);
    } else {
      Handshake::execute(&hs, target);
      guarantee(hs.completed(), "Handshake failed: Target thread is not alive?");
    }

*** 353,11 ***
  
  
  void
  JvmtiEventControllerPrivate::leave_interp_only_mode(JvmtiThreadState *state) {
    EC_TRACE(("[%s] # Leaving interpreter only mode",
!             JvmtiTrace::safe_get_thread_name(state->get_thread())));
    state->leave_interp_only_mode();
  }
  
  
  void
--- 369,11 ---
  
  
  void
  JvmtiEventControllerPrivate::leave_interp_only_mode(JvmtiThreadState *state) {
    EC_TRACE(("[%s] # Leaving interpreter only mode",
!             JvmtiTrace::safe_get_thread_name(state->get_thread_or_saved())));
    state->leave_interp_only_mode();
  }
  
  
  void

*** 369,11 ***
      for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
        jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei);
        if (changed & bit) {
          // it changed, print it
           log_trace(jvmti)("[%s] # %s event %s",
!                       JvmtiTrace::safe_get_thread_name(state->get_thread()),
                        (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei));
        }
      }
    }
  #endif /*JVMTI_TRACE */
--- 385,11 ---
      for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
        jlong bit = JvmtiEventEnabled::bit_for((jvmtiEvent)ei);
        if (changed & bit) {
          // it changed, print it
           log_trace(jvmti)("[%s] # %s event %s",
!                       JvmtiTrace::safe_get_thread_name(state->get_thread_or_saved()),
                        (now_enabled & bit)? "Enabling" : "Disabling", JvmtiTrace::event_name((jvmtiEvent)ei));
        }
      }
    }
  #endif /*JVMTI_TRACE */

*** 526,11 ***
  JvmtiEventControllerPrivate::recompute_thread_enabled(JvmtiThreadState *state) {
    if (state == NULL) {
      // associated JavaThread is exiting
      return (jlong)0;
    }
- 
    julong was_any_env_enabled = state->thread_event_enable()->_event_enabled.get_bits();
    julong any_env_enabled = 0;
    // JVMTI_EVENT_FRAME_POP can be disabled (in the case FRAME_POP_BIT is not set),
    // but we need to set interp_only if some JvmtiEnvThreadState has frame pop set
    // to clear the request
--- 542,10 ---

*** 549,13 ***
  
    if (any_env_enabled != was_any_env_enabled) {
      // mark if event is truly enabled on this thread in any environment
      state->thread_event_enable()->_event_enabled.set_bits(any_env_enabled);
  
!     // update the JavaThread cached value for thread-specific should_post_on_exceptions value
!     bool should_post_on_exceptions = (any_env_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0;
!     state->set_should_post_on_exceptions(should_post_on_exceptions);
    }
  
    // compute interp_only mode
    bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0 || has_frame_pops;
    bool is_now_interp = state->is_interp_only_mode();
--- 564,19 ---
  
    if (any_env_enabled != was_any_env_enabled) {
      // mark if event is truly enabled on this thread in any environment
      state->thread_event_enable()->_event_enabled.set_bits(any_env_enabled);
  
!     // pointer to JavaThread can be NULL for unmouted virtual thread
!     if (state->get_thread() != NULL) {
!       // update the JavaThread cached value for thread-specific should_post_on_exceptions value
+       bool should_post_on_exceptions = (any_env_enabled & SHOULD_POST_ON_EXCEPTIONS_BITS) != 0;
+       state->set_should_post_on_exceptions(should_post_on_exceptions);
+     }
+   }
+   if (state->get_thread() == NULL) {
+     return any_env_enabled;
    }
  
    // compute interp_only mode
    bool should_be_interp = (any_env_enabled & INTERP_EVENT_BITS) != 0 || has_frame_pops;
    bool is_now_interp = state->is_interp_only_mode();

*** 566,10 ***
--- 587,15 ---
      } else {
        leave_interp_only_mode(state);
      }
    }
  
+   // TBD: there is a race here, so get_thread() can return NULL below.
+   if (state->get_thread() != NULL) {
+     Continuation::set_cont_fastpath_thread_state(state->get_thread());
+   }
+ 
    return any_env_enabled;
  }
  
  
  // Compute truly enabled events - meaning if the event can and could be

*** 595,11 ***
    julong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits();
    julong any_env_thread_enabled = 0;
  
    EC_TRACE(("[-] # recompute enabled - before " JULONG_FORMAT_X, was_any_env_thread_enabled));
  
!   // compute non-thread-filters events.
    // This must be done separately from thread-filtered events, since some
    // events can occur before any threads exist.
    JvmtiEnvIterator it;
    for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
      any_env_thread_enabled |= recompute_env_enabled(env);
--- 621,11 ---
    julong was_any_env_thread_enabled = JvmtiEventController::_universal_global_event_enabled.get_bits();
    julong any_env_thread_enabled = 0;
  
    EC_TRACE(("[-] # recompute enabled - before " JULONG_FORMAT_X, was_any_env_thread_enabled));
  
!   // Compute non-thread-filtered events.
    // This must be done separately from thread-filtered events, since some
    // events can occur before any threads exist.
    JvmtiEnvIterator it;
    for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
      any_env_thread_enabled |= recompute_env_enabled(env);

*** 608,12 ***
    // We need to create any missing jvmti_thread_state if there are globally set thread
    // filtered events and there weren't last time
    if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
        (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
      for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
!       // state_for_while_locked() makes tp->is_exiting() check
!       JvmtiThreadState::state_for_while_locked(tp);  // create the thread state if missing
      }
    }
  
    // compute and set thread-filtered events
    for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) {
--- 634,20 ---
    // We need to create any missing jvmti_thread_state if there are globally set thread
    // filtered events and there weren't last time
    if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
        (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
      for (JavaThreadIteratorWithHandle jtiwh; JavaThread *tp = jtiwh.next(); ) {
!       oop jt_oop = tp->threadObj();
! 
+       // create the thread state if missing, state_for_while_locked() makes tp->is_exiting() check
+       JvmtiThreadState* state = JvmtiThreadState::state_for_while_locked(tp, jt_oop);
+ 
+       // create the thread state for mounted virtual thread if missing
+       oop vt_oop = tp->mounted_vthread();
+       if (vt_oop != NULL && java_lang_VirtualThread::is_instance(vt_oop)) {
+         state = JvmtiThreadState::state_for_while_locked(tp, vt_oop);
+       } 
      }
    }
  
    // compute and set thread-filtered events
    for (JvmtiThreadState *state = JvmtiThreadState::first(); state != NULL; state = state->next()) {

*** 642,10 ***
--- 676,14 ---
      JvmtiExport::set_should_post_resource_exhausted((any_env_thread_enabled & RESOURCE_EXHAUSTED_BIT) != 0);
      JvmtiExport::set_should_post_compiled_method_load((any_env_thread_enabled & COMPILED_METHOD_LOAD_BIT) != 0);
      JvmtiExport::set_should_post_compiled_method_unload((any_env_thread_enabled & COMPILED_METHOD_UNLOAD_BIT) != 0);
      JvmtiExport::set_should_post_vm_object_alloc((any_env_thread_enabled & VM_OBJECT_ALLOC_BIT) != 0);
      JvmtiExport::set_should_post_sampled_object_alloc((any_env_thread_enabled & SAMPLED_OBJECT_ALLOC_BIT) != 0);
+     JvmtiExport::set_should_post_vthread_start((any_env_thread_enabled & VTHREAD_START_BIT) != 0);
+     JvmtiExport::set_should_post_vthread_end((any_env_thread_enabled & VTHREAD_END_BIT) != 0);
+     JvmtiExport::set_should_post_vthread_mount((any_env_thread_enabled & VTHREAD_MOUNT_BIT) != 0);
+     JvmtiExport::set_should_post_vthread_unmount((any_env_thread_enabled & VTHREAD_UNMOUNT_BIT) != 0);
  
      // need this if we want thread events or we need them to init data
      JvmtiExport::set_should_post_thread_life((any_env_thread_enabled & NEED_THREAD_LIFE_EVENTS) != 0);
  
      // If single stepping is turned on or off, execute the VM op to change it.

*** 717,11 ***
  
    // May be changing the event handler for ObjectFree.
    flush_object_free_events(env);
  
    env->set_event_callbacks(callbacks, size_of_callbacks);
!   jlong enabled_bits = 0;
    for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
      jvmtiEvent evt_t = (jvmtiEvent)ei;
      if (env->has_callback(evt_t)) {
        enabled_bits |= JvmtiEventEnabled::bit_for(evt_t);
      }
--- 755,12 ---
  
    // May be changing the event handler for ObjectFree.
    flush_object_free_events(env);
  
    env->set_event_callbacks(callbacks, size_of_callbacks);
!   jlong enabled_bits = env->env_event_enable()->_event_callback_enabled.get_bits();
+ 
    for (int ei = JVMTI_MIN_EVENT_TYPE_VAL; ei <= JVMTI_MAX_EVENT_TYPE_VAL; ++ei) {
      jvmtiEvent evt_t = (jvmtiEvent)ei;
      if (env->has_callback(evt_t)) {
        enabled_bits |= JvmtiEventEnabled::bit_for(evt_t);
      }

*** 751,18 ***
    // Prevent a possible race condition where events are re-enabled by a call to
    // set event callbacks, where the DisposeEnvironment occurs after the boiler-plate
    // environment check and before the lock is acquired.
    // We can safely do the is_valid check now, as JvmtiThreadState_lock is held.
    bool enabling = (callback != NULL) && (env->is_valid());
-   env->env_event_enable()->set_user_enabled(event_type, enabling);
  
    // update the callback
    jvmtiExtEventCallbacks* ext_callbacks = env->ext_callbacks();
    switch (extension_event_index) {
      case EXT_EVENT_CLASS_UNLOAD :
        ext_callbacks->ClassUnload = callback;
        break;
      default:
        ShouldNotReachHere();
    }
  
    // update the callback enable/disable bit
--- 790,23 ---
    // Prevent a possible race condition where events are re-enabled by a call to
    // set event callbacks, where the DisposeEnvironment occurs after the boiler-plate
    // environment check and before the lock is acquired.
    // We can safely do the is_valid check now, as JvmtiThreadState_lock is held.
    bool enabling = (callback != NULL) && (env->is_valid());
  
    // update the callback
    jvmtiExtEventCallbacks* ext_callbacks = env->ext_callbacks();
    switch (extension_event_index) {
      case EXT_EVENT_CLASS_UNLOAD :
        ext_callbacks->ClassUnload = callback;
        break;
+     case EXT_EVENT_VIRTUAL_THREAD_MOUNT :
+       ext_callbacks->VirtualThreadMount = callback;
+       break;
+     case EXT_EVENT_VIRTUAL_THREAD_UNMOUNT :
+       ext_callbacks->VirtualThreadUnmount = callback;
+       break;
      default:
        ShouldNotReachHere();
    }
  
    // update the callback enable/disable bit

*** 820,11 ***
    env->env_dispose();
  }
  
  
  void
! JvmtiEventControllerPrivate::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread,
                                            jvmtiEvent event_type, bool enabled) {
    assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  
    EC_TRACE(("[%s] # user %s event %s",
              thread==NULL? "ALL": JvmtiTrace::safe_get_thread_name(thread),
--- 864,11 ---
    env->env_dispose();
  }
  
  
  void
! JvmtiEventControllerPrivate::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, oop thread_oop,
                                            jvmtiEvent event_type, bool enabled) {
    assert(Threads::number_of_threads() == 0 || JvmtiThreadState_lock->is_locked(), "sanity check");
  
    EC_TRACE(("[%s] # user %s event %s",
              thread==NULL? "ALL": JvmtiTrace::safe_get_thread_name(thread),

*** 832,15 ***
  
    if (event_type == JVMTI_EVENT_OBJECT_FREE) {
      flush_object_free_events(env);
    }
  
!   if (thread == NULL) {
      env->env_event_enable()->set_user_enabled(event_type, enabled);
    } else {
      // create the thread state (if it didn't exist before)
!     JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread);
      if (state != NULL) {
        state->env_thread_state(env)->event_enable()->set_user_enabled(event_type, enabled);
      }
    }
    recompute_enabled();
--- 876,15 ---
  
    if (event_type == JVMTI_EVENT_OBJECT_FREE) {
      flush_object_free_events(env);
    }
  
!   if (thread == NULL && thread_oop == NULL) { // thread can be NULL for unmounted virtual trheads
      env->env_event_enable()->set_user_enabled(event_type, enabled);
    } else {
      // create the thread state (if it didn't exist before)
!     JvmtiThreadState *state = JvmtiThreadState::state_for_while_locked(thread, thread_oop);
      if (state != NULL) {
        state->env_thread_state(env)->event_enable()->set_user_enabled(event_type, enabled);
      }
    }
    recompute_enabled();

*** 848,40 ***
  
  
  void
  JvmtiEventControllerPrivate::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    EC_TRACE(("[%s] # set frame pop - frame=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread()),
              fpop.frame_number() ));
  
    ets->get_frame_pops()->set(fpop);
!   recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
  }
  
  
  void
  JvmtiEventControllerPrivate::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    EC_TRACE(("[%s] # clear frame pop - frame=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread()),
              fpop.frame_number() ));
  
    ets->get_frame_pops()->clear(fpop);
!   recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
  }
  
  
  void
  JvmtiEventControllerPrivate::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    int cleared_cnt = ets->get_frame_pops()->clear_to(fpop);
  
    EC_TRACE(("[%s] # clear to frame pop - frame=%d, count=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread()),
              fpop.frame_number(),
              cleared_cnt ));
  
    if (cleared_cnt > 0) {
!     recompute_thread_enabled(ets->get_thread()->jvmti_thread_state());
    }
  }
  
  void
  JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool added) {
--- 892,40 ---
  
  
  void
  JvmtiEventControllerPrivate::set_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    EC_TRACE(("[%s] # set frame pop - frame=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread_or_saved()),
              fpop.frame_number() ));
  
    ets->get_frame_pops()->set(fpop);
!   recompute_thread_enabled(ets->jvmti_thread_state());
  }
  
  
  void
  JvmtiEventControllerPrivate::clear_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    EC_TRACE(("[%s] # clear frame pop - frame=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread_or_saved()),
              fpop.frame_number() ));
  
    ets->get_frame_pops()->clear(fpop);
!   recompute_thread_enabled(ets->jvmti_thread_state());
  }
  
  
  void
  JvmtiEventControllerPrivate::clear_to_frame_pop(JvmtiEnvThreadState *ets, JvmtiFramePop fpop) {
    int cleared_cnt = ets->get_frame_pops()->clear_to(fpop);
  
    EC_TRACE(("[%s] # clear to frame pop - frame=%d, count=%d",
!             JvmtiTrace::safe_get_thread_name(ets->get_thread_or_saved()),
              fpop.frame_number(),
              cleared_cnt ));
  
    if (cleared_cnt > 0) {
!     recompute_thread_enabled(ets->jvmti_thread_state());
    }
  }
  
  void
  JvmtiEventControllerPrivate::change_field_watch(jvmtiEvent event_type, bool added) {

*** 979,18 ***
    jlong bit_for = ((jlong)1) << (event_type - TOTAL_MIN_EVENT_TYPE_VAL);
    return((bit_for & GLOBAL_EVENT_BITS)!=0);
  }
  
  void
! JvmtiEventController::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, jvmtiEvent event_type, bool enabled) {
    if (Threads::number_of_threads() == 0) {
      // during early VM start-up locks don't exist, but we are safely single threaded,
      // call the functionality without holding the JvmtiThreadState_lock.
!     JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled);
    } else {
      MutexLocker mu(JvmtiThreadState_lock);
!     JvmtiEventControllerPrivate::set_user_enabled(env, thread, event_type, enabled);
    }
  }
  
  
  void
--- 1023,22 ---
    jlong bit_for = ((jlong)1) << (event_type - TOTAL_MIN_EVENT_TYPE_VAL);
    return((bit_for & GLOBAL_EVENT_BITS)!=0);
  }
  
  void
! JvmtiEventController::set_user_enabled(JvmtiEnvBase *env, JavaThread *thread, oop thread_oop,
+                                        jvmtiEvent event_type, bool enabled) {
    if (Threads::number_of_threads() == 0) {
      // during early VM start-up locks don't exist, but we are safely single threaded,
      // call the functionality without holding the JvmtiThreadState_lock.
!     JvmtiEventControllerPrivate::set_user_enabled(env, thread, NULL, event_type, enabled);
    } else {
+     Thread* current_thread = Thread::current();
+     HandleMark hm(current_thread);
+     Handle thread_oop_h = Handle(current_thread, thread_oop);
      MutexLocker mu(JvmtiThreadState_lock);
!     JvmtiEventControllerPrivate::set_user_enabled(env, thread, thread_oop_h(), event_type, enabled);
    }
  }
  
  
  void
< prev index next >