Skip to content

Commit d3f9ce6

Browse files
committed
Handle race condition in outOfLineINL
In the below example, compareAndExchangeRelease translates to an OutOfLine INL method named OutOfLineINL_jdk_internal_misc_Unsafe_compareAndExchangeIntVolatile. Example: InstFieldVH <- InstanceFieldVarHandle provides access to an int field in an object. 1000 threads concurrently execute { int old, new; do { old = (int)InstFieldVH.getVolatile(object); new = old + 2; } while (old != InstFieldVH.compareAndExchangeRelease(object, old, new)); } There is a race condition between 1) invoking the target method in BytecodeInterpreter.hpp::outOfLineINL; and 2) resolving the native address (J9Method->extra) of the target method in BytecodeInterpreter.hpp::bindNative. Due to the race condition, the native address of the target method may not be resolved when certain threads invoke outOfLineINL. In such cases, outOfLineINL should resolve the native address before proceeding. bindnatv.cpp::resolveNativeAddress - The code to resolve the native address is protected by the J9JavaVM->bindNativeMutex. So, it can be safely invoked by multiple threads. If the native address is already resolved, then it returns without repeating the resolution process. Signed-off-by: Babneet Singh <sbabneet@ca.ibm.com>
1 parent a602362 commit d3f9ce6

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

Diff for: runtime/vm/BytecodeInterpreter.hpp

+50-27
Original file line numberDiff line numberDiff line change
@@ -2019,40 +2019,50 @@ obj:;
20192019
}
20202020

20212021
VMINLINE VM_BytecodeAction
2022-
bindNative(REGISTER_ARGS_LIST)
2022+
resolveNativeAddressWithErrorHandling()
20232023
{
2024-
VM_BytecodeAction rc = GOTO_RUN_METHOD;
2025-
buildMethodFrame(REGISTER_ARGS, _sendMethod, jitStackFrameFlags(REGISTER_ARGS, 0));
2026-
updateVMStruct(REGISTER_ARGS);
20272024
UDATA bindRC = resolveNativeAddress(_currentThread, _sendMethod, TRUE);
20282025
if (J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY == bindRC) {
20292026
_vm->memoryManagerFunctions->j9gc_modron_global_collect_with_overrides(_currentThread, J9MMCONSTANT_EXPLICIT_GC_NATIVE_OUT_OF_MEMORY);
20302027
bindRC = resolveNativeAddress(_currentThread, _sendMethod, TRUE);
20312028
}
2032-
switch(bindRC) {
2033-
case J9_NATIVE_METHOD_BIND_SUCCESS: {
2034-
VMStructHasBeenUpdated(REGISTER_ARGS);
2035-
J9SFMethodFrame *methodFrame = (J9SFMethodFrame*)_sp;
2036-
_currentThread->jitStackFrameFlags = methodFrame->specialFrameFlags & J9_SSF_JIT_NATIVE_TRANSITION_FRAME;
2037-
restoreSpecialStackFrameLeavingArgs(REGISTER_ARGS, ((UDATA*)(methodFrame + 1)) - 1);
2038-
break;
2039-
}
2040-
case J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY:
2041-
setNativeBindOutOfMemoryError(_currentThread, _sendMethod);
2042-
VMStructHasBeenUpdated(REGISTER_ARGS);
2043-
rc = GOTO_THROW_CURRENT_EXCEPTION;
2044-
break;
2045-
case J9_NATIVE_METHOD_BIND_RECURSIVE:
2046-
setRecursiveBindError(_currentThread, _sendMethod);
2047-
VMStructHasBeenUpdated(REGISTER_ARGS);
2048-
rc = GOTO_THROW_CURRENT_EXCEPTION;
2049-
break;
2050-
default:
2051-
setNativeNotFoundError(_currentThread, _sendMethod);
2052-
VMStructHasBeenUpdated(REGISTER_ARGS);
2029+
2030+
VM_BytecodeAction rc = GOTO_RUN_METHOD;
2031+
if (J9_NATIVE_METHOD_BIND_SUCCESS != bindRC) {
20532032
rc = GOTO_THROW_CURRENT_EXCEPTION;
2054-
break;
2033+
switch(bindRC) {
2034+
case J9_NATIVE_METHOD_BIND_OUT_OF_MEMORY:
2035+
setNativeBindOutOfMemoryError(_currentThread, _sendMethod);
2036+
break;
2037+
case J9_NATIVE_METHOD_BIND_RECURSIVE:
2038+
setRecursiveBindError(_currentThread, _sendMethod);
2039+
break;
2040+
default:
2041+
setNativeNotFoundError(_currentThread, _sendMethod);
2042+
break;
2043+
}
20552044
}
2045+
2046+
return rc;
2047+
}
2048+
2049+
VMINLINE VM_BytecodeAction
2050+
bindNative(REGISTER_ARGS_LIST)
2051+
{
2052+
VM_BytecodeAction rc = GOTO_RUN_METHOD;
2053+
2054+
buildMethodFrame(REGISTER_ARGS, _sendMethod, jitStackFrameFlags(REGISTER_ARGS, 0));
2055+
2056+
updateVMStruct(REGISTER_ARGS);
2057+
rc = resolveNativeAddressWithErrorHandling();
2058+
VMStructHasBeenUpdated(REGISTER_ARGS);
2059+
2060+
if (GOTO_RUN_METHOD == rc) {
2061+
J9SFMethodFrame *methodFrame = (J9SFMethodFrame *)_sp;
2062+
_currentThread->jitStackFrameFlags = methodFrame->specialFrameFlags & J9_SSF_JIT_NATIVE_TRANSITION_FRAME;
2063+
restoreSpecialStackFrameLeavingArgs(REGISTER_ARGS, ((UDATA *)(methodFrame + 1)) - 1);
2064+
}
2065+
20562066
return rc;
20572067
}
20582068

@@ -4618,8 +4628,21 @@ done:;
46184628
outOfLineINL(REGISTER_ARGS_LIST)
46194629
{
46204630
updateVMStruct(REGISTER_ARGS);
4631+
46214632
J9OutOfLineINLMethod *target = (J9OutOfLineINLMethod *)(((UDATA)_sendMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED);
4622-
VM_BytecodeAction rc = target(_currentThread, _sendMethod);
4633+
VM_BytecodeAction rc = GOTO_RUN_METHOD;
4634+
if (NULL == target) {
4635+
/* Resolve the native address and retry. */
4636+
rc = resolveNativeAddressWithErrorHandling();
4637+
if (GOTO_RUN_METHOD != rc) {
4638+
goto done;
4639+
}
4640+
target = (J9OutOfLineINLMethod *)(((UDATA)_sendMethod->extra) & ~J9_STARTPC_NOT_TRANSLATED);
4641+
}
4642+
4643+
Assert_VM_true(NULL != target);
4644+
rc = target(_currentThread, _sendMethod);
4645+
done:
46234646
VMStructHasBeenUpdated(REGISTER_ARGS);
46244647
return rc;
46254648
}

0 commit comments

Comments
 (0)