Skip to content

Commit 52513fa

Browse files
authored
Merge pull request #18948 from cjjdespres/new-deserializer
Implement a deserializer and shared cache interface that ignores the local SCC
2 parents 8464788 + 6086e20 commit 52513fa

File tree

10 files changed

+899
-1
lines changed

10 files changed

+899
-1
lines changed

runtime/compiler/control/CompilationThread.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,6 +2319,7 @@ bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, T
23192319
case compilationStreamVersionIncompatible:
23202320
case compilationStreamLostMessage:
23212321
case aotCacheDeserializationFailure:
2322+
case aotDeserializerReset:
23222323
#endif
23232324
case compilationInterrupted:
23242325
case compilationCodeReservationFailure:
@@ -11702,6 +11703,10 @@ TR::CompilationInfoPerThreadBase::processException(
1170211703
{
1170311704
// error code was already set in remoteCompile()
1170411705
}
11706+
catch (const J9::AOTDeserializerReset &e)
11707+
{
11708+
_methodBeingCompiled->_compErrCode = aotDeserializerReset;
11709+
}
1170511710
#endif /* defined(J9VM_OPT_JITSERVER) */
1170611711
catch (...)
1170711712
{

runtime/compiler/control/rossa.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ const char *compilationErrorNames[]={
212212
"compilationStreamVersionIncompatible", // compilationFirstJITServerFailure + 3 = 51
213213
"compilationStreamInterrupted", // compilationFirstJITServerFailure + 4 = 52
214214
"aotCacheDeserializationFailure", // compilationFirstJITServerFailure + 5 = 53
215+
"aotDeserializerReset", // compilationFirstJITServerFailure + 6 = 54
215216
#endif /* defined(J9VM_OPT_JITSERVER) */
216217
"compilationMaxError"
217218
};

runtime/compiler/control/rossa.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ typedef enum {
8282
compilationStreamVersionIncompatible = compilationFirstJITServerFailure + 3, // 51
8383
compilationStreamInterrupted = compilationFirstJITServerFailure + 4, // 52
8484
aotCacheDeserializationFailure = compilationFirstJITServerFailure + 5, // 53
85+
aotDeserializerReset = compilationFirstJITServerFailure + 6, // 54
8586
#endif /* defined(J9VM_OPT_JITSERVER) */
8687

8788
/* must be the last one */

runtime/compiler/env/ClassLoaderTable.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,20 @@ TR_PersistentClassLoaderTable::lookupClassLoaderAndChainAssociatedWithClassName(
382382
return { info->_loader, info->_chain };
383383
}
384384

385+
void *
386+
TR_PersistentClassLoaderTable::lookupClassLoaderAssociatedWithClassName(const uint8_t *data, size_t length) const
387+
{
388+
assertCurrentThreadCanRead();
389+
390+
NameKey key { data, length };
391+
size_t index;
392+
TR_ClassLoaderInfo *prev;
393+
TR_ClassLoaderInfo *info = lookup<Name>(_nameTable, index, prev, &key);
394+
if (!info)
395+
return NULL;
396+
return info->_loader;
397+
}
398+
385399
const J9UTF8 *
386400
TR_PersistentClassLoaderTable::lookupClassNameAssociatedWithClassLoader(void *loader) const
387401
{

runtime/compiler/env/ClassLoaderTable.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class TR_PersistentClassLoaderTable
4646
// in order to support AOT method serialization (and caching at JITServer) and deserialization.
4747
std::pair<void *, void *>// loader, chain
4848
lookupClassLoaderAndChainAssociatedWithClassName(const uint8_t *data, size_t length) const;
49+
void *lookupClassLoaderAssociatedWithClassName(const uint8_t *data, size_t length) const;
4950
const J9UTF8 *lookupClassNameAssociatedWithClassLoader(void *loader) const;
5051
#endif /* defined(J9VM_OPT_JITSERVER) */
5152
void removeClassLoader(J9VMThread *vmThread, void *loader);

runtime/compiler/env/J9SharedCache.cpp

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#if defined(J9VM_OPT_JITSERVER)
4646
#include "control/JITServerHelpers.hpp"
4747
#include "runtime/JITClientSession.hpp"
48+
#include "runtime/JITServerAOTDeserializer.hpp"
4849
#endif
4950

5051
#define LOG(logLevel, format, ...) \
@@ -148,7 +149,10 @@ TR_J9SharedCache::TR_J9SharedCache(TR_J9VMBase *fe)
148149
_numDigitsForCacheOffsets = 8;
149150

150151
#if defined(J9VM_OPT_JITSERVER)
151-
TR_ASSERT_FATAL(_sharedCacheConfig || _compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "Must have _sharedCacheConfig");
152+
TR_ASSERT_FATAL(_sharedCacheConfig || _compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER
153+
|| (_compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT
154+
&& _compInfo->getPersistentInfo()->getJITServerUseAOTCache()),
155+
"Must have _sharedCacheConfig");
152156
#else
153157
TR_ASSERT_FATAL(_sharedCacheConfig, "Must have _sharedCacheConfig");
154158
#endif
@@ -1647,4 +1651,108 @@ TR_J9JITServerSharedCache::storeSharedData(J9VMThread *vmThread, const char *key
16471651
return std::get<0>(_stream->read<const void *>());
16481652
}
16491653

1654+
TR_J9DeserializerSharedCache::TR_J9DeserializerSharedCache(TR_J9VMBase *fe, JITServerNoSCCAOTDeserializer *deserializer)
1655+
: TR_J9SharedCache(fe)
1656+
{
1657+
_deserializer = deserializer;
1658+
}
1659+
1660+
J9ROMClass *
1661+
TR_J9DeserializerSharedCache::romClassFromOffsetInSharedCache(uintptr_t offset)
1662+
{
1663+
TR::Compilation *comp = TR::compInfoPT->getCompilation();
1664+
bool wasReset = false;
1665+
auto romClass = _deserializer->romClassFromOffsetInSharedCache(offset, comp, wasReset);
1666+
if (wasReset)
1667+
comp->failCompilation<J9::AOTDeserializerReset>(
1668+
"Deserializer reset during relocation of method %s", comp->signature());
1669+
TR_ASSERT_FATAL(romClass, "ROM class for offset %zu could not be found",
1670+
offset,
1671+
JITServerNoSCCAOTDeserializer::offsetId(offset),
1672+
JITServerNoSCCAOTDeserializer::offsetType(offset));
1673+
return romClass;
1674+
}
1675+
1676+
void *
1677+
TR_J9DeserializerSharedCache::pointerFromOffsetInSharedCache(uintptr_t offset)
1678+
{
1679+
TR::Compilation *comp = TR::compInfoPT->getCompilation();
1680+
bool wasReset = false;
1681+
auto ptr = _deserializer->pointerFromOffsetInSharedCache(offset, comp, wasReset);
1682+
if (wasReset)
1683+
comp->failCompilation<J9::AOTDeserializerReset>(
1684+
"Deserializer reset during relocation of method %s", comp->signature());
1685+
TR_ASSERT_FATAL(ptr, "Pointer for offset %zu ID %zu type %u could not be found",
1686+
offset,
1687+
JITServerNoSCCAOTDeserializer::offsetId(offset),
1688+
JITServerNoSCCAOTDeserializer::offsetType(offset));
1689+
return ptr;
1690+
}
1691+
1692+
void *
1693+
TR_J9DeserializerSharedCache::lookupClassLoaderAssociatedWithClassChain(void *chainData)
1694+
{
1695+
// We return chainData directly because the only thing this function can be called on is the result of
1696+
// TR_J9DeserializerSharedCache::pointerFromOffsetInSharedCache(), and that will return a (J9ClassLoader *)
1697+
// directly when given a class loader offset.
1698+
return chainData;
1699+
}
1700+
1701+
bool
1702+
TR_J9DeserializerSharedCache::classMatchesCachedVersion(J9Class *clazz, UDATA *chainData)
1703+
{
1704+
// During deserialization, we find a matching J9Class for the first entry of the chainData, meaning that
1705+
// its ROM class chain matches what was recorded during compilation. This provides the same guarantees
1706+
// that TR_J9SharedCache::validateClassChain() does, which is what TR_J9SharedCache::validateClassChain()
1707+
// uses to verify that the given clazz matches chainData. Thus we only have to check that that cached J9Class
1708+
// is equal to the one we are trying to validate.
1709+
TR::Compilation *comp = TR::compInfoPT->getCompilation();
1710+
bool wasReset = false;
1711+
auto ramClass = _deserializer->classFromOffset(chainData[1], comp, wasReset);
1712+
if (wasReset)
1713+
comp->failCompilation<J9::AOTDeserializerReset>(
1714+
"Deserializer reset during relocation of method %s", comp->signature());
1715+
TR_ASSERT_FATAL(ramClass, "RAM class for offset %zu ID %zu type %zu could not be found",
1716+
chainData[1],
1717+
JITServerNoSCCAOTDeserializer::offsetId(chainData[1]),
1718+
JITServerNoSCCAOTDeserializer::offsetType(chainData[1]));
1719+
return ramClass == clazz;
1720+
}
1721+
1722+
TR_OpaqueClassBlock *
1723+
TR_J9DeserializerSharedCache::lookupClassFromChainAndLoader(uintptr_t *chainData, void *classLoader)
1724+
{
1725+
// The base TR_J9SharedCache::lookupClassFromChainAndLoader(), when given a class chain and class loader, will look in the loader
1726+
// a J9Class correspoding to the first class in the chain. If one could be found, it then verifies that the class matches the cached version.
1727+
// We do not need to perform that checking here, because during deserialization we will have already resolved the first class in the chain to
1728+
// a J9Class and verified that it matches. Thus we can simply return that cached first J9Class.
1729+
TR::Compilation *comp = TR::compInfoPT->getCompilation();
1730+
bool wasReset = false;
1731+
auto clazz = _deserializer->classFromOffset(chainData[1], comp, wasReset);
1732+
if (wasReset)
1733+
comp->failCompilation<J9::AOTDeserializerReset>(
1734+
"Deserializer reset during relocation of method %s", comp->signature());
1735+
TR_ASSERT_FATAL(clazz, "Class for offset %zu could not be found",
1736+
chainData[1],
1737+
JITServerNoSCCAOTDeserializer::offsetId(chainData[1]),
1738+
JITServerNoSCCAOTDeserializer::offsetType(chainData[1]));
1739+
return reinterpret_cast<TR_OpaqueClassBlock *>(clazz);
1740+
}
1741+
1742+
J9ROMMethod *
1743+
TR_J9DeserializerSharedCache::romMethodFromOffsetInSharedCache(uintptr_t offset)
1744+
{
1745+
TR::Compilation *comp = TR::compInfoPT->getCompilation();
1746+
bool wasReset = false;
1747+
auto romMethod = _deserializer->romMethodFromOffsetInSharedCache(offset, comp, wasReset);
1748+
if (wasReset)
1749+
comp->failCompilation<J9::AOTDeserializerReset>(
1750+
"Deserializer reset during relocation of method %s", comp->signature());
1751+
TR_ASSERT_FATAL(romMethod, "ROM method for offset %zu ID %zu type %zu could not be found",
1752+
offset,
1753+
JITServerNoSCCAOTDeserializer::offsetId(offset),
1754+
JITServerNoSCCAOTDeserializer::offsetType(offset));
1755+
return romMethod;
1756+
}
1757+
16501758
#endif

runtime/compiler/env/J9SharedCache.hpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace TR { class CompilationInfo; }
3939
#if defined(J9VM_OPT_JITSERVER)
4040
namespace TR { class CompilationInfoPerThread; }
4141
namespace JITServer { class ServerStream; }
42+
class JITServerNoSCCAOTDeserializer;
4243
#endif
4344

4445
struct J9SharedClassConfig;
@@ -106,6 +107,10 @@ class TR_J9SharedCache : public TR_SharedCache
106107
* \brief Converts a shared cache offset, calculated from the end of the SCC, into the
107108
* metadata section of the SCC into a pointer.
108109
*
110+
* The pointer returned from this function should be considered opaque by the consumers of this API,
111+
* as some subclasses (like TR_J9DeserializerSharedCache) might not return, say, an actual (uintptr *) class chain
112+
* given an offset that is ostensibly to such a chain.
113+
*
109114
* \param[in] offset The offset to convert.
110115
* \return A pointer. Raises a fatal assertion before returning NULL if the offset is invalid.
111116
*/
@@ -689,6 +694,80 @@ class TR_J9JITServerSharedCache : public TR_J9SharedCache
689694
JITServer::ServerStream *_stream;
690695
TR::CompilationInfoPerThread *_compInfoPT;
691696
};
697+
698+
/**
699+
* \class TR_J9DeserializerSharedCache
700+
* \brief Class used by a JITServer client for querying the deserializer during AOT cache loads
701+
*
702+
* This class is an extension of the TR_J9SharedCache class which overrides a number
703+
* of TR_J9SharedCache's APIs. TR_J9DeserializerSharedCache is used by a client of a JITServer
704+
* when relocating a method received from the JITServer's AOT cache. It ignores any local shared cache
705+
* that may exist, and instead will query the JITServerNoSCCAOTDeserializer during relocation, fetching the
706+
* deserializer's cached information.
707+
*
708+
* The offsets used by this class are different from those of the other TR_J9SharedCache classes and their derivatives;
709+
* they are the idAndType of the AOTSerializationRecord records maintained by a JITServer's AOT cache, and don't
710+
* correspond to any storage location of the entities that the offsets refer to.
711+
*/
712+
class TR_J9DeserializerSharedCache : public TR_J9SharedCache
713+
{
714+
public:
715+
TR_ALLOC(TR_Memory::SharedCache)
716+
717+
TR_J9DeserializerSharedCache(TR_J9VMBase *fe, JITServerNoSCCAOTDeserializer *deserializer);
718+
719+
virtual void *pointerFromOffsetInSharedCache(uintptr_t offset) override;
720+
virtual void *lookupClassLoaderAssociatedWithClassChain(void *chainData) override;
721+
virtual J9ROMClass *romClassFromOffsetInSharedCache(uintptr_t offset) override;
722+
virtual J9ROMMethod *romMethodFromOffsetInSharedCache(uintptr_t offset) override;
723+
virtual bool classMatchesCachedVersion(J9Class *clazz, UDATA *chainData=NULL) override;
724+
virtual TR_OpaqueClassBlock *lookupClassFromChainAndLoader(uintptr_t *chainData, void *classLoader) override;
725+
726+
virtual bool isHint(TR_ResolvedMethod *, TR_SharedCacheHint, uint16_t *dataField = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
727+
virtual bool isHint(J9Method *, TR_SharedCacheHint, uint16_t *dataField = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
728+
virtual uint16_t getAllEnabledHints(J9Method *method) override { TR_ASSERT_FATAL(false, "called"); return 0; }
729+
virtual void addHint(J9Method *, TR_SharedCacheHint) override { TR_ASSERT_FATAL(false, "called"); }
730+
virtual void addHint(TR_ResolvedMethod *, TR_SharedCacheHint) override { TR_ASSERT_FATAL(false, "called"); }
731+
virtual bool isMostlyFull() override { TR_ASSERT_FATAL(false, "called"); return false; }
732+
733+
virtual uintptr_t offsetInSharedCacheFromPointer(void *ptr) override { TR_ASSERT_FATAL(false, "called"); return 0; }
734+
virtual uintptr_t offsetInSharedCacheFromROMClass(J9ROMClass *romClass) override { TR_ASSERT_FATAL(false, "called"); return 0; }
735+
virtual uintptr_t offsetInSharedCacheFromROMMethod(J9ROMMethod *romMethod) override { TR_ASSERT_FATAL(false, "called"); return 0; }
736+
virtual void *ptrToROMClassesSectionFromOffsetInSharedCache(uintptr_t offset) override { TR_ASSERT_FATAL(false, "called"); return NULL; }
737+
virtual uintptr_t offsetInSharedCacheFromPtrToROMClassesSection(void *ptr) override { TR_ASSERT_FATAL(false, "called"); return 0; }
738+
739+
virtual void persistIprofileInfo(TR::ResolvedMethodSymbol *, TR::Compilation *comp) override { TR_ASSERT_FATAL(false, "called"); }
740+
virtual void persistIprofileInfo(TR::ResolvedMethodSymbol *, TR_ResolvedMethod*, TR::Compilation *comp) override { TR_ASSERT_FATAL(false, "called"); }
741+
742+
virtual bool canRememberClass(TR_OpaqueClassBlock *classPtr) override { TR_ASSERT_FATAL(false, "called"); return false; }
743+
virtual uintptr_t rememberClass(TR_OpaqueClassBlock *classPtr,
744+
const AOTCacheClassChainRecord **classChainRecord = NULL) override
745+
{ TR_ASSERT_FATAL(false, "called"); return TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET; }
746+
747+
virtual uintptr_t rememberClass(J9Class *clazz, const AOTCacheClassChainRecord **classChainRecord = NULL,
748+
bool create = true) override
749+
{ TR_ASSERT_FATAL(false, "called"); return TR_SharedCache::INVALID_CLASS_CHAIN_OFFSET; }
750+
751+
virtual UDATA rememberDebugCounterName(const char *name) override { TR_ASSERT_FATAL(false, "called"); return 0; }
752+
virtual const char *getDebugCounterName(UDATA offset) override { TR_ASSERT_FATAL(false, "called"); return NULL; }
753+
754+
virtual bool isPointerInSharedCache(void *ptr, uintptr_t *cacheOffset = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
755+
virtual bool isOffsetInSharedCache(uintptr_t encoded_offset, void *ptr = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
756+
virtual bool isROMClassInSharedCache(J9ROMClass *romClass, uintptr_t *cacheOffset = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
757+
virtual bool isROMClassOffsetInSharedCache(uintptr_t offset, J9ROMClass **romClassPtr = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
758+
virtual bool isROMMethodInSharedCache(J9ROMMethod *romMethod, uintptr_t *cacheOffset = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
759+
virtual bool isROMMethodOffsetInSharedCache(uintptr_t offset, J9ROMMethod **romMethodPtr = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
760+
virtual bool isPtrToROMClassesSectionInSharedCache(void *ptr, uintptr_t *cacheOffset = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
761+
virtual bool isOffsetOfPtrToROMClassesSectionInSharedCache(uintptr_t offset, void **ptr = NULL) override { TR_ASSERT_FATAL(false, "called"); return false; }
762+
virtual uintptr_t getClassChainOffsetIdentifyingLoader(TR_OpaqueClassBlock *clazz, uintptr_t **classChain = NULL) override { TR_ASSERT_FATAL(false, "called"); return 0; }
763+
virtual const void *storeSharedData(J9VMThread *vmThread, const char *key, const J9SharedDataDescriptor *descriptor) override { TR_ASSERT_FATAL(false, "called"); return NULL; }
764+
765+
virtual J9SharedClassCacheDescriptor *getCacheDescriptorList() override { TR_ASSERT_FATAL(false, "called"); return NULL; }
766+
767+
private:
768+
JITServerNoSCCAOTDeserializer *_deserializer;
769+
};
770+
692771
#endif /* defined(J9VM_OPT_JITSERVER) */
693772

694773
#endif

runtime/compiler/exceptions/AOTFailure.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,16 @@ class AOTCacheDeserializationFailure : public virtual RuntimeFailure
148148
{
149149
virtual const char *what() const throw() { return "AOT cache deserialization failure"; }
150150
};
151+
152+
/**
153+
* JITServer AOT Deserializer Reset exception type.
154+
*
155+
* Thrown when a concurrent JITServer AOT deserializer reset has been detected.
156+
*/
157+
class AOTDeserializerReset : public virtual RuntimeFailure
158+
{
159+
virtual const char *what() const throw() { return "AOT deserializer reset"; }
160+
};
151161
#endif /* defined(J9VM_OPT_JITSERVER) */
152162
}
153163

0 commit comments

Comments
 (0)