diff --git a/runtime/compiler/compile/J9Compilation.cpp b/runtime/compiler/compile/J9Compilation.cpp index 8545557ef44..4064937c3da 100644 --- a/runtime/compiler/compile/J9Compilation.cpp +++ b/runtime/compiler/compile/J9Compilation.cpp @@ -857,8 +857,9 @@ bool J9::Compilation::compilePortableCode() { return (self()->fej9()->inSnapshotMode() || - (self()->compileRelocatableCode() && - self()->fej9()->isPortableSCCEnabled())); + self()->fej9()->isPortableRestoreModeEnabled() || + (self()->compileRelocatableCode() && + self()->fej9()->isPortableSCCEnabled())); } diff --git a/runtime/compiler/control/HookedByTheJit.cpp b/runtime/compiler/control/HookedByTheJit.cpp index 637ee396f17..b53ecacbbbf 100644 --- a/runtime/compiler/control/HookedByTheJit.cpp +++ b/runtime/compiler/control/HookedByTheJit.cpp @@ -1856,7 +1856,7 @@ static void jitHookPrepareRestore(J9HookInterface * * hookInterface, UDATA event * remove the portability restrictions on the target CPU (used * for JIT compiles) to allow optimal code generation */ - if (!javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)) + if (!javaVM->internalVMFunctions->isJVMInPortableRestoreMode(vmThread)) { TR::Compiler->target.cpu = TR::CPU::detect(TR::Compiler->omrPortLib); jitConfig->targetProcessor = TR::Compiler->target.cpu.getProcessorDescription(); diff --git a/runtime/compiler/control/J9Options.cpp b/runtime/compiler/control/J9Options.cpp index 81be702b1d6..0a069e43314 100644 --- a/runtime/compiler/control/J9Options.cpp +++ b/runtime/compiler/control/J9Options.cpp @@ -1496,7 +1496,7 @@ void J9::Options::preProcessMmf(J9JavaVM *vm, J9JITConfig *jitConfig) if (J9_ARE_ANY_BITS_SET(vm->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE) #if defined(J9VM_OPT_CRIU_SUPPORT) - || vm->internalVMFunctions->isCheckpointAllowed(vmThread) + || vm->internalVMFunctions->isJVMInPortableRestoreMode(vmThread) #endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ ) { @@ -2375,7 +2375,7 @@ bool J9::Options::preProcessJitServer(J9JavaVM *vm, J9JITConfig *jitConfig) if (implicitClientMode && useJitServerExplicitlySpecified) { compInfo->setRemoteCompilationRequestedAtBootstrap(true); - if (!ifuncs->isNonPortableRestoreMode(currentThread)) + if (ifuncs->isJVMInPortableRestoreMode(currentThread)) compInfo->setCanPerformRemoteCompilationInCRIUMode(true); } #endif diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index d4034543391..28f4c758852 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -524,9 +524,10 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes vmInfo._aotHeader = *header; } vmInfo._inSnapshotMode = fe->inSnapshotMode(); + vmInfo._isPortableRestoreMode = fe->isPortableRestoreModeEnabled(); vmInfo._isSnapshotModeEnabled = fe->isSnapshotModeEnabled(); #if defined(J9VM_OPT_CRIU_SUPPORT) - vmInfo._isNonPortableRestoreMode = javaVM->internalVMFunctions->isNonPortableRestoreMode(vmThread); + vmInfo._isNonPortableRestoreMode = !javaVM->internalVMFunctions->isJVMInPortableRestoreMode(vmThread); #else vmInfo._isNonPortableRestoreMode = false; #endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index da5e8388f10..835fbde1065 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -1999,7 +1999,7 @@ aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig) * is because, the restore run may not be on the same machine as the one that created * the snapshot; thus the JIT code must be portable. */ - if (javaVM->internalVMFunctions->isCheckpointAllowed(curThread)) + if (javaVM->internalVMFunctions->isJVMInPortableRestoreMode(curThread)) { TR::Compiler->target.cpu = TR::CPU::detectRelocatable(TR::Compiler->omrPortLib); if (!J9_ARE_ANY_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_PORTABLE_SHARED_CACHE)) diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index e2a6ef6432d..6543531b98b 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -9377,6 +9377,16 @@ TR_J9VMBase::inSnapshotMode() #endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ } +bool +TR_J9VMBase::isPortableRestoreModeEnabled() + { +#if defined(J9VM_OPT_CRIU_SUPPORT) + return getJ9JITConfig()->javaVM->internalVMFunctions->isJVMInPortableRestoreMode(vmThread()); +#else /* defined(J9VM_OPT_CRIU_SUPPORT) */ + return false; +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ + } + bool TR_J9VMBase::isSnapshotModeEnabled() { diff --git a/runtime/compiler/env/VMJ9.h b/runtime/compiler/env/VMJ9.h index 346b85083e0..f2d593b4e73 100644 --- a/runtime/compiler/env/VMJ9.h +++ b/runtime/compiler/env/VMJ9.h @@ -1398,6 +1398,13 @@ class TR_J9VMBase : public TR_FrontEnd */ virtual bool inSnapshotMode(); + /** + * \brief Answers whether the JIT should generate portable restore code. + * + * \return True if portable restore code should be generated, false otherwise. + */ + virtual bool isPortableRestoreModeEnabled(); + /** * \brief Answers whether checkpoint and restore mode is enabled (but not necessarily * whether snapshots can be taken or if any restores have already occurred). diff --git a/runtime/compiler/env/VMJ9Server.cpp b/runtime/compiler/env/VMJ9Server.cpp index e58200304d8..71ff94ce80e 100644 --- a/runtime/compiler/env/VMJ9Server.cpp +++ b/runtime/compiler/env/VMJ9Server.cpp @@ -2481,6 +2481,14 @@ TR_J9ServerVM::isSnapshotModeEnabled() return vmInfo->_isSnapshotModeEnabled; } +bool +TR_J9ServerVM::isPortableRestoreModeEnabled() + { + JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream; + auto *vmInfo = _compInfoPT->getClientData()->getOrCacheVMInfo(stream); + return vmInfo->_isPortableRestoreMode; + } + bool TR_J9SharedCacheServerVM::isClassLibraryMethod(TR_OpaqueMethodBlock *method, bool vettedForAOT) { diff --git a/runtime/compiler/env/VMJ9Server.hpp b/runtime/compiler/env/VMJ9Server.hpp index 27e47a1f87f..e7268adbf1b 100644 --- a/runtime/compiler/env/VMJ9Server.hpp +++ b/runtime/compiler/env/VMJ9Server.hpp @@ -247,6 +247,7 @@ class TR_J9ServerVM: public TR_J9VM virtual bool isMethodHandleExpectedType(TR::Compilation *comp, TR::KnownObjectTable::Index mhIndex, TR::KnownObjectTable::Index expectedTypeIndex) override; virtual bool inSnapshotMode() override; virtual bool isSnapshotModeEnabled() override; + virtual bool isPortableRestoreModeEnabled() override; private: bool instanceOfOrCheckCastHelper(J9Class *instanceClass, J9Class* castClass, bool cacheUpdate); diff --git a/runtime/compiler/net/CommunicationStream.hpp b/runtime/compiler/net/CommunicationStream.hpp index e75575628a8..40cdc322c38 100644 --- a/runtime/compiler/net/CommunicationStream.hpp +++ b/runtime/compiler/net/CommunicationStream.hpp @@ -118,7 +118,7 @@ class CommunicationStream // likely to lose an increment when merging/rebasing/etc. // static const uint8_t MAJOR_NUMBER = 1; - static const uint16_t MINOR_NUMBER = 52; // ID: vKDVVxR2fImMeQKnbv6I + static const uint16_t MINOR_NUMBER = 53; // ID: 7dZlozupV5RwUvR62RqE static const uint8_t PATCH_NUMBER = 0; static uint32_t CONFIGURATION_FLAGS; diff --git a/runtime/compiler/runtime/JITClientSession.hpp b/runtime/compiler/runtime/JITClientSession.hpp index eef78c6fe88..5cc4922a44f 100644 --- a/runtime/compiler/runtime/JITClientSession.hpp +++ b/runtime/compiler/runtime/JITClientSession.hpp @@ -326,6 +326,7 @@ class ClientSessionData // Do not protect them with #if defined(J9VM_OPT_CRIU_SUPPORT) because we want JITServer to be // able to handle all clients whether or not they have CRIU support enabled bool _inSnapshotMode; + bool _isPortableRestoreMode; bool _isSnapshotModeEnabled; bool _isNonPortableRestoreMode; }; // struct VMInfo diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index 7d1cea5bd26..2b0bdfc746c 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -4200,6 +4200,7 @@ typedef struct J9DelayedLockingOpertionsRecord { #define J9VM_CRIU_IS_NON_PORTABLE_RESTORE_MODE 0x4 #define J9VM_CRIU_IS_JDWP_ENABLED 0x8 #define J9VM_CRIU_IS_THROW_ON_DELAYED_CHECKPOINT_ENABLED 0x10 +#define J9VM_CRIU_IS_PORTABLE_JVM_RESTORE_MODE 0x20 typedef struct J9CRIUCheckpointState { U_32 flags; @@ -5021,6 +5022,7 @@ typedef struct J9InternalVMFunctions { BOOLEAN (*isCRIUSupportEnabled_VM)(struct J9JavaVM *vm); BOOLEAN (*isCheckpointAllowed)(struct J9VMThread *currentThread); BOOLEAN (*isNonPortableRestoreMode)(struct J9VMThread *currentThread); + BOOLEAN (*isJVMInPortableRestoreMode)(struct J9VMThread *currentThread); BOOLEAN (*runInternalJVMCheckpointHooks)(struct J9VMThread *currentThread, const char **nlsMsgFormat); BOOLEAN (*runInternalJVMRestoreHooks)(struct J9VMThread *currentThread, const char **nlsMsgFormat); BOOLEAN (*runDelayedLockRelatedOperations)(struct J9VMThread *currentThread); diff --git a/runtime/oti/jvminit.h b/runtime/oti/jvminit.h index a654c7831e0..8bac5ab7699 100644 --- a/runtime/oti/jvminit.h +++ b/runtime/oti/jvminit.h @@ -426,6 +426,8 @@ enum INIT_STAGE { #define VMOPT_XXDISABLECRIU "-XX:-EnableCRIUSupport" #define VMOPT_XXENABLECRIUNONPORTABLEMODE "-XX:+CRIURestoreNonPortableMode" #define VMOPT_XXDISABLECRIUNONPORTABLEMODE "-XX:-CRIURestoreNonPortableMode" +#define VMOPT_XXENABLEJVMRESTOREPORTABLEMODE "-XX:+JVMPortableRestoreMode" +#define VMOPT_XXDISABLEJVMRESTOREPORTABLEMODE "-XX:-JVMPortableRestoreMode" #define VMOPT_XSHARECLASSES_DISABLEONRESTORE "-Xshareclasses:disableOnRestore" #define VMOPT_XXENABLETHROWONDELAYECHECKPOINTOPERATION "-XX:+ThrowOnDelayedCheckpointOperation" #define VMOPT_XXDISABLETHROWONDELAYECHECKPOINTOPERATION "-XX:-ThrowOnDelayedCheckpointOperation" diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index f2443d23645..c1aa40f171d 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -541,6 +541,19 @@ isCheckpointAllowed(J9VMThread *currentThread); BOOLEAN isNonPortableRestoreMode(J9VMThread *currentThread); +/** + * @brief Queries if portable restore mode (specified via + * -XX:+JVMPortableRestoreMode) is enabled. If so, the JVM + * will remain in portable mode after restore. However, this + * will have no impact on the JCL and taking another checkpoint + * will still not be permitted. + * + * @param currentThread vmthread token + * @return TRUE if enabled, FALSE otherwise + */ +BOOLEAN +isJVMInPortableRestoreMode(J9VMThread *currentThread); + /** * @brief JVM hooks to run before performing a JVM checkpoint * diff --git a/runtime/vm/CRIUHelpers.cpp b/runtime/vm/CRIUHelpers.cpp index b601530f63e..8add440abdc 100644 --- a/runtime/vm/CRIUHelpers.cpp +++ b/runtime/vm/CRIUHelpers.cpp @@ -134,6 +134,12 @@ isNonPortableRestoreMode(J9VMThread *currentThread) return J9_ARE_ALL_BITS_SET(currentThread->javaVM->checkpointState.flags, J9VM_CRIU_IS_NON_PORTABLE_RESTORE_MODE); } +BOOLEAN +isJVMInPortableRestoreMode(J9VMThread *currentThread) +{ + return (!isNonPortableRestoreMode(currentThread) || J9_ARE_ALL_BITS_SET(currentThread->javaVM->checkpointState.flags, J9VM_CRIU_IS_PORTABLE_JVM_RESTORE_MODE)) && isCRIUSupportEnabled(currentThread); +} + /** * This adds an internal CRIU hook to trace all heap objects of instanceType and its subclasses if specified. * diff --git a/runtime/vm/intfunc.c b/runtime/vm/intfunc.c index 74be1e76e6f..0575aa8b5d2 100644 --- a/runtime/vm/intfunc.c +++ b/runtime/vm/intfunc.c @@ -411,6 +411,7 @@ J9InternalVMFunctions J9InternalFunctions = { isCRIUSupportEnabled_VM, isCheckpointAllowed, isNonPortableRestoreMode, + isJVMInPortableRestoreMode, runInternalJVMCheckpointHooks, runInternalJVMRestoreHooks, runDelayedLockRelatedOperations, diff --git a/runtime/vm/jvminit.c b/runtime/vm/jvminit.c index 1034193dae1..498a8336753 100644 --- a/runtime/vm/jvminit.c +++ b/runtime/vm/jvminit.c @@ -3893,6 +3893,16 @@ processVMArgsFromFirstToLast(J9JavaVM * vm) } } + { + IDATA enableJVMRestorePortableeMode = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXENABLEJVMRESTOREPORTABLEMODE, NULL); + IDATA disableJVMRestorePortableMode = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXDISABLEJVMRESTOREPORTABLEMODE, NULL); + if (enableJVMRestorePortableeMode > disableJVMRestorePortableMode) { + if (J9_ARE_ALL_BITS_SET(vm->checkpointState.flags, J9VM_CRIU_IS_CHECKPOINT_ENABLED)) { + vm->checkpointState.flags |= J9VM_CRIU_IS_PORTABLE_JVM_RESTORE_MODE; + } + } + } + { IDATA enableThrowOnDelayedCheckpointOperation = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXENABLETHROWONDELAYECHECKPOINTOPERATION, NULL); IDATA disableThrowOnDelayedCheckpointOperation = FIND_AND_CONSUME_VMARG(EXACT_MATCH, VMOPT_XXDISABLETHROWONDELAYECHECKPOINTOPERATION, NULL); diff --git a/test/functional/cmdLineTests/criu/playlist.xml b/test/functional/cmdLineTests/criu/playlist.xml index 8dbb0151f79..8eda2355acb 100644 --- a/test/functional/cmdLineTests/criu/playlist.xml +++ b/test/functional/cmdLineTests/criu/playlist.xml @@ -91,6 +91,8 @@ -Xjit -XX:+CRIURestoreNonPortableMode -Xint -XX:+CRIURestoreNonPortableMode + -XX:+JVMPortableRestoreMode + -Xjit:count=0 -XX:+JVMPortableRestoreMode -Xjit:count=0 -XX:+CRIURestoreNonPortableMode -Xgcpolicy:optthruput -Xgcpolicy:optavgpause @@ -191,6 +193,7 @@ -Xjit -Xjit:count=0 -Xjit:vlog=vlog + -XX:+JVMPortableRestoreMode if [ -x $(Q)$(TEST_JDK_BIN)$(D)jitserver$(Q) ]; \ @@ -352,6 +355,7 @@ -Xjit -XX:+CRIURestoreNonPortableMode -Xint -XX:+CRIURestoreNonPortableMode -Xjit:count=0 -XX:+CRIURestoreNonPortableMode + -XX:+JVMPortableRestoreMode $(JAVA_COMMAND) $(CMDLINETESTER_JVM_OPTIONS) -Xdump \ diff --git a/test/functional/cmdLineTests/criu/src/org/openj9/criu/CRIUSimpleTest.java b/test/functional/cmdLineTests/criu/src/org/openj9/criu/CRIUSimpleTest.java index b7a91d98342..59eed76054d 100644 --- a/test/functional/cmdLineTests/criu/src/org/openj9/criu/CRIUSimpleTest.java +++ b/test/functional/cmdLineTests/criu/src/org/openj9/criu/CRIUSimpleTest.java @@ -25,6 +25,11 @@ import java.nio.file.Paths; import java.nio.file.Path; +import javax.swing.SwingUtilities; +import javax.swing.JFrame; +import java.lang.management.*; + + public class CRIUSimpleTest { public static void main(String args[]) { @@ -36,12 +41,24 @@ public static void main(String args[]) { } } + private static void loadNewClasses() { + try { + SwingUtilities.isEventDispatchThread(); + JFrame frame = new JFrame("Test code"); + } catch (Throwable t) { + //ignore + } + + ThreadMXBean mxb = ManagementFactory.getThreadMXBean(); + } + public static void checkpoints(int num_checkpoints) { Path path = Paths.get("cpData"); System.out.println("Total checkpoint(s) " + num_checkpoints + ":\nPre-checkpoint"); for (int cur_checkpint = 1; cur_checkpint <= num_checkpoints; ++cur_checkpint) { CRIUTestUtils.checkPointJVM(path); System.out.println("Post-checkpoint " + cur_checkpint); + loadNewClasses(); } } }