mirror of
https://github.com/darlinghq/darling-openjdk.git
synced 2025-02-22 09:11:05 +00:00
8222295: more baseline cleanups from Async Monitor Deflation project
Reviewed-by: coleenp, acorn, dholmes
This commit is contained in:
parent
ad207e278d
commit
baf1349a2f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -37,9 +37,9 @@ void markOopDesc::print_on(outputStream* st) const {
|
||||
if (mon == NULL) {
|
||||
st->print("NULL (this should never be seen!)");
|
||||
} else {
|
||||
st->print("{count=0x%08x,waiters=0x%08x"
|
||||
st->print("{contentions=0x%08x,waiters=0x%08x"
|
||||
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
|
||||
mon->count(), mon->waiters(), mon->recursions(),
|
||||
mon->contentions(), mon->waiters(), mon->recursions(),
|
||||
p2i(mon->owner()));
|
||||
}
|
||||
} else if (is_locked()) {
|
||||
|
@ -276,9 +276,13 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
// Note that if we acquire the monitor from an initial spin
|
||||
// we forgo posting JVMTI events and firing DTRACE probes.
|
||||
if (TrySpin(Self) > 0) {
|
||||
assert(_owner == Self, "invariant");
|
||||
assert(_recursions == 0, "invariant");
|
||||
assert(((oop)(object()))->mark() == markOopDesc::encode(this), "invariant");
|
||||
assert(_owner == Self, "must be Self: owner=" INTPTR_FORMAT, p2i(_owner));
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT,
|
||||
_recursions);
|
||||
assert(((oop)object())->mark() == markOopDesc::encode(this),
|
||||
"object mark must match encoded this: mark=" INTPTR_FORMAT
|
||||
", encoded this=" INTPTR_FORMAT, p2i(((oop)object())->mark()),
|
||||
p2i(markOopDesc::encode(this)));
|
||||
Self->_Stalled = 0;
|
||||
return;
|
||||
}
|
||||
@ -290,11 +294,11 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert(jt->thread_state() != _thread_blocked, "invariant");
|
||||
assert(this->object() != NULL, "invariant");
|
||||
assert(_count >= 0, "invariant");
|
||||
assert(_contentions >= 0, "invariant");
|
||||
|
||||
// Prevent deflation at STW-time. See deflate_idle_monitors() and is_busy().
|
||||
// Ensure the object-monitor relationship remains stable while there's contention.
|
||||
Atomic::inc(&_count);
|
||||
Atomic::inc(&_contentions);
|
||||
|
||||
JFR_ONLY(JfrConditionalFlushWithStacktrace<EventJavaMonitorEnter> flush(jt);)
|
||||
EventJavaMonitorEnter event;
|
||||
@ -355,8 +359,8 @@ void ObjectMonitor::enter(TRAPS) {
|
||||
// acquire it.
|
||||
}
|
||||
|
||||
Atomic::dec(&_count);
|
||||
assert(_count >= 0, "invariant");
|
||||
Atomic::dec(&_contentions);
|
||||
assert(_contentions >= 0, "invariant");
|
||||
Self->_Stalled = 0;
|
||||
|
||||
// Must either set _recursions = 0 or ASSERT _recursions == 0.
|
||||
@ -809,7 +813,7 @@ void ObjectMonitor::UnlinkAfterAcquire(Thread *Self, ObjectWaiter *SelfNode) {
|
||||
// There's one exception to the claim above, however. EnterI() can call
|
||||
// exit() to drop a lock if the acquirer has been externally suspended.
|
||||
// In that case exit() is called with _thread_state as _thread_blocked,
|
||||
// but the monitor's _count field is > 0, which inhibits reclamation.
|
||||
// but the monitor's _contentions field is > 0, which inhibits reclamation.
|
||||
//
|
||||
// 1-0 exit
|
||||
// ~~~~~~~~
|
||||
|
@ -163,9 +163,9 @@ class ObjectMonitor {
|
||||
volatile int _Spinner; // for exit->spinner handoff optimization
|
||||
volatile int _SpinDuration;
|
||||
|
||||
volatile jint _count; // reference count to prevent reclamation/deflation
|
||||
// at stop-the-world time. See ObjectSynchronizer::deflate_monitor().
|
||||
// _count is approximately |_WaitSet| + |_EntryList|
|
||||
volatile jint _contentions; // Number of active contentions in enter(). It is used by is_busy()
|
||||
// along with other fields to determine if an ObjectMonitor can be
|
||||
// deflated. See ObjectSynchronizer::deflate_monitor().
|
||||
protected:
|
||||
ObjectWaiter * volatile _WaitSet; // LL of threads wait()ing on the monitor
|
||||
volatile jint _waiters; // number of waiting threads
|
||||
@ -207,7 +207,6 @@ class ObjectMonitor {
|
||||
static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); }
|
||||
static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); }
|
||||
static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); }
|
||||
static int count_offset_in_bytes() { return offset_of(ObjectMonitor, _count); }
|
||||
static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); }
|
||||
static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq); }
|
||||
static int succ_offset_in_bytes() { return offset_of(ObjectMonitor, _succ); }
|
||||
@ -232,10 +231,8 @@ class ObjectMonitor {
|
||||
void set_header(markOop hdr);
|
||||
|
||||
intptr_t is_busy() const {
|
||||
// TODO-FIXME: merge _count and _waiters.
|
||||
// TODO-FIXME: assert _owner == null implies _recursions = 0
|
||||
// TODO-FIXME: assert _WaitSet != null implies _count > 0
|
||||
return _count|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList);
|
||||
return _contentions|_waiters|intptr_t(_owner)|intptr_t(_cxq)|intptr_t(_EntryList);
|
||||
}
|
||||
|
||||
intptr_t is_entered(Thread* current) const;
|
||||
@ -245,8 +242,6 @@ class ObjectMonitor {
|
||||
|
||||
jint waiters() const;
|
||||
|
||||
jint count() const;
|
||||
void set_count(jint count);
|
||||
jint contentions() const;
|
||||
intptr_t recursions() const { return _recursions; }
|
||||
|
||||
@ -263,14 +258,14 @@ class ObjectMonitor {
|
||||
~ObjectMonitor() {
|
||||
// TODO: Add asserts ...
|
||||
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
|
||||
// _count == 0 _EntryList == NULL etc
|
||||
// _contentions == 0 _EntryList == NULL etc
|
||||
}
|
||||
|
||||
private:
|
||||
void Recycle() {
|
||||
// TODO: add stronger asserts ...
|
||||
// _cxq == 0 _succ == NULL _owner == NULL _waiters == 0
|
||||
// _count == 0 EntryList == NULL
|
||||
// _contentions == 0 EntryList == NULL
|
||||
// _recursions == 0 _WaitSet == NULL
|
||||
assert(((is_busy()|_recursions) == 0), "freeing inuse monitor");
|
||||
_succ = NULL;
|
||||
|
@ -45,10 +45,6 @@ inline void ObjectMonitor::set_header(markOop hdr) {
|
||||
_header = hdr;
|
||||
}
|
||||
|
||||
inline jint ObjectMonitor::count() const {
|
||||
return _count;
|
||||
}
|
||||
|
||||
inline jint ObjectMonitor::waiters() const {
|
||||
return _waiters;
|
||||
}
|
||||
@ -58,12 +54,12 @@ inline void* ObjectMonitor::owner() const {
|
||||
}
|
||||
|
||||
inline void ObjectMonitor::clear() {
|
||||
assert(_header != NULL, "Fatal logic error in ObjectMonitor header!");
|
||||
assert(_count == 0, "Fatal logic error in ObjectMonitor count!");
|
||||
assert(_waiters == 0, "Fatal logic error in ObjectMonitor waiters!");
|
||||
assert(_recursions == 0, "Fatal logic error in ObjectMonitor recursions!");
|
||||
assert(_object != NULL, "Fatal logic error in ObjectMonitor object!");
|
||||
assert(_owner == NULL, "Fatal logic error in ObjectMonitor owner!");
|
||||
assert(_header != NULL, "must be non-NULL");
|
||||
assert(_contentions == 0, "must be 0: contentions=%d", _contentions);
|
||||
assert(_waiters == 0, "must be 0: waiters=%d", _waiters);
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTPTR_FORMAT, _recursions);
|
||||
assert(_object != NULL, "must be non-NULL");
|
||||
assert(_owner == NULL, "must be NULL: owner=" INTPTR_FORMAT, p2i(_owner));
|
||||
|
||||
_header = NULL;
|
||||
_object = NULL;
|
||||
@ -96,10 +92,10 @@ inline bool ObjectMonitor::check(TRAPS) {
|
||||
|
||||
// return number of threads contending for this monitor
|
||||
inline jint ObjectMonitor::contentions() const {
|
||||
return _count;
|
||||
return _contentions;
|
||||
}
|
||||
|
||||
// Do NOT set _count = 0. There is a race such that _count could
|
||||
// Do NOT set _contentions = 0. There is a race such that _contentions could
|
||||
// be set while inflating prior to setting _owner
|
||||
// Just use Atomic::inc/dec and assert 0 when monitor put on free list
|
||||
inline void ObjectMonitor::set_owner(void* owner) {
|
||||
|
@ -735,7 +735,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
|
||||
} 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 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
}
|
||||
|
||||
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
// 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 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread * Self,
|
||||
//
|
||||
// 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 @@ bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
|
||||
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 @@ bool ObjectSynchronizer::deflate_monitor(ObjectMonitor* mid, oop obj,
|
||||
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 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
|
||||
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 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread * jt, ObjectMonitor * n,
|
||||
": 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 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
|
||||
|
||||
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 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out,
|
||||
}
|
||||
|
||||
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("================== ================== === ================== ==================");
|
||||
|
@ -896,7 +896,7 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
|
||||
volatile_nonstatic_field(ObjectMonitor, _header, markOop) \
|
||||
unchecked_nonstatic_field(ObjectMonitor, _object, sizeof(void *)) /* NOTE: no type */ \
|
||||
unchecked_nonstatic_field(ObjectMonitor, _owner, sizeof(void *)) /* NOTE: no type */ \
|
||||
volatile_nonstatic_field(ObjectMonitor, _count, jint) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _contentions, jint) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _waiters, jint) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \
|
||||
nonstatic_field(ObjectMonitor, FreeNext, ObjectMonitor*) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -50,7 +50,7 @@ public class ObjectMonitor extends VMObject {
|
||||
ownerFieldOffset = f.getOffset();
|
||||
f = type.getField("FreeNext");
|
||||
FreeNextFieldOffset = f.getOffset();
|
||||
countField = type.getJIntField("_count");
|
||||
contentionsField = type.getJIntField("_contentions");
|
||||
waitersField = type.getJIntField("_waiters");
|
||||
recursionsField = type.getCIntegerField("_recursions");
|
||||
}
|
||||
@ -87,19 +87,14 @@ public class ObjectMonitor extends VMObject {
|
||||
// FIXME
|
||||
// void set_queue(void* owner);
|
||||
|
||||
public int count() { return countField.getValue(addr); }
|
||||
// FIXME
|
||||
// void set_count(int count);
|
||||
|
||||
public long recursions() { return recursionsField.getValue(addr); }
|
||||
|
||||
public OopHandle object() {
|
||||
return addr.getOopHandleAt(objectFieldOffset);
|
||||
}
|
||||
|
||||
// contentions is always equal to count
|
||||
public int contentions() {
|
||||
return count();
|
||||
return contentionsField.getValue(addr);
|
||||
}
|
||||
|
||||
// FIXME
|
||||
@ -114,7 +109,7 @@ public class ObjectMonitor extends VMObject {
|
||||
private static long objectFieldOffset;
|
||||
private static long ownerFieldOffset;
|
||||
private static long FreeNextFieldOffset;
|
||||
private static JIntField countField;
|
||||
private static JIntField contentionsField;
|
||||
private static JIntField waitersField;
|
||||
private static CIntegerField recursionsField;
|
||||
// FIXME: expose platform-dependent stuff
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 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
|
||||
@ -83,7 +83,7 @@ public class MonitorCacheDumpPanel extends JPanel {
|
||||
}
|
||||
}
|
||||
}
|
||||
tty.println(" _count: " + mon.count());
|
||||
tty.println(" _contentions: " + mon.contentions());
|
||||
tty.println(" _waiters: " + mon.waiters());
|
||||
tty.println(" _recursions: " + mon.recursions());
|
||||
}
|
||||
@ -98,7 +98,7 @@ public class MonitorCacheDumpPanel extends JPanel {
|
||||
ObjectMonitor mon;
|
||||
while (i.hasNext()) {
|
||||
mon = (ObjectMonitor)i.next();
|
||||
if (mon.count() != 0 || mon.waiters() != 0 || mon.owner() != null) {
|
||||
if (mon.contentions() != 0 || mon.waiters() != 0 || mon.owner() != null) {
|
||||
OopHandle object = mon.object();
|
||||
if (object == null) {
|
||||
dumpMonitor(tty, mon, true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user