< prev index next >

src/hotspot/share/runtime/objectMonitor.cpp

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

@@ -37,10 +37,11 @@
  #include "oops/oopHandle.inline.hpp"
  #include "oops/weakHandle.inline.hpp"
  #include "prims/jvmtiDeferredUpdates.hpp"
  #include "prims/jvmtiExport.hpp"
  #include "runtime/atomic.hpp"
+ #include "runtime/globals.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/interfaceSupport.inline.hpp"
  #include "runtime/mutexLocker.hpp"
  #include "runtime/objectMonitor.hpp"
  #include "runtime/objectMonitor.inline.hpp"

@@ -51,10 +52,11 @@
  #include "runtime/safepointMechanism.inline.hpp"
  #include "runtime/sharedRuntime.hpp"
  #include "runtime/thread.inline.hpp"
  #include "services/threadService.hpp"
  #include "utilities/dtrace.hpp"
+ #include "utilities/globalDefinitions.hpp"
  #include "utilities/macros.hpp"
  #include "utilities/preserveException.hpp"
  #if INCLUDE_JFR
  #include "jfr/support/jfrFlush.hpp"
  #endif

@@ -316,11 +318,74 @@
  }
  
  // -----------------------------------------------------------------------------
  // Enter support
  
+ bool ObjectMonitor::enter_for(JavaThread* locking_thread) {
+   // Used by ObjectSynchronizer::enter_for to enter for another thread.
+   // The monitor is private to or already owned by locking_thread which must be suspended.
+   // So this code may only contend with deflation.
+   assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be");
+ 
+   // Block out deflation as soon as possible.
+   add_to_contentions(1);
+ 
+   bool success = false;
+   if (!is_being_async_deflated()) {
+     void* prev_owner = try_set_owner_from(nullptr, locking_thread);
+ 
+     if (prev_owner == nullptr) {
+       assert(_recursions == 0, "invariant");
+       success = true;
+     } else if (prev_owner == locking_thread) {
+       _recursions++;
+       success = true;
+     } else if (prev_owner == DEFLATER_MARKER) {
+       // Racing with deflation.
+       prev_owner = try_set_owner_from(DEFLATER_MARKER, locking_thread);
+       if (prev_owner == DEFLATER_MARKER) {
+         // Cancelled deflation. Increment contentions as part of the deflation protocol.
+         add_to_contentions(1);
+         success = true;
+       } else if (prev_owner == nullptr) {
+         // At this point we cannot race with deflation as we have both incremented
+         // contentions, seen contention > 0 and seen a DEFLATER_MARKER.
+         // success will only be false if this races with something other than
+         // deflation.
+         prev_owner = try_set_owner_from(nullptr, locking_thread);
+         success = prev_owner == nullptr;
+       }
+     } else if (LockingMode == LM_LEGACY && locking_thread->is_lock_owned((address)prev_owner)) {
+       assert(_recursions == 0, "must be");
+       _recursions = 1;
+       set_owner_from_BasicLock(prev_owner, locking_thread);
+       success = true;
+     }
+     assert(success, "Failed to enter_for: locking_thread=" INTPTR_FORMAT
+            ", this=" INTPTR_FORMAT "{owner=" INTPTR_FORMAT "}, observed owner: " INTPTR_FORMAT,
+            p2i(locking_thread), p2i(this), p2i(owner_raw()), p2i(prev_owner));
+   } else {
+     // Async deflation is in progress and our contentions increment
+     // above lost the race to async deflation. Undo the work and
+     // force the caller to retry.
+     const oop l_object = object();
+     if (l_object != nullptr) {
+       // Attempt to restore the header/dmw to the object's header so that
+       // we only retry once if the deflater thread happens to be slow.
+       install_displaced_markword_in_object(l_object);
+     }
+   }
+ 
+   add_to_contentions(-1);
+ 
+   assert(!success || owner_raw() == locking_thread, "must be");
+ 
+   return success;
+ }
+ 
  bool ObjectMonitor::enter(JavaThread* current) {
+   assert(current == JavaThread::current(), "must be");
    // The following code is ordered to check the most common cases first
    // and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
  
    void* cur = try_set_owner_from(NULL, current);
    if (cur == NULL) {

@@ -332,11 +397,11 @@
      // TODO-FIXME: check for integer overflow!  BUGID 6557169.
      _recursions++;
      return true;
    }
  
-   if (current->is_lock_owned((address)cur)) {
+   if (LockingMode != LM_LIGHTWEIGHT && current->is_lock_owned((address)cur)) {
      assert(_recursions == 0, "internal state error");
      _recursions = 1;
      set_owner_from_BasicLock(cur, current);  // Convert from BasicLock* to Thread*.
      return true;
    }

@@ -598,10 +663,26 @@
    // We leave owner == DEFLATER_MARKER and contentions < 0
    // to force any racing threads to retry.
    return true;  // Success, ObjectMonitor has been deflated.
  }
  
+ // We might access the dead object headers for parsable heap walk, make sure
+ // headers are in correct shape, e.g. monitors deflated.
+ void ObjectMonitor::maybe_deflate_dead(oop* p) {
+   oop obj = *p;
+   assert(obj != NULL, "must not yet been cleared");
+   markWord mark = obj->mark();
+   if (mark.has_monitor()) {
+     ObjectMonitor* monitor = mark.monitor();
+     if (p == monitor->_object.ptr_raw()) {
+       assert(monitor->object_peek() == obj, "lock object must match");
+       markWord dmw = monitor->header();
+       obj->set_mark(dmw);
+     }
+   }
+ }
+ 
  // Install the displaced mark word (dmw) of a deflating ObjectMonitor
  // into the header of the object associated with the monitor. This
  // idempotent method is called by a thread that is deflating a
  // monitor and by other threads that have detected a race with the
  // deflation process.

@@ -1133,11 +1214,11 @@
  // of such futile wakups is low.
  
  void ObjectMonitor::exit(JavaThread* current, bool not_suspended) {
    void* cur = owner_raw();
    if (current != cur) {
-     if (current->is_lock_owned((address)cur)) {
+     if (LockingMode != LM_LIGHTWEIGHT && current->is_lock_owned((address)cur)) {
        assert(_recursions == 0, "invariant");
        set_owner_from_BasicLock(cur, current);  // Convert from BasicLock* to Thread*.
        _recursions = 0;
      } else {
        // Apparent unbalanced locking ...

@@ -1353,11 +1434,11 @@
  intx ObjectMonitor::complete_exit(JavaThread* current) {
    assert(InitDone, "Unexpectedly not initialized");
  
    void* cur = owner_raw();
    if (current != cur) {
-     if (current->is_lock_owned((address)cur)) {
+     if (LockingMode != LM_LIGHTWEIGHT && current->is_lock_owned((address)cur)) {
        assert(_recursions == 0, "internal state error");
        set_owner_from_BasicLock(cur, current);  // Convert from BasicLock* to Thread*.
        _recursions = 0;
      }
    }

@@ -1402,14 +1483,15 @@
  // (IMSE). If there is a pending exception and the specified thread
  // is not the owner, that exception will be replaced by the IMSE.
  bool ObjectMonitor::check_owner(TRAPS) {
    JavaThread* current = THREAD;
    void* cur = owner_raw();
+   assert(cur != anon_owner_ptr(), "no anon owner here");
    if (cur == current) {
      return true;
    }
-   if (current->is_lock_owned((address)cur)) {
+   if (LockingMode != LM_LIGHTWEIGHT && current->is_lock_owned((address)cur)) {
      set_owner_from_BasicLock(cur, current);  // Convert from BasicLock* to Thread*.
      _recursions = 0;
      return true;
    }
    THROW_MSG_(vmSymbols::java_lang_IllegalMonitorStateException(),
< prev index next >