Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Post Restore Options Processing Part 4 #16852

Merged
merged 3 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion doc/compiler/control/OptionsPostRestore.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ Finally, `postProcessInternalCompilerOptions` performs tasks that need
to be done after the `-Xjit:`, `-Xaot:`, and external options have all
been processed.

# Subtleties
# Important Notes

### JIT and AOT compiled code

Expand Down Expand Up @@ -138,3 +138,20 @@ file(s) are closed and the post-restore file(s) are opened. A
consequence of this is that if the same file name is specified then a
new file will be opened. This can have the consequence of overwriting
the previous file if the PID of the restored process is the same.

### Start and Elapsed Time

The Checkpoint phase is conceptually part of building the application;
therefore it does not make sense to expect a user who specifies an
option such as `-XsamplingExpirationTime` to take into account the time
spent executing in the Checkpoint phase. Therefore, on restore, both
the start and elapsed time are reset.

### `-Xrs`, `-Xtrace`, `-Xjit:disableTraps`, `-Xjit:noResumableTrapHandler`

Currently, unless specified pre-checkpoint, the compiler generates will
generate code assuming these options are not set. If these options are
then specified post-restore, the options processing code will
invalidate all JIT code in the code cache, as well as prevent further
AOT compilation (since the AOT method header would have already been
validated).
8 changes: 8 additions & 0 deletions runtime/compiler/control/CompilationRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,12 @@ class CompilationInfo
void setReadyForCheckpointRestore() { _checkpointStatus = TR_CheckpointStatus::READY_FOR_CHECKPOINT_RESTORE; }
bool shouldCheckpointBeInterrupted() { return _checkpointStatus == TR_CheckpointStatus::INTERRUPT_CHECKPOINT; }
void interruptCheckpoint() { _checkpointStatus = TR_CheckpointStatus::INTERRUPT_CHECKPOINT; }

void setVMMethodTraceEnabled(bool trace) { _vmMethodTraceEnabled = trace; }
bool isVMMethodTraceEnabled() { return _vmMethodTraceEnabled; }

bool resetStartAndElapsedTime() { return _resetStartAndElapsedTime; }
void setResetStartAndElapsedTime(bool reset) { _resetStartAndElapsedTime = reset; }
#endif

TR_PersistentMemory * persistentMemory() { return _persistentMemory; }
Expand Down Expand Up @@ -1368,6 +1374,8 @@ class CompilationInfo
#if defined(J9VM_OPT_CRIU_SUPPORT)
TR::Monitor *_crMonitor;
TR_CheckpointStatus _checkpointStatus;
bool _vmMethodTraceEnabled;
bool _resetStartAndElapsedTime;
#endif

TR::Monitor *_vlogMonitor;
Expand Down
20 changes: 15 additions & 5 deletions runtime/compiler/control/CompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,12 @@ TR::CompilationInfo::CompilationInfo(J9JITConfig *jitConfig) :
#if defined(J9VM_OPT_CRIU_SUPPORT)
_crMonitor = TR::Monitor::create("JIT-CheckpointRestoreMonitor");
_checkpointStatus = TR_CheckpointStatus::NO_CHECKPOINT_IN_PROGRESS;

// TR::CompilationInfo is initialized in the JIT_INITIALIZED bootstrap
// stage, whereas J9_EXTENDED_RUNTIME_METHOD_TRACE_ENABLED is set in the
// TRACE_ENGINE_INITIALIZED stage, which happens first.
_vmMethodTraceEnabled = jitConfig->javaVM->extendedRuntimeFlags & J9_EXTENDED_RUNTIME_METHOD_TRACE_ENABLED;
_resetStartAndElapsedTime = false;
#endif
_iprofilerBufferArrivalMonitor = TR::Monitor::create("JIT-IProfilerBufferArrivalMonitor");
_classUnloadMonitor = TR::MonitorTable::get()->getClassUnloadMonitor(); // by this time this variable is initialized
Expand Down Expand Up @@ -2890,18 +2896,18 @@ void TR::CompilationInfo::prepareForCheckpoint()
acquireCompMonitor(vmThread);
}

/* Check if the checkpoint is interrupted */
// Check if the checkpoint is interrupted
if (shouldCheckpointBeInterrupted())
return;

TR_ASSERT_FATAL(!isCheckpointInProgress(), "Checkpoint already in progress!\n");

/* Compile methods for checkpoint */
// Compile methods for checkpoint
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCompilationBeforeCheckpoint))
if (!compileMethodsForCheckpoint(vmThread))
return;

/* Suspend compilation threads for checkpoint */
// Suspend compilation threads for checkpoint
if (!suspendCompThreadsForCheckpoint(vmThread))
return;

