Skip to content

Commit

Permalink
Delay AOT validation until restore under -XX:+DebugOnRestore
Browse files Browse the repository at this point in the history
Under -XX:+DebugOnRestore, the JIT generates FSD code. This is
problematic for AOT as either:

1. An existing SCC will fail validation, since the AOT code therein will
   not have been generated with FSD, or
2. An unpopulated SCC will contain FSD code, which will be useless for
   any JVM that does not have FSD enabled

This commit delays AOT validation until after restore; this ensures that
AOT code from the SCC can be loaded post-restore, and that any code
added to the SCC is maximally sharable.

Signed-off-by: Irwin D'Souza <[email protected]>
  • Loading branch information
dsouzai committed Apr 17, 2024
1 parent d162e56 commit b1bcfa7
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 34 deletions.
39 changes: 36 additions & 3 deletions runtime/compiler/control/OptionsPostRestore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand All @@ -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();
}

Expand Down
49 changes: 19 additions & 30 deletions runtime/compiler/control/rossa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<TR_JitPrivateConfig *>(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<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_no
|| !compInfo->reloRuntime()->storeAOTHeader(fe, curThread))
{
static_cast<TR_JitPrivateConfig *>(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))
Expand All @@ -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)
{
Expand Down
39 changes: 39 additions & 0 deletions runtime/compiler/env/J9SharedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,45 @@ TR_J9SharedCache::TR_J9SharedCacheDisabledReason TR_J9SharedCache::_sharedCacheS
TR_YesNoMaybe TR_J9SharedCache::_sharedCacheDisabledBecauseFull = TR_maybe;
UDATA TR_J9SharedCache::_storeSharedDataFailedLength = 0;

#if defined(J9VM_OPT_CRIU_SUPPORT)
bool TR_J9SharedCache::_aotHeaderValidationDelayed = false;
#endif

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<TR_JitPrivateConfig *>(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<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_no
|| !compInfo->reloRuntime()->storeAOTHeader(fe, vmThread))
{
static_cast<TR_JitPrivateConfig *>(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)
{
if (_sharedCacheDisabledBecauseFull == TR_maybe)
Expand Down
14 changes: 13 additions & 1 deletion runtime/compiler/env/J9SharedCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -400,14 +402,21 @@ 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; }
static TR_J9SharedCacheDisabledReason getSharedCacheDisabledReason() { return _sharedCacheState; }
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:
Expand Down Expand Up @@ -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) */
};


Expand Down
6 changes: 6 additions & 0 deletions runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down

0 comments on commit b1bcfa7

Please sign in to comment.