Skip to content

Commit

Permalink
Merge pull request #20637 from cjjdespres/dep-compilations-union
Browse files Browse the repository at this point in the history
Track method dependencies during AOT store compilations
  • Loading branch information
mpirvu authored Nov 22, 2024
2 parents eae6d58 + ac1d4a4 commit ff43532
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 72 deletions.
52 changes: 35 additions & 17 deletions runtime/compiler/codegen/J9AheadOfTimeCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -502,8 +502,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
fieldRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
fieldRecord->setConstantPool(reloTarget, reinterpret_cast<uintptr_t>(aotCI->_constantPool));
fieldRecord->setCpIndex(reloTarget, static_cast<uintptr_t>(aotCI->_cpIndex));
fieldRecord->setClassChainOffsetInSharedCache(reloTarget, aotCI->_classChainOffset,
self(), aotCI->getAOTCacheClassChainRecord());
fieldRecord->setClassChainOffsetInSharedCache(reloTarget, aotCI, self());
}
break;

Expand Down Expand Up @@ -601,8 +600,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
vsfRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
vsfRecord->setConstantPool(reloTarget, reinterpret_cast<uintptr_t>(aotCI->_constantPool));
vsfRecord->setCpIndex(reloTarget, aotCI->_cpIndex);
vsfRecord->setRomClassOffsetInSharedCache(reloTarget, romClassOffsetInSharedCache,
self(), aotCI->getAOTCacheClassChainRecord());
vsfRecord->setRomClassOffsetInSharedCache(reloTarget, romClassOffsetInSharedCache, self(), aotCI);
}
break;

Expand All @@ -616,8 +614,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
vcRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
vcRecord->setConstantPool(reloTarget, reinterpret_cast<uintptr_t>(aotCI->_constantPool));
vcRecord->setCpIndex(reloTarget, aotCI->_cpIndex);
vcRecord->setClassChainOffsetInSharedCache(reloTarget, aotCI->_classChainOffset,
self(), aotCI->getAOTCacheClassChainRecord());
vcRecord->setClassChainOffsetInSharedCache(reloTarget, aotCI, self());
}
break;

Expand Down Expand Up @@ -671,7 +668,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
pRecord->setInlinedSiteIndex(reloTarget, inlinedSiteIndex);
pRecord->setConstantPool(reloTarget, reinterpret_cast<uintptr_t>(owningMethod->constantPool()));
pRecord->setCpIndex(reloTarget, cpIndexOrData);
pRecord->setRomClassOffsetInSharedCache(reloTarget, romClassOffsetInSharedCache, self(), classChainRecord);
pRecord->setRomClassOffsetInSharedCache(reloTarget, romClassOffsetInSharedCache, self(), inlinedCodeClass, classChainRecord);
pRecord->setClassChainIdentifyingLoaderOffsetInSharedCache(reloTarget, classChainIdentifyingLoaderOffsetInSharedCache,
self(), classChainRecord);
pRecord->setClassChainForInlinedMethod(reloTarget, classChainOffsetInSharedCache, self(), classChainRecord);
Expand Down Expand Up @@ -758,8 +755,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal

vacRecord->setClassChainIdentifyingLoaderOffset(reloTarget, classChainOffsetInSharedCacheForCL,
self(), aotCI->getAOTCacheClassChainRecord());
vacRecord->setClassChainOffsetForClassBeingValidated(reloTarget, aotCI->_classChainOffset,
self(), aotCI->getAOTCacheClassChainRecord());
vacRecord->setClassChainOffsetForClassBeingValidated(reloTarget, aotCI, self());
}
break;

Expand All @@ -783,8 +779,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal

cbnRecord->setClassID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_class));
cbnRecord->setBeholderID(reloTarget, symValManager->getSymbolIDFromValue(svmRecord->_beholder));
cbnRecord->setClassChainOffset(reloTarget, svmRecord->_classChainOffset,
self(), svmRecord->getAOTCacheClassChainRecord());
cbnRecord->setClassChainOffset(reloTarget, svmRecord, self());
}
break;

Expand All @@ -801,8 +796,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal

pcRecord->setClassID(reloTarget, symValManager->getSymbolIDFromValue(classToValidate));
//store the classchain's offset for the class that needs to be validated in the second run
pcRecord->setClassChainOffset(reloTarget, svmRecord->_classChainOffset,
self(), svmRecord->getAOTCacheClassChainRecord());
pcRecord->setClassChainOffset(reloTarget, svmRecord, self());
pcRecord->setClassChainOffsetForClassLoader(reloTarget, classChainOffsetInSharedCacheForCL,
self(), svmRecord->getAOTCacheClassChainRecord());
}
Expand Down Expand Up @@ -892,8 +886,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
scmRecord->setSystemClassID(reloTarget, symValManager->getSymbolIDFromValue(classToValidate));
// Store class chain to get name of class. Checking the class chain for
// this record eliminates the need for a separate class chain validation.
scmRecord->setClassChainOffset(reloTarget, svmRecord->_classChainOffset,
self(), svmRecord->getAOTCacheClassChainRecord());
scmRecord->setClassChainOffset(reloTarget, svmRecord, self());
}
break;

Expand Down Expand Up @@ -943,8 +936,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
ccRecord->setClassID(reloTarget, symValManager->getSymbolIDFromValue(classToValidate));
// Store class chain to get name of class. Checking the class chain for
// this record eliminates the need for a separate class chain validation.
ccRecord->setClassChainOffset(reloTarget, svmRecord->_classChainOffset,
self(), svmRecord->getAOTCacheClassChainRecord());
ccRecord->setClassChainOffset(reloTarget, svmRecord, self());
}
break;

Expand Down Expand Up @@ -2626,4 +2618,30 @@ void J9::AheadOfTimeCompile::processRelocations()
relocationDataCursor += s->getSizeOfRelocationData();
}
}
#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
if (!comp->getOption(TR_DisableDependencyTracking))
{
auto method = comp->getMethodBeingCompiled()->getPersistentIdentifier();
auto definingClass = comp->fe()->getClassOfMethod(method);

Vector<uintptr_t> dependencies(comp->trMemory()->currentStackRegion());
uintptr_t totalDependencies = comp->populateAOTMethodDependencies(definingClass, dependencies);

if (totalDependencies == 0)
{
// If there are zero dependencies, we skip storing the chain. This
// flag must still be set to distinguish methods with zero
// dependencies from methods with untracked dependencies.
comp->getAotMethodHeaderEntry()->flags |= TR_AOTMethodHeader_TracksDependencies;
}
else
{
auto sharedCache = fej9->sharedCache();
auto vmThread = fej9->getCurrentVMThread();
auto dependencyChain = sharedCache->storeAOTMethodDependencies(vmThread, method, definingClass, dependencies.data(), dependencies.size());
if (dependencyChain)
comp->getAotMethodHeaderEntry()->flags |= TR_AOTMethodHeader_TracksDependencies;
}
}
#endif /* !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED) */
}
4 changes: 2 additions & 2 deletions runtime/compiler/compile/AOTClassInfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ class AOTClassInfo
}

#if defined(J9VM_OPT_JITSERVER)
const AOTCacheClassChainRecord *getAOTCacheClassChainRecord() { return _aotCacheClassChainRecord; }
const AOTCacheClassChainRecord *getAOTCacheClassChainRecord() const { return _aotCacheClassChainRecord; }
#else /* defined(J9VM_OPT_JITSERVER) */
const AOTCacheClassChainRecord *getAOTCacheClassChainRecord() { return NULL; }
const AOTCacheClassChainRecord *getAOTCacheClassChainRecord() const { return NULL; }
#endif /* defined(J9VM_OPT_JITSERVER) */

