< prev index next >

src/hotspot/share/runtime/objectMonitor.cpp

Print this page
*** 302,17 ***
--- 302,32 ---
    _wait_set_lock(0)
  { }
  
  ObjectMonitor::~ObjectMonitor() {
    _object.release(_oop_storage);
+   _object_strong.release(JavaThread::thread_oop_storage());
  }
  
  oop ObjectMonitor::object() const {
    check_object_context();
    return _object.resolve();
  }
  
+ // Keep object protected during ObjectLocker preemption.
+ void ObjectMonitor::set_object_strong() {
+   check_object_context();
+   if (_object_strong.is_empty()) {
+     if (Thread::TrySpinAcquire(&_object_strong_lock)) {
+       if (_object_strong.is_empty()) {
+         assert(_object.resolve() != nullptr, "");
+         _object_strong = OopHandle(JavaThread::thread_oop_storage(), _object.resolve());
+       }
+       Thread::SpinRelease(&_object_strong_lock);
+     }
+   }
+ }
+ 
  void ObjectMonitor::ExitOnSuspend::operator()(JavaThread* current) {
    if (current->is_suspended()) {
      _om->_recursions = 0;
      _om->clear_successor();
      // Don't need a full fence after clearing successor here because of the call to exit().

*** 1811,11 ***
        JvmtiExport::post_monitor_wait(current, object(), millis);
      }
      current->set_current_waiting_monitor(this);
      result = Continuation::try_preempt(current, ce->cont_oop(current));
      if (result == freeze_ok) {
!       vthread_wait(current, millis);
        current->set_current_waiting_monitor(nullptr);
        return;
      }
    }
    // The jtiows does nothing for non-interruptible.
--- 1826,11 ---
        JvmtiExport::post_monitor_wait(current, object(), millis);
      }
      current->set_current_waiting_monitor(this);
      result = Continuation::try_preempt(current, ce->cont_oop(current));
      if (result == freeze_ok) {
!       vthread_wait(current, millis, interruptible);
        current->set_current_waiting_monitor(nullptr);
        return;
      }
    }
    // The jtiows does nothing for non-interruptible.

*** 2168,16 ***
    if ((tally > 0) && event.should_commit()) {
      post_monitor_notify_event(&event, this, /* notified_count = */ tally);
    }
  }
  
! void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis) {
    oop vthread = current->vthread();
    ObjectWaiter* node = new ObjectWaiter(vthread, this);
    node->_is_wait = true;
    node->TState = ObjectWaiter::TS_WAIT;
    java_lang_VirtualThread::set_notified(vthread, false);  // Reset notified flag
  
    // Enter the waiting queue, which is a circular doubly linked list in this case
    // but it could be a priority queue or any data structure.
    // _wait_set_lock protects the wait queue.  Normally the wait queue is accessed only
    // by the owner of the monitor *except* in the case where park()
--- 2183,18 ---
    if ((tally > 0) && event.should_commit()) {
      post_monitor_notify_event(&event, this, /* notified_count = */ tally);
    }
  }
  
! void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis, bool interruptible) {
    oop vthread = current->vthread();
    ObjectWaiter* node = new ObjectWaiter(vthread, this);
    node->_is_wait = true;
+   node->_interruptible = interruptible;
    node->TState = ObjectWaiter::TS_WAIT;
    java_lang_VirtualThread::set_notified(vthread, false);  // Reset notified flag
+   java_lang_VirtualThread::set_interruptible_wait(vthread, interruptible);
  
    // Enter the waiting queue, which is a circular doubly linked list in this case
    // but it could be a priority queue or any data structure.
    // _wait_set_lock protects the wait queue.  Normally the wait queue is accessed only
    // by the owner of the monitor *except* in the case where park()

*** 2219,15 ***
    // If this was an interrupted case, set the _interrupted boolean so that
    // once we re-acquire the monitor we know if we need to throw IE or not.
    ObjectWaiter::TStates state = node->TState;
    bool was_notified = state == ObjectWaiter::TS_ENTER;
    assert(was_notified || state == ObjectWaiter::TS_RUN, "");
!   node->_interrupted = !was_notified && current->is_interrupted(false);
  
!   // Post JFR and JVMTI events.
    EventJavaMonitorWait wait_event;
!   if (wait_event.should_commit() || JvmtiExport::should_post_monitor_waited()) {
      vthread_monitor_waited_event(current, node, cont, &wait_event, !was_notified && !node->_interrupted);
    }
  
    // Mark that we are at reenter so that we don't call this method again.
    node->_at_reenter = true;
--- 2236,16 ---
    // If this was an interrupted case, set the _interrupted boolean so that
    // once we re-acquire the monitor we know if we need to throw IE or not.
    ObjectWaiter::TStates state = node->TState;
    bool was_notified = state == ObjectWaiter::TS_ENTER;
    assert(was_notified || state == ObjectWaiter::TS_RUN, "");
!   node->_interrupted = node->_interruptible && !was_notified && current->is_interrupted(false);
  
!   // Post JFR and JVMTI events. If non-interruptible we are in
+   // ObjectLocker case so we don't post anything.
    EventJavaMonitorWait wait_event;
!   if (node->_interruptible && (wait_event.should_commit() || JvmtiExport::should_post_monitor_waited())) {
      vthread_monitor_waited_event(current, node, cont, &wait_event, !was_notified && !node->_interrupted);
    }
  
    // Mark that we are at reenter so that we don't call this method again.
    node->_at_reenter = true;
< prev index next >