Skip to content

Commit 8c94893

Browse files
authored
Merge pull request #19433 from babsingh/main1_v0.45.0-release
(0.45) ScopedMemoryAccess closeScope0 Updates
2 parents 62b8685 + 0de9810 commit 8c94893

File tree

10 files changed

+200
-47
lines changed

10 files changed

+200
-47
lines changed

runtime/gc_structs/VMThreadSlotIterator.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ GC_VMThreadSlotIterator::nextSlot()
6565
case 11:
6666
return &(_vmThread->scopedValueCache);
6767
#endif /* JAVA_SPEC_VERSION >= 19 */
68+
#if JAVA_SPEC_VERSION >= 22
69+
case 12:
70+
return &(_vmThread->scopedError);
71+
case 13:
72+
return &(_vmThread->closeScopeObj);
73+
#endif /* JAVA_SPEC_VERSION >= 22 */
6874
default:
6975
break;
7076
}

runtime/jcl/common/jdk_internal_misc_ScopedMemoryAccess.cpp

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -37,49 +37,28 @@ Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives(JNIEnv *env, jclass cl
3737
{
3838
}
3939

40-
static UDATA
41-
closeScope0FrameWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState)
42-
{
43-
if (JNI_FALSE == *(jboolean *)walkState->userData2) {
44-
/* scope has been found */
45-
return J9_STACKWALK_STOP_ITERATING;
46-
}
47-
return J9_STACKWALK_KEEP_ITERATING;
48-
}
49-
50-
static void
51-
closeScope0OSlotWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState, j9object_t *slot, const void *stackLocation)
52-
{
53-
J9Method *method = walkState->method;
54-
if (NULL != method) {
55-
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
56-
if (NULL != romMethod && J9ROMMETHOD_HAS_EXTENDED_MODIFIERS(romMethod)) {
57-
U_32 extraModifiers = getExtendedModifiersDataFromROMMethod(romMethod);
58-
if (J9ROMMETHOD_HAS_SCOPED_ANNOTATION(extraModifiers)) {
59-
if (*slot == J9_JNI_UNWRAP_REFERENCE(walkState->userData1)) {
60-
*(jboolean *)walkState->userData2 = JNI_FALSE;
61-
}
62-
}
63-
}
64-
}
65-
}
66-
6740
/**
6841
* For each thread, walk Java stack and look for the scope instance. Methods that can take and access a scope
6942
* instance are marked with the "@Scoped" extended modifier. If the scope instance is found in a method, that
7043
* method is accessing the memory segment associated with the scope and thus closing the scope will fail.
7144
*/
45+
#if JAVA_SPEC_VERSION >= 22
46+
void JNICALL
47+
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject error)
48+
#elif (JAVA_SPEC_VERSION >= 19) && (JAVA_SPEC_VERSION <= 21) /* JAVA_SPEC_VERSION >= 22 */
7249
jboolean JNICALL
73-
#if JAVA_SPEC_VERSION >= 19
7450
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope)
75-
#else /* JAVA_SPEC_VERSION >= 19 */
51+
#else /* JAVA_SPEC_VERSION >= 22 */
52+
jboolean JNICALL
7653
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject exception)
77-
#endif /* JAVA_SPEC_VERSION >= 19 */
54+
#endif /* JAVA_SPEC_VERSION >= 22 */
7855
{
7956
J9VMThread *currentThread = (J9VMThread *)env;
8057
J9JavaVM *vm = currentThread->javaVM;
8158
const J9InternalVMFunctions *vmFuncs = vm->internalVMFunctions;
82-
jboolean scopeNotFound = JNI_TRUE;
59+
#if JAVA_SPEC_VERSION <= 21
60+
jboolean scopeFound = JNI_FALSE;
61+
#endif /* JAVA_SPEC_VERSION <= 21 */
8362

8463
vmFuncs->internalEnterVMFromJNI(currentThread);
8564

@@ -88,21 +67,31 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta
8867
} else {
8968
vmFuncs->acquireExclusiveVMAccess(currentThread);
9069
J9VMThread *walkThread = J9_LINKED_LIST_START_DO(vm->mainThread);
70+
j9object_t closeScopeObj = J9_JNI_UNWRAP_REFERENCE(scope);
71+
#if JAVA_SPEC_VERSION >= 22
72+
j9object_t errorObj = J9_JNI_UNWRAP_REFERENCE(error);
73+
#endif /* JAVA_SPEC_VERSION >= 22 */
9174
while (NULL != walkThread) {
9275
if (VM_VMHelpers::threadCanRunJavaCode(walkThread)) {
93-
J9StackWalkState walkState;
94-
walkState.walkThread = walkThread;
95-
walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_ITERATE_O_SLOTS;
96-
walkState.skipCount = 0;
97-
walkState.userData1 = (void *)scope;
98-
walkState.userData2 = (void *)&scopeNotFound;
99-
walkState.frameWalkFunction = closeScope0FrameWalkFunction;
100-
walkState.objectSlotWalkFunction = closeScope0OSlotWalkFunction;
76+
#if JAVA_SPEC_VERSION >= 22
77+
/* Skip since an exception is already pending to be thrown.*/
78+
if (NULL != walkThread->scopedError) {
79+
continue;
80+
}
81+
#endif /* JAVA_SPEC_VERSION >= 22 */
10182

102-
vm->walkStackFrames(walkThread, &walkState);
103-
if (JNI_FALSE == *(jboolean *)walkState.userData2) {
104-
/* scope found */
83+
if (vmFuncs->hasMemoryScope(walkThread, closeScopeObj)) {
84+
/* Scope found. */
85+
#if JAVA_SPEC_VERSION >= 22
86+
setHaltFlag(walkThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE);
87+
walkThread->scopedError = errorObj;
88+
walkThread->closeScopeObj = closeScopeObj;
89+
/* Atomic add is not needed since exclusive VM access has been acquired. */
90+
vm->closeScopeNotifyCount += 1;
91+
#else /* JAVA_SPEC_VERSION >= 22 */
92+
scopeFound = JNI_TRUE;
10593
break;
94+
#endif /* JAVA_SPEC_VERSION >= 22 */
10695
}
10796
}
10897

@@ -112,7 +101,24 @@ Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject insta
112101
}
113102

114103
vmFuncs->internalExitVMToJNI(currentThread);
115-
return scopeNotFound;
104+
105+
#if JAVA_SPEC_VERSION >= 22
106+
/* There are gaps where async exceptions are not processed in time
107+
* (e.g. JIT compiled code in a loop). Wait until J9VMThread->scopedError
108+
* (async exception) is transferred to J9VMThread->currentException. The
109+
* wait prevents a MemorySession to be closed until no more operations are
110+
* being performed on it.
111+
*/
112+
omrthread_monitor_enter(vm->closeScopeMutex);
113+
while (0 != vm->closeScopeNotifyCount) {
114+
omrthread_monitor_wait(vm->closeScopeMutex);
115+
}
116+
omrthread_monitor_exit(vm->closeScopeMutex);
117+
#endif /* JAVA_SPEC_VERSION >= 22 */
118+
119+
#if JAVA_SPEC_VERSION <= 21
120+
return !scopeFound;
121+
#endif /* JAVA_SPEC_VERSION <= 21 */
116122
}
117123
#endif /* JAVA_SPEC_VERSION >= 16 */
118124

runtime/oti/j9consts.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ extern "C" {
203203
#define J9_PUBLIC_FLAGS_THREAD_PARKED 0x20000
204204
#define J9_PUBLIC_FLAGS_EXCLUSIVE_SET_NOT_SAFE 0x40000
205205
#define J9_PUBLIC_FLAGS_THREAD_TIMED 0x80000
206-
#define J9_PUBLIC_FLAGS_UNUSED_0x100000 0x100000
206+
#define J9_PUBLIC_FLAGS_CLOSE_SCOPE 0x100000
207207
#define J9_PUBLIC_FLAGS_HALT_THREAD_FOR_CHECKPOINT 0x200000
208208
#define J9_PUBLIC_FLAGS_JNI_CRITICAL_REGION 0x400000
209209
#define J9_PUBLIC_FLAGS_POP_FRAMES_INTERRUPT 0x800000

runtime/oti/j9nonbuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5090,6 +5090,7 @@ typedef struct J9InternalVMFunctions {
50905090
float (JNICALL *native2InterpJavaUpcallF)(struct J9UpcallMetaData *data, void *argsListPointer);
50915091
double (JNICALL *native2InterpJavaUpcallD)(struct J9UpcallMetaData *data, void *argsListPointer);
50925092
U_8 * (JNICALL *native2InterpJavaUpcallStruct)(struct J9UpcallMetaData *data, void *argsListPointer);
5093+
BOOLEAN (*hasMemoryScope)(struct J9VMThread *walkThread, j9object_t scope);
50935094
#endif /* JAVA_SPEC_VERSION >= 16 */
50945095
#if JAVA_SPEC_VERSION >= 19
50955096
void (*copyFieldsFromContinuation)(struct J9VMThread *currentThread, struct J9VMThread *vmThread, struct J9VMEntryLocalStorage *els, struct J9VMContinuation *continuation);
@@ -5456,6 +5457,10 @@ typedef struct J9VMThread {
54565457
#if JAVA_SPEC_VERSION >= 21
54575458
BOOLEAN isInCriticalDownCall;
54585459
#endif /* JAVA_SPEC_VERSION >= 21 */
5460+
#if JAVA_SPEC_VERSION >= 22
5461+
j9object_t scopedError;
5462+
j9object_t closeScopeObj;
5463+
#endif /* JAVA_SPEC_VERSION >= 22 */
54595464
} J9VMThread;
54605465

54615466
#define J9VMTHREAD_ALIGNMENT 0x100
@@ -6044,6 +6049,10 @@ typedef struct J9JavaVM {
60446049
/* Pool for allocating J9MemberNameListNode. */
60456050
struct J9Pool *memberNameListNodePool;
60466051
#endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */
6052+
#if JAVA_SPEC_VERSION >= 22
6053+
omrthread_monitor_t closeScopeMutex;
6054+
UDATA closeScopeNotifyCount;
6055+
#endif /* JAVA_SPEC_VERSION >= 22 */
60476056
} J9JavaVM;
60486057

60496058
#define J9VM_PHASE_STARTUP 1

runtime/oti/jclprots.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,12 +1285,16 @@ Java_jdk_internal_foreign_abi_UpcallStubs_freeUpcallStub0(JNIEnv *env, jclass cl
12851285
void JNICALL
12861286
Java_jdk_internal_misc_ScopedMemoryAccess_registerNatives(JNIEnv *env, jclass clazz);
12871287

1288+
#if JAVA_SPEC_VERSION >= 22
1289+
void JNICALL
1290+
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject error);
1291+
#elif (JAVA_SPEC_VERSION >= 19) && (JAVA_SPEC_VERSION < 22) /* JAVA_SPEC_VERSION >= 22 */
12881292
jboolean JNICALL
1289-
#if JAVA_SPEC_VERSION >= 19
12901293
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope);
1291-
#else /* JAVA_SPEC_VERSION >= 19 */
1294+
#else /* JAVA_SPEC_VERSION >= 22 */
1295+
jboolean JNICALL
12921296
Java_jdk_internal_misc_ScopedMemoryAccess_closeScope0(JNIEnv *env, jobject instance, jobject scope, jobject exception);
1293-
#endif /* JAVA_SPEC_VERSION >= 19 */
1297+
#endif /* JAVA_SPEC_VERSION >= 22 */
12941298
#endif /* JAVA_SPEC_VERSION >= 16 */
12951299

12961300
#if defined(J9VM_OPT_CRIU_SUPPORT)

runtime/oti/vm_api.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5267,6 +5267,16 @@ native2InterpJavaUpcallD(J9UpcallMetaData *data, void *argsListPointer);
52675267
U_8 * JNICALL
52685268
native2InterpJavaUpcallStruct(J9UpcallMetaData *data, void *argsListPointer);
52695269

5270+
/**
5271+
* @brief Check if the memory's scope exists on the stack of the thread.
5272+
*
5273+
* @param[in] walkThread the J9VMThread to be walked
5274+
* @param[in] scope the object searched during the walk
5275+
*
5276+
* @return true if scope is found, false if not
5277+
*/
5278+
BOOLEAN
5279+
hasMemoryScope(J9VMThread *walkThread, j9object_t scope);
52705280
#endif /* JAVA_SPEC_VERSION >= 16 */
52715281

52725282
#ifdef __cplusplus

runtime/vm/AsyncMessageHandler.cpp

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,74 @@
3333

3434
extern "C" {
3535

36+
#if JAVA_SPEC_VERSION >= 16
37+
/**
38+
* Frame walk function, which is used with hasMemoryScope.
39+
*
40+
* @param[in] vmThread the J9VMThread
41+
* @param[in] walkState the stack walk state
42+
*
43+
* @return J9_STACKWALK_STOP_ITERATING to stop iterating, and
44+
* J9_STACKWALK_KEEP_ITERATING to continue iterating
45+
*/
46+
static UDATA
47+
closeScope0FrameWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState)
48+
{
49+
if (*(bool *)walkState->userData2) {
50+
/* Scope has been found. */
51+
return J9_STACKWALK_STOP_ITERATING;
52+
}
53+
return J9_STACKWALK_KEEP_ITERATING;
54+
}
55+
56+
/**
57+
* O-slot walk function, which is used with hasMemoryScope.
58+
*
59+
* @param[in] vmThread the J9VMThread
60+
* @param[in] walkState the stack walk state
61+
* @param[in] slot the O-slot pointer
62+
* @param[in] stackLocation the stack location
63+
*/
64+
static void
65+
closeScope0OSlotWalkFunction(J9VMThread *vmThread, J9StackWalkState *walkState, j9object_t *slot, const void *stackLocation)
66+
{
67+
J9Method *method = walkState->method;
68+
if (NULL != method) {
69+
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
70+
if (NULL != romMethod && J9ROMMETHOD_HAS_EXTENDED_MODIFIERS(romMethod)) {
71+
U_32 extraModifiers = getExtendedModifiersDataFromROMMethod(romMethod);
72+
if (J9ROMMETHOD_HAS_SCOPED_ANNOTATION(extraModifiers)) {
73+
if (*slot == walkState->userData1) {
74+
*(bool *)walkState->userData2 = true;
75+
}
76+
}
77+
}
78+
}
79+
}
80+
81+
BOOLEAN
82+
hasMemoryScope(J9VMThread *walkThread, j9object_t scope)
83+
{
84+
bool scopeFound = false;
85+
86+
if (NULL != scope) {
87+
J9StackWalkState walkState;
88+
89+
walkState.walkThread = walkThread;
90+
walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_ITERATE_O_SLOTS;
91+
walkState.skipCount = 0;
92+
walkState.userData1 = (void *)scope;
93+
walkState.userData2 = (void *)&scopeFound;
94+
walkState.frameWalkFunction = closeScope0FrameWalkFunction;
95+
walkState.objectSlotWalkFunction = closeScope0OSlotWalkFunction;
96+
97+
walkThread->javaVM->walkStackFrames(walkThread, &walkState);
98+
}
99+
100+
return scopeFound;
101+
}
102+
#endif /* JAVA_SPEC_VERSION >= 16 */
103+
36104
void
37105
clearAsyncEventFlags(J9VMThread *vmThread, UDATA flags)
38106
{
@@ -72,6 +140,44 @@ javaCheckAsyncMessages(J9VMThread *currentThread, UDATA throwExceptions)
72140
result = J9_CHECK_ASYNC_POP_FRAMES;
73141
break;
74142
}
143+
#if JAVA_SPEC_VERSION >= 22
144+
/* Check for a close scope request. */
145+
if (J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_CLOSE_SCOPE)) {
146+
bool notifyThreads = false;
147+
if (hasMemoryScope(currentThread, currentThread->closeScopeObj)) {
148+
if (throwExceptions) {
149+
currentThread->currentException = currentThread->scopedError;
150+
currentThread->scopedError = NULL;
151+
currentThread->closeScopeObj = NULL;
152+
clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE);
153+
result = J9_CHECK_ASYNC_THROW_EXCEPTION;
154+
notifyThreads = true;
155+
} else {
156+
VM_VMHelpers::indicateAsyncMessagePending(currentThread);
157+
}
158+
} else {
159+
currentThread->scopedError = NULL;
160+
currentThread->closeScopeObj = NULL;
161+
clearEventFlag(currentThread, J9_PUBLIC_FLAGS_CLOSE_SCOPE);
162+
notifyThreads = true;
163+
}
164+
if (notifyThreads) {
165+
J9JavaVM *vm = currentThread->javaVM;
166+
/* Notify all threads that are waiting in ScopedMemoryAccess closeScope0
167+
* to continue since the MemorySession(s) will no longer be used and it
168+
* is safe to close them.
169+
*/
170+
omrthread_monitor_enter(vm->closeScopeMutex);
171+
Assert_VM_true(vm->closeScopeNotifyCount > 0);
172+
vm->closeScopeNotifyCount -= 1;
173+
if (0 == vm->closeScopeNotifyCount) {
174+
omrthread_monitor_notify_all(vm->closeScopeMutex);
175+
}
176+
omrthread_monitor_exit(vm->closeScopeMutex);
177+
}
178+
break;
179+
}
180+
#endif /* JAVA_SPEC_VERSION >= 22 */
75181
/* Check for a thread halt request */
76182
if (J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_RELEASE_ACCESS_REQUIRED_MASK)) {
77183
Assert_VM_false(J9_ARE_ANY_BITS_SET(publicFlags, J9_PUBLIC_FLAGS_NOT_AT_SAFE_POINT));

runtime/vm/intfunc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ J9InternalVMFunctions J9InternalFunctions = {
438438
native2InterpJavaUpcallF,
439439
native2InterpJavaUpcallD,
440440
native2InterpJavaUpcallStruct,
441+
hasMemoryScope,
441442
#endif /* JAVA_SPEC_VERSION >= 16 */
442443
#if JAVA_SPEC_VERSION >= 19
443444
copyFieldsFromContinuation,

runtime/vm/jvminit.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,13 @@ freeJavaVM(J9JavaVM * vm)
10251025
}
10261026
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
10271027

1028+
#if JAVA_SPEC_VERSION >= 22
1029+
if (NULL != vm->closeScopeMutex) {
1030+
omrthread_monitor_destroy(vm->closeScopeMutex);
1031+
vm->closeScopeMutex = NULL;
1032+
}
1033+
#endif /* JAVA_SPEC_VERSION >= 22 */
1034+
10281035
j9mem_free_memory(vm);
10291036

10301037
if (NULL != tmpLib->self_handle) {

runtime/vm/vmthinit.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@ UDATA initializeVMThreading(J9JavaVM *vm)
9999
omrthread_monitor_init_with_name(&vm->delayedLockingOperationsMutex, 0, "Delayed locking operations mutex") ||
100100
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
101101

102+
#if JAVA_SPEC_VERSION >= 22
103+
omrthread_monitor_init_with_name(&vm->closeScopeMutex, 0, "ScopedMemoryAccess closeScope0 mutex") ||
104+
#endif /* JAVA_SPEC_VERSION >= 22 */
105+
102106
initializeMonitorTable(vm)
103107
)
104108
{

0 commit comments

Comments
 (0)