8325303: Replace markWord.is_neutral() with markWord.is_unlocked()
Reviewed-by: stefank, dcubed
This commit is contained in:
parent
27cfcef99f
commit
34f7974a40
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -80,8 +80,8 @@ void markWord::print_on(outputStream* st, bool print_monitor_info) const {
|
|||||||
st->print(" locked(" INTPTR_FORMAT ")", value());
|
st->print(" locked(" INTPTR_FORMAT ")", value());
|
||||||
} else {
|
} else {
|
||||||
st->print(" mark(");
|
st->print(" mark(");
|
||||||
if (is_neutral()) { // last bits = 01
|
if (is_unlocked()) { // last bits = 01
|
||||||
st->print("is_neutral");
|
st->print("is_unlocked");
|
||||||
if (has_no_hash()) {
|
if (has_no_hash()) {
|
||||||
st->print(" no_hash");
|
st->print(" no_hash");
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -143,7 +143,7 @@ class markWord {
|
|||||||
bool is_marked() const {
|
bool is_marked() const {
|
||||||
return (mask_bits(value(), lock_mask_in_place) == marked_value);
|
return (mask_bits(value(), lock_mask_in_place) == marked_value);
|
||||||
}
|
}
|
||||||
bool is_neutral() const {
|
bool is_neutral() const { // Not locked, or marked - a "clean" neutral state
|
||||||
return (mask_bits(value(), lock_mask_in_place) == unlocked_value);
|
return (mask_bits(value(), lock_mask_in_place) == unlocked_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,10 +40,10 @@ void BasicLock::print_on(outputStream* st, oop owner) const {
|
|||||||
void BasicLock::move_to(oop obj, BasicLock* dest) {
|
void BasicLock::move_to(oop obj, BasicLock* dest) {
|
||||||
// Check to see if we need to inflate the lock. This is only needed
|
// Check to see if we need to inflate the lock. This is only needed
|
||||||
// if an object is locked using "this" lightweight monitor. In that
|
// if an object is locked using "this" lightweight monitor. In that
|
||||||
// case, the displaced_header() is unlocked/is_neutral, because the
|
// case, the displaced_header() is unlocked/neutral, because the
|
||||||
// displaced_header() contains the header for the originally unlocked
|
// displaced_header() contains the header for the originally unlocked
|
||||||
// object. However the lock could have already been inflated. But it
|
// object. However the lock could have already been inflated. But it
|
||||||
// does not matter, this inflation will just a no-op. For other cases,
|
// does not matter, this inflation will just be a no-op. For other cases,
|
||||||
// the displaced header will be either 0x0 or 0x3, which are location
|
// the displaced header will be either 0x0 or 0x3, which are location
|
||||||
// independent, therefore the BasicLock is free to move.
|
// independent, therefore the BasicLock is free to move.
|
||||||
//
|
//
|
||||||
@ -63,11 +63,11 @@ void BasicLock::move_to(oop obj, BasicLock* dest) {
|
|||||||
// one stack location to another. This avoids inflation. Obviously,
|
// one stack location to another. This avoids inflation. Obviously,
|
||||||
// we need to ensure that both locations refer to the current thread's stack.
|
// we need to ensure that both locations refer to the current thread's stack.
|
||||||
// There are some subtle concurrency issues, however, and since the benefit is
|
// There are some subtle concurrency issues, however, and since the benefit is
|
||||||
// is small (given the support for inflated fast-path locking in the fast_lock, etc)
|
// small (given the support for inflated fast-path locking in the fast_lock, etc)
|
||||||
// we'll leave that optimization for another time.
|
// we'll leave that optimization for another time.
|
||||||
|
|
||||||
if (LockingMode == LM_LEGACY) {
|
if (LockingMode == LM_LEGACY) {
|
||||||
if (displaced_header().is_neutral()) {
|
if (displaced_header().is_unlocked()) {
|
||||||
// The object is locked and the resulting ObjectMonitor* will also be
|
// The object is locked and the resulting ObjectMonitor* will also be
|
||||||
// locked so it can't be async deflated until ownership is dropped.
|
// locked so it can't be async deflated until ownership is dropped.
|
||||||
ObjectSynchronizer::inflate_helper(obj);
|
ObjectSynchronizer::inflate_helper(obj);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -34,6 +34,8 @@ class BasicLock {
|
|||||||
friend class VMStructs;
|
friend class VMStructs;
|
||||||
friend class JVMCIVMStructs;
|
friend class JVMCIVMStructs;
|
||||||
private:
|
private:
|
||||||
|
// This is either the actual displaced header from a locked object, or
|
||||||
|
// a sentinel zero value indicating a recursive stack-lock.
|
||||||
volatile markWord _displaced_header;
|
volatile markWord _displaced_header;
|
||||||
public:
|
public:
|
||||||
markWord displaced_header() const {
|
markWord displaced_header() const {
|
||||||
@ -46,7 +48,7 @@ class BasicLock {
|
|||||||
|
|
||||||
void print_on(outputStream* st, oop owner) const;
|
void print_on(outputStream* st, oop owner) const;
|
||||||
|
|
||||||
// move a basic lock (used during deoptimization
|
// move a basic lock (used during deoptimization)
|
||||||
void move_to(oop obj, BasicLock* dest);
|
void move_to(oop obj, BasicLock* dest);
|
||||||
|
|
||||||
static int displaced_header_offset_in_bytes() { return (int)offset_of(BasicLock, _displaced_header); }
|
static int displaced_header_offset_in_bytes() { return (int)offset_of(BasicLock, _displaced_header); }
|
||||||
|
@ -602,7 +602,7 @@ bool ObjectSynchronizer::enter_fast_impl(Handle obj, BasicLock* lock, JavaThread
|
|||||||
}
|
}
|
||||||
|
|
||||||
markWord mark = obj()->mark_acquire();
|
markWord mark = obj()->mark_acquire();
|
||||||
while (mark.is_neutral()) {
|
while (mark.is_unlocked()) {
|
||||||
// Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
|
// Retry until a lock state change has been observed. cas_set_mark() may collide with non lock bits modifications.
|
||||||
// Try to swing into 'fast-locked' state.
|
// Try to swing into 'fast-locked' state.
|
||||||
assert(!lock_stack.contains(obj()), "thread must not already hold the lock");
|
assert(!lock_stack.contains(obj()), "thread must not already hold the lock");
|
||||||
@ -625,7 +625,7 @@ bool ObjectSynchronizer::enter_fast_impl(Handle obj, BasicLock* lock, JavaThread
|
|||||||
return false;
|
return false;
|
||||||
} else if (LockingMode == LM_LEGACY) {
|
} else if (LockingMode == LM_LEGACY) {
|
||||||
markWord mark = obj->mark();
|
markWord mark = obj->mark();
|
||||||
if (mark.is_neutral()) {
|
if (mark.is_unlocked()) {
|
||||||
// Anticipate successful CAS -- the ST of the displaced mark must
|
// Anticipate successful CAS -- the ST of the displaced mark must
|
||||||
// be visible <= the ST performed by the CAS.
|
// be visible <= the ST performed by the CAS.
|
||||||
lock->set_displaced_header(mark);
|
lock->set_displaced_header(mark);
|
||||||
@ -696,7 +696,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current)
|
|||||||
// Only do diagnostics if we are not racing an inflation. Simply
|
// Only do diagnostics if we are not racing an inflation. Simply
|
||||||
// exiting a recursive enter of a Java Monitor that is being
|
// exiting a recursive enter of a Java Monitor that is being
|
||||||
// inflated is safe; see the has_monitor() comment below.
|
// inflated is safe; see the has_monitor() comment below.
|
||||||
assert(!mark.is_neutral(), "invariant");
|
assert(!mark.is_unlocked(), "invariant");
|
||||||
assert(!mark.has_locker() ||
|
assert(!mark.has_locker() ||
|
||||||
current->is_lock_owned((address)mark.locker()), "invariant");
|
current->is_lock_owned((address)mark.locker()), "invariant");
|
||||||
if (mark.has_monitor()) {
|
if (mark.has_monitor()) {
|
||||||
@ -1009,7 +1009,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
|
|||||||
assert(LockingMode == LM_MONITOR, "+VerifyHeavyMonitors requires LockingMode == 0 (LM_MONITOR)");
|
assert(LockingMode == LM_MONITOR, "+VerifyHeavyMonitors requires LockingMode == 0 (LM_MONITOR)");
|
||||||
guarantee((obj->mark().value() & markWord::lock_mask_in_place) != markWord::locked_value, "must not be lightweight/stack-locked");
|
guarantee((obj->mark().value() & markWord::lock_mask_in_place) != markWord::locked_value, "must not be lightweight/stack-locked");
|
||||||
}
|
}
|
||||||
if (mark.is_neutral() || (LockingMode == LM_LIGHTWEIGHT && mark.is_fast_locked())) {
|
if (mark.is_unlocked() || (LockingMode == LM_LIGHTWEIGHT && mark.is_fast_locked())) {
|
||||||
hash = mark.hash();
|
hash = mark.hash();
|
||||||
if (hash != 0) { // if it has a hash, just return it
|
if (hash != 0) { // if it has a hash, just return it
|
||||||
return hash;
|
return hash;
|
||||||
@ -1139,7 +1139,7 @@ bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
|
|||||||
return monitor->is_entered(current) != 0;
|
return monitor->is_entered(current) != 0;
|
||||||
}
|
}
|
||||||
// Unlocked case, header in place
|
// Unlocked case, header in place
|
||||||
assert(mark.is_neutral(), "sanity check");
|
assert(mark.is_unlocked(), "sanity check");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1172,7 +1172,7 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob
|
|||||||
// Unlocked case, header in place
|
// Unlocked case, header in place
|
||||||
// Cannot have assertion since this object may have been
|
// Cannot have assertion since this object may have been
|
||||||
// locked by another thread when reaching here.
|
// locked by another thread when reaching here.
|
||||||
// assert(mark.is_neutral(), "sanity check");
|
// assert(mark.is_unlocked(), "sanity check");
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -1423,7 +1423,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
|
|||||||
// * stack-locked - Coerce it to inflated from stack-locked.
|
// * stack-locked - Coerce it to inflated from stack-locked.
|
||||||
// * INFLATING - Busy wait for conversion from stack-locked to
|
// * INFLATING - Busy wait for conversion from stack-locked to
|
||||||
// inflated.
|
// inflated.
|
||||||
// * neutral - Aggressively inflate the object.
|
// * unlocked - Aggressively inflate the object.
|
||||||
|
|
||||||
// CASE: inflated
|
// CASE: inflated
|
||||||
if (mark.has_monitor()) {
|
if (mark.has_monitor()) {
|
||||||
@ -1601,7 +1601,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CASE: neutral
|
// CASE: unlocked
|
||||||
// TODO-FIXME: for entry we currently inflate and then try to CAS _owner.
|
// TODO-FIXME: for entry we currently inflate and then try to CAS _owner.
|
||||||
// If we know we're inflating for entry it's better to inflate by swinging a
|
// If we know we're inflating for entry it's better to inflate by swinging a
|
||||||
// pre-locked ObjectMonitor pointer into the object header. A successful
|
// pre-locked ObjectMonitor pointer into the object header. A successful
|
||||||
@ -1610,9 +1610,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
|
|||||||
// to inflate and then CAS() again to try to swing _owner from null to current.
|
// to inflate and then CAS() again to try to swing _owner from null to current.
|
||||||
// An inflateTry() method that we could call from enter() would be useful.
|
// An inflateTry() method that we could call from enter() would be useful.
|
||||||
|
|
||||||
// Catch if the object's header is not neutral (not locked and
|
assert(mark.is_unlocked(), "invariant: header=" INTPTR_FORMAT, mark.value());
|
||||||
// not marked is what we care about here).
|
|
||||||
assert(mark.is_neutral(), "invariant: header=" INTPTR_FORMAT, mark.value());
|
|
||||||
ObjectMonitor* m = new ObjectMonitor(object);
|
ObjectMonitor* m = new ObjectMonitor(object);
|
||||||
// prepare m for installation - set monitor to initial state
|
// prepare m for installation - set monitor to initial state
|
||||||
m->set_header(mark);
|
m->set_header(mark);
|
||||||
@ -1635,7 +1633,7 @@ ObjectMonitor* ObjectSynchronizer::inflate_impl(JavaThread* inflating_thread, oo
|
|||||||
OM_PERFDATA_OP(Inflations, inc());
|
OM_PERFDATA_OP(Inflations, inc());
|
||||||
if (log_is_enabled(Trace, monitorinflation)) {
|
if (log_is_enabled(Trace, monitorinflation)) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark="
|
lsh.print_cr("inflate(unlocked): object=" INTPTR_FORMAT ", mark="
|
||||||
INTPTR_FORMAT ", type='%s'", p2i(object),
|
INTPTR_FORMAT ", type='%s'", p2i(object),
|
||||||
object->mark().value(), object->klass()->external_name());
|
object->mark().value(), object->klass()->external_name());
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user