diff --git a/runtime/compiler/control/OptionsPostRestore.cpp b/runtime/compiler/control/OptionsPostRestore.cpp index 46b40a94767..3cc098e4472 100644 --- a/runtime/compiler/control/OptionsPostRestore.cpp +++ b/runtime/compiler/control/OptionsPostRestore.cpp @@ -537,6 +537,10 @@ J9::OptionsPostRestore::invalidateCompiledMethodsIfNeeded(bool invalidateAll) void J9::OptionsPostRestore::disableAOTCompilation() { + static bool aotDisabled = false; + if (aotDisabled) + return; + // Ideally when disabling AOT, the vmThread->aotVMwithThreadInfo->_sharedCache // would also be freed and set to NULL. However, it isn't obvious whether non // compilation and java threads that could be running at the moment could make @@ -555,6 +559,9 @@ J9::OptionsPostRestore::disableAOTCompilation() TR::Options::setSharedClassCache(false); TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED); + aotDisabled = true; + _disableAOTPostRestore = true; + j9nls_printf(PORTLIB, (UDATA) J9NLS_WARNING, J9NLS_JIT_CHECKPOINT_RESTORE_AOT_DISABLED); } @@ -736,7 +743,28 @@ J9::OptionsPostRestore::postProcessInternalCompilerOptions() // Disable AOT compilation if needed if (disableAOT) + { disableAOTCompilation(); + } + // If at this point AOT is not disabled, then reset all the options and + // validate the AOT Header if the validation was delayed pre-checkpoint + else if (TR_J9SharedCache::aotHeaderValidationDelayed()) + { + _jitConfig->javaVM->sharedClassConfig->runtimeFlags |= J9SHR_RUNTIMEFLAG_ENABLE_AOT; + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT, false); + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT, false); + TR::Options::setSharedClassCache(true); + TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::NOT_DISABLED); + TR_J9SharedCache::resetAOTHeaderValidationDelayed(); + + TR_J9SharedCache::validateAOTHeader(_jitConfig, _vmThread, _compInfo); + + if (TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT)) + { + _jitConfig->javaVM->sharedClassConfig->runtimeFlags &= ~J9SHR_RUNTIMEFLAG_ENABLE_AOT; + TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED); + } + } // Set option to print code cache if necessary if (_argIndexPrintCodeCache > _argIndexDisablePrintCodeCache) @@ -791,7 +819,7 @@ J9::OptionsPostRestore::processCompilerOptions() PORT_ACCESS_FROM_JAVAVM(vm); bool jitEnabled = TR::Options::canJITCompile(); - bool aotEnabled = TR::Options::sharedClassCache(); + bool aotEnabled = TR_J9SharedCache::aotHeaderValidationDelayed() ? true : TR::Options::sharedClassCache(); _argIndexXjit = FIND_AND_CONSUME_RESTORE_ARG(OPTIONAL_LIST_MATCH, J9::Options::_externalOptionStrings[J9::ExternalOptions::Xjit], 0); _argIndexXnojit = FIND_AND_CONSUME_RESTORE_ARG(OPTIONAL_LIST_MATCH, J9::Options::_externalOptionStrings[J9::ExternalOptions::Xnojit], 0); @@ -802,14 +830,19 @@ J9::OptionsPostRestore::processCompilerOptions() jitEnabled = (_argIndexXjit > _argIndexXnojit); // If -Xnoaot was specified pre-checkpoint, there is a lot of infrastructure - // that needs to be set up, including validating the existing SCC. For now, - // Ignore -Xaot post-restore if -Xnoaot was specified pre-checkpoint. + // that needs to be set up. For now, ignore -Xaot post-restore if -Xnoaot + // was specified pre-checkpoint. if (aotEnabled) aotEnabled = (_argIndexXaot >= _argIndexXnoaot); if (!aotEnabled) { _disableAOTPostRestore = true; + } + + if (_disableAOTPostRestore) + { + aotEnabled = false; disableAOTCompilation(); } diff --git a/runtime/compiler/control/rossa.cpp b/runtime/compiler/control/rossa.cpp index 776505e112a..8b79459050e 100644 --- a/runtime/compiler/control/rossa.cpp +++ b/runtime/compiler/control/rossa.cpp @@ -2025,6 +2025,8 @@ aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig) #endif #if defined(J9VM_OPT_CRIU_SUPPORT) + bool debugOnRestoreEnabled = javaVM->internalVMFunctions->isDebugOnRestoreEnabled(curThread); + /* If the JVM is in CRIU mode and checkpointing is allowed, then the JIT should be * limited to the same processor features as those used in Portable AOT mode. This * is because, the restore run may not be on the same machine as the one that created @@ -2049,38 +2051,14 @@ aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig) validateSCC = false; #endif /* defined(J9VM_OPT_JITSERVER) */ +#if defined(J9VM_OPT_CRIU_SUPPORT) + if (debugOnRestoreEnabled) + validateSCC = false; +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ + if (validateSCC) { - /* If AOT Shared Classes is turned ON, perform compatibility checks for AOT Shared Classes - * - * This check has to be done after latePostProcessJIT so that all the necessary JIT options - * can be set - */ - TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, curThread); - if (!compInfo->reloRuntime()->validateAOTHeader(fe, curThread)) - { - TR_ASSERT_FATAL(static_cast(jitConfig->privateConfig)->aotValidHeader != TR_yes, - "aotValidHeader is TR_yes after failing to validate AOT header\n"); - - /* If this is the second run, then failing to validate AOT header will cause aotValidHeader - * to be TR_no, in which case the SCC is not valid for use. However, if this is the first - * run, then aotValidHeader will be TR_maybe; try to store the AOT Header in this case. - */ - if (static_cast(jitConfig->privateConfig)->aotValidHeader == TR_no - || !compInfo->reloRuntime()->storeAOTHeader(fe, curThread)) - { - static_cast(jitConfig->privateConfig)->aotValidHeader = TR_no; - TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT); - TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT); - TR::Options::setSharedClassCache(false); - TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED); - } - } - else - { - TR::Compiler->relocatableTarget.cpu = TR::CPU::customize(compInfo->reloRuntime()->getProcessorDescriptionFromSCC(curThread)); - jitConfig->relocatableTargetProcessor = TR::Compiler->relocatableTarget.cpu.getProcessorDescription(); - } + TR_J9SharedCache::validateAOTHeader(jitConfig, curThread, compInfo); } if (TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT)) @@ -2107,6 +2085,17 @@ aboutToBootstrap(J9JavaVM * javaVM, J9JITConfig * jitConfig) } #endif /* defined(J9VM_OPT_JITSERVER) */ } +#if defined(J9VM_OPT_CRIU_SUPPORT) + else if (debugOnRestoreEnabled) + { + javaVM->sharedClassConfig->runtimeFlags &= ~J9SHR_RUNTIMEFLAG_ENABLE_AOT; + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT); + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT); + TR::Options::setSharedClassCache(false); + TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_HEADER_VALIDATION_DELAYED); + TR_J9SharedCache::setAOTHeaderValidationDelayed(); + } +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ if (javaVM->sharedClassConfig->runtimeFlags & J9SHR_RUNTIMEFLAG_ENABLE_READONLY) { diff --git a/runtime/compiler/env/J9SharedCache.cpp b/runtime/compiler/env/J9SharedCache.cpp index 01fc380ff71..b6a8f18347b 100644 --- a/runtime/compiler/env/J9SharedCache.cpp +++ b/runtime/compiler/env/J9SharedCache.cpp @@ -65,6 +65,42 @@ static_assert(TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET != COULD_CREATE_CLASS_C TR_J9SharedCache::TR_J9SharedCacheDisabledReason TR_J9SharedCache::_sharedCacheState = TR_J9SharedCache::UNINITIALIZED; TR_YesNoMaybe TR_J9SharedCache::_sharedCacheDisabledBecauseFull = TR_maybe; UDATA TR_J9SharedCache::_storeSharedDataFailedLength = 0; +bool TR_J9SharedCache::_aotHeaderValidationDelayed = false; + +void +TR_J9SharedCache::validateAOTHeader(J9JITConfig *jitConfig, J9VMThread *vmThread, TR::CompilationInfo *compInfo) + { + /* If AOT Shared Classes is turned ON, perform compatibility checks for AOT Shared Classes + * + * This check has to be done after latePostProcessJIT so that all the necessary JIT options + * can be set + */ + TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, vmThread); + if (!compInfo->reloRuntime()->validateAOTHeader(fe, vmThread)) + { + TR_ASSERT_FATAL(static_cast(jitConfig->privateConfig)->aotValidHeader != TR_yes, + "aotValidHeader is TR_yes after failing to validate AOT header\n"); + + /* If this is the second run, then failing to validate AOT header will cause aotValidHeader + * to be TR_no, in which case the SCC is not valid for use. However, if this is the first + * run, then aotValidHeader will be TR_maybe; try to store the AOT Header in this case. + */ + if (static_cast(jitConfig->privateConfig)->aotValidHeader == TR_no + || !compInfo->reloRuntime()->storeAOTHeader(fe, vmThread)) + { + static_cast(jitConfig->privateConfig)->aotValidHeader = TR_no; + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT); + TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT); + TR::Options::setSharedClassCache(false); + TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED); + } + } + else + { + TR::Compiler->relocatableTarget.cpu = TR::CPU::customize(compInfo->reloRuntime()->getProcessorDescriptionFromSCC(vmThread)); + jitConfig->relocatableTargetProcessor = TR::Compiler->relocatableTarget.cpu.getProcessorDescription(); + } + } TR_YesNoMaybe TR_J9SharedCache::isSharedCacheDisabledBecauseFull(TR::CompilationInfo *compInfo) { diff --git a/runtime/compiler/env/J9SharedCache.hpp b/runtime/compiler/env/J9SharedCache.hpp index 3343d52f933..7b244d7da80 100644 --- a/runtime/compiler/env/J9SharedCache.hpp +++ b/runtime/compiler/env/J9SharedCache.hpp @@ -103,6 +103,8 @@ class TR_J9SharedCache : public TR_SharedCache virtual void addHint(TR_ResolvedMethod *, TR_SharedCacheHint); virtual bool isMostlyFull(); + static void validateAOTHeader(J9JITConfig *jitConfig, J9VMThread *vmThread, TR::CompilationInfo *compInfo); + /** * \brief Converts a shared cache offset, calculated from the end of the SCC, into the * metadata section of the SCC into a pointer. @@ -400,7 +402,8 @@ class TR_J9SharedCache : public TR_SharedCache // The following are probably equivalent to SHARED_CACHE_FULL - // they could have failed because of no space but no error code is returned. SHARED_CACHE_CLASS_CHAIN_STORE_FAILED, - AOT_HEADER_STORE_FAILED + AOT_HEADER_STORE_FAILED, + AOT_HEADER_VALIDATION_DELAYED }; static void setSharedCacheDisabledReason(TR_J9SharedCacheDisabledReason state) { _sharedCacheState = state; } @@ -408,6 +411,12 @@ class TR_J9SharedCache : public TR_SharedCache static TR_YesNoMaybe isSharedCacheDisabledBecauseFull(TR::CompilationInfo *compInfo); static void setStoreSharedDataFailedLength(UDATA length) {_storeSharedDataFailedLength = length; } +#if defined(J9VM_OPT_CRIU_SUPPORT) + static void setAOTHeaderValidationDelayed() { _aotHeaderValidationDelayed = true; } + static void resetAOTHeaderValidationDelayed() { _aotHeaderValidationDelayed = false; } + static bool aotHeaderValidationDelayed() { return _aotHeaderValidationDelayed; } +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ + virtual J9SharedClassCacheDescriptor *getCacheDescriptorList(); protected: @@ -613,6 +622,9 @@ class TR_J9SharedCache : public TR_SharedCache static TR_J9SharedCacheDisabledReason _sharedCacheState; static TR_YesNoMaybe _sharedCacheDisabledBecauseFull; static UDATA _storeSharedDataFailedLength; +#if defined(J9VM_OPT_CRIU_SUPPORT) + static bool _aotHeaderValidationDelayed; +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ }; diff --git a/runtime/compiler/env/VMJ9.cpp b/runtime/compiler/env/VMJ9.cpp index 97ef26d35da..abc179bd168 100644 --- a/runtime/compiler/env/VMJ9.cpp +++ b/runtime/compiler/env/VMJ9.cpp @@ -814,6 +814,12 @@ TR_J9VMBase::TR_J9VMBase( #if defined(J9VM_OPT_JITSERVER) || (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER) #endif /* defined(J9VM_OPT_JITSERVER) */ +#if defined(J9VM_OPT_CRIU_SUPPORT) + || (vmThread + && jitConfig->javaVM->sharedClassConfig + && jitConfig->javaVM->internalVMFunctions->isDebugOnRestoreEnabled(vmThread) + && jitConfig->javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)) +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ ) // shared classes and AOT must be enabled, or we should be on the JITServer with remote AOT enabled {