diff --git a/runtime/nls/j9vm/j9vm.nls b/runtime/nls/j9vm/j9vm.nls index 55823db809a..48ae04a716d 100644 --- a/runtime/nls/j9vm/j9vm.nls +++ b/runtime/nls/j9vm/j9vm.nls @@ -2394,3 +2394,10 @@ J9NLS_VM_DEPRECATED_OPTION.explanation=The command line option is deprecated. J9NLS_VM_DEPRECATED_OPTION.system_action=The JVM will print a deprecation warning. J9NLS_VM_DEPRECATED_OPTION.user_response=Remove the command line option from the command line. # END NON-TRANSLATABLE + +J9NLS_VM_CRIU_CHECK_TRANSITION_TO_DEBUG_INTERPRETER_FAILED=The check for the transition to the debug interpreter failed +# START NON-TRANSLATABLE +J9NLS_VM_CRIU_CHECK_TRANSITION_TO_DEBUG_INTERPRETER_FAILED.explanation=checkTransitionToDebugInterpreter failed. +J9NLS_VM_CRIU_CHECK_TRANSITION_TO_DEBUG_INTERPRETER_FAILED.system_action=The JVM will throw a JVMRestoreException. +J9NLS_VM_CRIU_CHECK_TRANSITION_TO_DEBUG_INTERPRETER_FAILED.user_response=View CRIU documentation to determine how to resolve the error. +# END NON-TRANSLATABLE diff --git a/runtime/vm/CRIUHelpers.cpp b/runtime/vm/CRIUHelpers.cpp index 4d8a903d43f..e526d9a0282 100644 --- a/runtime/vm/CRIUHelpers.cpp +++ b/runtime/vm/CRIUHelpers.cpp @@ -59,6 +59,12 @@ static BOOLEAN criuRestoreInitializeXrs(J9VMThread *currentThread, void *userDat static BOOLEAN criuRestoreDisableSharedClassCache(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat); static BOOLEAN criuRestoreInitializeDump(J9VMThread *currentThread, void *userData, const char **nlsMsgFormat); static jvmtiIterationControl objectIteratorCallback(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData); +#if defined(OMR_GC_FULL_POINTERS) +UDATA debugBytecodeLoopFull(J9VMThread *currentThread); +#endif /* defined(OMR_GC_FULL_POINTERS) */ +#if defined(OMR_GC_COMPRESSED_POINTERS) +UDATA debugBytecodeLoopCompressed(J9VMThread *currentThread); +#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */ #define STRING_BUFFER_SIZE 256 #define ENV_FILE_BUFFER 1024 @@ -1443,6 +1449,49 @@ loadRestoreArguments(J9VMThread *currentThread, const char *optionsFile, char *e return result; } +static void +transitionToDebugInterpreter(J9JavaVM *vm) +{ + if (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm)) { +#if defined(OMR_GC_COMPRESSED_POINTERS) + vm->bytecodeLoop = debugBytecodeLoopCompressed; +#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */ + } else { +#if defined(OMR_GC_FULL_POINTERS) + vm->bytecodeLoop = debugBytecodeLoopFull; +#endif /* defined(OMR_GC_FULL_POINTERS) */ + } + J9VMThread *walkThread = J9_LINKED_LIST_START_DO(vm->mainThread); + while (NULL != walkThread) { + VM_VMHelpers::requestInterpreterReentry(walkThread); + walkThread = J9_LINKED_LIST_NEXT_DO(vm->mainThread, walkThread); + } +} + +static BOOLEAN +checkTransitionToDebugInterpreter(J9VMThread *currentThread) +{ + BOOLEAN result = TRUE; + J9JavaVM *vm = currentThread->javaVM; + if (NULL != vm->checkpointState.restoreArgsList) { + J9VMInitArgs *restoreArgsList = vm->checkpointState.restoreArgsList; + IDATA debugOn = FIND_AND_CONSUME_ARG(restoreArgsList, EXACT_MATCH, VMOPT_XXDEBUGINTERPRETER, NULL); + IDATA debugOff = FIND_AND_CONSUME_ARG(restoreArgsList, EXACT_MATCH, VMOPT_XXNODEBUGINTERPRETER, NULL); + if (debugOn > debugOff) { + /* + * The transition to the debug interpreter currently only works with -Xint, + * and the null check for vm->jitConfig will be removed when the jit changes are completed. + */ + if (isDebugOnRestoreEnabled(currentThread) && (NULL == vm->jitConfig)) { + transitionToDebugInterpreter(vm); + } else { + result = FALSE; + } + } + } + return result; +} + void JNICALL criuCheckpointJVMImpl(JNIEnv *env, jstring imagesDir, @@ -1823,6 +1872,15 @@ criuCheckpointJVMImpl(JNIEnv *env, case RESTORE_ARGS_RETURN_OK: break; } + + if (!checkTransitionToDebugInterpreter(currentThread)) { + currentExceptionClass = vm->checkpointState.criuJVMRestoreExceptionClass; + nlsMsgFormat = j9nls_lookup_message( + J9NLS_DO_NOT_PRINT_MESSAGE_TAG | J9NLS_DO_NOT_APPEND_NEWLINE, + J9NLS_VM_CRIU_CHECK_TRANSITION_TO_DEBUG_INTERPRETER_FAILED, + NULL); + goto wakeJavaThreadsWithExclusiveVMAccess; + } } VM_VMHelpers::setVMState(currentThread, J9VMSTATE_CRIU_SUPPORT_RESTORE_PHASE_JAVA_HOOKS); diff --git a/test/functional/cmdLineTests/criu/criu_nonPortable.xml b/test/functional/cmdLineTests/criu/criu_nonPortable.xml index a8b79292122..00da93931f2 100644 --- a/test/functional/cmdLineTests/criu/criu_nonPortable.xml +++ b/test/functional/cmdLineTests/criu/criu_nonPortable.xml @@ -761,6 +761,24 @@ org.eclipse.openj9.criu.JVMRestoreException User requested Java dump using + + + + bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$ -XX:+DebugOnRestore -Xint" $MAINCLASS_ENVVAR_TEST$ testCheckTransitionToDebugInterpreterWithEnvVarFile 1 false false + Killed + Pre-checkpoint + Post-checkpoint + CRIU is not enabled + Operation not permitted + + Thread pid mismatch + do not match expected + Unable to create a thread: + + Could not dump the JVM processes, err=-70 + User requested Java dump using + + bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_OPTIONSFILE_TEST$ TraceOptionsTest1 1 false false Killed @@ -906,6 +924,23 @@ User requested Java dump using + + + bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$ -XX:+DebugOnRestore -Xint" $MAINCLASS_OPTIONSFILE_TEST$ testCheckTransitionToDebugInterpreterWithOptionsFile 1 false false + Killed + Pre-checkpoint + Post-checkpoint + CRIU is not enabled + Operation not permitted + + Thread pid mismatch + do not match expected + Unable to create a thread: + + Could not dump the JVM processes, err=-70 + User requested Java dump using + + bash $SCRIPPATH$ $TEST_RESROOT$ $JAVA_COMMAND$ "$JVM_OPTIONS$" $MAINCLASS_USERNAME_TEST$ unusedArgument 1 false false Killed diff --git a/test/functional/cmdLineTests/criu/src/org/openj9/criu/EnvVarFileTest.java b/test/functional/cmdLineTests/criu/src/org/openj9/criu/EnvVarFileTest.java index 418a12a0497..3416109ecfe 100644 --- a/test/functional/cmdLineTests/criu/src/org/openj9/criu/EnvVarFileTest.java +++ b/test/functional/cmdLineTests/criu/src/org/openj9/criu/EnvVarFileTest.java @@ -83,6 +83,9 @@ public static void main(String[] args) { case "EnvVarFileTest16": envVarFileTest16(); break; + case "testCheckTransitionToDebugInterpreterWithEnvVarFile": + testCheckTransitionToDebugInterpreterWithEnvVarFile(); + break; default: throw new RuntimeException("incorrect parameters"); } @@ -404,4 +407,15 @@ static void envVarFileTest16() { System.out.println("Post-checkpoint"); } + static void testCheckTransitionToDebugInterpreterWithEnvVarFile() { + String optionsContents = RESTORE_ENV_VAR + "=-XX:+DebugInterpreter"; + Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents); + Path imagePath = Paths.get("cpData"); + CRIUTestUtils.createCheckpointDirectory(imagePath); + CRIUSupport criuSupport = new CRIUSupport(imagePath); + criuSupport.registerRestoreEnvFile(optionsFilePath); + System.out.println("Pre-checkpoint"); + CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true); + System.out.println("Post-checkpoint"); + } } diff --git a/test/functional/cmdLineTests/criu/src/org/openj9/criu/OptionsFileTest.java b/test/functional/cmdLineTests/criu/src/org/openj9/criu/OptionsFileTest.java index ae686891851..92e6ffab884 100644 --- a/test/functional/cmdLineTests/criu/src/org/openj9/criu/OptionsFileTest.java +++ b/test/functional/cmdLineTests/criu/src/org/openj9/criu/OptionsFileTest.java @@ -71,6 +71,9 @@ public static void main(String[] args) { case "JitOptionsTest": jitOptionsTest(args); break; + case "testCheckTransitionToDebugInterpreterWithOptionsFile": + testCheckTransitionToDebugInterpreterWithOptionsFile(); + break; default: throw new RuntimeException("incorrect parameters"); } @@ -332,4 +335,15 @@ static void jitOptionsTest(String[] args) { } } + static void testCheckTransitionToDebugInterpreterWithOptionsFile() { + String optionsContents = "-XX:+DebugInterpreter"; + Path optionsFilePath = CRIUTestUtils.createOptionsFile("options", optionsContents); + Path imagePath = Paths.get("cpData"); + CRIUTestUtils.createCheckpointDirectory(imagePath); + CRIUSupport criuSupport = new CRIUSupport(imagePath); + criuSupport.registerRestoreOptionsFile(optionsFilePath); + System.out.println("Pre-checkpoint"); + CRIUTestUtils.checkPointJVM(criuSupport, imagePath, true); + System.out.println("Post-checkpoint"); + } }