< prev index next >

src/hotspot/share/runtime/synchronizer.cpp

Print this page
rev 58110 : v2.09a with 8235795, 8235931 and 8236035 extracted; rebased to jdk-14+28; merge with 8236035.patch.cr1; merge with 8235795.patch.cr1; merge with 8236035.patch.cr2; merge with 8235795.patch.cr2; merge with 8235795.patch.cr3.
rev 58111 : See CR9-to-CR10-changes; merge with jdk-15+11.

@@ -137,15 +137,14 @@
   // Global ObjectMonitor in-use list. When a JavaThread is exiting,
   // ObjectMonitors on its per-thread in-use list are prepended here.
   ObjectMonitor* _in_use_list;
   DEFINE_PAD_MINUS_SIZE(2, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*));
 
-  // Global ObjectMonitor wait list. If HandshakeAfterDeflateIdleMonitors
-  // is true, deflated ObjectMonitors wait on this list until after a
-  // handshake or a safepoint for platforms that don't support handshakes.
-  // After the handshake or safepoint, the deflated ObjectMonitors are
-  // prepended to free_list.
+  // Global ObjectMonitor wait list. Deflated ObjectMonitors wait on
+  // this list until after a handshake or a safepoint for platforms
+  // that don't support handshakes. After the handshake or safepoint,
+  // the deflated ObjectMonitors are prepended to free_list.
   ObjectMonitor* _wait_list;
   DEFINE_PAD_MINUS_SIZE(3, OM_CACHE_LINE_SIZE, sizeof(ObjectMonitor*));
 
   int _free_count;    // # on free_list
   DEFINE_PAD_MINUS_SIZE(4, OM_CACHE_LINE_SIZE, sizeof(int));

@@ -318,11 +317,10 @@
 // Prepend a list of ObjectMonitors to om_list_globals._wait_list.
 // 'tail' is the last ObjectMonitor in the list and there are 'count'
 // on the list. Also updates om_list_globals._wait_count.
 static void prepend_list_to_global_wait_list(ObjectMonitor* list,
                                              ObjectMonitor* tail, int count) {
-  assert(HandshakeAfterDeflateIdleMonitors, "sanity check");
   prepend_list_to_common(list, tail, count, &om_list_globals._wait_list,
                          &om_list_globals._wait_count);
 }
 
 // Prepend a list of ObjectMonitors to om_list_globals._in_use_list.

@@ -533,12 +531,11 @@
 
       if (AsyncDeflateIdleMonitors &&
           m->try_set_owner_from(DEFLATER_MARKER, self) == DEFLATER_MARKER) {
         // The deflation protocol finished the first part (setting owner),
         // but it failed the second part (making ref_count negative) and
-        // bailed. Or the ObjectMonitor was async deflated and reused.
-        // Acquired the monitor.
+        // bailed. Acquired the monitor.
         assert(m->_recursions == 0, "invariant");
         return true;
       }
     }
     break;

@@ -1033,14 +1030,11 @@
         assert(AsyncDeflateIdleMonitors, "sanity check");
         continue;
       }
       monitor = omh.om_ptr();
       temp = monitor->header();
-      // Allow for a lagging install_displaced_markword_in_object() to
-      // have marked the ObjectMonitor's header/dmw field.
-      assert(temp.is_neutral() || (AsyncDeflateIdleMonitors && temp.is_marked()),
-             "invariant: header=" INTPTR_FORMAT, temp.value());
+      assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
       hash = temp.hash();
       if (hash != 0) {                  // if it has a hash, just return it
         return hash;
       }
       // Fall thru so we only have one place that installs the hash in

@@ -1068,40 +1062,24 @@
     ObjectMonitorHandle omh;
     inflate(&omh, self, obj, inflate_cause_hash_code);
     monitor = omh.om_ptr();
     // Load ObjectMonitor's header/dmw field and see if it has a hash.
     mark = monitor->header();
-    // Allow for a lagging install_displaced_markword_in_object() to
-    // have marked the ObjectMonitor's header/dmw field.
-    assert(mark.is_neutral() || (AsyncDeflateIdleMonitors && mark.is_marked()),
-           "invariant: header=" INTPTR_FORMAT, mark.value());
+    assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
     hash = mark.hash();
     if (hash == 0) {                    // if it does not have a hash
       hash = get_next_hash(self, obj);  // get a new hash
       temp = mark.copy_set_hash(hash);  // merge the hash into header
-      if (AsyncDeflateIdleMonitors && temp.is_marked()) {
-        // A lagging install_displaced_markword_in_object() has marked
-        // the ObjectMonitor's header/dmw field. We clear it to avoid
-        // any confusion if we are able to set the hash.
-        temp.set_unmarked();
-      }
       assert(temp.is_neutral(), "invariant: header=" INTPTR_FORMAT, temp.value());
       uintptr_t v = Atomic::cmpxchg((volatile uintptr_t*)monitor->header_addr(), mark.value(), temp.value());
       test = markWord(v);
       if (test != mark) {
         // The attempt to update the ObjectMonitor's header/dmw field
         // did not work. This can happen if another thread managed to
-        // merge in the hash just before our cmpxchg(). With async
-        // deflation, a lagging install_displaced_markword_in_object()
-        // could have just marked or just unmarked the header/dmw field.
+        // merge in the hash just before our cmpxchg().
         // If we add any new usages of the header/dmw field, this code
         // will need to be updated.
-        if (AsyncDeflateIdleMonitors) {
-          // Since async deflation gives us two possible reasons for
-          // the cmwxchg() to fail, it is easier to simply retry.
-          continue;
-        }
         hash = test.hash();
         assert(test.is_neutral(), "invariant: header=" INTPTR_FORMAT, test.value());
         assert(hash != 0, "should only have lost the race to a thread that set a non-zero hash");
       }
     }

