diff -r 2fecd8bdc8e9 -r 9fc139ad74b5 hotspot/src/share/vm/runtime/synchronizer.cpp --- 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");