< 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 >