Expand All @@ -2920,17 +2926,21 @@ void TR::CompilationInfo::prepareForRestore()
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCheckpointRestore))
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Preparing for restore");

// Inform the Sampler Thread to reset the start and elapsed time it maintains
setResetStartAndElapsedTime(true);

// Process the post-restore options
J9::OptionsPostRestore::processOptionsPostRestore(vmThread, _jitConfig, this);

{
OMR::CriticalSection resumeCompThreadsCriticalSection(getCompilationMonitor());

TR_ASSERT_FATAL(readyForCheckpointRestore(), "Not ready for Checkpoint Restore\n");

/* Reset the checkpoint in progress flag. */
// Reset the checkpoint in progress flag.
resetCheckpointInProgress();

/* Resume suspended compilation threads. */
// Resume suspended compilation threads.
resumeCompilationThread();
}

Expand Down
24 changes: 24 additions & 0 deletions runtime/compiler/control/HookedByTheJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6102,6 +6102,30 @@ static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)
while (!shutdownSamplerThread && // watch for shutdown signals
j9thread_sleep_interruptable((IDATA) samplingPeriod, 0) == 0) // Anything non-0 is an error condition so we shouldn't do the sampling //!= J9THREAD_INTERRUPTED)
{
#if defined(J9VM_OPT_CRIU_SUPPORT)
// Post-restore, reset the start and elapsed time. The Checkpoint
// phase is conceptually part of building the application; therefore
// it does not make sense to expect a user who specifies an option such
// as -XsamplingExpirationTime to take into account the time spent
// executing in the Checkpoint phase.
if (compInfo->resetStartAndElapsedTime())
{
if (TR::Options::isAnyVerboseOptionSet())
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Start and elapsed time: startTime=%6u, elapsedTime=%6u",
(uint32_t)persistentInfo->getStartTime(), (uint32_t)persistentInfo->getElapsedTime());

persistentInfo->setStartTime(j9time_current_time_millis());
persistentInfo->setElapsedTime(0);

if (TR::Options::isAnyVerboseOptionSet())
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Reset start and elapsed time: startTime=%6u, elapsedTime=%6u",
(uint32_t)persistentInfo->getStartTime(), (uint32_t)persistentInfo->getElapsedTime());

// Only reset the time once
compInfo->setResetStartAndElapsedTime(false);
}
#endif // #if defined(J9VM_OPT_CRIU_SUPPORT)

J9VMThread * currentThread;

persistentInfo->updateElapsedTime(samplingPeriod);
Expand Down
5 changes: 4 additions & 1 deletion runtime/compiler/control/J9Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ int32_t J9::Options::_jProfilingEnablementSampleThreshold = 10000;

bool J9::Options::_aggressiveLockReservation = false;

bool J9::Options::_xrsSync = false;

