Skip to content

Commit

Permalink
Merge pull request #19847 from cjjdespres/send-cached-hash
Browse files Browse the repository at this point in the history
Send cached J9ROMClass hashes to JITServer
  • Loading branch information
mpirvu authored Jul 18, 2024
2 parents c70cb5d + 3a50aeb commit c0c18a9
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 41 deletions.
2 changes: 1 addition & 1 deletion runtime/compiler/control/JITServerCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -905,7 +905,7 @@ TR::CompilationInfoPerThreadRemote::processEntry(TR_MethodToBeCompiled &entry, J
// If the client sent us the desired information in the compilation request, use that.
if(!(std::get<0>(classInfoTuple).empty()))
{
romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), clientSession->persistentMemory());
romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), clientSession->persistentMemory());
}
else
{
Expand Down
25 changes: 17 additions & 8 deletions runtime/compiler/control/JITServerHelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1052,12 +1052,17 @@ JITServerHelpers::packRemoteROMClassInfo(J9Class *clazz, J9VMThread *vmThread, T
}

std::string packedROMClassStr;
std::string romClassHash;
if (serializeClass)
{
TR::StackMemoryRegion stackMemoryRegion(*trMemory);
size_t hashedSize;
J9ROMClass *packedROMClass = packROMClass(clazz->romClass, trMemory, fe, hashedSize);
packedROMClassStr = std::string((const char *)packedROMClass, packedROMClass->romSize);

auto deserializer = fe->_compInfo->getJITServerAOTDeserializer();
if (deserializer)
romClassHash = deserializer->findGeneratedClassHash((J9ClassLoader *)classLoader, clazz, fe, vmThread);
}

int32_t arrayElementSize = vmThread->javaVM->internalVMFunctions->arrayElementSize((J9ArrayClass*)clazz);
Expand All @@ -1076,15 +1081,19 @@ JITServerHelpers::packRemoteROMClassInfo(J9Class *clazz, J9VMThread *vmThread, T
TR::Compiler->cls.getITable((TR_OpaqueClassBlock *)clazz), methodTracingInfo,
classHasFinalFields, classDepthAndFlags, classInitialized, byteOffsetToLockword, leafComponentClass,
classLoader, hostClass, componentClass, arrayClass, totalInstanceSize, clazz->romClass,
cp, classFlags, classChainOffsetIdentifyingLoader, origROMMethods, classNameIdentifyingLoader, arrayElementSize, defaultValueSlotAddress
cp, classFlags, classChainOffsetIdentifyingLoader, origROMMethods, classNameIdentifyingLoader, arrayElementSize,
defaultValueSlotAddress, romClassHash
);
}

J9ROMClass *
JITServerHelpers::romClassFromString(const std::string &romClassStr, TR_PersistentMemory *persistentMemory)
JITServerHelpers::romClassFromString(const std::string &romClassStr, const std::string &romClassHashStr, TR_PersistentMemory *persistentMemory)
{
if (auto cache = TR::CompilationInfo::get()->getJITServerSharedROMClassCache())
return cache->getOrCreate((const J9ROMClass *)romClassStr.data());
{
auto hash = romClassHashStr.empty() ? NULL : (const JITServerROMClassHash *)romClassHashStr.data();
return cache->getOrCreate((const J9ROMClass *)romClassStr.data(), hash);
}

auto romClass = (J9ROMClass *)persistentMemory->allocatePersistentMemory(romClassStr.size(), TR_Memory::ROMClass);
if (!romClass)
Expand All @@ -1100,7 +1109,7 @@ JITServerHelpers::getRemoteROMClass(J9Class *clazz, JITServer::ServerStream *str
stream->write(JITServer::MessageType::ResolvedMethod_getRemoteROMClassAndMethods, clazz);
auto recv = stream->read<ClassInfoTuple>();
classInfoTuple = std::get<0>(recv);
return romClassFromString(std::get<0>(classInfoTuple), persistentMemory);
return romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), persistentMemory);
}

