Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions runtime/oti/j9.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,14 @@ static_assert((LITERAL_STRLEN(J9_UNMODIFIABLE_CLASS_ANNOTATION) < (size_t)'/'),
} while (0)
#endif /* JAVA_SPEC_VERSION >= 24 */

#if JAVA_SPEC_VERSION >= 24
#define J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm) \
(J9_ARE_ANY_BITS_SET((vm)->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION) \
&& J9_ARE_ANY_BITS_SET((vm)->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION))
#else
#define J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm) (1 == 0)
#endif

#define DIR_LIB_STR "lib"

#if defined(J9VM_OPT_JFR)
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ extern "C" {
#define J9_EXTENDED_RUNTIME3_GCCONTAINERHEURISTICS 0x400
#define J9_EXTENDED_RUNTIME3_USE_VECTOR_LENGTH_256 0x800
#define J9_EXTENDED_RUNTIME3_USE_VECTOR_LENGTH_512 0x1000
#define J9_EXTENDED_RUNTIME3_VTHREAD_CREATED 0x2000


#define J9_OBJECT_HEADER_AGE_DEFAULT 0xA /* OBJECT_HEADER_AGE_DEFAULT */
Expand Down
12 changes: 7 additions & 5 deletions runtime/vm/BytecodeInterpreter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ class INTERPRETER_CLASS
rc = objectMonitorEnterNonBlocking(_currentThread, obj);
if (J9_OBJECT_MONITOR_BLOCKING == rc) {
#if JAVA_SPEC_VERSION >= 24
if (VM_ContinuationHelpers::isYieldableVirtualThread(_currentThread)) {
if (_pinningSupportEnabled && VM_ContinuationHelpers::isYieldableVirtualThread(_currentThread)) {
/* Try to yield the virtual thread if it will be blocked. */
updateVMStruct(REGISTER_ARGS);
rc = preparePinnedVirtualThreadForUnmount(_currentThread, obj, false);
Expand All @@ -1225,7 +1225,7 @@ class INTERPRETER_CLASS
}
}
#if JAVA_SPEC_VERSION >= 24
if (rc == (UDATA)obj) {
if (_pinningSupportEnabled && (rc == (UDATA)obj)) {
J9VMContinuation *continuation = _currentThread->currentContinuation;
if (NULL != continuation) {
if (J9_ARE_ALL_BITS_SET(continuation->runtimeFlags, J9VM_CONTINUATION_RUNTIMEFLAG_JVMTI_CONTENDED_MONITOR_ENTER_RECORDED)) {
Expand Down Expand Up @@ -3041,7 +3041,7 @@ class INTERPRETER_CLASS
{
if (VM_ObjectMonitor::getMonitorForNotify(_currentThread, receiver, &monitorPtr, true)) {
#if JAVA_SPEC_VERSION >= 24
if (J9_ARE_ANY_BITS_SET(_vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)) {
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(_vm)) {
j9objectmonitor_t lock = 0;
j9objectmonitor_t *lockEA = NULL;
J9ObjectMonitor *objectMonitor = NULL;
Expand Down Expand Up @@ -6001,7 +6001,7 @@ class INTERPRETER_CLASS
buildInternalNativeStackFrame(REGISTER_ARGS);
updateVMStruct(REGISTER_ARGS);
#if JAVA_SPEC_VERSION >= 24
if (J9_ARE_ANY_BITS_SET(_vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
if (_pinningSupportEnabled)
&& (_currentThread->ownedMonitorCount > 0)
&& !isFinished
) {
Expand Down Expand Up @@ -10392,7 +10392,9 @@ class INTERPRETER_CLASS
#if defined(LOCAL_LITERALS)
J9Method *_literals = vmThread->literals;
#endif

#if JAVA_SPEC_VERSION >= 24
const bool _pinningSupportEnabled = J9_ARE_ANY_BITS_SET(vmThread->javaVM->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION
#endif /* JAVA_SPEC_VERSION >= 24 */
DEBUG_MUST_HAVE_VM_ACCESS(vmThread);
vmThread->jitStackFrameFlags = 0;

Expand Down
2 changes: 2 additions & 0 deletions runtime/vm/ContinuationHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ createContinuation(J9VMThread *currentThread, j9object_t continuationObject)
I_64 start = j9time_hires_clock();
#endif /* defined(J9VM_PROF_CONTINUATION_ALLOCATION) */

vm->extendedRuntimeFlags3 |= J9_EXTENDED_RUNTIME3_VTHREAD_CREATED;

/* First check if local cache is available. */
if (NULL != currentThread->continuationT1Cache) {
for (U_32 i = 0; i < vm->continuationT1Size; i++) {
Expand Down
4 changes: 2 additions & 2 deletions runtime/vm/FastJNI_java_lang_Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Fast_java_lang_Object_notifyAll(J9VMThread *currentThread, j9object_t receiverOb
if (VM_ObjectMonitor::getMonitorForNotify(currentThread, receiverObject, &monitorPtr, true)) {
#if JAVA_SPEC_VERSION >= 24
J9JavaVM *vm = currentThread->javaVM;
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)) {
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)) {
j9objectmonitor_t lock = 0;
j9objectmonitor_t *lockEA = NULL;
J9ObjectMonitor *objectMonitor = NULL;
Expand Down Expand Up @@ -107,7 +107,7 @@ Fast_java_lang_Object_notify(J9VMThread *currentThread, j9object_t receiverObjec
if (VM_ObjectMonitor::getMonitorForNotify(currentThread, receiverObject, &monitorPtr, true)) {
#if JAVA_SPEC_VERSION >= 24
J9JavaVM *vm = currentThread->javaVM;
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)) {
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)) {
j9objectmonitor_t lock = 0;
j9objectmonitor_t *lockEA = NULL;
J9ObjectMonitor *objectMonitor = NULL;
Expand Down
206 changes: 106 additions & 100 deletions runtime/vm/monhelpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
lock = J9_LOAD_LOCKWORD(vmStruct, lockEA);

if (J9_FLATLOCK_OWNER(lock) == vmStruct) {
#if JAVA_SPEC_VERSION >= 24
J9JavaVM *vm = vmStruct->javaVM;
#endif /* JAVA_SPEC_VERSION >= 24 */
/* The current thread owns the monitor, and it's a flat lock. */
UDATA count = (UDATA)lock & OBJECT_HEADER_LOCK_BITS_MASK;
/*
Expand All @@ -96,133 +99,136 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
#endif /* if !(defined(AIXPPC) || defined(LINUXPPC)) */
#endif /* ifndef J9VM_THR_LOCK_RESERVATION */
#if JAVA_SPEC_VERSION >= 24
if (OBJECT_HEADER_LOCK_FLC == count) {
/* FLC set, non-recursive. */
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);

if (NULL == objectMonitor) {
/* Out of memory - impossible? */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else {
omrthread_monitor_t monitor = objectMonitor->monitor;
J9JavaVM *vm = vmStruct->javaVM;
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)) {
if (OBJECT_HEADER_LOCK_FLC == count) {
/* FLC set, non-recursive. */
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);

if (NULL == objectMonitor) {
/* Out of memory - impossible? */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else {
omrthread_monitor_t monitor = objectMonitor->monitor;

TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vm->hookInterface, vmStruct, monitor);

omrthread_monitor_exit(monitor);
omrthread_monitor_exit(monitor);

if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
&& (0 != objectMonitor->virtualThreadWaitCount)
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)
&& (0 != objectMonitor->virtualThreadWaitCount)
) {
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
}
}
} else {
j9objectmonitor_t newLock = 0;
BOOLEAN casSuccess = FALSE;
if (0x00 == count) {
/* Just release the flatlock. */
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
) {
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
/* Learning state case. */
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
/* Lock is in Learning state but unowned.
* (if it were owned it would have been caught by the first Learning state check)
*/
goto done;
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
/* Just decrement the flatlock recursion count. */
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
#ifdef J9VM_THR_LOCK_RESERVATION
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
/* Lock is reserved but unowned.
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
*/
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
goto done;
#endif /* J9VM_THR_LOCK_RESERVATION */
}

monitorExitWriteBarrier();
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
casSuccess = (lock == compareAndSwapU32((uint32_t *)lockEA, (uint32_t)lock, (uint32_t)newLock));
} else {
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
}

if (!casSuccess) {
/* Another thread has attempted to get the lock and may have update the FLC flag. */
goto restart;
}
}
} else {
j9objectmonitor_t newLock = 0;
BOOLEAN casSuccess = FALSE;
} else
#endif /* JAVA_SPEC_VERSION >= 24 */
{
if (0x00 == count) {
/* Just release the flatlock. */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
) {
/* Learning state case. */
newLock = lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT;
BOOLEAN casSuccess = FALSE;

if (1 == J9_FLATLOCK_COUNT(lock)) {
/* If RC field is 1, this fully unlocks the object so a write barrier is needed. */
monitorExitWriteBarrier();
}

if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
casSuccess = (lock == compareAndSwapU32((uint32_t*)lockEA, (uint32_t)lock,
(uint32_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
} else {
casSuccess = (lock == compareAndSwapUDATA((uintptr_t*)lockEA, (uintptr_t)lock,
(uintptr_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
}

if (!casSuccess) {
/*
* Another thread has attempted to get the lock and atomically changed the state to Flat.
* Start over and read the new lockword. The lock can not go back to Learning so this will
* only happen once.
*/
goto restart;
}
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
/* Lock is in Learning state but unowned.
* (if it were owned it would have been caught by the first Learning state check)
*/
* (if it were owned it would have been caught by the first Learning state check)
*/
Trc_VM_objectMonitorExit_Exit_LearningStateUnowned(vmStruct, lock, object);
goto done;
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
/* Just decrement the flatlock recursion count. */
newLock = lock - OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
lock -= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
J9_STORE_LOCKWORD(vmStruct, lockEA, lock);
#ifdef J9VM_THR_LOCK_RESERVATION
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
/* Lock is reserved but unowned.
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
*/
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
*/
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
goto done;
#endif /* J9VM_THR_LOCK_RESERVATION */
}

monitorExitWriteBarrier();
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
casSuccess = (lock == compareAndSwapU32((uint32_t *)lockEA, (uint32_t)lock, (uint32_t)newLock));
} else {
casSuccess = (lock == compareAndSwapUDATA((uintptr_t *)lockEA, (uintptr_t)lock, (uintptr_t)newLock));
}
/* FLC set, non-recursive. */
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);

if (!casSuccess) {
/* Another thread has attempted to get the lock and may have update the FLC flag. */
goto restart;
if (NULL == objectMonitor) {
/* Out of memory - impossible? */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else {
omrthread_monitor_t monitor = objectMonitor->monitor;
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vmStruct->javaVM->hookInterface, vmStruct, monitor);
omrthread_monitor_exit(monitor);
}
}
}
#else /* JAVA_SPEC_VERSION >= 24 */
if (0x00 == count) {
/* Just release the flatlock. */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)
&& J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING_RECURSION_MASK)
) {
/* Learning state case. */
BOOLEAN casSuccess = FALSE;

if (1 == J9_FLATLOCK_COUNT(lock)) {
/* If RC field is 1, this fully unlocks the object so a write barrier is needed. */
monitorExitWriteBarrier();
}

if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmStruct)) {
casSuccess = (lock == compareAndSwapU32((uint32_t*)lockEA, (uint32_t)lock,
(uint32_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
} else {
casSuccess = (lock == compareAndSwapUDATA((uintptr_t*)lockEA, (uintptr_t)lock,
(uintptr_t)(lock - OBJECT_HEADER_LOCK_LEARNING_FIRST_RECURSION_BIT)));
}

if (!casSuccess) {
/*
* Another thread has attempted to get the lock and atomically changed the state to Flat.
* Start over and read the new lockword. The lock can not go back to Learning so this will
* only happen once.
*/
goto restart;
}
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_LEARNING)) {
/* Lock is in Learning state but unowned.
* (if it were owned it would have been caught by the first Learning state check)
*/
Trc_VM_objectMonitorExit_Exit_LearningStateUnowned(vmStruct, lock, object);
goto done;
} else if (count >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT) {
/* Just decrement the flatlock recursion count. */
lock -= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT;
J9_STORE_LOCKWORD(vmStruct, lockEA, lock);
#ifdef J9VM_THR_LOCK_RESERVATION
} else if (J9_ARE_ANY_BITS_SET(count, OBJECT_HEADER_LOCK_RESERVED)) {
/* Lock is reserved but unowned.
* (if it were owned the count would be >= OBJECT_HEADER_LOCK_FIRST_RECURSION_BIT)
*/
Trc_VM_objectMonitorExit_Exit_ReservedButUnownedFlatLock(vmStruct, lock, object);
goto done;
#endif /* J9VM_THR_LOCK_RESERVATION */
} else {
/* FLC set, non-recursive. */
J9ObjectMonitor *objectMonitor = objectMonitorInflate(vmStruct, object, lock);

if (NULL == objectMonitor) {
/* Out of memory - impossible? */
monitorExitWriteBarrier();
J9_STORE_LOCKWORD(vmStruct, lockEA, 0);
} else {
omrthread_monitor_t monitor = objectMonitor->monitor;
TRIGGER_J9HOOK_VM_MONITOR_CONTENDED_EXIT(vmStruct->javaVM->hookInterface, vmStruct, monitor);
omrthread_monitor_exit(monitor);
}
}
#endif /* JAVA_SPEC_VERSION >= 24 */
Trc_VM_objectMonitorExit_Exit_FCBSet(vmStruct);
rc = 0;
goto done;
Expand Down Expand Up @@ -308,7 +314,7 @@ objectMonitorExit(J9VMThread* vmStruct, j9object_t object)
#endif /* JAVA_SPEC_VERSION >= 24 */
rc = omrthread_monitor_exit((omrthread_monitor_t)monitor);
#if JAVA_SPEC_VERSION >= 24
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)
&& (0 != objectMonitor->virtualThreadWaitCount)
) {
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
Expand Down
2 changes: 1 addition & 1 deletion runtime/vm/threadhelp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ notifyUnblocker(void *userData)
{
J9VMThread *currentThread = (J9VMThread *)userData;
J9JavaVM *vm = currentThread->javaVM;
if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags3, J9_EXTENDED_RUNTIME3_YIELD_PINNED_CONTINUATION)) {
if (J9VM_ARE_PINNED_YIELDABLE_VIRTUALTHREADS_ACTIVE(vm)) {
J9VM_SEND_VIRTUAL_UNBLOCKER_THREAD_SIGNAL(vm);
Trc_VM_ThreadHelp_notifyUnblocker(currentThread);
}
Expand Down