/**
* This string array should be kept in sync with the
* J9::ExternalOptions enum in J9Options.hpp
Expand Down Expand Up @@ -2975,7 +2977,8 @@ bool J9::Options::feLatePostProcess(void * base, TR::OptionSet * optionSet)
// -Xrs Ignore all signals (J9_SIG_XRS_SYNC, J9_SIG_XRS_ASYNC)
// -Xrs:sync Ignore synchronous signals (J9_SIG_XRS_SYNC)
// -Xrs:async Ignore asynchronous signals (J9_SIG_XRS_ASYNC)
if (J9_ARE_ALL_BITS_SET(javaVM->sigFlags, J9_SIG_XRS_SYNC))
_xrsSync = J9_ARE_ALL_BITS_SET(javaVM->sigFlags, J9_SIG_XRS_SYNC);
if (_xrsSync)
{
self()->setOption(TR_NoResumableTrapHandler);
self()->setOption(TR_DisablePackedDecimalIntrinsics);
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/control/J9Options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,8 @@ class OMR_EXTENSIBLE Options : public OMR::OptionsConnector

static bool _aggressiveLockReservation;

static bool _xrsSync;

static char * _externalOptionStrings[ExternalOptions::TR_NumExternalOptions];

static void printPID();
Expand Down
66 changes: 53 additions & 13 deletions runtime/compiler/control/OptionsPostRestore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "j9.h"
#include "j9nonbuilder.h"
#include "jvminit.h"
#include "j9comp.h"
#include "env/CompilerEnv.hpp"
#include "env/TRMemory.hpp"
#include "compile/Method.hpp"
Expand Down Expand Up @@ -72,7 +73,13 @@ J9::OptionsPostRestore::OptionsPostRestore(J9VMThread *vmThread, J9JITConfig *ji
_argIndexDisableUseJITServer(-1),
_argIndexJITServerAddress(-1),
_argIndexJITServerAOTCacheName(-1)
{}
{
TR::Options *options = TR::Options::getCmdLineOptions();
_disableTrapsPreCheckpoint
= J9::Options::_xrsSync
|| options->getOption(TR_NoResumableTrapHandler)
|| options->getOption(TR_DisableTraps);
}

void
J9::OptionsPostRestore::iterateOverExternalOptions()
Expand Down Expand Up @@ -450,6 +457,23 @@ J9::OptionsPostRestore::invalidateCompiledMethodsIfNeeded(bool invalidateAll)
}
}

void
J9::OptionsPostRestore::disableAOTCompilation()
{
// 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
// use of it, in which case there could be a race. To avoid this, it's safer
// to just leave _sharedCache alone; at worst some SCC API could be invoked,
// but not during a compilation as all compilation threads are suspended at
// this point, and so it won't impact AOT code.

TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT);
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT);
TR::Options::setSharedClassCache(false);
TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED);
}

void
J9::OptionsPostRestore::openNewVlog(char *vLogFileName)
{
Expand Down Expand Up @@ -558,6 +582,7 @@ J9::OptionsPostRestore::preProcessInternalCompilerOptions()
void
J9::OptionsPostRestore::postProcessInternalCompilerOptions()
{
J9JavaVM *vm = _jitConfig->javaVM;
// TODO: Based on whether the following is enabled, do necessary compensation
// - disabling recompilation (optLevel=, inhibit recomp, etc)
// - OMR::Options::_logFile (both global and subsets)
Expand All @@ -575,8 +600,33 @@ J9::OptionsPostRestore::postProcessInternalCompilerOptions()
// Open vlog and rtLog if applicable
openLogFilesIfNeeded();

// If -Xrs, -Xtrace, or disabling traps is specified post-restore,
// invalidate all method bodies
bool invalidateAll = false;
bool disableAOT = false;
if (!_disableTrapsPreCheckpoint
&& (J9_ARE_ALL_BITS_SET(vm->sigFlags, J9_SIG_XRS_SYNC)
|| TR::Options::getCmdLineOptions()->getOption(TR_NoResumableTrapHandler)
|| TR::Options::getCmdLineOptions()->getOption(TR_DisableTraps)))
{
J9:Options::_xrsSync = J9_ARE_ALL_BITS_SET(vm->sigFlags, J9_SIG_XRS_SYNC);
invalidateAll = true;
disableAOT = true;
}
else if (!_compInfo->isVMMethodTraceEnabled()
&& (vm->extendedRuntimeFlags & J9_EXTENDED_RUNTIME_METHOD_TRACE_ENABLED))
{
_compInfo->setVMMethodTraceEnabled(true);
invalidateAll = true;
disableAOT = true;
}

// Invalidate method bodies if needed
invalidateCompiledMethodsIfNeeded();
invalidateCompiledMethodsIfNeeded(invalidateAll);

// Disable AOT compilation if needed
if (disableAOT)
disableAOTCompilation();

// Set option to print code cache if necessary
if (_argIndexPrintCodeCache > _argIndexDisablePrintCodeCache)
Expand Down Expand Up @@ -621,19 +671,9 @@ J9::OptionsPostRestore::processCompilerOptions()
if (aotEnabled)
aotEnabled = (_argIndexXaot >= _argIndexXnoaot);

// 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
// use of it, in which case there could be a race. To avoid this, it's safer
// to just leave _sharedCache alone; at worst some SCC API could be invoked,
// but not during a compilation as all compilation threads are suspended at
// this point, and so it won't impact AOT code.
if (!aotEnabled)
{
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT);
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT);
TR::Options::setSharedClassCache(false);
TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::AOT_DISABLED);
disableAOTCompilation();
}

if (!jitEnabled)
Expand Down
5 changes: 5 additions & 0 deletions runtime/compiler/control/OptionsPostRestore.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,10 @@ class OptionsPostRestore
*/
void invalidateCompiledMethodsIfNeeded(bool invalidateAll = false);

/**
* \brief Helper method to disable further AOT compilation.
*/
void disableAOTCompilation();

/**
* \brief Helper method to perform tasks prior to processing
Expand Down Expand Up @@ -162,6 +166,7 @@ class OptionsPostRestore
char *_oldRtLogFileName;

bool _asyncCompilationPreCheckpoint;
bool _disableTrapsPreCheckpoint;

int32_t _argIndexXjit;
int32_t _argIndexXjitcolon;
Expand Down