// Return true if able to get data from cache, return false otherwise.
Expand Down Expand Up @@ -1129,7 +1138,7 @@ JITServerHelpers::getAndCacheRAMClassInfo(J9Class *clazz, ClientSessionData *cli
auto it = clientSessionData->getROMClassMap().find(clazz);
if (it == clientSessionData->getROMClassMap().end())
{
auto romClass = romClassFromString(std::get<0>(classInfoTuple), clientSessionData->persistentMemory());
auto romClass = romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), clientSessionData->persistentMemory());
auto &classInfoStruct = JITServerHelpers::cacheRemoteROMClass(clientSessionData, clazz, romClass, classInfoTuple);
JITServerHelpers::getROMClassData(classInfoStruct, dataType, data);
}
Expand Down Expand Up @@ -1168,7 +1177,7 @@ JITServerHelpers::getAndCacheRAMClassInfo(J9Class *clazz, ClientSessionData *cli
auto it = clientSessionData->getROMClassMap().find(clazz);
if (it == clientSessionData->getROMClassMap().end())
{
auto romClass = romClassFromString(std::get<0>(classInfoTuple), clientSessionData->persistentMemory());
auto romClass = romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), clientSessionData->persistentMemory());
auto &classInfoStruct = JITServerHelpers::cacheRemoteROMClass(clientSessionData, clazz, romClass, classInfoTuple);
JITServerHelpers::getROMClassData(classInfoStruct, dataType1, data1);
JITServerHelpers::getROMClassData(classInfoStruct, dataType2, data2);
Expand Down Expand Up @@ -1408,7 +1417,7 @@ JITServerHelpers::getRemoteClassDepthAndFlagsWhenROMClassNotCached(J9Class *claz
auto it = clientSessionData->getROMClassMap().find(clazz);
if (it == clientSessionData->getROMClassMap().end())
{
auto romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), clientSessionData->persistentMemory());
auto romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), clientSessionData->persistentMemory());
auto &classInfoStruct = JITServerHelpers::cacheRemoteROMClass(clientSessionData, clazz, romClass, classInfoTuple);
return classInfoStruct._classDepthAndFlags;
}
Expand Down Expand Up @@ -1467,7 +1476,7 @@ JITServerHelpers::cacheRemoteROMClassBatch(ClientSessionData *clientData, const

for (size_t i = 0; i < ramClasses.size(); ++i)
{
auto romClass = romClassFromString(std::get<0>(classInfoTuples[i]), clientData->persistentMemory());
auto romClass = romClassFromString(std::get<0>(classInfoTuples[i]), std::get<25>(classInfoTuples[i]), clientData->persistentMemory());
cacheRemoteROMClassOrFreeIt(clientData, ramClasses[i], romClass, classInfoTuples[i]);
}
}
Expand Down
5 changes: 3 additions & 2 deletions runtime/compiler/control/JITServerHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ class JITServerHelpers
std::vector<J9ROMMethod *>, // 21: _origROMMethods
std::string, // 22: _classNameIdentifyingLoader
int32_t, // 23: _arrayElementSize
j9object_t * // 24: _defaultValueSlotAddress
j9object_t *, // 24: _defaultValueSlotAddress
std::string // 25: optional hash of packedROMClass
>;

