--- a/src/hotspot/share/runtime/synchronizer.cpp Tue Jan 29 10:09:13 2019 -0800
+++ b/src/hotspot/share/runtime/synchronizer.cpp Tue Jan 29 14:09:38 2019 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -326,9 +326,7 @@
}
// We have to take the slow-path of possible inflation and then exit.
- ObjectSynchronizer::inflate(THREAD,
- object,
- inflate_cause_vm_internal)->exit(true, THREAD);
+ inflate(THREAD, object, inflate_cause_vm_internal)->exit(true, THREAD);
}
// -----------------------------------------------------------------------------
@@ -361,9 +359,7 @@
// must be non-zero to avoid looking like a re-entrant lock,
// and must not look locked either.
lock->set_displaced_header(markOopDesc::unused_mark());
- ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_monitor_enter)->enter(THREAD);
+ inflate(THREAD, obj(), inflate_cause_monitor_enter)->enter(THREAD);
}
// This routine is used to handle interpreter/compiler slow case
@@ -392,9 +388,7 @@
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
- ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_vm_internal);
+ ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
return monitor->complete_exit(THREAD);
}
@@ -406,9 +400,7 @@
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
- ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_vm_internal);
+ ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
monitor->reenter(recursion, THREAD);
}
@@ -422,7 +414,7 @@
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
THREAD->set_current_pending_monitor_is_from_java(false);
- ObjectSynchronizer::inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD);
+ inflate(THREAD, obj(), inflate_cause_jni_enter)->enter(THREAD);
THREAD->set_current_pending_monitor_is_from_java(true);
}
@@ -435,9 +427,7 @@
}
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
- ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
- obj,
- inflate_cause_jni_exit);
+ ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
// If this thread has locked the object, exit the monitor. Note: can't use
// monitor->check(CHECK); must exit even if an exception is pending.
if (monitor->check(THREAD)) {
@@ -477,9 +467,7 @@
if (millis < 0) {
THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
- ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_wait);
+ ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_wait);
DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
monitor->wait(millis, true, THREAD);
@@ -499,9 +487,7 @@
if (millis < 0) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
}
- ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_wait)->wait(millis, false, THREAD);
+ inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD);
}
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
@@ -514,9 +500,7 @@
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
return;
}
- ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_notify)->notify(THREAD);
+ inflate(THREAD, obj(), inflate_cause_notify)->notify(THREAD);
}
// NOTE: see comment of notify()
@@ -530,9 +514,7 @@
if (mark->has_locker() && THREAD->is_lock_owned((address)mark->locker())) {
return;
}
- ObjectSynchronizer::inflate(THREAD,
- obj(),
- inflate_cause_notify)->notifyAll(THREAD);
+ inflate(THREAD, obj(), inflate_cause_notify)->notifyAll(THREAD);
}
// -----------------------------------------------------------------------------
@@ -736,7 +718,7 @@
if (mark->is_neutral()) {
hash = mark->hash(); // this is a normal header
- if (hash) { // if it has hash, just return it
+ if (hash != 0) { // if it has hash, just return it
return hash;
}
hash = get_next_hash(Self, obj); // allocate a new hash code
@@ -752,17 +734,17 @@
} else if (mark->has_monitor()) {
monitor = mark->monitor();
temp = monitor->header();
- assert(temp->is_neutral(), "invariant");
+ assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
hash = temp->hash();
- if (hash) {
+ if (hash != 0) {
return hash;
}
// 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");
+ assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)temp));
hash = temp->hash(); // by current thread, check if the displaced
- if (hash) { // header contains hash code
+ if (hash != 0) { // header contains hash code
return hash;
}
// WARNING:
@@ -777,22 +759,22 @@
}
// Inflate the monitor to set hash code
- monitor = ObjectSynchronizer::inflate(Self, obj, inflate_cause_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");
+ assert(mark->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)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");
+ assert(temp->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)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
hash = test->hash();
- assert(test->is_neutral(), "invariant");
+ assert(test->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)test));
assert(hash != 0, "Trivial unexpected object/monitor header usage.");
}
}
@@ -864,7 +846,7 @@
owner_self : owner_other;
}
- // CASE: inflated. Mark (tagged pointer) points to an objectMonitor.
+ // CASE: inflated. Mark (tagged pointer) points to an ObjectMonitor.
// The Object:ObjectMonitor relationship is stable as long as we're
// not at a safepoint.
if (mark->has_monitor()) {
@@ -901,7 +883,7 @@
}
// Contended case, header points to ObjectMonitor (tagged pointer)
- if (mark->has_monitor()) {
+ else if (mark->has_monitor()) {
ObjectMonitor* monitor = mark->monitor();
assert(monitor != NULL, "monitor should be non-null");
owner = (address) monitor->owner();
@@ -1076,7 +1058,7 @@
// Reprovision the thread's omFreeList.
// Use bulk transfers to reduce the allocation rate and heat
// on various locks.
- Thread::muxAcquire(&gListLock, "omAlloc");
+ Thread::muxAcquire(&gListLock, "omAlloc(1)");
for (int i = Self->omFreeProvision; --i >= 0 && gFreeList != NULL;) {
gMonitorFreeCount--;
ObjectMonitor * take = gFreeList;
@@ -1150,7 +1132,7 @@
// Acquire the gListLock to manipulate gBlockList and gFreeList.
// An Oyama-Taura-Yonezawa scheme might be more efficient.
- Thread::muxAcquire(&gListLock, "omAlloc [2]");
+ Thread::muxAcquire(&gListLock, "omAlloc(2)");
gMonitorPopulation += _BLOCKSIZE-1;
gMonitorFreeCount += _BLOCKSIZE-1;
@@ -1178,10 +1160,11 @@
//
// Key constraint: all ObjectMonitors on a thread's free list and the global
// free list must have their object field set to null. This prevents the
-// scavenger -- deflate_idle_monitors -- from reclaiming them.
+// scavenger -- deflate_monitor_list() -- from reclaiming them.
void ObjectSynchronizer::omRelease(Thread * Self, ObjectMonitor * m,
bool fromPerThreadAlloc) {
+ guarantee(m->header() == NULL, "invariant");
guarantee(m->object() == NULL, "invariant");
guarantee(((m->is_busy()|m->_recursions) == 0), "freeing in-use monitor");
// Remove from omInUseList
@@ -1223,16 +1206,15 @@
//
// We currently call omFlush() from Threads::remove() _before the thread
// has been excised from the thread list and is no longer a mutator.
-// This means that omFlush() can not run concurrently with a safepoint and
-// interleave with the scavenge operator. In particular, this ensures that
-// the thread's monitors are scanned by a GC safepoint, either via
-// Thread::oops_do() (if safepoint happens before omFlush()) or via
+// This means that omFlush() cannot run concurrently with a safepoint and
+// interleave with the deflate_idle_monitors scavenge operator. In particular,
+// this ensures that the thread's monitors are scanned by a GC safepoint,
+// either via Thread::oops_do() (if safepoint happens before omFlush()) or via
// ObjectSynchronizer::oops_do() (if it happens after omFlush() and the thread's
// monitors have been transferred to the global in-use list).
void ObjectSynchronizer::omFlush(Thread * Self) {
ObjectMonitor * list = Self->omFreeList; // Null-terminated SLL
- Self->omFreeList = NULL;
ObjectMonitor * tail = NULL;
int tally = 0;
if (list != NULL) {
@@ -1248,14 +1230,16 @@
guarantee(!s->is_busy(), "invariant");
s->set_owner(NULL); // redundant but good hygiene
}
- guarantee(tail != NULL && list != NULL, "invariant");
+ guarantee(tail != NULL, "invariant");
+ assert(Self->omFreeCount == tally, "free-count off");
+ Self->omFreeList = NULL;
+ Self->omFreeCount = 0;
}
ObjectMonitor * inUseList = Self->omInUseList;
ObjectMonitor * inUseTail = NULL;
int inUseTally = 0;
if (inUseList != NULL) {
- Self->omInUseList = NULL;
ObjectMonitor *cur_om;
// The thread is going away, however the omInUseList inflated
// monitors may still be in-use by other threads.
@@ -1265,9 +1249,10 @@
inUseTail = cur_om;
inUseTally++;
}
+ guarantee(inUseTail != NULL, "invariant");
assert(Self->omInUseCount == inUseTally, "in-use count off");
+ Self->omInUseList = NULL;
Self->omInUseCount = 0;
- guarantee(inUseTail != NULL && inUseList != NULL, "invariant");
}
Thread::muxAcquire(&gListLock, "omFlush");
@@ -1275,8 +1260,6 @@
tail->FreeNext = gFreeList;
gFreeList = list;
gMonitorFreeCount += tally;
- assert(Self->omFreeCount == tally, "free-count off");
- Self->omFreeCount = 0;
}
if (inUseTail != NULL) {
@@ -1300,22 +1283,19 @@
}
// Fast path code shared by multiple functions
-ObjectMonitor* ObjectSynchronizer::inflate_helper(oop obj) {
+void ObjectSynchronizer::inflate_helper(oop obj) {
markOop mark = obj->mark();
if (mark->has_monitor()) {
assert(ObjectSynchronizer::verify_objmon_isinpool(mark->monitor()), "monitor is invalid");
assert(mark->monitor()->header()->is_neutral(), "monitor must record a good object header");
- return mark->monitor();
+ return;
}
- return ObjectSynchronizer::inflate(Thread::current(),
- obj,
- inflate_cause_vm_internal);
+ inflate(Thread::current(), obj, inflate_cause_vm_internal);
}
ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
- oop object,
- const InflateCause cause) {
-
+ oop object,
+ const InflateCause cause) {
// Inflate mutates the heap ...
// Relaxing assertion for bug 6320749.
assert(Universe::verify_in_progress() ||
@@ -1337,7 +1317,8 @@
// CASE: inflated
if (mark->has_monitor()) {
ObjectMonitor * inf = mark->monitor();
- assert(inf->header()->is_neutral(), "invariant");
+ markOop dmw = inf->header();
+ assert(dmw->is_neutral(), "invariant: header=" INTPTR_FORMAT, p2i((address)dmw));
assert(oopDesc::equals((oop) inf->object(), object), "invariant");
assert(ObjectSynchronizer::verify_objmon_isinpool(inf), "monitor is invalid");
return inf;
@@ -1444,8 +1425,9 @@
OM_PERFDATA_OP(Inflations, inc());
if (log_is_enabled(Debug, monitorinflation)) {
if (object->is_instance()) {
- ResourceMark rm;
- log_debug(monitorinflation)("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
+ ResourceMark rm(Self);
+ log_debug(monitorinflation)("inflate(has_locker): "
+ "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'",
p2i(object), p2i(object->mark()),
object->klass()->external_name());
}
@@ -1478,8 +1460,8 @@
m->_SpinDuration = ObjectMonitor::Knob_SpinLimit; // consider: keep metastats by type/class
if (object->cas_set_mark(markOopDesc::encode(m), mark) != mark) {
+ m->set_header(NULL);
m->set_object(NULL);
- m->set_owner(NULL);
m->Recycle();
omRelease(Self, m, true);
m = NULL;
@@ -1494,8 +1476,9 @@
OM_PERFDATA_OP(Inflations, inc());
if (log_is_enabled(Debug, monitorinflation)) {
if (object->is_instance()) {
- ResourceMark rm;
- log_debug(monitorinflation)("Inflating object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s",
+ ResourceMark rm(Self);
+ log_debug(monitorinflation)("inflate(neutral): "
+ "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'",
p2i(object), p2i(object->mark()),
object->klass()->external_name());
}
@@ -1549,8 +1532,8 @@
if (log_is_enabled(Debug, monitorinflation)) {
if (obj->is_instance()) {
ResourceMark rm;
- log_debug(monitorinflation)("Deflating object " INTPTR_FORMAT " , "
- "mark " INTPTR_FORMAT " , type %s",
+ log_debug(monitorinflation)("deflate_monitor: "
+ "object=" INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", type='%s'",
p2i(obj), p2i(obj->mark()),
obj->klass()->external_name());
}
@@ -1577,7 +1560,7 @@
// Walk a given monitor list, and deflate idle monitors
// The given list could be a per-thread list or a global list
-// Caller acquires gListLock.
+// Caller acquires gListLock as needed.
//
// In the case of parallel processing of thread local monitor lists,
// work is done by Threads::parallel_threads_do() which ensures that
@@ -1621,7 +1604,7 @@
void ObjectSynchronizer::prepare_deflate_idle_monitors(DeflateMonitorCounters* counters) {
counters->nInuse = 0; // currently associated with objects
counters->nInCirculation = 0; // extant
- counters->nScavenged = 0; // reclaimed
+ counters->nScavenged = 0; // reclaimed (global and per-thread)
counters->perThreadTimes = 0.0; // per-thread scavenge times
}
@@ -1635,7 +1618,7 @@
// Prevent omFlush from changing mids in Thread dtor's during deflation
// And in case the vm thread is acquiring a lock during a safepoint
// See e.g. 6320749
- Thread::muxAcquire(&gListLock, "scavenge - return");
+ Thread::muxAcquire(&gListLock, "deflate_idle_monitors");
// Note: the thread-local monitors lists get deflated in
// a separate pass. See deflate_thread_local_monitors().
@@ -1700,7 +1683,7 @@
timer.stop();
- Thread::muxAcquire(&gListLock, "scavenge - return");
+ Thread::muxAcquire(&gListLock, "deflate_thread_local_monitors");
// Adjust counters
counters->nInCirculation += thread->omInUseCount;