src/hotspot/share/runtime/synchronizer.cpp
changeset 54609 04857e2cd509
parent 54291 e6c86f6012bf
child 54786 ebf733a324d4
--- a/src/hotspot/share/runtime/synchronizer.cpp	Wed Apr 24 15:37:55 2019 +0200
+++ b/src/hotspot/share/runtime/synchronizer.cpp	Wed Apr 24 10:20:25 2019 -0400
@@ -735,7 +735,7 @@
   } else if (mark->has_monitor()) {
     monitor = mark->monitor();
     temp = monitor->header();
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     hash = temp->hash();
     if (hash != 0) {
       return hash;
@@ -743,39 +743,38 @@
     // Skip to the following code to reduce code size
   } else if (Self->is_lock_owned((address)mark->locker())) {
     temp = mark->displaced_mark_helper(); // this is a lightweight monitor owned
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     hash = temp->hash();              // by current thread, check if the displaced
     if (hash != 0) {                  // header contains hash code
       return hash;
     }
     // WARNING:
-    //   The displaced header is strictly immutable.
-    // It can NOT be changed in ANY cases. So we have
-    // to inflate the header into heavyweight monitor
-    // even the current thread owns the lock. The reason
-    // is the BasicLock (stack slot) will be asynchronously
-    // read by other threads during the inflate() function.
-    // Any change to stack may not propagate to other threads
-    // correctly.
+    // The displaced header in the BasicLock on a thread's stack
+    // is strictly immutable. It CANNOT be changed in ANY cases.
+    // So we have to inflate the stack lock into an ObjectMonitor
+    // even if the current thread owns the lock. The BasicLock on
+    // a thread's stack can be asynchronously read by other threads
+    // during an inflate() call so any change to that stack memory
+    // may not propagate to other threads correctly.
   }
 
   // Inflate the monitor to set hash code
   monitor = inflate(Self, obj, inflate_cause_hash_code);
   // Load displaced header and check it has hash code
   mark = monitor->header();
-  assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)mark));
+  assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
   hash = mark->hash();
   if (hash == 0) {
     hash = get_next_hash(Self, obj);
     temp = mark->copy_set_hash(hash); // merge hash code into header
-    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
+    assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(temp));
     test = Atomic::cmpxchg(temp, monitor->header_addr(), mark);
     if (test != mark) {
-      // The only update to the header in the monitor (outside GC)
-      // is install the hash code. If someone add new usage of
-      // displaced header, please update this code
+      // The only update to the ObjectMonitor's header/dmw field
+      // is to merge in the hash code. If someone adds a new usage
+      // of the header/dmw field, please update this code.
       hash = test->hash();
-      assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)test));
+      assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(test));
       assert(hash != 0, "Trivial unexpected object/monitor header usage.");
     }
   }
@@ -1334,7 +1333,7 @@
     if (mark->has_monitor()) {
       ObjectMonitor * inf = mark->monitor();
       markOop dmw = inf->header();
-      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)dmw));
+      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
       assert(oopDesc::equals((oop) inf->object(), object), "invariant");
       assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
       return inf;
@@ -1398,7 +1397,7 @@
       // Consider what happens when a thread unlocks a stack-locked object.
       // It attempts to use CAS to swing the displaced header value from the
       // on-stack basiclock back into the object header.  Recall also that the
-      // header value (hashcode, etc) can reside in (a) the object header, or
+      // header value (hash code, etc) can reside in (a) the object header, or
       // (b) a displaced header associated with the stack-lock, or (c) a displaced
       // header in an objectMonitor.  The inflate() routine must copy the header
       // value from the basiclock on the owner's stack to the objectMonitor, all
@@ -1419,7 +1418,9 @@
       // object is in the mark.  Furthermore the owner can't complete
       // an unlock on the object, either.
       markOop dmw = mark->displaced_mark_helper();
-      assert(dmw->is_neutral(), "invariant");
+      // Catch if the object's header is not neutral (not locked and
+      // not marked is what we care about here).
+      assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
 
       // Setup monitor fields to proper values -- prepare the monitor
       m->set_header(dmw);
@@ -1463,7 +1464,9 @@
     // An inflateTry() method that we could call from fast_enter() and slow_enter()
     // would be useful.
 
-    assert(mark->is_neutral(), "invariant");
+    // Catch if the object's header is not neutral (not locked and
+    // not marked is what we care about here).
+    assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(mark));
     ObjectMonitor * m = omAlloc(Self);
     // prepare m for installation - set monitor to initial state
     m->Recycle();
@@ -1503,7 +1506,7 @@
 }
 
 
-// We create a list of in-use monitors for each thread.
+// We maintain a list of in-use monitors for each thread.
 //
 // deflate_thread_local_monitors() scans a single thread's in-use list, while
 // deflate_idle_monitors() scans only a global list of in-use monitors which
@@ -1512,7 +1515,7 @@
 // These operations are called at all safepoints, immediately after mutators
 // are stopped, but before any objects have moved. Collectively they traverse
 // the population of in-use monitors, deflating where possible. The scavenged