@@ -1263,11 +1241,11 @@
   while (block != NULL) {
     assert(block->object() == CHAINMARKER, "must be a block header");
     for (int i = _BLOCKSIZE - 1; i > 0; i--) {
       ObjectMonitor* mid = (ObjectMonitor *)(block + i);
       ObjectMonitorHandle omh;
-      if (!mid->is_free() && omh.set_om_ptr_if_safe(mid)) {
+      if (!mid->is_free() && omh.save_om_ptr_if_safe(mid)) {
         // The ObjectMonitor* is not free and it has been made safe.
         if (mid->object() == NULL) {
           // Only process with closure if the object is set.
           continue;
         }

@@ -1284,14 +1262,12 @@
   int population = Atomic::load(&om_list_globals._population);
   if (population == 0) {
     return false;
   }
   if (MonitorUsedDeflationThreshold > 0) {
-    int monitors_used = population - Atomic::load(&om_list_globals._free_count);
-    if (HandshakeAfterDeflateIdleMonitors) {
-      monitors_used -= Atomic::load(&om_list_globals._wait_count);
-    }
+    int monitors_used = population - Atomic::load(&om_list_globals._free_count) -
+                        Atomic::load(&om_list_globals._wait_count);
     int monitor_usage = (monitors_used * 100LL) / population;
     return monitor_usage > MonitorUsedDeflationThreshold;
   }
   return false;
 }

@@ -1320,14 +1296,12 @@
     // in order to not swamp the ServiceThread.
     _last_async_deflation_time_ns = os::javaTimeNanos();
     return true;
   }
   int monitors_used = Atomic::load(&om_list_globals._population) -
-                      Atomic::load(&om_list_globals._free_count);
-  if (HandshakeAfterDeflateIdleMonitors) {
-    monitors_used -= Atomic::load(&om_list_globals._wait_count);
-  }
+                      Atomic::load(&om_list_globals._free_count) -
+                      Atomic::load(&om_list_globals._wait_count);
   if (is_MonitorBound_exceeded(monitors_used)) {
     // Not enough ObjectMonitors on the global free list.
     return true;
   }
   return false;

@@ -1496,15 +1470,14 @@
           break;  // No more are available.
         }
         guarantee(take->object() == NULL, "invariant");
         if (AsyncDeflateIdleMonitors) {
           // We allowed 3 field values to linger during async deflation.
-          // We clear header and restore ref_count here, but we leave
-          // owner == DEFLATER_MARKER so the simple C2 ObjectMonitor
-          // enter optimization can no longer race with async deflation
-          // and reuse.
+          // Clear or restore them as appropriate.
           take->set_header(markWord::zero());
+          // DEFLATER_MARKER is the only non-NULL value we should see here.
+          take->try_set_owner_from(DEFLATER_MARKER, NULL);
           if (take->ref_count() < 0) {
             // Add back max_jint to restore the ref_count field to its
             // proper value.
             Atomic::add(&take->_ref_count, max_jint);
 

@@ -2041,13 +2014,14 @@
     ADIM_guarantee(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
     ObjectMonitor* m = om_alloc(self);
     // prepare m for installation - set monitor to initial state
     m->Recycle();
     m->set_header(mark);
-    // If we leave _owner == DEFLATER_MARKER here, then the simple C2
-    // ObjectMonitor enter optimization can no longer race with async
-    // deflation and reuse.
+    if (AsyncDeflateIdleMonitors) {
+      // DEFLATER_MARKER is the only non-NULL value we should see here.
+      m->try_set_owner_from(DEFLATER_MARKER, NULL);
+    }
     m->set_object(object);
     m->_Responsible  = NULL;
     m->_SpinDuration = ObjectMonitor::Knob_SpinLimit;       // consider: keep metastats by type/class
 
     omh_p->set_om_ptr(m);

@@ -2179,14 +2153,12 @@
     }
 
     // Restore the header back to obj
     obj->release_set_mark(dmw);
     if (AsyncDeflateIdleMonitors) {
-      // clear() expects the owner field to be NULL and we won't race
-      // with the simple C2 ObjectMonitor enter optimization since
-      // we're at a safepoint. DEFLATER_MARKER is the only non-NULL
-      // value we should see here.
+      // clear() expects the owner field to be NULL.
+      // DEFLATER_MARKER is the only non-NULL value we should see here.
       mid->try_set_owner_from(DEFLATER_MARKER, NULL);
     }
     mid->clear();
 
     assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT,

@@ -2309,12 +2281,11 @@
                p2i(mid->object()));
         assert(mid->is_free(), "must be free: allocation_state=%d",
                (int) mid->allocation_state());
 
         // Move the deflated ObjectMonitor to the working free list
-        // defined by free_head_p and free_tail_p. No races on this list
-        // so no need for load_acquire() or store_release().
+        // defined by free_head_p and free_tail_p.
         if (*free_head_p == NULL) {
           // First one on the list.
           *free_head_p = mid;
         }
         if (*free_tail_p != NULL) {

@@ -2467,12 +2438,12 @@
     om_lock(mid);
     next = unmarked_next(mid);
   }
 
   while (true) {
-    // The current mid's next field is marked at this point. If we have
-    // a cur_mid_in_use, then its next field is also marked at this point.
+    // The current mid is locked at this point. If we have a
+    // cur_mid_in_use, then it is also locked at this point.
 
     if (next != NULL) {
       // We lock next so that an om_flush() thread that is behind us
       // cannot pass us when we unlock the current mid.
       om_lock(next);

@@ -2667,12 +2638,11 @@
                              Atomic::load(&om_list_globals._wait_count));
 
   // The ServiceThread's async deflation request has been processed.
   set_is_async_deflation_requested(false);
 
-  if (HandshakeAfterDeflateIdleMonitors &&
-      Atomic::load(&om_list_globals._wait_count) > 0) {
+  if (Atomic::load(&om_list_globals._wait_count) > 0) {
     // There are deflated ObjectMonitors waiting for a handshake
     // (or a safepoint) for safety.
 
     ObjectMonitor* list = Atomic::load(&om_list_globals._wait_list);
     ADIM_guarantee(list != NULL, "om_list_globals._wait_list must not be NULL");

@@ -2749,11 +2719,14 @@
           deflate_monitor_list_using_JT(&om_list_globals._in_use_list,
                                         &om_list_globals._in_use_count,
                                         &free_head_p, &free_tail_p,
                                         &saved_mid_in_use_p);
     } else {
-      local_deflated_count = deflate_monitor_list_using_JT(&target->om_in_use_list, &target->om_in_use_count, &free_head_p, &free_tail_p, &saved_mid_in_use_p);
+      local_deflated_count =
+          deflate_monitor_list_using_JT(&target->om_in_use_list,
+                                        &target->om_in_use_count, &free_head_p,
+                                        &free_tail_p, &saved_mid_in_use_p);
     }
     deflated_count += local_deflated_count;
 
     if (free_head_p != NULL) {
       // Move the deflated ObjectMonitors to the global free list.

@@ -2769,15 +2742,11 @@
 #ifdef ASSERT
       ObjectMonitor* l_next_om = unmarked_next(free_tail_p);
 #endif
       assert(l_next_om == NULL, "must be NULL: _next_om=" INTPTR_FORMAT, p2i(l_next_om));
 
-      if (HandshakeAfterDeflateIdleMonitors) {
         prepend_list_to_global_wait_list(free_head_p, free_tail_p, local_deflated_count);
-      } else {
-        prepend_list_to_global_free_list(free_head_p, free_tail_p, local_deflated_count);
-      }
 
       OM_PERFDATA_OP(Deflations, inc(local_deflated_count));
     }
 
     if (saved_mid_in_use_p != NULL) {

@@ -3041,14 +3010,12 @@
   chk_global_in_use_list_and_count(ls, &error_cnt);
 
   // Check om_list_globals._free_list and om_list_globals._free_count:
   chk_global_free_list_and_count(ls, &error_cnt);
 
-  if (HandshakeAfterDeflateIdleMonitors) {
     // Check om_list_globals._wait_list and om_list_globals._wait_count:
     chk_global_wait_list_and_count(ls, &error_cnt);
-  }
 
   ls->print_cr("Checking per-thread lists:");
 
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
     // Check om_in_use_list and om_in_use_count:

@@ -3431,14 +3398,11 @@
   int l_free_count = Atomic::load(&om_list_globals._free_count);
   int l_wait_count = Atomic::load(&om_list_globals._wait_count);
   out->print_cr("%18s  %10d  %10d  %10d  %10d", "", l_in_use_count,
                 l_free_count, l_wait_count,
                 Atomic::load(&om_list_globals._population));
-  pop_count += l_in_use_count + l_free_count;
-  if (HandshakeAfterDeflateIdleMonitors) {
-    pop_count += l_wait_count;
-  }
+  pop_count += l_in_use_count + l_free_count + l_wait_count;
 
   out->print_cr("%18s  %10s  %10s  %10s",
                 "Per-Thread Lists:", "InUse", "Free", "Provision");
   out->print_cr("==================  ==========  ==========  ==========");
 
< prev index next >