hotspot/src/share/vm/runtime/synchronizer.cpp
changeset 37251 9fc139ad74b5
parent 37250 2fecd8bdc8e9
child 40655 9f644073d3a0
--- a/hotspot/src/share/vm/runtime/synchronizer.cpp	Mon Apr 04 14:41:00 2016 -0700
+++ b/hotspot/src/share/vm/runtime/synchronizer.cpp	Mon Apr 04 14:49:19 2016 -0700
@@ -283,38 +283,52 @@
 }
 
 void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
-  assert(!object->mark()->has_bias_pattern(), "should not see bias pattern here");
-  // if displaced header is null, the previous enter is recursive enter, no-op
+  markOop mark = object->mark();
+  // We cannot check for Biased Locking if we are racing an inflation.
+  assert(mark == markOopDesc::INFLATING() ||
+         !mark->has_bias_pattern(), "should not see bias pattern here");
+
   markOop dhw = lock->displaced_header();
-  markOop mark;
   if (dhw == NULL) {
-    // Recursive stack-lock.
-    // Diagnostics -- Could be: stack-locked, inflating, inflated.
-    mark = object->mark();
-    assert(!mark->is_neutral(), "invariant");
-    if (mark->has_locker() && mark != markOopDesc::INFLATING()) {
-      assert(THREAD->is_lock_owned((address)mark->locker()), "invariant");
+    // If the displaced header is NULL, then this exit matches up with
+    // a recursive enter. No real work to do here except for diagnostics.
+#ifndef PRODUCT
+    if (mark != markOopDesc::INFLATING()) {
+      // Only do diagnostics if we are not racing an inflation. Simply
+      // exiting a recursive enter of a Java Monitor that is being
+      // inflated is safe; see the has_monitor() comment below.
+      assert(!mark->is_neutral(), "invariant");
+      assert(!mark->has_locker() ||
+             THREAD->is_lock_owned((address)mark->locker()), "invariant");
+      if (mark->has_monitor()) {
+        // The BasicLock's displaced_header is marked as a recursive
+        // enter and we have an inflated Java Monitor (ObjectMonitor).
+        // This is a special case where the Java Monitor was inflated
+        // after this thread entered the stack-lock recursively. When a
+        // Java Monitor is inflated, we cannot safely walk the Java
+        // Monitor owner's stack and update the BasicLocks because a
+        // Java Monitor can be asynchronously inflated by a thread that
+        // does not own the Java Monitor.
+        ObjectMonitor * m = mark->monitor();
+        assert(((oop)(m->object()))->mark() == mark, "invariant");
+        assert(m->is_entered(THREAD), "invariant");
+      }
     }
-    if (mark->has_monitor()) {
-      ObjectMonitor * m = mark->monitor();
-      assert(((oop)(m->object()))->mark() == mark, "invariant");
-      assert(m->is_entered(THREAD), "invariant");
-    }
+#endif
     return;
   }
 
-  mark = object->mark();
-
-  // If the object is stack-locked by the current thread, try to
-  // swing the displaced header from the box back to the mark.
   if (mark == (markOop) lock) {
+    // If the object is stack-locked by the current thread, try to
+    // swing the displaced header from the BasicLock back to the mark.
     assert(dhw->is_neutral(), "invariant");
-    if ((markOop) Atomic::cmpxchg_ptr (dhw, object->mark_addr(), mark) == mark) {
-      TEVENT(fast_exit: release stacklock);
+    if ((markOop) Atomic::cmpxchg_ptr(dhw, object->mark_addr(), mark) == mark) {
+      TEVENT(fast_exit: release stack-lock);
       return;
     }
   }
 
+  // We have to take the slow-path of possible inflation and then exit.
   ObjectSynchronizer::inflate(THREAD,
                               object,
                               inflate_cause_vm_internal)->exit(true, THREAD);
@@ -1747,6 +1761,7 @@
   void do_monitor(ObjectMonitor* mid) {
     if (mid->owner() == THREAD) {
       if (ObjectMonitor::Knob_VerifyMatch != 0) {
+        ResourceMark rm;
         Handle obj((oop) mid->object());
         tty->print("INFO: unexpected locked object:");
         javaVFrame::print_locked_object_class_name(tty, obj, "locked");