// Packs a ROMClass to be transferred to the server.
Expand All @@ -107,7 +108,7 @@ class JITServerHelpers
static J9ROMClass *getRemoteROMClassIfCached(ClientSessionData *clientSessionData, J9Class *clazz);
static J9ROMClass *getRemoteROMClass(J9Class *clazz, JITServer::ServerStream *stream,
TR_PersistentMemory *persistentMemory, ClassInfoTuple &classInfoTuple);
static J9ROMClass *romClassFromString(const std::string &romClassStr, TR_PersistentMemory *persistentMemory);
static J9ROMClass *romClassFromString(const std::string &romClassStr, const std::string &romClassHashStr, TR_PersistentMemory *persistentMemory);
static bool getAndCacheRAMClassInfo(J9Class *clazz, ClientSessionData *clientSessionData,
JITServer::ServerStream *stream, ClassInfoDataType dataType, void *data);
static bool getAndCacheRAMClassInfo(J9Class *clazz, ClientSessionData *clientSessionData,
Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/net/CommunicationStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ class CommunicationStream
// likely to lose an increment when merging/rebasing/etc.
//
static const uint8_t MAJOR_NUMBER = 1;
static const uint16_t MINOR_NUMBER = 64; // ID: EbRgDu72oycJkc90HtnO
static const uint16_t MINOR_NUMBER = 65; // ID: YxVkiLqD7B1LhYMv58y8
static const uint8_t PATCH_NUMBER = 0;
static uint32_t CONFIGURATION_FLAGS;

Expand Down
64 changes: 38 additions & 26 deletions runtime/compiler/runtime/JITServerAOTCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -814,48 +814,55 @@ JITServerAOTCache::getClassRecord(const AOTCacheClassLoaderRecord *classLoaderRe
auto cache = compInfo->getJITServerSharedROMClassCache();

JITServerROMClassHash hash;
size_t size = 0;
//NOTE: Assuming array classes are not runtime-generated
size_t prefixLength = numDimensions ? 0 : JITServerHelpers::getGeneratedClassNamePrefixLength(romClass);
if (prefixLength)

if (cache)
{
hash = cache->getHash(romClass);
}
else
{
// The class is runtime-generated. Re-pack the romClass to compute its deterministic hash.
J9ROMClass *packedROMClass;
if (scratchSegmentProvider)
const J9ROMClass *packedROMClass;
if (prefixLength)
{
// Called from outside of a compilation. Use supplied scratchSegmentProvider for scratch memory allocations.
size_t segmentSize = scratchSegmentProvider->getPreferredSegmentSize();
if (!segmentSize)
segmentSize = 1 << 24/*16 MB*/;
TR::RawAllocator rawAllocator(compInfo->getJITConfig()->javaVM);
J9::SystemSegmentProvider segmentProvider(1 << 16/*64 KB*/, segmentSize, TR::Options::getScratchSpaceLimit(),
*scratchSegmentProvider, rawAllocator);
TR::Region region(segmentProvider, rawAllocator);
TR_Memory trMemory(*compInfo->persistentMemory(), region);
packedROMClass = JITServerHelpers::packROMClass(romClass, &trMemory, NULL, size, 0, prefixLength);
// The class is runtime-generated. Re-pack the romClass to compute its deterministic hash.
if (scratchSegmentProvider)
{
// Called from outside of a compilation. Use supplied scratchSegmentProvider for scratch memory allocations.
size_t segmentSize = scratchSegmentProvider->getPreferredSegmentSize();
if (!segmentSize)
segmentSize = 1 << 24/*16 MB*/;
TR::RawAllocator rawAllocator(compInfo->getJITConfig()->javaVM);
J9::SystemSegmentProvider segmentProvider(1 << 16/*64 KB*/, segmentSize, TR::Options::getScratchSpaceLimit(),
*scratchSegmentProvider, rawAllocator);
TR::Region region(segmentProvider, rawAllocator);
TR_Memory trMemory(*compInfo->persistentMemory(), region);
size_t packedSize = 0;
packedROMClass = JITServerHelpers::packROMClass(romClass, &trMemory, NULL, packedSize, 0, prefixLength);
}
else
{
TR_ASSERT(TR::comp(), "Must be inside a compilation");
TR_Memory *trMemory = TR::comp()->trMemory();
TR::StackMemoryRegion region(*trMemory);
size_t packedSize = 0;
packedROMClass = JITServerHelpers::packROMClass(romClass, trMemory, NULL, packedSize, 0, prefixLength);
}
}
else
{
TR_ASSERT(TR::comp(), "Must be inside a compilation");
TR_Memory *trMemory = TR::comp()->trMemory();
TR::StackMemoryRegion region(*trMemory);
packedROMClass = JITServerHelpers::packROMClass(romClass, trMemory, NULL, size, 0, prefixLength);
packedROMClass = romClass;
}

hash = JITServerROMClassHash(packedROMClass);
}
else
{
hash = cache ? cache->getHash(romClass) : JITServerROMClassHash(romClass);
size = romClass->romSize;
}

if (numDimensions)
{
TR_ASSERT(baseComponent, "Invalid arguments");
JITServerROMClassHash baseHash = cache ? cache->getHash(baseComponent) : JITServerROMClassHash(baseComponent);
hash = JITServerROMClassHash(hash, baseHash, numDimensions);
size = romClass->romSize;
}

OMR::CriticalSection cs(_classMonitor);
Expand All @@ -867,7 +874,12 @@ JITServerAOTCache::getClassRecord(const AOTCacheClassLoaderRecord *classLoaderRe
if (!JITServerAOTCacheMap::cacheHasSpace())
return NULL;

auto record = AOTCacheClassRecord::create(_nextClassId, classLoaderRecord, hash, size,
// The romSize of the packed romClass received from the client is used as the size in the
// AOTCacheClassRecord. This will be slightly larger than the deterministic packed size if the romClass
// is runtime-generated, but this won't matter as long as we are consistent in what size is used.
// This also doesn't currently matter at the client, as runtime-generated classes are looked up by hash
// during deserialization, and the size in their class record is never examined.
auto record = AOTCacheClassRecord::create(_nextClassId, classLoaderRecord, hash, romClass->romSize,
prefixLength != 0, romClass, baseComponent, numDimensions);
addToMap(_classMap, _classHead, _classTail, it, getRecordKey(record), record);
++_nextClassId;
Expand Down
21 changes: 21 additions & 0 deletions runtime/compiler/runtime/JITServerAOTDeserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,27 @@ JITServerAOTDeserializer::findGeneratedClass(J9ClassLoader *loader, const uint8_
return (h_it != n_it->second._classHashMap.end()) ? h_it->second : NULL;
}

std::string
JITServerAOTDeserializer::findGeneratedClassHash(J9ClassLoader *loader, J9Class *ramClass, TR_J9VM *fe, J9VMThread *vmThread)
{
assertSharedVmAccess(vmThread);

size_t namePrefixLength = JITServerHelpers::getGeneratedClassNamePrefixLength(ramClass->romClass);
if (namePrefixLength == 0)
return std::string();
const uint8_t *name = J9UTF8_DATA(J9ROMCLASS_CLASSNAME(ramClass->romClass));

OMR::CriticalSection cs(_generatedClassesMonitor);

auto n_it = _generatedClasses.find({ loader, StringKey(name, namePrefixLength) });
if (n_it == _generatedClasses.end())
return std::string();

auto h_it = n_it->second._classPtrMap.find(ramClass);
if (h_it == n_it->second._classPtrMap.end())
return std::string();
return std::string((const char *)&h_it->second, sizeof(h_it->second));
}

void
JITServerAOTDeserializer::printStats(FILE *f) const
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/runtime/JITServerAOTDeserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class JITServerAOTDeserializer
// Find a runtime-generated class for given class loader, deterministic class name prefix, and ROMClass hash
J9Class *findGeneratedClass(J9ClassLoader *loader, const uint8_t *namePrefix, size_t namePrefixLength,
const JITServerROMClassHash &hash, J9VMThread *vmThread);
// Find the stored hash for ramClass loaded by loader if it exists in the generated classes map.
std::string findGeneratedClassHash(J9ClassLoader *loader, J9Class *ramClass, TR_J9VM *fe, J9VMThread *vmThread);
// Get the RAMClass for a previously deserialized ROMClass offset for a runtime-generated class
virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, TR::Compilation *comp) = 0;

Expand Down
4 changes: 2 additions & 2 deletions runtime/compiler/runtime/JITServerSharedROMClassCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,9 @@ JITServerSharedROMClassCache::shutdown(bool lastClient)


J9ROMClass *
JITServerSharedROMClassCache::getOrCreate(const J9ROMClass *packedROMClass)
JITServerSharedROMClassCache::getOrCreate(const J9ROMClass *packedROMClass, const JITServerROMClassHash *packedROMClassHash)
{
JITServerROMClassHash hash(packedROMClass);
JITServerROMClassHash hash = packedROMClassHash ? *packedROMClassHash : JITServerROMClassHash(packedROMClass);
return getPartition(hash).getOrCreate(packedROMClass, hash);
}

Expand Down
4 changes: 3 additions & 1 deletion runtime/compiler/runtime/JITServerSharedROMClassCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class JITServerSharedROMClassCache
// Releases memory used by the cache. Must be called when the last client session is destroyed.
void shutdown(bool lastClient = true);

J9ROMClass *getOrCreate(const J9ROMClass *packedROMClass);
// Get an existing cache entry for packedROMClass or create one. The packedROMClassHash may be NULL; if not,
// it will be the cached deterministic hash of packedROMClass received from the client.
J9ROMClass *getOrCreate(const J9ROMClass *packedROMClass, const JITServerROMClassHash *packedROMClassHash);
void release(J9ROMClass *romClass);

// Get precomputed hash of a shared ROMClass
Expand Down

0 comments on commit c0c18a9

Please sign in to comment.