< prev index next >
src/hotspot/share/runtime/synchronizer.cpp
Print this page
@@ -127,10 +127,23 @@
static volatile intptr_t gListLock = 0; // protects global monitor lists
static volatile int gMonitorFreeCount = 0; // # on gFreeList
static volatile int gMonitorPopulation = 0; // # Extant -- in circulation
+#define CHECK_THROW_NOSYNC_IMSE(obj) \
+ if ((obj)->mark()->is_always_locked()) { \
+ ResourceMark rm(THREAD); \
+ THROW_MSG(vmSymbols::java_lang_IllegalMonitorStateException(), obj->klass()->external_name()); \
+ }
+
+#define CHECK_THROW_NOSYNC_IMSE_0(obj) \
+ if ((obj)->mark()->is_always_locked()) { \
+ ResourceMark rm(THREAD); \
+ THROW_MSG_0(vmSymbols::java_lang_IllegalMonitorStateException(), obj->klass()->external_name()); \
+ }
+
+
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
// =====================> Quick functions
@@ -158,10 +171,11 @@
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(self->is_Java_thread(), "invariant");
assert(((JavaThread *) self)->thread_state() == _thread_in_Java, "invariant");
NoSafepointVerifier nsv;
if (obj == NULL) return false; // slow-path for invalid obj
+ assert(!EnableValhalla || !obj->klass()->is_value(), "monitor op on value type");
const markOop mark = obj->mark();
if (mark->has_locker() && self->is_lock_owned((address)mark->locker())) {
// Degenerate notify
// stack-locked by caller so by definition the implied waitset is empty.
@@ -208,10 +222,11 @@
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
assert(Self->is_Java_thread(), "invariant");
assert(((JavaThread *) Self)->thread_state() == _thread_in_Java, "invariant");
NoSafepointVerifier nsv;
if (obj == NULL) return false; // Need to throw NPE
+ assert(!EnableValhalla || !obj->klass()->is_value(), "monitor op on value type");
const markOop mark = obj->mark();
if (mark->has_monitor()) {
ObjectMonitor * const m = mark->monitor();
assert(oopDesc::equals((oop) m->object(), obj), "invariant");
@@ -263,10 +278,11 @@
// if the following function is changed. The implementation is
// extremely sensitive to race condition. Be careful.
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock,
bool attempt_rebias, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
if (!SafepointSynchronize::is_at_safepoint()) {
BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD);
if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) {
return;
@@ -281,10 +297,14 @@
slow_enter(obj, lock, THREAD);
}
void ObjectSynchronizer::fast_exit(oop object, BasicLock* lock, TRAPS) {
markOop mark = object->mark();
+ if (EnableValhalla && mark->is_always_locked()) {
+ return;
+ }
+ assert(!EnableValhalla || !object->klass()->is_value(), "monitor op on value type");
// 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();
@@ -334,10 +354,11 @@
// Interpreter/Compiler Slow Case
// This routine is used to handle interpreter/compiler slow case
// We don't need to use fast path here, because it must have been
// failed in the interpreter/compiler code.
void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
markOop mark = obj->mark();
assert(!mark->has_bias_pattern(), "should not see bias pattern here");
if (mark->is_neutral()) {
// Anticipate successful CAS -- the ST of the displaced mark must
@@ -382,10 +403,11 @@
// 3) when notified on lock2, unlock lock2
// 4) reenter lock1 with original recursion count
// 5) lock lock2
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
intptr_t ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
+ assert(!EnableValhalla || !obj->klass()->is_value(), "monitor op on value type");
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
@@ -394,10 +416,11 @@
return monitor->complete_exit(THREAD);
}
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
void ObjectSynchronizer::reenter(Handle obj, intptr_t recursion, TRAPS) {
+ assert(!EnableValhalla || !obj->klass()->is_value(), "monitor op on value type");
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
@@ -408,10 +431,11 @@
// -----------------------------------------------------------------------------
// JNI locks on java objects
// NOTE: must use heavy weight monitor to handle jni monitor enter
void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
// the current locking is from JNI instead of Java code
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
THREAD->set_current_pending_monitor_is_from_java(false);
@@ -419,10 +443,11 @@
THREAD->set_current_pending_monitor_is_from_java(true);
}
// NOTE: must use heavy weight monitor to handle jni monitor exit
void ObjectSynchronizer::jni_exit(oop obj, Thread* THREAD) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
Handle h_obj(THREAD, obj);
BiasedLocking::revoke_and_rebias(h_obj, false, THREAD);
obj = h_obj();
}
@@ -459,10 +484,11 @@
// -----------------------------------------------------------------------------
// Wait/Notify/NotifyAll
// NOTE: must use heavy weight monitor to handle wait()
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE_0(obj);
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
@@ -479,10 +505,11 @@
// DTRACE_MONITOR_PROBE(waited, monitor, obj(), THREAD);
return dtrace_waited_probe(monitor, obj, THREAD);
}
void ObjectSynchronizer::waitUninterruptibly(Handle obj, jlong millis, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
if (millis < 0) {
@@ -490,10 +517,11 @@
}
inflate(THREAD, obj(), inflate_cause_wait)->wait(millis, false, THREAD);
}
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
@@ -504,10 +532,11 @@
inflate(THREAD, obj(), inflate_cause_notify)->notify(THREAD);
}
// NOTE: see comment of notify()
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
+ CHECK_THROW_NOSYNC_IMSE(obj);
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(obj, false, THREAD);
assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
@@ -677,10 +706,18 @@
assert(value != markOopDesc::no_hash, "invariant");
return value;
}
intptr_t ObjectSynchronizer::FastHashCode(Thread * Self, oop obj) {
+ if (EnableValhalla && obj->klass()->is_value()) {
+ // Expected tooling to override hashCode for value type, just don't crash
+ if (log_is_enabled(Debug, monitorinflation)) {
+ ResourceMark rm;
+ log_debug(monitorinflation)("FastHashCode for value type: %s", obj->klass()->external_name());
+ }
+ return obj->klass()->java_mirror()->identity_hash();
+ }
if (UseBiasedLocking) {
// NOTE: many places throughout the JVM do not expect a safepoint
// to be taken here, in particular most operations on perm gen
// objects. However, we only ever bias Java instances and all of
// the call sites of identity_hash that might revoke biases have
@@ -781,19 +818,16 @@
}
// We finally get the hash
return hash;
}
-// Deprecated -- use FastHashCode() instead.
-
-intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
- return FastHashCode(Thread::current(), obj());
-}
-
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
Handle h_obj) {
+ if (EnableValhalla && h_obj->mark()->is_always_locked()) {
+ return false;
+ }
if (UseBiasedLocking) {
BiasedLocking::revoke_and_rebias(h_obj, false, thread);
assert(!h_obj->mark()->has_bias_pattern(), "biases should be revoked by now");
}
@@ -1300,10 +1334,14 @@
// Inflate mutates the heap ...
// Relaxing assertion for bug 6320749.
assert(Universe::verify_in_progress() ||
!SafepointSynchronize::is_at_safepoint(), "invariant");
+ if (EnableValhalla) {
+ guarantee(!object->klass()->is_value(), "Attempt to inflate value type");
+ }
+
EventJavaMonitorInflate event;
for (;;) {
const markOop mark = object->mark();
assert(!mark->has_bias_pattern(), "invariant");
< prev index next >