TR_ExternalRelocationTargetKind _reloKind; // identifies validation needed (instance field, static field, class, arbitrary class)
Expand Down
71 changes: 71 additions & 0 deletions runtime/compiler/compile/J9Compilation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "compile/Compilation.hpp"
#include "compile/Compilation_inlines.hpp"
#include "compile/CompilationTypes.hpp"
#include "env/DependencyTable.hpp"
#include "compile/ResolvedMethod.hpp"
#include "control/OptimizationPlan.hpp"
#include "control/Options.hpp"
Expand Down Expand Up @@ -205,6 +206,9 @@ J9::Compilation::Compilation(int32_t id,
_serializationRecords(decltype(_serializationRecords)::allocator_type(heapMemoryRegion)),
_thunkRecords(decltype(_thunkRecords)::allocator_type(heapMemoryRegion)),
#endif /* defined(J9VM_OPT_JITSERVER) */
#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
_aotMethodDependencies(decltype(_aotMethodDependencies)::allocator_type(heapMemoryRegion)),
#endif /* !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED) */
_osrProhibitedOverRangeOfTrees(false),
_wasFearPointAnalysisDone(false)
{
Expand Down Expand Up @@ -1583,6 +1587,73 @@ J9::Compilation::canAddOSRAssumptions()
&& !self()->wasFearPointAnalysisDone();
}

#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
void
J9::Compilation::addAOTMethodDependency(TR_OpaqueClassBlock *clazz)
{
if (getOption(TR_DisableDependencyTracking))
return;

auto chainOffset = self()->fej9()->sharedCache()->rememberClass(clazz);

if (TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET == chainOffset)
self()->failCompilation<J9::ClassChainPersistenceFailure>("classChainOffset == INVALID_CLASS_CHAIN_OFFSET");

addAOTMethodDependency(chainOffset, self()->fej9()->isClassInitialized(clazz));
}

void
J9::Compilation::addAOTMethodDependency(TR_OpaqueClassBlock *clazz, uintptr_t chainOffset)
{
if (getOption(TR_DisableDependencyTracking))
return;

addAOTMethodDependency(chainOffset, self()->fej9()->isClassInitialized(clazz));
}

void
J9::Compilation::addAOTMethodDependency(uintptr_t chainOffset, bool ensureClassIsInitialized)
{
TR_ASSERT(TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET != chainOffset, "Attempted to remember invalid chain offset");
TR_ASSERT(self()->compileRelocatableCode(), "Must be generating AOT code");

auto it = _aotMethodDependencies.find(chainOffset);
if (it != _aotMethodDependencies.end())
it->second = it->second || ensureClassIsInitialized;
else
_aotMethodDependencies.insert(it, {chainOffset, ensureClassIsInitialized});
}

// Populate the given dependencyBuffer with dependencies of this method, in the
// format needed by TR_J9SharedCache::storeAOTMethodDependencies(). Returns the
// total number of dependencies.
uintptr_t
J9::Compilation::populateAOTMethodDependencies(TR_OpaqueClassBlock *definingClass, Vector<uintptr_t> &dependencyBuffer)
{
// TODO: Methods may be able to run before their defining class is
// initialized. Adding this back in will save a fair amount of space in the
// SCC once that's figured out.
//
// uintptr_t definingClassChainOffset = self()->fej9()->sharedCache()->rememberClass(definingClass);
// TR_ASSERT_FATAL(TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET != definingClassChainOffset, "Defining class %p of an AOT-compiled method must be remembered");
// _aotMethodDependencies.erase(definingClassChainOffset);

uintptr_t totalDependencies = _aotMethodDependencies.size();
if (totalDependencies == 0)
return totalDependencies;

dependencyBuffer.reserve(totalDependencies + 1);
dependencyBuffer.push_back(totalDependencies);
for (auto &entry : _aotMethodDependencies)
{
uintptr_t encodedOffset = TR_AOTDependencyTable::encodeDependencyOffset(entry.first, entry.second);
dependencyBuffer.push_back(encodedOffset);
}

return totalDependencies;
}
#endif /* !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED) */

#if defined(J9VM_OPT_JITSERVER)
void
J9::Compilation::addSerializationRecord(const AOTCacheRecord *record, uintptr_t reloDataOffset)
Expand Down
23 changes: 21 additions & 2 deletions runtime/compiler/compile/J9Compilation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ namespace J9 { typedef J9::Compilation CompilationConnector; }
#include "env/OMRMemory.hpp"
#include "compile/AOTClassInfo.hpp"
#include "runtime/SymbolValidationManager.hpp"
#if defined(J9VM_OPT_JITSERVER)
#include "env/PersistentCollections.hpp"
#endif /* defined(J9VM_OPT_JITSERVER) */


class TR_AOTGuardSite;
Expand Down Expand Up @@ -432,6 +430,15 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
void setOSRProhibitedOverRangeOfTrees() { _osrProhibitedOverRangeOfTrees = true; }
bool isOSRProhibitedOverRangeOfTrees() { return _osrProhibitedOverRangeOfTrees; }

#if defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
void addAOTMethodDependency(TR_OpaqueClassBlock *ramClass) {}
void addAOTMethodDependency(TR_OpaqueClassBlock *ramClass, uintptr_t chainOffset) {}
#else
void addAOTMethodDependency(TR_OpaqueClassBlock *ramClass);
void addAOTMethodDependency(TR_OpaqueClassBlock *ramClass, uintptr_t chainOffset);
uintptr_t populateAOTMethodDependencies(TR_OpaqueClassBlock *definingClass, Vector<uintptr_t> &chainBuffer);
#endif

private:
enum CachedClassPointerId
{
Expand All @@ -446,6 +453,10 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector

TR_OpaqueClassBlock *getCachedClassPointer(CachedClassPointerId which);

#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
void addAOTMethodDependency(uintptr_t offset, bool classIsInitialized);
#endif /* !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED) */

J9VMThread *_j9VMThread;

bool _doneHWProfile;
Expand Down Expand Up @@ -561,6 +572,14 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
UnorderedSet<const AOTCacheThunkRecord *> _thunkRecords;
#endif /* defined(J9VM_OPT_JITSERVER) */

#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
// A map recording the dependencies of an AOT method. The keys are the class
// chain offsets of classes this method depends on, and the values record
// whether the class needs to be initialized before method loading, or only
// loaded.
UnorderedMap<uintptr_t, bool> _aotMethodDependencies;
#endif /* defined(PERSISTENT_COLLECTIONS_UNSUPPORTED) */

TR::SymbolValidationManager *_symbolValidationManager;
bool _osrProhibitedOverRangeOfTrees;
bool _wasFearPointAnalysisDone;
Expand Down
3 changes: 3 additions & 0 deletions runtime/compiler/control/CompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8632,6 +8632,9 @@ TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void *
options->setOption(TR_UseSymbolValidationManager, false);
}

if (!vm->canTrackAOTDependencies() || !that->_compInfo.getPersistentInfo()->getTrackAOTDependencies())
options->setOption(TR_DisableDependencyTracking);

// Adjust Options for AOT compilation
if (vm->isAOT_DEPRECATED_DO_NOT_USE())
{
Expand Down
9 changes: 9 additions & 0 deletions runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3322,6 +3322,15 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod
}
compiler->setIgnoringLocalSCC(aotCacheStore && compiler->getPersistentInfo()->getJITServerAOTCacheIgnoreLocalSCC());

// TODO: To support dependency tracking with the JITServer AOT cache while
// ignoring the local SCC, we would have to store the dependencies at the
// server and detect (with the help of the server's serialization records)
// when they were satisfied. More limited support also makes sense when not
// ignoring the local SCC - the dependencies would just have to be saved at
// the server so they could be sent to and stored by the client.
if (aotCacheLoad || aotCacheStore)
compiler->setOption(TR_DisableDependencyTracking);

// This thread may have been notified at some point in the past that the deserializer was reset.
// Since this is the start of a new compilation, we must clear the reset flag in order to detect
// a concurrent deserializer reset during the course of this compilation. This clearing must
Expand Down
4 changes: 2 additions & 2 deletions runtime/compiler/env/J9SharedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1636,11 +1636,11 @@ TR_J9JITServerSharedCache::TR_J9JITServerSharedCache(TR_J9VMBase *fe)
uintptr_t
TR_J9JITServerSharedCache::rememberClass(J9Class *clazz, const AOTCacheClassChainRecord **classChainRecord, bool create)
{
TR_ASSERT_FATAL(classChainRecord || !create, "Must pass classChainRecord if creating class chain at JITServer");
TR::Compilation *comp = _compInfoPT->getCompilation();
TR_ASSERT_FATAL(classChainRecord || !create || !comp->isAOTCacheStore(), "Must pass classChainRecord if creating class chain at JITServer");
TR_ASSERT(_stream, "stream must be initialized by now");

uintptr_t clientClassChainOffset = TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET;
TR::Compilation *comp = _compInfoPT->getCompilation();
ClientSessionData *clientData = comp->getClientData();
bool needClassChainRecord = comp->isAOTCacheStore();
bool useServerOffsets = clientData->useServerOffsets(_stream) && needClassChainRecord;
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/env/VMJ9.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ class TR_J9VMBase : public TR_FrontEnd
virtual bool needsContiguousCodeAndDataCacheAllocation() { return false; }
virtual bool supportsJitMethodEntryAlignment() { return true; }
virtual bool canUseSymbolValidationManager() { return false; }
virtual bool canTrackAOTDependencies() { return false; }

/////
// Inlining optimization
Expand Down Expand Up @@ -1632,6 +1633,7 @@ class TR_J9SharedCacheVM : public TR_J9VM

// replacing calls to isAOT
virtual bool canUseSymbolValidationManager() { return true; }
virtual bool canTrackAOTDependencies() { return true; }
virtual bool supportsCodeCacheSnippets() { return false; }
virtual bool needClassAndMethodPointerRelocations() { return true; }
virtual bool inlinedAllocationsMustBeVerified() { return true; }
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/env/VMJ9Server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ class TR_J9SharedCacheServerVM: public TR_J9ServerVM

// replacing calls to isAOT
virtual bool canUseSymbolValidationManager() override { return true; }
virtual bool canTrackAOTDependencies() override { return true; }
virtual bool supportsCodeCacheSnippets() override { return false; }
virtual bool needClassAndMethodPointerRelocations() override { return true; }
virtual bool inlinedAllocationsMustBeVerified() override { return true; }
Expand Down
Loading

0 comments on commit ff43532

Please sign in to comment.