mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8262910: Cleanup THREAD/TRAPS/naming and typing issues in ObjectMonitor and related code
Reviewed-by: coleenp, pchilanomate, dcubed, cjplummer, sspitsyn
This commit is contained in:
parent
57f16f9fe5
commit
c6d74bd933
18 changed files with 470 additions and 521 deletions
|
@ -546,12 +546,12 @@ void SystemDictionary::validate_protection_domain(InstanceKlass* klass,
|
|||
//
|
||||
// The notify allows applications that did an untimed wait() on
|
||||
// the classloader object lock to not hang.
|
||||
void SystemDictionary::double_lock_wait(Thread* thread, Handle lockObject) {
|
||||
void SystemDictionary::double_lock_wait(JavaThread* thread, Handle lockObject) {
|
||||
assert_lock_strong(SystemDictionary_lock);
|
||||
|
||||
assert(lockObject() != NULL, "lockObject must be non-NULL");
|
||||
bool calledholdinglock
|
||||
= ObjectSynchronizer::current_thread_holds_lock(thread->as_Java_thread(), lockObject);
|
||||
= ObjectSynchronizer::current_thread_holds_lock(thread, lockObject);
|
||||
assert(calledholdinglock, "must hold lock for notify");
|
||||
assert(!is_parallelCapable(lockObject), "lockObject must not be parallelCapable");
|
||||
// These don't throw exceptions.
|
||||
|
@ -626,7 +626,7 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
|
|||
if (class_loader.is_null()) {
|
||||
SystemDictionary_lock->wait();
|
||||
} else {
|
||||
double_lock_wait(THREAD, lockObject);
|
||||
double_lock_wait(THREAD->as_Java_thread(), lockObject);
|
||||
}
|
||||
} else {
|
||||
// If not in SD and not in PH, the other thread is done loading the super class
|
||||
|
@ -693,7 +693,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
|||
// ParallelCapable Classloaders and the bootstrap classloader
|
||||
// do not acquire lock here.
|
||||
Handle lockObject = get_loader_lock_or_null(class_loader);
|
||||
ObjectLocker ol(lockObject, THREAD);
|
||||
ObjectLocker ol(lockObject, THREAD->as_Java_thread());
|
||||
|
||||
// Check again (after locking) if the class already exists in SystemDictionary
|
||||
bool class_has_been_loaded = false;
|
||||
|
@ -777,7 +777,7 @@ InstanceKlass* SystemDictionary::resolve_instance_class_or_null(Symbol* name,
|
|||
} else {
|
||||
// case 4: traditional with broken classloader lock. wait on first
|
||||
// requestor.
|
||||
double_lock_wait(THREAD, lockObject);
|
||||
double_lock_wait(THREAD->as_Java_thread(), lockObject);
|
||||
}
|
||||
// Check if classloading completed while we were waiting
|
||||
InstanceKlass* check = dictionary->find_class(name_hash, name);
|
||||
|
@ -1051,7 +1051,7 @@ InstanceKlass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
|||
// Classloaders that support parallelism, e.g. bootstrap classloader,
|
||||
// do not acquire lock here
|
||||
Handle lockObject = get_loader_lock_or_null(class_loader);
|
||||
ObjectLocker ol(lockObject, THREAD);
|
||||
ObjectLocker ol(lockObject, THREAD->as_Java_thread());
|
||||
|
||||
// Parse the stream and create a klass.
|
||||
// Note that we do this even though this klass might
|
||||
|
@ -1339,7 +1339,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
|
|||
{
|
||||
HandleMark hm(THREAD);
|
||||
Handle lockObject = get_loader_lock_or_null(class_loader);
|
||||
ObjectLocker ol(lockObject, THREAD);
|
||||
ObjectLocker ol(lockObject, THREAD->as_Java_thread());
|
||||
// prohibited package check assumes all classes loaded from archive call
|
||||
// restore_unshareable_info which calls ik->set_package()
|
||||
ik->restore_unshareable_info(loader_data, protection_domain, pkg_entry, CHECK_NULL);
|
||||
|
|
|
@ -345,7 +345,7 @@ private:
|
|||
// waiting; relocks lockObject with correct recursion count
|
||||
// after waiting, but before reentering SystemDictionary_lock
|
||||
// to preserve lock order semantics.
|
||||
static void double_lock_wait(Thread* thread, Handle lockObject);
|
||||
static void double_lock_wait(JavaThread* thread, Handle lockObject);
|
||||
static void define_instance_class(InstanceKlass* k, Handle class_loader, TRAPS);
|
||||
static InstanceKlass* find_or_define_helper(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
|
|
|
@ -732,7 +732,7 @@ JRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, Ba
|
|||
Handle h_obj(thread, elem->obj());
|
||||
assert(Universe::heap()->is_in_or_null(h_obj()),
|
||||
"must be NULL or an object");
|
||||
ObjectSynchronizer::enter(h_obj, elem->lock(), CHECK);
|
||||
ObjectSynchronizer::enter(h_obj, elem->lock(), thread);
|
||||
assert(Universe::heap()->is_in_or_null(elem->obj()),
|
||||
"must be NULL or an object");
|
||||
#ifdef ASSERT
|
||||
|
@ -752,7 +752,7 @@ JRT_LEAF(void, InterpreterRuntime::monitorexit(BasicObjectLock* elem))
|
|||
}
|
||||
return;
|
||||
}
|
||||
ObjectSynchronizer::exit(obj, elem->lock(), Thread::current());
|
||||
ObjectSynchronizer::exit(obj, elem->lock(), JavaThread::current());
|
||||
// Free entry. If it is not cleared, the exception handling code will try to unlock the monitor
|
||||
// again at method exit or in the case of an exception.
|
||||
elem->set_obj(NULL);
|
||||
|
|
|
@ -139,7 +139,7 @@ void JfrJavaSupport::notify_all(jobject object, TRAPS) {
|
|||
HandleMark hm(THREAD);
|
||||
Handle h_obj(THREAD, resolve_non_null(object));
|
||||
assert(h_obj.not_null(), "invariant");
|
||||
ObjectSynchronizer::jni_enter(h_obj, THREAD);
|
||||
ObjectSynchronizer::jni_enter(h_obj, THREAD->as_Java_thread());
|
||||
ObjectSynchronizer::notifyall(h_obj, THREAD);
|
||||
ObjectSynchronizer::jni_exit(h_obj(), THREAD);
|
||||
DEBUG_ONLY(check_java_thread_in_vm(THREAD));
|
||||
|
|
|
@ -258,7 +258,7 @@
|
|||
volatile_nonstatic_field(ObjectMonitor, _recursions, intptr_t) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _cxq, ObjectWaiter*) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _EntryList, ObjectWaiter*) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _succ, Thread*) \
|
||||
volatile_nonstatic_field(ObjectMonitor, _succ, JavaThread*) \
|
||||
\
|
||||
volatile_nonstatic_field(oopDesc, _mark, markWord) \
|
||||
volatile_nonstatic_field(oopDesc, _metadata._klass, Klass*) \
|
||||
|
|
|
@ -374,13 +374,14 @@ void ConstantPoolCacheEntry::set_method_handle_common(const constantPoolHandle&
|
|||
// the lock, so that when the losing writer returns, he can use the linked
|
||||
// cache entry.
|
||||
|
||||
objArrayHandle resolved_references(Thread::current(), cpool->resolved_references());
|
||||
JavaThread* current = JavaThread::current();
|
||||
objArrayHandle resolved_references(current, cpool->resolved_references());
|
||||
// Use the resolved_references() lock for this cpCache entry.
|
||||
// resolved_references are created for all classes with Invokedynamic, MethodHandle
|
||||
// or MethodType constant pool cache entries.
|
||||
assert(resolved_references() != NULL,
|
||||
"a resolved_references array should have been created for this class");
|
||||
ObjectLocker ol(resolved_references, Thread::current());
|
||||
ObjectLocker ol(resolved_references, current);
|
||||
if (!is_f1_null()) {
|
||||
return;
|
||||
}
|
||||
|
@ -482,10 +483,11 @@ bool ConstantPoolCacheEntry::save_and_throw_indy_exc(
|
|||
// Use the resolved_references() lock for this cpCache entry.
|
||||
// resolved_references are created for all classes with Invokedynamic, MethodHandle
|
||||
// or MethodType constant pool cache entries.
|
||||
objArrayHandle resolved_references(Thread::current(), cpool->resolved_references());
|
||||
JavaThread* current = THREAD->as_Java_thread();
|
||||
objArrayHandle resolved_references(current, cpool->resolved_references());
|
||||
assert(resolved_references() != NULL,
|
||||
"a resolved_references array should have been created for this class");
|
||||
ObjectLocker ol(resolved_references, THREAD);
|
||||
ObjectLocker ol(resolved_references, current);
|
||||
|
||||
// if f1 is not null or the indy_resolution_failed flag is set then another
|
||||
// thread either succeeded in resolving the method or got a LinkageError
|
||||
|
|
|
@ -807,7 +807,7 @@ void InstanceKlass::eager_initialize_impl() {
|
|||
EXCEPTION_MARK;
|
||||
HandleMark hm(THREAD);
|
||||
Handle h_init_lock(THREAD, init_lock());
|
||||
ObjectLocker ol(h_init_lock, THREAD);
|
||||
ObjectLocker ol(h_init_lock, THREAD->as_Java_thread());
|
||||
|
||||
// abort if someone beat us to the initialization
|
||||
if (!is_not_initialized()) return; // note: not equivalent to is_initialized()
|
||||
|
@ -943,7 +943,7 @@ bool InstanceKlass::link_class_impl(TRAPS) {
|
|||
{
|
||||
HandleMark hm(THREAD);
|
||||
Handle h_init_lock(THREAD, init_lock());
|
||||
ObjectLocker ol(h_init_lock, THREAD);
|
||||
ObjectLocker ol(h_init_lock, jt);
|
||||
// rewritten will have been set if loader constraint error found
|
||||
// on an earlier link attempt
|
||||
// don't verify or rewrite if already rewritten
|
||||
|
@ -1068,7 +1068,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
// Step 1
|
||||
{
|
||||
Handle h_init_lock(THREAD, init_lock());
|
||||
ObjectLocker ol(h_init_lock, THREAD);
|
||||
ObjectLocker ol(h_init_lock, jt);
|
||||
|
||||
// Step 2
|
||||
// If we were to use wait() instead of waitInterruptibly() then
|
||||
|
@ -1211,7 +1211,7 @@ void InstanceKlass::initialize_impl(TRAPS) {
|
|||
void InstanceKlass::set_initialization_state_and_notify(ClassState state, TRAPS) {
|
||||
Handle h_init_lock(THREAD, init_lock());
|
||||
if (h_init_lock() != NULL) {
|
||||
ObjectLocker ol(h_init_lock, THREAD);
|
||||
ObjectLocker ol(h_init_lock, THREAD->as_Java_thread());
|
||||
set_init_thread(NULL); // reset _init_thread before changing _init_state
|
||||
set_init_state(state);
|
||||
fence_and_clear_init_lock();
|
||||
|
|
|
@ -2712,7 +2712,7 @@ JNI_ENTRY(jint, jni_MonitorEnter(JNIEnv *env, jobject jobj))
|
|||
}
|
||||
|
||||
Handle obj(thread, JNIHandles::resolve_non_null(jobj));
|
||||
ObjectSynchronizer::jni_enter(obj, CHECK_(JNI_ERR));
|
||||
ObjectSynchronizer::jni_enter(obj, thread);
|
||||
ret = JNI_OK;
|
||||
return ret;
|
||||
JNI_END
|
||||
|
|
|
@ -693,7 +693,7 @@ JvmtiEnv::AddToSystemClassLoaderSearch(const char* segment) {
|
|||
// The phase is checked by the wrapper that called this function,
|
||||
// but this thread could be racing with the thread that is
|
||||
// terminating the VM so we check one more time.
|
||||
Thread* THREAD = Thread::current();
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
HandleMark hm(THREAD);
|
||||
|
||||
// create the zip entry (which will open the zip file and hence
|
||||
|
|
|
@ -1079,13 +1079,12 @@ JvmtiEnvBase::get_object_monitor_usage(JavaThread* calling_thread, jobject objec
|
|||
nWait = j;
|
||||
break;
|
||||
}
|
||||
Thread *t = mon->thread_of_waiter(waiter);
|
||||
if (t != NULL && t->is_Java_thread()) {
|
||||
JavaThread *wjava_thread = t->as_Java_thread();
|
||||
JavaThread *w = mon->thread_of_waiter(waiter);
|
||||
if (w != NULL) {
|
||||
// If the thread was found on the ObjectWaiter list, then
|
||||
// it has not been notified. This thread can't change the
|
||||
// state of the monitor so it doesn't need to be suspended.
|
||||
Handle th(current_thread, wjava_thread->threadObj());
|
||||
Handle th(current_thread, w->threadObj());
|
||||
ret.waiters[offset + j] = (jthread)jni_reference(calling_thread, th);
|
||||
ret.notify_waiters[j++] = (jthread)jni_reference(calling_thread, th);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -46,14 +46,14 @@ class ObjectWaiter : public StackObj {
|
|||
enum TStates { TS_UNDEF, TS_READY, TS_RUN, TS_WAIT, TS_ENTER, TS_CXQ };
|
||||
ObjectWaiter* volatile _next;
|
||||
ObjectWaiter* volatile _prev;
|
||||
Thread* _thread;
|
||||
JavaThread* _thread;
|
||||
jlong _notifier_tid;
|
||||
ParkEvent * _event;
|
||||
volatile int _notified;
|
||||
volatile TStates TState;
|
||||
bool _active; // Contention monitoring is enabled
|
||||
public:
|
||||
ObjectWaiter(Thread* thread);
|
||||
ObjectWaiter(JavaThread* current);
|
||||
|
||||
void wait_reenter_begin(ObjectMonitor *mon);
|
||||
void wait_reenter_end(ObjectMonitor *mon);
|
||||
|
@ -162,8 +162,8 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
// acting as proxies for Threads.
|
||||
|
||||
ObjectWaiter* volatile _cxq; // LL of recently-arrived threads blocked on entry.
|
||||
Thread* volatile _succ; // Heir presumptive thread - used for futile wakeup throttling
|
||||
Thread* volatile _Responsible;
|
||||
JavaThread* volatile _succ; // Heir presumptive thread - used for futile wakeup throttling
|
||||
JavaThread* volatile _Responsible;
|
||||
|
||||
volatile int _Spinner; // for exit->spinner handoff optimization
|
||||
volatile int _SpinDuration;
|
||||
|
@ -249,7 +249,7 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
}
|
||||
const char* is_busy_to_string(stringStream* ss);
|
||||
|
||||
intptr_t is_entered(Thread* current) const;
|
||||
intptr_t is_entered(JavaThread* current) const;
|
||||
|
||||
void* owner() const; // Returns NULL if DEFLATER_MARKER is observed.
|
||||
void* owner_raw() const;
|
||||
|
@ -261,8 +261,8 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
void release_clear_owner(void* old_value);
|
||||
// Simply set _owner field to new_value; current value must match old_value.
|
||||
void set_owner_from(void* old_value, void* new_value);
|
||||
// Simply set _owner field to self; current value must match basic_lock_p.
|
||||
void set_owner_from_BasicLock(void* basic_lock_p, Thread* self);
|
||||
// Simply set _owner field to current; current value must match basic_lock_p.
|
||||
void set_owner_from_BasicLock(void* basic_lock_p, JavaThread* current);
|
||||
// Try to set _owner field to new_value if the current value matches
|
||||
// old_value, using Atomic::cmpxchg(). Otherwise, does not change the
|
||||
// _owner field. Returns the prior value of the _owner field.
|
||||
|
@ -290,7 +290,7 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
// JVM/TI GetObjectMonitorUsage() needs this:
|
||||
ObjectWaiter* first_waiter() { return _WaitSet; }
|
||||
ObjectWaiter* next_waiter(ObjectWaiter* o) { return o->_next; }
|
||||
Thread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; }
|
||||
JavaThread* thread_of_waiter(ObjectWaiter* o) { return o->_thread; }
|
||||
|
||||
ObjectMonitor(oop object);
|
||||
~ObjectMonitor();
|
||||
|
@ -300,11 +300,11 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
|
||||
// Returns true if the specified thread owns the ObjectMonitor. Otherwise
|
||||
// returns false and throws IllegalMonitorStateException (IMSE).
|
||||
bool check_owner(Thread* THREAD);
|
||||
bool check_owner(TRAPS);
|
||||
|
||||
bool enter(TRAPS);
|
||||
void exit(bool not_suspended, TRAPS);
|
||||
void wait(jlong millis, bool interruptable, TRAPS);
|
||||
bool enter(JavaThread* current);
|
||||
void exit(bool not_suspended, JavaThread* current);
|
||||
void wait(jlong millis, bool interruptible, TRAPS);
|
||||
void notify(TRAPS);
|
||||
void notifyAll(TRAPS);
|
||||
|
||||
|
@ -315,22 +315,21 @@ class ObjectMonitor : public CHeapObj<mtInternal> {
|
|||
void print_on(outputStream* st) const;
|
||||
|
||||
// Use the following at your own risk
|
||||
intx complete_exit(TRAPS);
|
||||
bool reenter(intx recursions, TRAPS);
|
||||
intx complete_exit(JavaThread* current);
|
||||
bool reenter(intx recursions, JavaThread* current);
|
||||
|
||||
private:
|
||||
void AddWaiter(ObjectWaiter* waiter);
|
||||
void INotify(Thread* self);
|
||||
void INotify(JavaThread* current);
|
||||
ObjectWaiter* DequeueWaiter();
|
||||
void DequeueSpecificWaiter(ObjectWaiter* waiter);
|
||||
void EnterI(TRAPS);
|
||||
void ReenterI(Thread* self, ObjectWaiter* self_node);
|
||||
void UnlinkAfterAcquire(Thread* self, ObjectWaiter* self_node);
|
||||
int TryLock(Thread* self);
|
||||
int NotRunnable(Thread* self, Thread* Owner);
|
||||
int TrySpin(Thread* self);
|
||||
void ExitEpilog(Thread* self, ObjectWaiter* Wakee);
|
||||
bool ExitSuspendEquivalent(JavaThread* self);
|
||||
void EnterI(JavaThread* current);
|
||||
void ReenterI(JavaThread* current, ObjectWaiter* current_node);
|
||||
void UnlinkAfterAcquire(JavaThread* current, ObjectWaiter* current_node);
|
||||
int TryLock(JavaThread* current);
|
||||
int NotRunnable(JavaThread* current, JavaThread* Owner);
|
||||
int TrySpin(JavaThread* current);
|
||||
void ExitEpilog(JavaThread* current, ObjectWaiter* Wakee);
|
||||
|
||||
// Deflation support
|
||||
bool deflate_monitor();
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
#include "runtime/objectMonitor.hpp"
|
||||
#include "runtime/synchronizer.hpp"
|
||||
|
||||
inline intptr_t ObjectMonitor::is_entered(TRAPS) const {
|
||||
inline intptr_t ObjectMonitor::is_entered(JavaThread* current) const {
|
||||
void* owner = owner_raw();
|
||||
if (THREAD == owner || THREAD->is_lock_owned((address)owner)) {
|
||||
if (current == owner || current->is_lock_owned((address)owner)) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -116,7 +116,7 @@ inline void ObjectMonitor::set_owner_from(void* old_value, void* new_value) {
|
|||
}
|
||||
|
||||
// Simply set _owner field to self; current value must match basic_lock_p.
|
||||
inline void ObjectMonitor::set_owner_from_BasicLock(void* basic_lock_p, Thread* self) {
|
||||
inline void ObjectMonitor::set_owner_from_BasicLock(void* basic_lock_p, JavaThread* current) {
|
||||
#ifdef ASSERT
|
||||
void* prev = Atomic::load(&_owner);
|
||||
assert(prev == basic_lock_p, "unexpected prev owner=" INTPTR_FORMAT
|
||||
|
@ -124,11 +124,11 @@ inline void ObjectMonitor::set_owner_from_BasicLock(void* basic_lock_p, Thread*
|
|||
#endif
|
||||
// Non-null owner field to non-null owner field is safe without
|
||||
// cmpxchg() as long as all readers can tolerate either flavor.
|
||||
Atomic::store(&_owner, self);
|
||||
Atomic::store(&_owner, current);
|
||||
log_trace(monitorinflation, owner)("set_owner_from_BasicLock(): mid="
|
||||
INTPTR_FORMAT ", basic_lock_p="
|
||||
INTPTR_FORMAT ", new_value=" INTPTR_FORMAT,
|
||||
p2i(this), p2i(basic_lock_p), p2i(self));
|
||||
p2i(this), p2i(basic_lock_p), p2i(current));
|
||||
}
|
||||
|
||||
// Try to set _owner field to new_value if the current value matches
|
||||
|
|
|
@ -2122,7 +2122,7 @@ void SharedRuntime::monitor_enter_helper(oopDesc* obj, BasicLock* lock, JavaThre
|
|||
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
|
||||
}
|
||||
Handle h_obj(THREAD, obj);
|
||||
ObjectSynchronizer::enter(h_obj, lock, CHECK);
|
||||
ObjectSynchronizer::enter(h_obj, lock, thread);
|
||||
assert(!HAS_PENDING_EXCEPTION, "Should have no exception here");
|
||||
JRT_BLOCK_END
|
||||
}
|
||||
|
@ -2144,7 +2144,7 @@ void SharedRuntime::monitor_exit_helper(oopDesc* obj, BasicLock* lock, JavaThrea
|
|||
}
|
||||
return;
|
||||
}
|
||||
ObjectSynchronizer::exit(obj, lock, THREAD);
|
||||
ObjectSynchronizer::exit(obj, lock, thread);
|
||||
}
|
||||
|
||||
// Handles the uncommon cases of monitor unlocking in compiled code
|
||||
|
|
|
@ -80,7 +80,7 @@ size_t MonitorList::max() const {
|
|||
|
||||
// Walk the in-use list and unlink (at most MonitorDeflationMax) deflated
|
||||
// ObjectMonitors. Returns the number of unlinked ObjectMonitors.
|
||||
size_t MonitorList::unlink_deflated(Thread* self, LogStream* ls,
|
||||
size_t MonitorList::unlink_deflated(Thread* current, LogStream* ls,
|
||||
elapsedTimer* timer_p,
|
||||
GrowableArray<ObjectMonitor*>* unlinked_list) {
|
||||
size_t unlinked_count = 0;
|
||||
|
@ -124,9 +124,9 @@ size_t MonitorList::unlink_deflated(Thread* self, LogStream* ls,
|
|||
m = m->next_om();
|
||||
}
|
||||
|
||||
if (self->is_Java_thread()) {
|
||||
if (current->is_Java_thread()) {
|
||||
// A JavaThread must check for a safepoint/handshake and honor it.
|
||||
ObjectSynchronizer::chk_for_block_req(self->as_Java_thread(), "unlinking",
|
||||
ObjectSynchronizer::chk_for_block_req(current->as_Java_thread(), "unlinking",
|
||||
"unlinked_count", unlinked_count,
|
||||
ls, timer_p);
|
||||
}
|
||||
|
@ -263,14 +263,13 @@ static uintx _no_progress_cnt = 0;
|
|||
// the monitorexit operation. In that case the JIT could fuse the operations
|
||||
// into a single notifyAndExit() runtime primitive.
|
||||
|
||||
bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert(self->as_Java_thread()->thread_state() == _thread_in_Java, "invariant");
|
||||
bool ObjectSynchronizer::quick_notify(oopDesc* obj, JavaThread* current, bool all) {
|
||||
assert(current->thread_state() == _thread_in_Java, "invariant");
|
||||
NoSafepointVerifier nsv;
|
||||
if (obj == NULL) return false; // slow-path for invalid obj
|
||||
const markWord mark = obj->mark();
|
||||
|
||||
if (mark.has_locker() && self->is_lock_owned((address)mark.locker())) {
|
||||
if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
|
||||
// Degenerate notify
|
||||
// stack-locked by caller so by definition the implied waitset is empty.
|
||||
return true;
|
||||
|
@ -279,20 +278,20 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) {
|
|||
if (mark.has_monitor()) {
|
||||
ObjectMonitor* const mon = mark.monitor();
|
||||
assert(mon->object() == oop(obj), "invariant");
|
||||
if (mon->owner() != self) return false; // slow-path for IMS exception
|
||||
if (mon->owner() != current) return false; // slow-path for IMS exception
|
||||
|
||||
if (mon->first_waiter() != NULL) {
|
||||
// We have one or more waiters. Since this is an inflated monitor
|
||||
// that we own, we can transfer one or more threads from the waitset
|
||||
// to the entrylist here and now, avoiding the slow-path.
|
||||
if (all) {
|
||||
DTRACE_MONITOR_PROBE(notifyAll, mon, obj, self);
|
||||
DTRACE_MONITOR_PROBE(notifyAll, mon, obj, current);
|
||||
} else {
|
||||
DTRACE_MONITOR_PROBE(notify, mon, obj, self);
|
||||
DTRACE_MONITOR_PROBE(notify, mon, obj, current);
|
||||
}
|
||||
int free_count = 0;
|
||||
do {
|
||||
mon->INotify(self);
|
||||
mon->INotify(current);
|
||||
++free_count;
|
||||
} while (mon->first_waiter() != NULL && all);
|
||||
OM_PERFDATA_OP(Notifications, inc(free_count));
|
||||
|
@ -311,10 +310,9 @@ bool ObjectSynchronizer::quick_notify(oopDesc* obj, Thread* self, bool all) {
|
|||
// Note that we can't safely call AsyncPrintJavaStack() from within
|
||||
// quick_enter() as our thread state remains _in_Java.
|
||||
|
||||
bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
|
||||
bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current,
|
||||
BasicLock * lock) {
|
||||
assert(!SafepointSynchronize::is_at_safepoint(), "invariant");
|
||||
assert(self->as_Java_thread()->thread_state() == _thread_in_Java, "invariant");
|
||||
assert(current->thread_state() == _thread_in_Java, "invariant");
|
||||
NoSafepointVerifier nsv;
|
||||
if (obj == NULL) return false; // Need to throw NPE
|
||||
|
||||
|
@ -332,14 +330,14 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
|
|||
if (m->object_peek() == NULL) {
|
||||
return false;
|
||||
}
|
||||
Thread* const owner = (Thread *) m->owner_raw();
|
||||
JavaThread* const owner = (JavaThread*) m->owner_raw();
|
||||
|
||||
// Lock contention and Transactional Lock Elision (TLE) diagnostics
|
||||
// and observability
|
||||
// Case: light contention possibly amenable to TLE
|
||||
// Case: TLE inimical operations such as nested/recursive synchronization
|
||||
|
||||
if (owner == self) {
|
||||
if (owner == current) {
|
||||
m->_recursions++;
|
||||
return true;
|
||||
}
|
||||
|
@ -356,7 +354,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
|
|||
// and last are the inflated Java Monitor (ObjectMonitor) checks.
|
||||
lock->set_displaced_header(markWord::unused_mark());
|
||||
|
||||
if (owner == NULL && m->try_set_owner_from(NULL, self) == NULL) {
|
||||
if (owner == NULL && m->try_set_owner_from(NULL, current) == NULL) {
|
||||
assert(m->_recursions == 0, "invariant");
|
||||
return true;
|
||||
}
|
||||
|
@ -373,10 +371,8 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
|
|||
}
|
||||
|
||||
// Handle notifications when synchronizing on value based classes
|
||||
void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, Thread* current) {
|
||||
JavaThread* self = current->as_Java_thread();
|
||||
|
||||
frame last_frame = self->last_frame();
|
||||
void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread* current) {
|
||||
frame last_frame = current->last_frame();
|
||||
bool bcp_was_adjusted = false;
|
||||
// Don't decrement bcp if it points to the frame's first instruction. This happens when
|
||||
// handle_sync_on_value_based_class() is called because of a synchronized method. There
|
||||
|
@ -389,9 +385,9 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, Thread* cu
|
|||
}
|
||||
|
||||
if (DiagnoseSyncOnValueBasedClasses == FATAL_EXIT) {
|
||||
ResourceMark rm(self);
|
||||
ResourceMark rm(current);
|
||||
stringStream ss;
|
||||
self->print_stack_on(&ss);
|
||||
current->print_stack_on(&ss);
|
||||
char* base = (char*)strstr(ss.base(), "at");
|
||||
char* newline = (char*)strchr(ss.base(), '\n');
|
||||
if (newline != NULL) {
|
||||
|
@ -400,13 +396,13 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, Thread* cu
|
|||
fatal("Synchronizing on object " INTPTR_FORMAT " of klass %s %s", p2i(obj()), obj->klass()->external_name(), base);
|
||||
} else {
|
||||
assert(DiagnoseSyncOnValueBasedClasses == LOG_WARNING, "invalid value for DiagnoseSyncOnValueBasedClasses");
|
||||
ResourceMark rm(self);
|
||||
ResourceMark rm(current);
|
||||
Log(valuebasedclasses) vblog;
|
||||
|
||||
vblog.info("Synchronizing on object " INTPTR_FORMAT " of klass %s", p2i(obj()), obj->klass()->external_name());
|
||||
if (self->has_last_Java_frame()) {
|
||||
if (current->has_last_Java_frame()) {
|
||||
LogStream info_stream(vblog.info());
|
||||
self->print_stack_on(&info_stream);
|
||||
current->print_stack_on(&info_stream);
|
||||
} else {
|
||||
vblog.info("Cannot find the last Java frame");
|
||||
}
|
||||
|
@ -429,17 +425,13 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, Thread* cu
|
|||
// of this algorithm. Make sure to update that code if the following function is
|
||||
// changed. The implementation is extremely sensitive to race condition. Be careful.
|
||||
|
||||
void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
|
||||
void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, JavaThread* current) {
|
||||
if (obj->klass()->is_value_based()) {
|
||||
handle_sync_on_value_based_class(obj, THREAD);
|
||||
handle_sync_on_value_based_class(obj, current);
|
||||
}
|
||||
|
||||
if (UseBiasedLocking) {
|
||||
if (!SafepointSynchronize::is_at_safepoint()) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
} else {
|
||||
BiasedLocking::revoke_at_safepoint(obj);
|
||||
}
|
||||
BiasedLocking::revoke(obj, current);
|
||||
}
|
||||
|
||||
markWord mark = obj->mark();
|
||||
|
@ -454,7 +446,7 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
|
|||
}
|
||||
// Fall through to inflate() ...
|
||||
} else if (mark.has_locker() &&
|
||||
THREAD->is_lock_owned((address)mark.locker())) {
|
||||
current->is_lock_owned((address)mark.locker())) {
|
||||
assert(lock != mark.locker(), "must not re-lock the same lock");
|
||||
assert(lock != (BasicLock*)obj->mark().value(), "don't relock with same BasicLock");
|
||||
lock->set_displaced_header(markWord::from_pointer(NULL));
|
||||
|
@ -470,14 +462,14 @@ void ObjectSynchronizer::enter(Handle obj, BasicLock* lock, TRAPS) {
|
|||
// enter() can make the ObjectMonitor busy. enter() returns false if
|
||||
// we have lost the race to async deflation and we simply try again.
|
||||
while (true) {
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_monitor_enter);
|
||||
if (monitor->enter(THREAD)) {
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_monitor_enter);
|
||||
if (monitor->enter(current)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
||||
void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) {
|
||||
markWord mark = object->mark();
|
||||
// We cannot check for Biased Locking if we are racing an inflation.
|
||||
assert(mark == markWord::INFLATING() ||
|
||||
|
@ -494,7 +486,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
|||
// inflated is safe; see the has_monitor() comment below.
|
||||
assert(!mark.is_neutral(), "invariant");
|
||||
assert(!mark.has_locker() ||
|
||||
THREAD->is_lock_owned((address)mark.locker()), "invariant");
|
||||
current->is_lock_owned((address)mark.locker()), "invariant");
|
||||
if (mark.has_monitor()) {
|
||||
// The BasicLock's displaced_header is marked as a recursive
|
||||
// enter and we have an inflated Java Monitor (ObjectMonitor).
|
||||
|
@ -506,7 +498,7 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
|||
// does not own the Java Monitor.
|
||||
ObjectMonitor* m = mark.monitor();
|
||||
assert(m->object()->mark() == mark, "invariant");
|
||||
assert(m->is_entered(THREAD), "invariant");
|
||||
assert(m->is_entered(current), "invariant");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -525,8 +517,8 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
|||
// We have to take the slow-path of possible inflation and then exit.
|
||||
// The ObjectMonitor* can't be async deflated until ownership is
|
||||
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
|
||||
ObjectMonitor* monitor = inflate(THREAD, object, inflate_cause_vm_internal);
|
||||
monitor->exit(true, THREAD);
|
||||
ObjectMonitor* monitor = inflate(current, object, inflate_cause_vm_internal);
|
||||
monitor->exit(true, current);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -541,23 +533,23 @@ void ObjectSynchronizer::exit(oop object, BasicLock* lock, TRAPS) {
|
|||
// 4) reenter lock1 with original recursion count
|
||||
// 5) lock lock2
|
||||
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
|
||||
intx ObjectSynchronizer::complete_exit(Handle obj, TRAPS) {
|
||||
intx ObjectSynchronizer::complete_exit(Handle obj, JavaThread* current) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
|
||||
// The ObjectMonitor* can't be async deflated until ownership is
|
||||
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
|
||||
intptr_t ret_code = monitor->complete_exit(THREAD);
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_vm_internal);
|
||||
intptr_t ret_code = monitor->complete_exit(current);
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
// NOTE: must use heavy weight monitor to handle complete_exit/reenter()
|
||||
void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
|
||||
void ObjectSynchronizer::reenter(Handle obj, intx recursions, JavaThread* current) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
|
||||
|
@ -566,8 +558,8 @@ void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
|
|||
// enter() returns false if we have lost the race to async deflation
|
||||
// and we simply try again.
|
||||
while (true) {
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_vm_internal);
|
||||
if (monitor->reenter(recursions, THREAD)) {
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_vm_internal);
|
||||
if (monitor->reenter(recursions, current)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -576,53 +568,54 @@ void ObjectSynchronizer::reenter(Handle obj, intx recursions, TRAPS) {
|
|||
// -----------------------------------------------------------------------------
|
||||
// JNI locks on java objects
|
||||
// NOTE: must use heavy weight monitor to handle jni monitor enter
|
||||
void ObjectSynchronizer::jni_enter(Handle obj, TRAPS) {
|
||||
void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) {
|
||||
if (obj->klass()->is_value_based()) {
|
||||
handle_sync_on_value_based_class(obj, THREAD);
|
||||
handle_sync_on_value_based_class(obj, current);
|
||||
}
|
||||
|
||||
// the current locking is from JNI instead of Java code
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
THREAD->set_current_pending_monitor_is_from_java(false);
|
||||
current->set_current_pending_monitor_is_from_java(false);
|
||||
// An async deflation can race after the inflate() call and before
|
||||
// enter() can make the ObjectMonitor busy. enter() returns false if
|
||||
// we have lost the race to async deflation and we simply try again.
|
||||
while (true) {
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_jni_enter);
|
||||
if (monitor->enter(THREAD)) {
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_jni_enter);
|
||||
if (monitor->enter(current)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
THREAD->set_current_pending_monitor_is_from_java(true);
|
||||
current->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) {
|
||||
void ObjectSynchronizer::jni_exit(oop obj, TRAPS) {
|
||||
JavaThread* current = THREAD->as_Java_thread();
|
||||
if (UseBiasedLocking) {
|
||||
Handle h_obj(THREAD, obj);
|
||||
BiasedLocking::revoke(h_obj, THREAD);
|
||||
Handle h_obj(current, obj);
|
||||
BiasedLocking::revoke(h_obj, current);
|
||||
obj = h_obj();
|
||||
}
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
|
||||
// The ObjectMonitor* can't be async deflated until ownership is
|
||||
// dropped inside exit() and the ObjectMonitor* must be !is_busy().
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj, inflate_cause_jni_exit);
|
||||
ObjectMonitor* monitor = inflate(current, obj, inflate_cause_jni_exit);
|
||||
// If this thread has locked the object, exit the monitor. We
|
||||
// intentionally do not use CHECK here because we must exit the
|
||||
// monitor even if an exception is pending.
|
||||
// intentionally do not use CHECK on check_owner because we must exit the
|
||||
// monitor even if an exception was already pending.
|
||||
if (monitor->check_owner(THREAD)) {
|
||||
monitor->exit(true, THREAD);
|
||||
monitor->exit(true, current);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Internal VM locks on java objects
|
||||
// standard constructor, allows locking failures
|
||||
ObjectLocker::ObjectLocker(Handle obj, Thread* thread) {
|
||||
ObjectLocker::ObjectLocker(Handle obj, JavaThread* thread) {
|
||||
_thread = thread;
|
||||
_thread->check_for_valid_safepoint_state();
|
||||
_obj = obj;
|
||||
|
@ -643,8 +636,9 @@ ObjectLocker::~ObjectLocker() {
|
|||
// Wait/Notify/NotifyAll
|
||||
// NOTE: must use heavy weight monitor to handle wait()
|
||||
int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
|
||||
JavaThread* current = THREAD->as_Java_thread();
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
if (millis < 0) {
|
||||
|
@ -653,10 +647,10 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
|
|||
// The ObjectMonitor* can't be async deflated because the _waiters
|
||||
// field is incremented before ownership is dropped and decremented
|
||||
// after ownership is regained.
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_wait);
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_wait);
|
||||
|
||||
DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
|
||||
monitor->wait(millis, true, THREAD);
|
||||
DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), current, millis);
|
||||
monitor->wait(millis, true, THREAD); // Not CHECK as we need following code
|
||||
|
||||
// This dummy call is in place to get around dtrace bug 6254741. Once
|
||||
// that's fixed we can uncomment the following line, remove the call
|
||||
|
@ -666,52 +660,55 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
|
|||
return ret_code;
|
||||
}
|
||||
|
||||
void ObjectSynchronizer::wait_uninterruptibly(Handle obj, jlong millis, TRAPS) {
|
||||
// No exception are possible in this case as we only use this internally when locking is
|
||||
// correct and we have to wait until notified - so no interrupts or timeouts.
|
||||
void ObjectSynchronizer::wait_uninterruptibly(Handle obj, JavaThread* current) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
if (millis < 0) {
|
||||
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
|
||||
}
|
||||
// The ObjectMonitor* can't be async deflated because the _waiters
|
||||
// field is incremented before ownership is dropped and decremented
|
||||
// after ownership is regained.
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_wait);
|
||||
monitor->wait(millis, false, THREAD);
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_wait);
|
||||
monitor->wait(0 /* wait-forever */, false /* not interruptible */, current);
|
||||
}
|
||||
|
||||
void ObjectSynchronizer::notify(Handle obj, TRAPS) {
|
||||
JavaThread* current = THREAD->as_Java_thread();
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
|
||||
markWord mark = obj->mark();
|
||||
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
|
||||
if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
|
||||
// Not inflated so there can't be any waiters to notify.
|
||||
return;
|
||||
}
|
||||
// The ObjectMonitor* can't be async deflated until ownership is
|
||||
// dropped by the calling thread.
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_notify);
|
||||
monitor->notify(THREAD);
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_notify);
|
||||
monitor->notify(CHECK);
|
||||
}
|
||||
|
||||
// NOTE: see comment of notify()
|
||||
void ObjectSynchronizer::notifyall(Handle obj, TRAPS) {
|
||||
JavaThread* current = THREAD->as_Java_thread();
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(obj, THREAD);
|
||||
BiasedLocking::revoke(obj, current);
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
|
||||
markWord mark = obj->mark();
|
||||
if (mark.has_locker() && THREAD->is_lock_owned((address)mark.locker())) {
|
||||
if (mark.has_locker() && current->is_lock_owned((address)mark.locker())) {
|
||||
// Not inflated so there can't be any waiters to notify.
|
||||
return;
|
||||
}
|
||||
// The ObjectMonitor* can't be async deflated until ownership is
|
||||
// dropped by the calling thread.
|
||||
ObjectMonitor* monitor = inflate(THREAD, obj(), inflate_cause_notify);
|
||||
monitor->notifyAll(THREAD);
|
||||
ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_notify);
|
||||
monitor->notifyAll(CHECK);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -774,7 +771,7 @@ static markWord read_stable_mark(oop obj) {
|
|||
gInflationLocks[ix]->lock();
|
||||
while (obj->mark() == markWord::INFLATING()) {
|
||||
// Beware: naked_yield() is advisory and has almost no effect on some platforms
|
||||
// so we periodically call self->_ParkEvent->park(1).
|
||||
// so we periodically call current->_ParkEvent->park(1).
|
||||
// We use a mixed spin/yield/block mechanism.
|
||||
if ((YieldThenBlock++) >= 16) {
|
||||
Thread::current()->_ParkEvent->park(1);
|
||||
|
@ -807,7 +804,7 @@ static markWord read_stable_mark(oop obj) {
|
|||
// There are simple ways to "diffuse" the middle address bits over the
|
||||
// generated hashCode values:
|
||||
|
||||
static inline intptr_t get_next_hash(Thread* self, oop obj) {
|
||||
static inline intptr_t get_next_hash(Thread* current, oop obj) {
|
||||
intptr_t value = 0;
|
||||
if (hashCode == 0) {
|
||||
// This form uses global Park-Miller RNG.
|
||||
|
@ -830,14 +827,14 @@ static inline intptr_t get_next_hash(Thread* self, oop obj) {
|
|||
// Marsaglia's xor-shift scheme with thread-specific state
|
||||
// This is probably the best overall implementation -- we'll
|
||||
// likely make this the default in future releases.
|
||||
unsigned t = self->_hashStateX;
|
||||
unsigned t = current->_hashStateX;
|
||||
t ^= (t << 11);
|
||||
self->_hashStateX = self->_hashStateY;
|
||||
self->_hashStateY = self->_hashStateZ;
|
||||
self->_hashStateZ = self->_hashStateW;
|
||||
unsigned v = self->_hashStateW;
|
||||
current->_hashStateX = current->_hashStateY;
|
||||
current->_hashStateY = current->_hashStateZ;
|
||||
current->_hashStateZ = current->_hashStateW;
|
||||
unsigned v = current->_hashStateW;
|
||||
v = (v ^ (v >> 19)) ^ (t ^ (t >> 8));
|
||||
self->_hashStateW = v;
|
||||
current->_hashStateW = v;
|
||||
value = v;
|
||||
}
|
||||
|
||||
|
@ -847,7 +844,7 @@ static inline intptr_t get_next_hash(Thread* self, oop obj) {
|
|||
return value;
|
||||
}
|
||||
|
||||
intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
|
||||
intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) {
|
||||
if (UseBiasedLocking) {
|
||||
// NOTE: many places throughout the JVM do not expect a safepoint
|
||||
// to be taken here. However, we only ever bias Java instances and all
|
||||
|
@ -857,11 +854,11 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
|
|||
// thread-local storage.
|
||||
if (obj->mark().has_bias_pattern()) {
|
||||
// Handle for oop obj in case of STW safepoint
|
||||
Handle hobj(self, obj);
|
||||
Handle hobj(current, obj);
|
||||
if (SafepointSynchronize::is_at_safepoint()) {
|
||||
BiasedLocking::revoke_at_safepoint(hobj);
|
||||
} else {
|
||||
BiasedLocking::revoke(hobj, self);
|
||||
BiasedLocking::revoke(hobj, current);
|
||||
}
|
||||
obj = hobj();
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
|
@ -882,7 +879,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
|
|||
if (hash != 0) { // if it has a hash, just return it
|
||||
return hash;
|
||||
}
|
||||
hash = get_next_hash(self, obj); // get a new hash
|
||||
hash = get_next_hash(current, obj); // get a new hash
|
||||
temp = mark.copy_set_hash(hash); // merge the hash into header
|
||||
// try to install the hash
|
||||
test = obj->cas_set_mark(temp, mark);
|
||||
|
@ -920,7 +917,7 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
|
|||
}
|
||||
// Fall thru so we only have one place that installs the hash in
|
||||
// the ObjectMonitor.
|
||||
} else if (self->is_lock_owned((address)mark.locker())) {
|
||||
} else if (current->is_lock_owned((address)mark.locker())) {
|
||||
// This is a stack lock owned by the calling thread so fetch the
|
||||
// displaced markWord from the BasicLock on the stack.
|
||||
temp = mark.displaced_mark_helper();
|
||||
|
@ -943,13 +940,13 @@ intptr_t ObjectSynchronizer::FastHashCode(Thread* self, oop obj) {
|
|||
|
||||
// An async deflation can race after the inflate() call and before we
|
||||
// can update the ObjectMonitor's header with the hash value below.
|
||||
monitor = inflate(self, obj, inflate_cause_hash_code);
|
||||
monitor = inflate(current, obj, inflate_cause_hash_code);
|
||||
// Load ObjectMonitor's header/dmw field and see if it has a hash.
|
||||
mark = monitor->header();
|
||||
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
|
||||
hash = get_next_hash(current, obj); // get a new hash
|
||||
temp = mark.copy_set_hash(hash) ; // merge the hash into header
|
||||
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());
|
||||
|
@ -985,28 +982,28 @@ intptr_t ObjectSynchronizer::identity_hash_value_for(Handle obj) {
|
|||
}
|
||||
|
||||
|
||||
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* thread,
|
||||
bool ObjectSynchronizer::current_thread_holds_lock(JavaThread* current,
|
||||
Handle h_obj) {
|
||||
if (UseBiasedLocking) {
|
||||
BiasedLocking::revoke(h_obj, thread);
|
||||
BiasedLocking::revoke(h_obj, current);
|
||||
assert(!h_obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
|
||||
assert(thread == JavaThread::current(), "Can only be called on current thread");
|
||||
assert(current == JavaThread::current(), "Can only be called on current thread");
|
||||
oop obj = h_obj();
|
||||
|
||||
markWord mark = read_stable_mark(obj);
|
||||
|
||||
// Uncontended case, header points to stack
|
||||
if (mark.has_locker()) {
|
||||
return thread->is_lock_owned((address)mark.locker());
|
||||
return current->is_lock_owned((address)mark.locker());
|
||||
}
|
||||
// Contended case, header points to ObjectMonitor (tagged pointer)
|
||||
if (mark.has_monitor()) {
|
||||
// The first stage of async deflation does not affect any field
|
||||
// used by this comparison so the ObjectMonitor* is usable here.
|
||||
ObjectMonitor* monitor = mark.monitor();
|
||||
return monitor->is_entered(thread) != 0;
|
||||
return monitor->is_entered(current) != 0;
|
||||
}
|
||||
// Unlocked case, header in place
|
||||
assert(mark.is_neutral(), "sanity check");
|
||||
|
@ -1142,7 +1139,7 @@ bool ObjectSynchronizer::is_async_deflation_needed() {
|
|||
}
|
||||
|
||||
bool ObjectSynchronizer::request_deflate_idle_monitors() {
|
||||
Thread* self = Thread::current();
|
||||
JavaThread* current = JavaThread::current();
|
||||
bool ret_code = false;
|
||||
|
||||
jlong last_time = last_async_deflation_time_ns();
|
||||
|
@ -1158,11 +1155,9 @@ bool ObjectSynchronizer::request_deflate_idle_monitors() {
|
|||
ret_code = true;
|
||||
break;
|
||||
}
|
||||
if (self->is_Java_thread()) {
|
||||
{
|
||||
// JavaThread has to honor the blocking protocol.
|
||||
ThreadBlockInVM tbivm(self->as_Java_thread());
|
||||
os::naked_short_sleep(999); // sleep for almost 1 second
|
||||
} else {
|
||||
ThreadBlockInVM tbivm(current);
|
||||
os::naked_short_sleep(999); // sleep for almost 1 second
|
||||
}
|
||||
}
|
||||
|
@ -1200,7 +1195,7 @@ void ObjectSynchronizer::inflate_helper(oop obj) {
|
|||
(void)inflate(Thread::current(), obj, inflate_cause_vm_internal);
|
||||
}
|
||||
|
||||
ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
||||
ObjectMonitor* ObjectSynchronizer::inflate(Thread* current, oop object,
|
||||
const InflateCause cause) {
|
||||
EventJavaMonitorInflate event;
|
||||
|
||||
|
@ -1297,7 +1292,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
|||
m->set_header(dmw);
|
||||
|
||||
// Optimization: if the mark.locker stack address is associated
|
||||
// with this thread we could simply set m->_owner = self.
|
||||
// with this thread we could simply set m->_owner = current.
|
||||
// Note that a thread can inflate an object
|
||||
// that it has stack-locked -- as might happen in wait() -- directly
|
||||
// with CAS. That is, we can avoid the xchg-NULL .... ST idiom.
|
||||
|
@ -1318,7 +1313,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
|||
// to avoid false sharing on MP systems ...
|
||||
OM_PERFDATA_OP(Inflations, inc());
|
||||
if (log_is_enabled(Trace, monitorinflation)) {
|
||||
ResourceMark rm(self);
|
||||
ResourceMark rm(current);
|
||||
lsh.print_cr("inflate(has_locker): object=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", type='%s'", p2i(object),
|
||||
object->mark().value(), object->klass()->external_name());
|
||||
|
@ -1335,7 +1330,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
|||
// pre-locked ObjectMonitor pointer into the object header. A successful
|
||||
// CAS inflates the object *and* confers ownership to the inflating thread.
|
||||
// In the current implementation we use a 2-step mechanism where we CAS()
|
||||
// to inflate and then CAS() again to try to swing _owner from NULL to self.
|
||||
// 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.
|
||||
|
||||
// Catch if the object's header is not neutral (not locked and
|
||||
|
@ -1362,7 +1357,7 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
|||
// cache lines to avoid false sharing on MP systems ...
|
||||
OM_PERFDATA_OP(Inflations, inc());
|
||||
if (log_is_enabled(Trace, monitorinflation)) {
|
||||
ResourceMark rm(self);
|
||||
ResourceMark rm(current);
|
||||
lsh.print_cr("inflate(neutral): object=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", type='%s'", p2i(object),
|
||||
object->mark().value(), object->klass()->external_name());
|
||||
|
@ -1374,10 +1369,10 @@ ObjectMonitor* ObjectSynchronizer::inflate(Thread* self, oop object,
|
|||
}
|
||||
}
|
||||
|
||||
void ObjectSynchronizer::chk_for_block_req(JavaThread* self, const char* op_name,
|
||||
void ObjectSynchronizer::chk_for_block_req(JavaThread* current, const char* op_name,
|
||||
const char* cnt_name, size_t cnt,
|
||||
LogStream* ls, elapsedTimer* timer_p) {
|
||||
if (!SafepointMechanism::should_process(self)) {
|
||||
if (!SafepointMechanism::should_process(current)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1392,7 +1387,7 @@ void ObjectSynchronizer::chk_for_block_req(JavaThread* self, const char* op_name
|
|||
|
||||
{
|
||||
// Honor block request.
|
||||
ThreadBlockInVM tbivm(self);
|
||||
ThreadBlockInVM tbivm(current);
|
||||
}
|
||||
|
||||
if (ls != NULL) {
|
||||
|
@ -1405,7 +1400,7 @@ void ObjectSynchronizer::chk_for_block_req(JavaThread* self, const char* op_name
|
|||
|
||||
// Walk the in-use list and deflate (at most MonitorDeflationMax) idle
|
||||
// ObjectMonitors. Returns the number of deflated ObjectMonitors.
|
||||
size_t ObjectSynchronizer::deflate_monitor_list(Thread *self, LogStream* ls,
|
||||
size_t ObjectSynchronizer::deflate_monitor_list(Thread* current, LogStream* ls,
|
||||
elapsedTimer* timer_p) {
|
||||
MonitorList::Iterator iter = _in_use_list.iterator();
|
||||
size_t deflated_count = 0;
|
||||
|
@ -1419,9 +1414,9 @@ size_t ObjectSynchronizer::deflate_monitor_list(Thread *self, LogStream* ls,
|
|||
deflated_count++;
|
||||
}
|
||||
|
||||
if (self->is_Java_thread()) {
|
||||
if (current->is_Java_thread()) {
|
||||
// A JavaThread must check for a safepoint/handshake and honor it.
|
||||
chk_for_block_req(self->as_Java_thread(), "deflation", "deflated_count",
|
||||
chk_for_block_req(current->as_Java_thread(), "deflation", "deflated_count",
|
||||
deflated_count, ls, timer_p);
|
||||
}
|
||||
}
|
||||
|
@ -1443,8 +1438,8 @@ class HandshakeForDeflation : public HandshakeClosure {
|
|||
// ObjectMonitors. It is also called via do_final_audit_and_print_stats()
|
||||
// by the VMThread.
|
||||
size_t ObjectSynchronizer::deflate_idle_monitors() {
|
||||
Thread* self = Thread::current();
|
||||
if (self->is_Java_thread()) {
|
||||
Thread* current = Thread::current();
|
||||
if (current->is_Java_thread()) {
|
||||
// The async deflation request has been processed.
|
||||
_last_async_deflation_time_ns = os::javaTimeNanos();
|
||||
set_is_async_deflation_requested(false);
|
||||
|
@ -1467,7 +1462,7 @@ size_t ObjectSynchronizer::deflate_idle_monitors() {
|
|||
}
|
||||
|
||||
// Deflate some idle ObjectMonitors.
|
||||
size_t deflated_count = deflate_monitor_list(self, ls, &timer);
|
||||
size_t deflated_count = deflate_monitor_list(current, ls, &timer);
|
||||
if (deflated_count > 0 || is_final_audit()) {
|
||||
// There are ObjectMonitors that have been deflated or this is the
|
||||
// final audit and all the remaining ObjectMonitors have been
|
||||
|
@ -1477,9 +1472,9 @@ size_t ObjectSynchronizer::deflate_idle_monitors() {
|
|||
// Unlink deflated ObjectMonitors from the in-use list.
|
||||
ResourceMark rm;
|
||||
GrowableArray<ObjectMonitor*> delete_list((int)deflated_count);
|
||||
size_t unlinked_count = _in_use_list.unlink_deflated(self, ls, &timer,
|
||||
size_t unlinked_count = _in_use_list.unlink_deflated(current, ls, &timer,
|
||||
&delete_list);
|
||||
if (self->is_Java_thread()) {
|
||||
if (current->is_Java_thread()) {
|
||||
if (ls != NULL) {
|
||||
timer.stop();
|
||||
ls->print_cr("before handshaking: unlinked_count=" SIZE_FORMAT
|
||||
|
@ -1509,9 +1504,9 @@ size_t ObjectSynchronizer::deflate_idle_monitors() {
|
|||
delete monitor;
|
||||
deleted_count++;
|
||||
|
||||
if (self->is_Java_thread()) {
|
||||
if (current->is_Java_thread()) {
|
||||
// A JavaThread must check for a safepoint/handshake and honor it.
|
||||
chk_for_block_req(self->as_Java_thread(), "deletion", "deleted_count",
|
||||
chk_for_block_req(current->as_Java_thread(), "deletion", "deleted_count",
|
||||
deleted_count, ls, &timer);
|
||||
}
|
||||
}
|
||||
|
@ -1544,22 +1539,20 @@ size_t ObjectSynchronizer::deflate_idle_monitors() {
|
|||
// Monitor cleanup on JavaThread::exit
|
||||
|
||||
// Iterate through monitor cache and attempt to release thread's monitors
|
||||
// Gives up on a particular monitor if an exception occurs, but continues
|
||||
// the overall iteration, swallowing the exception.
|
||||
class ReleaseJavaMonitorsClosure: public MonitorClosure {
|
||||
private:
|
||||
TRAPS;
|
||||
JavaThread* _thread;
|
||||
|
||||
public:
|
||||
ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
|
||||
ReleaseJavaMonitorsClosure(JavaThread* thread) : _thread(thread) {}
|
||||
void do_monitor(ObjectMonitor* mid) {
|
||||
if (mid->owner() == THREAD) {
|
||||
(void)mid->complete_exit(CHECK);
|
||||
if (mid->owner() == _thread) {
|
||||
(void)mid->complete_exit(_thread);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Release all inflated monitors owned by THREAD. Lightweight monitors are
|
||||
// Release all inflated monitors owned by current thread. Lightweight monitors are
|
||||
// ignored. This is meant to be called during JNI thread detach which assumes
|
||||
// all remaining monitors are heavyweight. All exceptions are swallowed.
|
||||
// Scanning the extant monitor list can be time consuming.
|
||||
|
@ -1574,12 +1567,13 @@ class ReleaseJavaMonitorsClosure: public MonitorClosure {
|
|||
// Since the tests are extremely cheap we could leave them enabled
|
||||
// for normal product builds.
|
||||
|
||||
void ObjectSynchronizer::release_monitors_owned_by_thread(TRAPS) {
|
||||
assert(THREAD == JavaThread::current(), "must be current Java thread");
|
||||
void ObjectSynchronizer::release_monitors_owned_by_thread(JavaThread* current) {
|
||||
assert(current == JavaThread::current(), "must be current Java thread");
|
||||
NoSafepointVerifier nsv;
|
||||
ReleaseJavaMonitorsClosure rjmc(THREAD);
|
||||
ReleaseJavaMonitorsClosure rjmc(current);
|
||||
ObjectSynchronizer::monitors_iterate(&rjmc);
|
||||
THREAD->clear_pending_exception();
|
||||
assert(!current->has_pending_exception(), "Should not be possible");
|
||||
current->clear_pending_exception();
|
||||
}
|
||||
|
||||
const char* ObjectSynchronizer::inflate_cause_name(const InflateCause cause) {
|
||||
|
|
|
@ -45,7 +45,7 @@ private:
|
|||
|
||||
public:
|
||||
void add(ObjectMonitor* monitor);
|
||||
size_t unlink_deflated(Thread* self, LogStream* ls, elapsedTimer* timer_p,
|
||||
size_t unlink_deflated(Thread* current, LogStream* ls, elapsedTimer* timer_p,
|
||||
GrowableArray<ObjectMonitor*>* unlinked_list);
|
||||
size_t count() const;
|
||||
size_t max() const;
|
||||
|
@ -88,35 +88,35 @@ class ObjectSynchronizer : AllStatic {
|
|||
// deoptimization at monitor exit. Hence, it does not take a Handle argument.
|
||||
|
||||
// This is the "slow path" version of monitor enter and exit.
|
||||
static void enter(Handle obj, BasicLock* lock, TRAPS);
|
||||
static void exit(oop obj, BasicLock* lock, Thread* THREAD);
|
||||
static void enter(Handle obj, BasicLock* lock, JavaThread* current);
|
||||
static void exit(oop obj, BasicLock* lock, JavaThread* current);
|
||||
|
||||
// Used only to handle jni locks or other unmatched monitor enter/exit
|
||||
// Internally they will use heavy weight monitor.
|
||||
static void jni_enter(Handle obj, TRAPS);
|
||||
static void jni_exit(oop obj, Thread* THREAD);
|
||||
static void jni_enter(Handle obj, JavaThread* current);
|
||||
static void jni_exit(oop obj, TRAPS);
|
||||
|
||||
// Handle all interpreter, compiler and jni cases
|
||||
static int wait(Handle obj, jlong millis, TRAPS);
|
||||
static void notify(Handle obj, TRAPS);
|
||||
static void notifyall(Handle obj, TRAPS);
|
||||
|
||||
static bool quick_notify(oopDesc* obj, Thread* self, bool All);
|
||||
static bool quick_enter(oop obj, Thread* self, BasicLock* Lock);
|
||||
static bool quick_notify(oopDesc* obj, JavaThread* current, bool All);
|
||||
static bool quick_enter(oop obj, JavaThread* current, BasicLock* Lock);
|
||||
|
||||
// Special internal-use-only method for use by JVM infrastructure
|
||||
// that needs to wait() on a java-level object but that can't risk
|
||||
// throwing unexpected InterruptedExecutionExceptions.
|
||||
static void wait_uninterruptibly(Handle obj, jlong Millis, Thread* THREAD);
|
||||
// that needs to wait() on a java-level object but must not respond
|
||||
// to interrupt requests and doesn't timeout.
|
||||
static void wait_uninterruptibly(Handle obj, JavaThread* current);
|
||||
|
||||
// used by classloading to free classloader object lock,
|
||||
// wait on an internal lock, and reclaim original lock
|
||||
// with original recursion count
|
||||
static intx complete_exit(Handle obj, TRAPS);
|
||||
static void reenter (Handle obj, intx recursions, TRAPS);
|
||||
static intx complete_exit(Handle obj, JavaThread* current);
|
||||
static void reenter (Handle obj, intx recursions, JavaThread* current);
|
||||
|
||||
// Inflate light weight monitor to heavy weight monitor
|
||||
static ObjectMonitor* inflate(Thread* self, oop obj, const InflateCause cause);
|
||||
static ObjectMonitor* inflate(Thread* current, oop obj, const InflateCause cause);
|
||||
// This version is only for internal use
|
||||
static void inflate_helper(oop obj);
|
||||
static const char* inflate_cause_name(const InflateCause cause);
|
||||
|
@ -124,15 +124,15 @@ class ObjectSynchronizer : AllStatic {
|
|||
// Returns the identity hash value for an oop
|
||||
// NOTE: It may cause monitor inflation
|
||||
static intptr_t identity_hash_value_for(Handle obj);
|
||||
static intptr_t FastHashCode(Thread* self, oop obj);
|
||||
static intptr_t FastHashCode(Thread* current, oop obj);
|
||||
|
||||
// java.lang.Thread support
|
||||
static bool current_thread_holds_lock(JavaThread* thread, Handle h_obj);
|
||||
static bool current_thread_holds_lock(JavaThread* current, Handle h_obj);
|
||||
|
||||
static JavaThread* get_lock_owner(ThreadsList * t_list, Handle h_obj);
|
||||
|
||||
// JNI detach support
|
||||
static void release_monitors_owned_by_thread(TRAPS);
|
||||
static void release_monitors_owned_by_thread(JavaThread* current);
|
||||
static void monitors_iterate(MonitorClosure* m);
|
||||
|
||||
// Initialize the gInflationLocks
|
||||
|
@ -143,10 +143,10 @@ class ObjectSynchronizer : AllStatic {
|
|||
static size_t deflate_idle_monitors();
|
||||
|
||||
// Deflate idle monitors:
|
||||
static void chk_for_block_req(JavaThread* self, const char* op_name,
|
||||
static void chk_for_block_req(JavaThread* current, const char* op_name,
|
||||
const char* cnt_name, size_t cnt, LogStream* ls,
|
||||
elapsedTimer* timer_p);
|
||||
static size_t deflate_monitor_list(Thread* self, LogStream* ls,
|
||||
static size_t deflate_monitor_list(Thread* current, LogStream* ls,
|
||||
elapsedTimer* timer_p);
|
||||
static size_t in_use_list_ceiling();
|
||||
static void dec_in_use_list_ceiling();
|
||||
|
@ -183,7 +183,7 @@ class ObjectSynchronizer : AllStatic {
|
|||
static size_t get_gvars_size();
|
||||
static u_char* get_gvars_stw_random_addr();
|
||||
|
||||
static void handle_sync_on_value_based_class(Handle obj, Thread* current);
|
||||
static void handle_sync_on_value_based_class(Handle obj, JavaThread* current);
|
||||
};
|
||||
|
||||
// ObjectLocker enforces balanced locking and can never throw an
|
||||
|
@ -193,17 +193,17 @@ class ObjectSynchronizer : AllStatic {
|
|||
// the thread's pending exception if needed.
|
||||
class ObjectLocker : public StackObj {
|
||||
private:
|
||||
Thread* _thread;
|
||||
JavaThread* _thread;
|
||||
Handle _obj;
|
||||
BasicLock _lock;
|
||||
public:
|
||||
ObjectLocker(Handle obj, Thread* thread);
|
||||
ObjectLocker(Handle obj, JavaThread* current);
|
||||
~ObjectLocker();
|
||||
|
||||
// Monitor behavior
|
||||
void wait(TRAPS) { ObjectSynchronizer::wait(_obj, 0, CHECK); } // wait forever
|
||||
void notify_all(TRAPS) { ObjectSynchronizer::notifyall(_obj, CHECK); }
|
||||
void wait_uninterruptibly(TRAPS) { ObjectSynchronizer::wait_uninterruptibly(_obj, 0, CHECK); }
|
||||
void wait_uninterruptibly(JavaThread* current) { ObjectSynchronizer::wait_uninterruptibly(_obj, current); }
|
||||
};
|
||||
|
||||
#endif // SHARE_RUNTIME_SYNCHRONIZER_HPP
|
||||
|
|
|
@ -513,7 +513,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess {
|
|||
public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t", -1, gr21761);
|
||||
public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*", -1, jdk13Backport);
|
||||
public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*", -1, jdk13Backport);
|
||||
public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "Thread*", -1, jdk13Backport);
|
||||
public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, JDK < 17 ? "Thread*" : "JavaThread*", -1, jdk13Backport);
|
||||
|
||||
public final int markWordNoHashInPlace = getConstant(markWordField("no_hash_in_place"), Integer.class);
|
||||
public final int markWordNoLockInPlace = getConstant(markWordField("no_lock_in_place"), Integer.class);
|
||||
|
|
|
@ -64,7 +64,7 @@ class LockerThread : public JavaTestThread {
|
|||
virtual ~LockerThread() {}
|
||||
|
||||
void main_run() {
|
||||
Thread* THREAD = Thread::current();
|
||||
JavaThread* THREAD = JavaThread::current();
|
||||
HandleMark hm(THREAD);
|
||||
Handle h_obj(THREAD, _obj);
|
||||
ResourceMark rm(THREAD);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue