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

Recompile FSD Bodies generated under -XX:+DebugOnRestore #18982

Merged
merged 3 commits into from
Apr 12, 2024
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
2 changes: 1 addition & 1 deletion runtime/compiler/control/CompilationRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,7 @@ class CompilationInfo
static bool createCompilationInfo(J9JITConfig * jitConfig);
static void freeCompilationInfo(J9JITConfig *jitConfig);
static TR::CompilationInfo *get(J9JITConfig * = 0) { return _compilationRuntime; }
static bool shouldRetryCompilation(TR_MethodToBeCompiled *entry, TR::Compilation *comp);
static bool shouldRetryCompilation(J9VMThread *vmThread, TR_MethodToBeCompiled *entry, TR::Compilation *comp);
static bool shouldAbortCompilation(TR_MethodToBeCompiled *entry, TR::PersistentInfo *persistentInfo);
static bool canRelocateMethod(TR::Compilation * comp);
static int computeCompilationThreadPriority(J9JavaVM *vm);
Expand Down
62 changes: 58 additions & 4 deletions runtime/compiler/control/CompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2229,14 +2229,15 @@ bool TR::CompilationInfo::shouldAbortCompilation(TR_MethodToBeCompiled *entry, T
// This method has side-effects, It modifies the optimization plan and persistentMethodInfo
// This method is executed with compilationMonitor in hand
//
bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, TR::Compilation *comp)
bool TR::CompilationInfo::shouldRetryCompilation(J9VMThread *vmThread, TR_MethodToBeCompiled *entry, TR::Compilation *comp)
{
// The JITServer should not retry compilations on it's own,
// it should let the client make that decision
if (entry->isOutOfProcessCompReq())
return false;

bool tryCompilingAgain = false;
TR::CompilationInfo *compInfo = entry->_compInfoPT->getCompilationInfo();
TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
J9Method *method = details.getMethod();

Expand Down Expand Up @@ -2274,7 +2275,7 @@ bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, T
#if defined(J9VM_OPT_JITSERVER)
case compilationStreamFailure:
// if -XX:+JITServerRequireServer is used, we would like the client to fail when server crashes
if (entry->_compInfoPT->getCompilationInfo()->getPersistentInfo()->getRequireJITServer())
if (compInfo->getPersistentInfo()->getRequireJITServer())
{
TR_ASSERT_FATAL(false, "Option -XX:+JITServerRequireServer is used, terminate the JITClient due to unavailable JITServer.");
}
Expand Down Expand Up @@ -2459,10 +2460,36 @@ bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, T
}
}// if (entry->_compErrCode != compilationOK)

// If the JVM is shutting down, don't bother trying to compile again
if (compInfo->isInShutdownMode())
tryCompilingAgain = false;

// don't carry the decision to generate AOT code to the next compilation
// because it may no longer be the right thing to do at that point
if (tryCompilingAgain)
{
entry->_useAotCompilation = false;
}
#if defined(J9VM_OPT_CRIU_SUPPORT)
else if (entry->_compErrCode != compilationOK)
{
J9JavaVM *javaVM = compInfo->getJITConfig()->javaVM;
if (javaVM->internalVMFunctions->isDebugOnRestoreEnabled(vmThread)
&& javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)
&& !compInfo->getCRRuntime()->isCheckpointInProgress()
&& !compInfo->isInShutdownMode())
{
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCheckpointRestoreDetails))
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Pushing failed compilation %p", entry->getMethodDetails().getMethod());

TR_FilterBST *filter = NULL;
OMR::CriticalSection pushFailedComp(compInfo->getCRRuntime()->getCRRuntimeMonitor());
if (comp && entry->_compInfoPT->methodCanBeCompiled(comp->trMemory(), comp->fej9(), comp->getMethodBeingCompiled(), filter))
compInfo->getCRRuntime()->pushFailedCompilation(entry->getMethodDetails().getMethod());
}
}
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */


return tryCompilingAgain;
}
Expand Down Expand Up @@ -2520,6 +2547,11 @@ void TR::CompilationInfo::purgeMethodQueue(TR_CompilationErrorCode errorCode)
getLowPriorityCompQueue().purgeLPQ();
// and from JProfiling queue
getJProfilingCompQueue().purge();

#if defined(J9VM_OPT_CRIU_SUPPORT)
// and from the memoized compilations lists
getCRRuntime()->purgeMemoizedCompilations();
#endif
}

void TR::CompilationInfoPerThread::suspendCompilationThread()
Expand Down Expand Up @@ -6850,7 +6882,7 @@ TR::CompilationInfoPerThreadBase::installAotCachedMethod(
{
entry->_compErrCode = returnCode;
entry->setAotCodeToBeRelocated(NULL); // reset if relocation failed
entry->_tryCompilingAgain = _compInfo.shouldRetryCompilation(entry, compiler); // this will set entry->_doNotUseAotCodeFromSharedCache = true;
entry->_tryCompilingAgain = _compInfo.shouldRetryCompilation(vmThread, entry, compiler); // this will set entry->_doNotUseAotCodeFromSharedCache = true;

// Feature [Defect 172216/180384]: Implement hints for failed AOT validations. The idea is that the failed validations are due to the
// fact that AOT methods are loaded at a lower count than when they were compiled so the JVM is given less opportunity to resolve things.
Expand Down Expand Up @@ -7938,7 +7970,7 @@ TR::CompilationInfoPerThreadBase::postCompilationTasks(J9VMThread * vmThread,
{
metaData = 0;
}
else if (TR::CompilationInfo::shouldRetryCompilation(entry, _compiler))
else if (TR::CompilationInfo::shouldRetryCompilation(vmThread, entry, _compiler))
{
startPC = entry->_oldStartPC; // startPC == oldStartPC means compilation failure
entry->_tryCompilingAgain = true;
Expand Down Expand Up @@ -10530,6 +10562,26 @@ TR::CompilationInfo::compilationEnd(J9VMThread * vmThread, TR::IlGeneratorMethod
else
{
jitMethodTranslated(vmThread, method, startPC);
#if defined(J9VM_OPT_CRIU_SUPPORT)
if (jitConfig->javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)
&& jitConfig->javaVM->internalVMFunctions->isDebugOnRestoreEnabled(vmThread))
{
if (comp->getRecompilationInfo() && comp->getRecompilationInfo()->getJittedBodyInfo())
{
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCheckpointRestoreDetails))
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Will force %p to be recompiled post-restore", method);

OMR::CriticalSection pushForcedRecomp(compInfo->getCRRuntime()->getCRRuntimeMonitor());
compInfo->getCRRuntime()->pushForcedRecompilation(method);
}
else
{
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCheckpointRestoreDetails))
TR_VerboseLog::writeLineLocked(TR_Vlog_CHECKPOINT_RESTORE, "Cannot force %p to be recompiled post-restore because the bodyInfo does not exist", method);
}
}
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */

}
}
}
Expand Down Expand Up @@ -10871,6 +10923,8 @@ void TR::CompilationInfoPerThreadBase::logCompilationSuccess(
case TR_PersistentMethodInfo::RecompDueToEdo:
catchBlockCounter = bodyInfo->getMethodInfo()->getCatchBlockCounter();
recompReason = 'E'; break;
case TR_PersistentMethodInfo::RecompDueToCRIU:
recompReason = 'F'; break;
} // end switch
bodyInfo->getMethodInfo()->setReasonForRecompilation(0); // reset the flags
}
Expand Down
53 changes: 46 additions & 7 deletions runtime/compiler/control/HookedByTheJit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1369,7 +1369,11 @@ static void jitMethodSampleInterrupt(J9VMThread* vmThread, IDATA handlerKey, voi
* optimization that statistically should be useful.
*/
&& !compInfo->getCRRuntime()->shouldSuspendThreadsForCheckpoint()
#endif

/* Don't sample methods for recompilation pre-checkpoint if Debug On Restore is enabled */
&& (!jitConfig->javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)
|| !jitConfig->javaVM->internalVMFunctions->isDebugOnRestoreEnabled(vmThread))
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
&& !compInfo->getPersistentInfo()->getDisableFurtherCompilation())
{
static char *enableDebugDLT = feGetEnv("TR_DebugDLT");
Expand Down Expand Up @@ -1424,6 +1428,10 @@ static void jitMethodSampleInterrupt(J9VMThread* vmThread, IDATA handlerKey, voi
* optimization that statistically should be useful.
*/
&& !compInfo->getCRRuntime()->shouldSuspendThreadsForCheckpoint()

/* Don't sample methods for recompilation pre-checkpoint if Debug On Restore is enabled */
&& (!jitConfig->javaVM->internalVMFunctions->isCheckpointAllowed(vmThread)
|| !jitConfig->javaVM->internalVMFunctions->isDebugOnRestoreEnabled(vmThread))
#endif
&& !compInfo->getPersistentInfo()->getDisableFurtherCompilation())
{
Expand Down Expand Up @@ -1895,6 +1903,7 @@ static void jitHookClassesUnload(J9HookInterface * * hookInterface, UDATA eventN
J9VMThread * vmThread = unloadedEvent->currentThread;
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;

TR_J9VMBase * vmj9 = TR_J9VMBase::get(jitConfig, vmThread);
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
TR::PersistentInfo * persistentInfo = compInfo->getPersistentInfo();

Expand Down Expand Up @@ -2055,7 +2064,9 @@ static void jitHookAnonClassesUnload(J9HookInterface * * hookInterface, UDATA ev
}

J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
TR_J9VMBase * vmj9 = TR_J9VMBase::get(jitConfig, vmThread);
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);

#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
compInfo->cleanDLTRecordOnUnload();
if (compInfo->getDLT_HT())
Expand All @@ -2068,7 +2079,6 @@ static void jitHookAnonClassesUnload(J9HookInterface * * hookInterface, UDATA ev
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))
{
TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, vmThread));
TR_IProfiler *iProfiler = vmj9->getIProfiler();
if (iProfiler) // even if Iprofiler is disabled, there might be some buffers in the queue
{ // which need to be invalidated
Expand All @@ -2085,6 +2095,11 @@ static void jitHookAnonClassesUnload(J9HookInterface * * hookInterface, UDATA ev
for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)
{
cgOnClassUnloading(j9clazz);

#if defined(J9VM_OPT_CRIU_SUPPORT)
compInfo->getCRRuntime()->removeMethodsFromMemoizedCompilations<J9Class>(j9clazz);
#endif // defined(J9VM_OPT_CRIU_SUPPORT)

j9clazz->classLoader = NULL;
}
}
Expand Down Expand Up @@ -2134,6 +2149,9 @@ static void jitHookClassUnload(J9HookInterface * * hookInterface, UDATA eventNum
// remove from compilation request queue any methods that belong to this class
fej9->acquireCompilationLock();
fej9->invalidateCompilationRequestsForUnloadedMethods(clazz, false);
#if defined(J9VM_OPT_CRIU_SUPPORT)
compInfo->getCRRuntime()->removeMethodsFromMemoizedCompilations<J9Class>(j9clazz);
#endif // defined(J9VM_OPT_CRIU_SUPPORT)
fej9->releaseCompilationLock();

J9Method * resolvedMethods = (J9Method *) fej9->getMethods((TR_OpaqueClassBlock*)j9clazz);
Expand Down Expand Up @@ -2412,6 +2430,10 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
TR_ASSERT(0,"JIT HCR should make all methods recompilable, so startPC=%p should have a persistentBodyInfo", startPC);
}
}

#if defined(J9VM_OPT_CRIU_SUPPORT)
compInfo->getCRRuntime()->removeMethodsFromMemoizedCompilations<J9Method>(staleMethod);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because classes are redefined in place, I'm not 100% sure if the stale J9Methods point to the redefined class, or if they've been updated, So I used the J9Method variant of removeMethodsFromMemoizedCompilations here.

#endif // defined(J9VM_OPT_CRIU_SUPPORT)
}
classPair = (J9JITRedefinedClass *) ((char *) classPair->methodList + (classPair->methodCount * sizeof(struct J9JITMethodEquivalence)));
}
Expand All @@ -2424,8 +2446,13 @@ void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRede
reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate all compilation requests");
fe->invalidateCompilationRequestsForUnloadedMethods(NULL, true);

//clean up the trampolines
// clean up the trampolines
TR::CodeCacheManager::instance()->onFSDDecompile();

#if defined(J9VM_OPT_CRIU_SUPPORT)
// purge memoized compilations
compInfo->getCRRuntime()->purgeMemoizedCompilations();
#endif
}

fe->releaseCompilationLock();
Expand Down Expand Up @@ -6204,7 +6231,11 @@ static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)
CompilationDensity compDensity;
#endif /* defined(J9VM_OPT_JITSERVER) */

TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, 0);
#if defined(J9VM_OPT_CRIU_SUPPORT)
bool forcedRecompilations = false;
#endif

TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, samplerThread);

j9thread_set_name(j9thread_self(), "JIT Sampler");
while (!shutdownSamplerThread)
Expand All @@ -6218,7 +6249,8 @@ static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)
crtTime += samplingPeriod;

#if defined(J9VM_OPT_CRIU_SUPPORT)
if (vm->internalVMFunctions->isCheckpointAllowed(samplerThread)
if (vm->internalVMFunctions->isCheckpointAllowed(samplerThread))
{
/* It's ok to not acquire the comp monitor here. Even if at this
* point a checkpoint isn't in progress but later it is, the
* checkpoint will not complete until the sampler thread suspends
Expand All @@ -6230,9 +6262,16 @@ static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)
* isn't true (e.g., due to shutdown), then the sampler thread will
* not suspend itself.
*/
&& compInfo->getCRRuntime()->shouldSuspendThreadsForCheckpoint())
if (compInfo->getCRRuntime()->shouldSuspendThreadsForCheckpoint())
suspendSamplerThreadForCheckpoint(samplerThread,jitConfig, compInfo);
}
else if (vm->internalVMFunctions->isDebugOnRestoreEnabled(samplerThread))
{
suspendSamplerThreadForCheckpoint(samplerThread,jitConfig, compInfo);
if (!forcedRecompilations && jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP)
{
forcedRecompilations = true;
compInfo->getCRRuntime()->recompileMethodsCompiledPreCheckpoint();
}
}
#endif // #if defined(J9VM_OPT_CRIU_SUPPORT)

Expand Down
7 changes: 7 additions & 0 deletions runtime/compiler/control/J9CompilationStrategy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,13 @@ TR_OptimizationPlan *J9::CompilationStrategy::processEvent(TR_MethodEvent *event
*newPlanCreated = true;
}
break;
case TR_MethodEvent::ForcedRecompilationPostRestore:
{
hotnessLevel = warm;
plan = TR_OptimizationPlan::alloc(hotnessLevel);
*newPlanCreated = true;
}
break;
default:
TR_ASSERT(0, "Bad event type %d", event->_eventType);
}
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/control/J9CompilationStrategy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class TR_MethodEvent
JitCompilationInducedByDLT,
HWPRecompilationTrigger,
CompilationBeforeCheckpoint,
ForcedRecompilationPostRestore,
NumEvents // must be the last one
};
int32_t _eventType;
Expand Down
5 changes: 5 additions & 0 deletions runtime/compiler/control/OptionsPostRestore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,8 @@ J9::OptionsPostRestore::invalidateCompiledMethodsIfNeeded(bool invalidateAll)
shouldInvalidateCompiledMethod(method, fej9, compilationFiltersExist))
{
invalidateCompiledMethod(method, fej9);
if (!invalidateAll)
_compInfo->getCRRuntime()->removeMethodsFromMemoizedCompilations<J9Method>(method);
}
}
}
Expand All @@ -510,6 +512,9 @@ J9::OptionsPostRestore::invalidateCompiledMethodsIfNeeded(bool invalidateAll)
}
javaVM->internalVMFunctions->allClassesEndDo(&classWalkState);

if (invalidateAll)
_compInfo->getCRRuntime()->purgeMemoizedCompilations();

j9nls_printf(PORTLIB, (UDATA) J9NLS_WARNING, J9NLS_JIT_CHECKPOINT_RESTORE_CODE_INVALIDATED);
}
}
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/control/RecompilationInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ class TR_PersistentMethodInfo
RecompDueToRI = 0x000A0000,
RecompDueToJProfiling = 0x000B0000,
RecompDueToInlinedMethodRedefinition = 0x000C0000,
RecompDueToCRIU = 0x000D0000,

// NOTE: recompilations due to EDO decrementation cannot be tracked precisely
// because they are triggered from a snippet (must change the code for snippet)
// Also, the recompilations after a profiling step cannot be marked as such.
Expand Down
Loading