-// monitors are returned to the monitor free list.
+// monitors are returned to the global monitor free list.
 //
 // Beware that we scavenge at *every* stop-the-world point. Having a large
 // number of monitors in-use could negatively impact performance. We also want
@@ -1521,7 +1524,7 @@
 //
 // Perversely, the heap size -- and thus the STW safepoint rate --
 // typically drives the scavenge rate.  Large heaps can mean infrequent GC,
-// which in turn can mean large(r) numbers of objectmonitors in circulation.
+// which in turn can mean large(r) numbers of ObjectMonitors in circulation.
 // This is an unfortunate aspect of this design.
 
 // Deflate a single monitor if not in-use
@@ -1531,9 +1534,15 @@
                                          ObjectMonitor** freeTailp) {
   bool deflated;
   // Normal case ... The monitor is associated with obj.
-  guarantee(obj->mark() == markOopDesc::encode(mid), "invariant");
-  guarantee(mid == obj->mark()->monitor(), "invariant");
-  guarantee(mid->header()->is_neutral(), "invariant");
+  const markOop mark = obj->mark();
+  guarantee(mark == markOopDesc::encode(mid), "should match: mark="
+            INTPTR_FORMAT ", encoded mid=" INTPTR_FORMAT, p2i(mark),
+            p2i(markOopDesc::encode(mid)));
+  // Make sure that mark->monitor() and markOopDesc::encode() agree:
+  guarantee(mark->monitor() == mid, "should match: monitor()=" INTPTR_FORMAT
+            ", mid=" INTPTR_FORMAT, p2i(mark->monitor()), p2i(mid));
+  const markOop dmw = mid->header();
+  guarantee(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i(dmw));
 
   if (mid->is_busy()) {
     deflated = false;
@@ -1544,16 +1553,17 @@
     if (log_is_enabled(Trace, monitorinflation)) {
       ResourceMark rm;
       log_trace(monitorinflation)("deflate_monitor: "
-                                  "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'",
-                                  p2i(obj), p2i(obj->mark()),
-                                  obj->klass()->external_name());
+                                  "object=" INTPTR_FORMAT ", mark="
+                                  INTPTR_FORMAT ", type='%s'", p2i(obj),
+                                  p2i(mark), obj->klass()->external_name());
     }
 
     // Restore the header back to obj
-    obj->release_set_mark(mid->header());
+    obj->release_set_mark(dmw);
     mid->clear();
 
-    assert(mid->object() == NULL, "invariant");
+    assert(mid->object() == NULL, "invariant: object=" INTPTR_FORMAT,
+           p2i(mid->object()));
 
     // Move the object to the working free list defined by freeHeadp, freeTailp
     if (*freeHeadp == NULL) *freeHeadp = mid;
@@ -2022,13 +2032,12 @@
       out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
                     ": in-use per-thread monitor's object does not think "
                     "it has a monitor: obj=" INTPTR_FORMAT ", mark="
-                    INTPTR_FORMAT,  p2i(jt), p2i(n), p2i((address)obj),
-                    p2i((address)mark));
+                    INTPTR_FORMAT,  p2i(jt), p2i(n), p2i(obj), p2i(mark));
     } else {
       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
                     "monitor's object does not think it has a monitor: obj="
                     INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
-                    p2i((address)obj), p2i((address)mark));
+                    p2i(obj), p2i(mark));
     }
     *error_cnt_p = *error_cnt_p + 1;
   }
@@ -2039,14 +2048,12 @@
                     ": in-use per-thread monitor's object does not refer "
                     "to the same monitor: obj=" INTPTR_FORMAT ", mark="
                     INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt),
-                    p2i(n), p2i((address)obj), p2i((address)mark),
-                    p2i((address)obj_mon));
+                    p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
     } else {
       out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
                     "monitor's object does not refer to the same monitor: obj="
                     INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon="
-                    INTPTR_FORMAT, p2i(n), p2i((address)obj),
-                    p2i((address)mark), p2i((address)obj_mon));
+                    INTPTR_FORMAT, p2i(n), p2i(obj), p2i(mark), p2i(obj_mon));
     }
     *error_cnt_p = *error_cnt_p + 1;
   }
@@ -2105,7 +2112,7 @@
 
   if (gOmInUseCount > 0) {
     out->print_cr("In-use global monitor info:");
-    out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)");
+    out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
     out->print_cr("%18s  %s  %18s  %18s",
                   "monitor", "BHL", "object", "object type");
     out->print_cr("==================  ===  ==================  ==================");
@@ -2124,7 +2131,7 @@
   }
 
   out->print_cr("In-use per-thread monitor info:");
-  out->print_cr("(B -> is_busy, H -> has hashcode, L -> lock status)");
+  out->print_cr("(B -> is_busy, H -> has hash code, L -> lock status)");
   out->print_cr("%18s  %18s  %s  %18s  %18s",
                 "jt", "monitor", "BHL", "object", "object type");
   out->print_cr("==================  ==================  ===  ==================  ==================");