diff --git a/runtime/compiler/control/JITClientCompilationThread.cpp b/runtime/compiler/control/JITClientCompilationThread.cpp index f95f3b1cdb8..9139af8ca42 100644 --- a/runtime/compiler/control/JITClientCompilationThread.cpp +++ b/runtime/compiler/control/JITClientCompilationThread.cpp @@ -3031,13 +3031,14 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes if (auto deserializer = compInfo->getJITServerAOTDeserializer()) { bool wasReset = false; - deserializer->cacheRecords((const uint8_t *)recordsStr.data(), recordsStr.size(), comp, + auto context = DeserializerContext(comp); + deserializer->cacheRecords((const uint8_t *)recordsStr.data(), recordsStr.size(), context, /*ignoreFailures=*/true, wasReset); if (!wasReset) { for (uintptr_t id : classIds) { - J9Class *ramClass = deserializer->getRAMClass(id, comp, wasReset); + J9Class *ramClass = deserializer->getRAMClass(id, context, wasReset); if (wasReset) { ramClasses.clear(); @@ -3446,7 +3447,8 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod // 2. Accesses the JITServer AOT deserializer in any way. // That moment is currently right here, when we get the new known IDs that are cached in the deserializer. compInfoPT->getJ9VM()->clearDeserializerWasReset(); - std::vector newKnownIds = deserializer ? deserializer->getNewKnownIds(compiler) : std::vector(); + auto context = DeserializerContext(compiler); + std::vector newKnownIds = deserializer ? deserializer->getNewKnownIds(context) : std::vector(); // TODO: make this a synchronized region to avoid bad_alloc exceptions compInfo->getSequencingMonitor()->enter(); @@ -3564,7 +3566,8 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod auto method = SerializedAOTMethod::get(methodStr); bool usesSVM = false; - if (deserializer->deserialize(method, records, compiler, usesSVM)) + auto context = DeserializerContext(compiler); + if (deserializer->deserialize(method, records, context, usesSVM)) { compiler->setDeserializedAOTMethodStore(true); compiler->setDeserializedAOTMethod(true); @@ -3598,7 +3601,8 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod auto method = SerializedAOTMethod::get(methodStr); bool usesSVM = false; - if (deserializer->deserialize(method, records, compiler, usesSVM)) + auto context = DeserializerContext(compiler); + if (deserializer->deserialize(method, records, context, usesSVM)) { compiler->setDeserializedAOTMethod(true); compiler->setDeserializedAOTMethodUsingSVM(usesSVM); diff --git a/runtime/compiler/env/J9SharedCache.cpp b/runtime/compiler/env/J9SharedCache.cpp index b65939cdcab..6bd7fcd2018 100644 --- a/runtime/compiler/env/J9SharedCache.cpp +++ b/runtime/compiler/env/J9SharedCache.cpp @@ -1428,7 +1428,8 @@ TR_J9SharedCache::lookupClassFromChainAndLoader(uintptr_t *chainData, void *clas if (!clazz && comp->isDeserializedAOTMethod()) { auto deserializer = TR::CompilationInfo::get()->getJITServerAOTDeserializer(); - clazz = deserializer->getGeneratedClass((J9ClassLoader *)classLoader, romClassOffset, comp); + auto context = DeserializerContext(comp); + clazz = deserializer->getGeneratedClass((J9ClassLoader *)classLoader, romClassOffset, context); } #endif /* defined(J9VM_OPT_JITSERVER) */ @@ -1870,7 +1871,8 @@ TR_J9DeserializerSharedCache::romClassFromOffsetInSharedCache(uintptr_t offset) { TR::Compilation *comp = _compInfoPT->getCompilation(); bool wasReset = false; - auto romClass = _deserializer->romClassFromOffsetInSharedCache(offset, comp, wasReset); + auto context = DeserializerContext(comp); + auto romClass = _deserializer->romClassFromOffsetInSharedCache(offset, context, wasReset); if (wasReset) comp->failCompilation( "Deserializer reset during relocation of method %s", comp->signature()); @@ -1886,7 +1888,8 @@ TR_J9DeserializerSharedCache::pointerFromOffsetInSharedCache(uintptr_t offset) { TR::Compilation *comp = _compInfoPT->getCompilation(); bool wasReset = false; - auto ptr = _deserializer->pointerFromOffsetInSharedCache(offset, comp, wasReset); + auto context = DeserializerContext(comp); + auto ptr = _deserializer->pointerFromOffsetInSharedCache(offset, context, wasReset); if (wasReset) comp->failCompilation( "Deserializer reset during relocation of method %s", comp->signature()); @@ -1916,7 +1919,8 @@ TR_J9DeserializerSharedCache::classMatchesCachedVersion(J9Class *clazz, UDATA *c // is equal to the one we are trying to validate. TR::Compilation *comp = _compInfoPT->getCompilation(); bool wasReset = false; - auto ramClass = _deserializer->classFromOffset(chainData[1], comp, wasReset); + auto context = DeserializerContext(comp); + auto ramClass = _deserializer->classFromOffset(chainData[1], context, wasReset); if (wasReset) comp->failCompilation( "Deserializer reset during relocation of method %s", comp->signature()); @@ -1935,7 +1939,8 @@ TR_J9DeserializerSharedCache::lookupClassFromChainAndLoader(uintptr_t *chainData // We do not need to perform that checking here, because during deserialization we will have already resolved the first class in the chain to // a J9Class and verified that it matches. Thus we can simply return that cached first J9Class. bool wasReset = false; - auto clazz = _deserializer->classFromOffset(chainData[1], comp, wasReset); + auto context = DeserializerContext(comp); + auto clazz = _deserializer->classFromOffset(chainData[1], context, wasReset); if (wasReset) comp->failCompilation( "Deserializer reset during relocation of method %s", comp->signature()); @@ -1951,7 +1956,8 @@ TR_J9DeserializerSharedCache::romMethodFromOffsetInSharedCache(uintptr_t offset) { TR::Compilation *comp = _compInfoPT->getCompilation(); bool wasReset = false; - auto romMethod = _deserializer->romMethodFromOffsetInSharedCache(offset, comp, wasReset); + auto context = DeserializerContext(comp); + auto romMethod = _deserializer->romMethodFromOffsetInSharedCache(offset, context, wasReset); if (wasReset) comp->failCompilation( "Deserializer reset during relocation of method %s", comp->signature()); diff --git a/runtime/compiler/runtime/JITServerAOTDeserializer.cpp b/runtime/compiler/runtime/JITServerAOTDeserializer.cpp index 5394713b292..31279e61349 100644 --- a/runtime/compiler/runtime/JITServerAOTDeserializer.cpp +++ b/runtime/compiler/runtime/JITServerAOTDeserializer.cpp @@ -108,14 +108,14 @@ JITServerAOTDeserializer::deserializerWasReset(TR_J9VMBase *vm, bool &wasReset) bool JITServerAOTDeserializer::deserializationFailure(const SerializedAOTMethod *method, - TR::Compilation *comp, bool wasReset) + const DeserializerContext& context, bool wasReset) { ++_numDeserializationFailures; if (TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "ERROR: Failed to deserialize AOT method %s%s", - comp->signature(), wasReset ? " due to concurrent deserializer reset" : "" + method->signature(), wasReset ? " due to concurrent deserializer reset" : "" ); return false; } @@ -153,22 +153,22 @@ JITServerAOTDeserializer::reset(TR::CompilationInfoPerThread *compInfoPT) * @brief Add the given IDs to the list of _newKnownIds that will be sent to the server */ void -JITServerAOTDeserializer::addNewKnownIds(const Vector &newIds, TR::Compilation *comp) +JITServerAOTDeserializer::addNewKnownIds(const Vector &newIds, const DeserializerContext& context) { OMR::CriticalSection cs(_newKnownIdsMonitor); // Check again that a reset operation has not started. bool wasReset = false; - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return; _newKnownIds.insert(newIds.begin(), newIds.end()); } std::vector -JITServerAOTDeserializer::getNewKnownIds(TR::Compilation *comp) +JITServerAOTDeserializer::getNewKnownIds(const DeserializerContext& context) { OMR::CriticalSection cs(_newKnownIdsMonitor); bool wasReset = false; - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return std::vector(); std::vector result(_newKnownIds.begin(), _newKnownIds.end()); @@ -198,16 +198,16 @@ assertSharedVmAccess(J9VMThread *vmThread) * * @param records The serialization records in packed format (just a stream of bytes) * @param recordsSize The size of all the serialization records received - * @param comp Compilation object + * @param context DeserializerHelper object * @param ignoreFailures Do not stop at the first encountered failure * @param wasReset OUT. Boolean flag indicating that we must abort the entire deserialization process * @return false if deserializer was reset or if we encountered some failures during caching */ bool -JITServerAOTDeserializer::cacheRecords(const uint8_t *records, size_t recordsSize, TR::Compilation *comp, +JITServerAOTDeserializer::cacheRecords(const uint8_t *records, size_t recordsSize, const DeserializerContext& context, bool ignoreFailures, bool &wasReset) { - TR::StackMemoryRegion region(*comp->trMemory()); + TR::StackMemoryRegion region(*context._trMemory); Vector newIds(region); bool success = true; @@ -219,7 +219,7 @@ JITServerAOTDeserializer::cacheRecords(const uint8_t *records, size_t recordsSiz { auto record = (const AOTSerializationRecord *)current; bool isNew = false; - bool result = cacheRecord(record, comp, isNew, wasReset); + bool result = cacheRecord(record, context, isNew, wasReset); if (isNew && result && !wasReset) newIds.push_back(record->idAndType()); if (!result) @@ -238,19 +238,19 @@ JITServerAOTDeserializer::cacheRecords(const uint8_t *records, size_t recordsSiz // If we encountered an invalid record (i.e. adding it failed, but not because of a // concurrent reset), remember IDs of new records that were successfully cached so far. if (!wasReset && !newIds.empty()) - addNewKnownIds(newIds, comp); + addNewKnownIds(newIds, context); return success; } bool JITServerAOTDeserializer::deserialize(SerializedAOTMethod *method, const std::vector &records, - TR::Compilation *comp, bool &usesSVM) + const DeserializerContext& context, bool &usesSVM) { - assertSharedVmAccess(comp->j9VMThread()); + assertSharedVmAccess(context._vmThread); ++_numCacheHits; - TR::StackMemoryRegion stackMemoryRegion(*comp->trMemory()); - Vector newIds(Vector::allocator_type(comp->trMemory()->currentStackRegion())); + TR::StackMemoryRegion stackMemoryRegion(*context._trMemory); + Vector newIds(Vector::allocator_type(context._trMemory->currentStackRegion())); newIds.reserve(records.size()); bool wasReset = false; bool failed = false; @@ -263,7 +263,7 @@ JITServerAOTDeserializer::deserialize(SerializedAOTMethod *method, const std::ve auto record = AOTSerializationRecord::get(records[i]); bool isNew = false; - if (!cacheRecord(record, comp, isNew, wasReset)) + if (!cacheRecord(record, context, isNew, wasReset)) { failed = true; break; @@ -279,19 +279,19 @@ JITServerAOTDeserializer::deserialize(SerializedAOTMethod *method, const std::ve if (!wasReset) { OMR::CriticalSection cs(getNewKnownIdsMonitor()); - if (!deserializerWasReset(comp->fej9(), wasReset)) + if (!deserializerWasReset(context._fej9, wasReset)) _newKnownIds.insert(newIds.begin(), newIds.end()); } if (failed) - return deserializationFailure(method, comp, wasReset); + return deserializationFailure(method, context, wasReset); // Update SCC offsets in relocation data so that the method can be stored in the local SCC and AOT-loaded - if (!updateSCCOffsets(method, comp, wasReset, usesSVM)) - return deserializationFailure(method, comp, wasReset); + if (!updateSCCOffsets(method, context, wasReset, usesSVM)) + return deserializationFailure(method, context, wasReset); if (TR::Options::getVerboseOption(TR_VerboseJITServer)) - TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Deserialized AOT method %s", comp->signature()); + TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Deserialized AOT method %s", method->signature()); ++_numDeserializedMethods; return true; } @@ -401,23 +401,23 @@ JITServerAOTDeserializer::onClassLoad(J9Class *ramClass, J9VMThread *vmThread) bool -JITServerAOTDeserializer::cacheRecord(const AOTSerializationRecord *record, TR::Compilation *comp, +JITServerAOTDeserializer::cacheRecord(const AOTSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { switch (record->type()) { case ClassLoader: - return cacheRecord((const ClassLoaderSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const ClassLoaderSerializationRecord *)record, context, isNew, wasReset); case Class: - return cacheRecord((const ClassSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const ClassSerializationRecord *)record, context, isNew, wasReset); case Method: - return cacheRecord((const MethodSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const MethodSerializationRecord *)record, context, isNew, wasReset); case ClassChain: - return cacheRecord((const ClassChainSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const ClassChainSerializationRecord *)record, context, isNew, wasReset); case WellKnownClasses: - return cacheRecord((const WellKnownClassesSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const WellKnownClassesSerializationRecord *)record, context, isNew, wasReset); case Thunk: - return cacheRecord((const ThunkSerializationRecord *)record, comp, isNew, wasReset); + return cacheRecord((const ThunkSerializationRecord *)record, context, isNew, wasReset); default: TR_ASSERT_FATAL(false, "Invalid record type: %u", record->type()); return false; @@ -505,18 +505,18 @@ JITServerAOTDeserializer::GeneratedClassMap::~GeneratedClassMap() bool JITServerAOTDeserializer::isClassMatching(const ClassSerializationRecord *record, - J9Class *ramClass, TR::Compilation *comp) + J9Class *ramClass, const DeserializerContext& context) { int32_t numDimensions = 0; // Use base (non-SCC) front-end method to avoid needless validations auto baseComponent = (J9Class *)TR_J9VMBase::staticGetBaseComponentClass((TR_OpaqueClassBlock *)ramClass, numDimensions); TR_ASSERT(numDimensions >= 0, "Invalid number of array dimensions: %d", numDimensions); - TR::StackMemoryRegion stackMemoryRegion(*comp->trMemory()); + TR::StackMemoryRegion stackMemoryRegion(*context._trMemory); size_t packedSize; J9ROMClass *packedROMClass = JITServerHelpers::packROMClass((numDimensions ? baseComponent : ramClass)->romClass, - comp->trMemory(), comp->fej9(), packedSize, + context._trMemory, context._fej9, packedSize, numDimensions ? 0 : record->romClassSize()); if (!packedROMClass) { @@ -535,7 +535,7 @@ JITServerAOTDeserializer::isClassMatching(const ClassSerializationRecord *record JITServerROMClassHash hash(packedROMClass); if (numDimensions) { - auto &arrayHash = JITServerROMClassHash::getObjectArrayHash(ramClass->romClass, *comp->trMemory(), comp->fej9()); + auto &arrayHash = JITServerROMClassHash::getObjectArrayHash(ramClass->romClass, *context._trMemory, context._fej9); hash = JITServerROMClassHash(arrayHash, hash, numDimensions); } @@ -720,9 +720,9 @@ JITServerLocalSCCAOTDeserializer::invalidateClass(J9VMThread *vmThread, J9Class J9Class * JITServerLocalSCCAOTDeserializer::getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, - TR::Compilation *comp) + const DeserializerContext& context) { - assertSharedVmAccess(comp->j9VMThread()); + assertSharedVmAccess(context._vmThread); OMR::CriticalSection cs(getClassMonitor()); auto it = _generatedClassesSccMap.find({ loader, romClassSccOffset }); @@ -731,10 +731,10 @@ JITServerLocalSCCAOTDeserializer::getGeneratedClass(J9ClassLoader *loader, uintp bool -JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassLoaderMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classLoaderIdMap.find(record->id()); @@ -777,11 +777,11 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationReco } bool -JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *record, TR::Compilation *comp, +JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classIdMap.find(record->id()); @@ -797,7 +797,7 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *re // Get the class loader for this class loader ID (which should already be cached) uintptr_t loaderOffset = (uintptr_t)-1; - J9ClassLoader *loader = getClassLoader(record->classLoaderId(), loaderOffset, comp, wasReset); + J9ClassLoader *loader = getClassLoader(record->classLoaderId(), loaderOffset, context, wasReset); if (!loader) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -810,8 +810,8 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *re // Lookup the RAMClass by name in the class loader, or in the generated classes map if the class is runtime-generated J9Class *ramClass = record->isGenerated() - ? findGeneratedClass(loader, record->name(), record->nameLength(), record->hash(), comp->j9VMThread()) - : jitGetClassInClassloaderFromUTF8(comp->j9VMThread(), loader, (char *)record->name(), record->nameLength()); + ? findGeneratedClass(loader, record->name(), record->nameLength(), record->hash(), context._vmThread) + : jitGetClassInClassloaderFromUTF8(context._vmThread, loader, (char *)record->name(), record->nameLength()); if (!ramClass) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -834,7 +834,7 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *re // Check that the ROMClass hash matches, otherwise remember that it doesn't. Note that for generated classes, // the hash is already guaranteed to be valid since their RAMClasses are looked up based on the hash. - if (!record->isGenerated() && !isClassMatching(record, ramClass, comp)) + if (!record->isGenerated() && !isClassMatching(record, ramClass, context)) { addToMaps(_classIdMap, _classPtrMap, it, record->id(), { ramClass, (uintptr_t)-1, (uintptr_t)-1 }, ramClass); return false; @@ -855,11 +855,11 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *re } bool -JITServerLocalSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *record, TR::Compilation *comp, +JITServerLocalSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getMethodMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _methodMap.find(record->id()); @@ -868,7 +868,7 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *r isNew = true; // Get defining RAMClass using its ID (which should already be cached) - J9Class *ramClass = getRAMClass(record->definingClassId(), comp, wasReset); + J9Class *ramClass = getRAMClass(record->definingClassId(), context, wasReset); if (!ramClass) return false; @@ -889,11 +889,11 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *r } bool -JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *record, TR::Compilation *comp, +JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassChainMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classChainMap.find(record->id()); @@ -906,7 +906,7 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecor J9Class *ramClasses[TR_J9SharedCache::maxClassChainLength]; for (size_t i = 0; i < record->list().length(); ++i) { - ramClasses[i] = getRAMClass(record->list().ids()[i], comp, wasReset); + ramClasses[i] = getRAMClass(record->list().ids()[i], context, wasReset); if (!ramClasses[i]) return false; } @@ -966,10 +966,10 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecor bool JITServerLocalSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRecord *record, - TR::Compilation *comp, bool &isNew, bool &wasReset) + const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getWellKnownClassesMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _wellKnownClassesMap.find(record->id()); @@ -983,13 +983,13 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializatio // Get the class chain SCC offsets for each class chain ID (which should already be cached). for (size_t i = 0; i < record->list().length(); ++i) { - chainOffsets[1 + i] = getSCCOffset(AOTSerializationRecordType::ClassChain, record->list().ids()[i], comp, wasReset); + chainOffsets[1 + i] = getSCCOffset(AOTSerializationRecordType::ClassChain, record->list().ids()[i], context, wasReset); if (chainOffsets[1 + i] == (uintptr_t)-1) return false; } // Store the "well-known classes" object in the local SCC or find the existing one - const void *wkcOffsets = _sharedCache->storeWellKnownClasses(comp->j9VMThread(), chainOffsets, 1 + record->list().length(), record->includedClasses()); + const void *wkcOffsets = _sharedCache->storeWellKnownClasses(context._vmThread, chainOffsets, 1 + record->list().length(), record->includedClasses()); if (!wkcOffsets) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -1018,21 +1018,23 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializatio bool JITServerLocalSCCAOTDeserializer::cacheRecord(const ThunkSerializationRecord *record, - TR::Compilation *comp, bool &isNew, bool &wasReset) + const DeserializerContext& context, bool &isNew, bool &wasReset) { + TR_ASSERT_FATAL(context._comp, "Should not be trying to cache a ThunkSerializationRecord outside a compilation\n"); + // Unlike the rest of the cacheRecord functions, we do not need to acquire a monitor here, as we can rely on // the internal synchronization of getJ2IThunk and setJ2IThunk. We use a read barrier here for deserializerWasReset(). VM_AtomicSupport::readBarrier(); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; - auto fej9vm = comp->fej9vm(); - void *thunk = fej9vm->getJ2IThunk((char *)record->signature(), record->signatureSize(), comp); + auto fej9vm = context._fej9; + void *thunk = fej9vm->getJ2IThunk((char *)record->signature(), record->signatureSize(), context._comp); if (thunk) return true; isNew = true; - fej9vm->setJ2IThunk((char *)record->signature(), record->signatureSize(), record->thunkAddress(), comp); + fej9vm->setJ2IThunk((char *)record->signature(), record->signatureSize(), record->thunkAddress(), context._comp); if (TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Cached thunk record ID %zu -> for thunk %.*s", @@ -1042,10 +1044,10 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ThunkSerializationRecord *re J9ClassLoader * -JITServerLocalSCCAOTDeserializer::getClassLoader(uintptr_t id, uintptr_t &loaderSCCOffset, TR::Compilation *comp, bool &wasReset) +JITServerLocalSCCAOTDeserializer::getClassLoader(uintptr_t id, uintptr_t &loaderSCCOffset, const DeserializerContext& context, bool &wasReset) { OMR::CriticalSection cs(getClassLoaderMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return NULL; auto it = _classLoaderIdMap.find(id); @@ -1087,10 +1089,10 @@ JITServerLocalSCCAOTDeserializer::getClassLoader(uintptr_t id, uintptr_t &loader } J9Class * -JITServerLocalSCCAOTDeserializer::getRAMClass(uintptr_t id, TR::Compilation *comp, bool &wasReset) +JITServerLocalSCCAOTDeserializer::getRAMClass(uintptr_t id, const DeserializerContext& context, bool &wasReset) { OMR::CriticalSection cs(getClassMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return NULL; auto it = _classIdMap.find(id); @@ -1132,15 +1134,15 @@ JITServerLocalSCCAOTDeserializer::getRAMClass(uintptr_t id, TR::Compilation *com const J9UTF8 *name = J9ROMCLASS_CLASSNAME(romClass); // Try to lookup a new version of the class in its class loader by name - J9Class *ramClass = jitGetClassInClassloaderFromUTF8(comp->j9VMThread(), loader, (char *)J9UTF8_DATA(name), + J9Class *ramClass = jitGetClassInClassloaderFromUTF8(context._vmThread, loader, (char *)J9UTF8_DATA(name), J9UTF8_LENGTH(name)); if (!ramClass) { if (auto prefixLength = JITServerHelpers::getGeneratedClassNamePrefixLength(ramClass->romClass)) { // Try to lookup a new version of the generated class using its deterministic ROMClass hash - JITServerROMClassHash hash(romClass, *comp->trMemory(), comp->fej9(), true); - ramClass = findGeneratedClass(loader, J9UTF8_DATA(name), prefixLength, hash, comp->j9VMThread()); + JITServerROMClassHash hash(romClass, *context._trMemory, context._fej9, true); + ramClass = findGeneratedClass(loader, J9UTF8_DATA(name), prefixLength, hash, context._vmThread); } } @@ -1173,18 +1175,18 @@ JITServerLocalSCCAOTDeserializer::getRAMClass(uintptr_t id, TR::Compilation *com } uintptr_t -JITServerLocalSCCAOTDeserializer::getSCCOffset(AOTSerializationRecordType type, uintptr_t id, TR::Compilation *comp, bool &wasReset) +JITServerLocalSCCAOTDeserializer::getSCCOffset(AOTSerializationRecordType type, uintptr_t id, const DeserializerContext& context, bool &wasReset) { switch (type) { case ClassLoader: { - uintptr_t offset = findInMap(_classLoaderIdMap, id, getClassLoaderMonitor(), comp->fej9(), wasReset)._loaderChainSCCOffset; + uintptr_t offset = findInMap(_classLoaderIdMap, id, getClassLoaderMonitor(), context._fej9, wasReset)._loaderChainSCCOffset; return wasReset ? (uintptr_t)-1 : offset; } case Class: { - uintptr_t offset = findInMap(_classIdMap, id, getClassMonitor(), comp->fej9(), wasReset)._romClassSCCOffset; + uintptr_t offset = findInMap(_classIdMap, id, getClassMonitor(), context._fej9, wasReset)._romClassSCCOffset; // Check if this cached ID is for a valid class if ((offset == (uintptr_t)-1) && TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "ERROR: Mismatching class ID %zu", id); @@ -1192,17 +1194,17 @@ JITServerLocalSCCAOTDeserializer::getSCCOffset(AOTSerializationRecordType type, } case Method: { - uintptr_t offset = findInMap(_methodMap, id, getMethodMonitor(), comp->fej9(), wasReset); + uintptr_t offset = findInMap(_methodMap, id, getMethodMonitor(), context._fej9, wasReset); return wasReset ? (uintptr_t)-1 : offset; } case ClassChain: { - uintptr_t offset = findInMap(_classChainMap, id, getClassChainMonitor(), comp->fej9(), wasReset); + uintptr_t offset = findInMap(_classChainMap, id, getClassChainMonitor(), context._fej9, wasReset); return wasReset ? (uintptr_t)-1 : offset; } case WellKnownClasses: { - uintptr_t offset = findInMap(_wellKnownClassesMap, id, getWellKnownClassesMonitor(), comp->fej9(), wasReset); + uintptr_t offset = findInMap(_wellKnownClassesMap, id, getWellKnownClassesMonitor(), context._fej9, wasReset); return wasReset ? (uintptr_t)-1 : offset; } default: @@ -1212,7 +1214,7 @@ JITServerLocalSCCAOTDeserializer::getSCCOffset(AOTSerializationRecordType type, } bool -JITServerLocalSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, +JITServerLocalSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, const DeserializerContext& context, bool &wasReset, bool &usesSVM) { //NOTE: Defining class chain record is validated by now; there is no corresponding SCC offset to be updated @@ -1223,7 +1225,7 @@ JITServerLocalSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, "Invalid TR_AOTMethodHeader version: %d.%d", header->majorVersion, header->minorVersion); TR_ASSERT_FATAL((header->offsetToRelocationDataItems != 0) || (method->numRecords() == 0), "Unexpected %zu serialization records in serialized method %s with no relocation data", - method->numRecords(), comp->signature()); + method->numRecords(), method->signature()); usesSVM = (header->flags & TR_AOTMethodHeader_UsesSymbolValidationManager) != 0; uint8_t *start = method->data() + header->offsetToRelocationDataItems; @@ -1238,7 +1240,7 @@ JITServerLocalSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, if (serializedOffset.recordType() == AOTSerializationRecordType::Thunk) continue; - uintptr_t sccOffset = getSCCOffset(serializedOffset.recordType(), serializedOffset.recordId(), comp, wasReset); + uintptr_t sccOffset = getSCCOffset(serializedOffset.recordType(), serializedOffset.recordId(), context, wasReset); if (sccOffset == (uintptr_t)-1) return false; @@ -1246,13 +1248,13 @@ JITServerLocalSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, uint8_t *ptr = start + serializedOffset.reloDataOffset(); TR_ASSERT_FATAL((ptr >= start + sizeof(uintptr_t)/*skip the size word*/) && (ptr < end), "Out-of-bounds relocation data offset %zu in serialized method %s", - serializedOffset.reloDataOffset(), comp->signature()); + serializedOffset.reloDataOffset(), method->signature()); #if defined(DEBUG) if (TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Updating SCC offset %zu -> %zu for record type %u ID %zu at relo data offset %zu in serialized method %s", *(uintptr_t *)ptr, sccOffset, serializedOffset.recordType(), serializedOffset.recordId(), - serializedOffset.reloDataOffset(), comp->signature() + serializedOffset.reloDataOffset(), method->signature() ); #endif /* defined(DEBUG) */ *(uintptr_t *)ptr = sccOffset; @@ -1364,13 +1366,17 @@ JITServerNoSCCAOTDeserializer::invalidateMethod(J9Method *method) J9Class * JITServerNoSCCAOTDeserializer::getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, - TR::Compilation *comp) + const DeserializerContext& context) { + TR_ASSERT_FATAL(context._comp, "Should not be calling getGeneratedClass outside of a compilation\n"); + bool wasReset = false; - J9Class *ramClass = classFromOffset(romClassSccOffset, comp, wasReset); + J9Class *ramClass = classFromOffset(romClassSccOffset, context, wasReset); if (wasReset) - comp->failCompilation("Deserializer reset during relocation of method %s", - comp->signature()); + { + context._comp->failCompilation( + "Deserializer reset during relocation of method %s", context._comp->signature()); + } return ramClass; } @@ -1399,10 +1405,10 @@ JITServerNoSCCAOTDeserializer::clearCachedData() } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassLoaderMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classLoaderIdMap.find(record->id()); @@ -1432,10 +1438,10 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassLoaderSerializationRecord } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classIdMap.find(record->id()); @@ -1457,7 +1463,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *recor // The class loader for this class record should already have been deserialized, so if we can't find a // loader for this ID then it must have been marked as unloaded. We don't support loader reloading, so // we simply fail to deserialize here. - auto loader = findInMap(_classLoaderIdMap, record->classLoaderId(), getClassLoaderMonitor(), comp->fej9(), wasReset); + auto loader = findInMap(_classLoaderIdMap, record->classLoaderId(), getClassLoaderMonitor(), context._fej9, wasReset); if (!loader) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -1470,8 +1476,8 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *recor // Lookup the RAMClass by name in the class loader, or in the generated classes map if the class is runtime-generated J9Class *ramClass = record->isGenerated() - ? findGeneratedClass(loader, record->name(), record->nameLength(), record->hash(), comp->j9VMThread()) - : jitGetClassInClassloaderFromUTF8(comp->j9VMThread(), loader, (char *)record->name(), record->nameLength()); + ? findGeneratedClass(loader, record->name(), record->nameLength(), record->hash(), context._vmThread) + : jitGetClassInClassloaderFromUTF8(context._vmThread, loader, (char *)record->name(), record->nameLength()); if (!ramClass) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -1484,7 +1490,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *recor // Check that the ROMClass hash matches, otherwise remember that it doesn't. Note that for generated classes, // the hash is already guaranteed to be valid since their RAMClasses are looked up based on the hash. - if (!record->isGenerated() && !isClassMatching(record, ramClass, comp)) + if (!record->isGenerated() && !isClassMatching(record, ramClass, context)) { // We add {ID, NULL} and {ramClass, ID} to their respective maps because // @@ -1508,10 +1514,10 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *recor } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getMethodMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _methodIdMap.find(record->id()); @@ -1533,7 +1539,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *reco // Get the defining RAM class for this method using its ID. If it can't be found, // it was marked as invalid. We don't support reloading, so simply fail here in // that case. - auto ramClass = findInMap(_classIdMap, record->definingClassId(), getClassMonitor(), comp->fej9(), wasReset)._ramClass; + auto ramClass = findInMap(_classIdMap, record->definingClassId(), getClassMonitor(), context._fej9, wasReset)._ramClass; if (!ramClass) return false; @@ -1553,9 +1559,9 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *reco } void -JITServerNoSCCAOTDeserializer::getRAMClassChain(TR::Compilation *comp, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength) +JITServerNoSCCAOTDeserializer::getRAMClassChain(const DeserializerContext& context, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength) { - chainLength = comp->fej9()->necessaryClassChainLength(clazz) - 1; + chainLength = context._fej9->necessaryClassChainLength(clazz) - 1; J9Class **cursor = chainBuffer; *cursor++ = clazz; @@ -1584,10 +1590,10 @@ addToChainMap(PersistentUnorderedMap &map, } J9Class * -JITServerNoSCCAOTDeserializer::getRAMClass(uintptr_t id, TR::Compilation *comp, bool &wasReset) +JITServerNoSCCAOTDeserializer::getRAMClass(uintptr_t id, const DeserializerContext& context, bool &wasReset) { OMR::CriticalSection cs(getClassMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return NULL; auto it = _classIdMap.find(id); @@ -1608,10 +1614,10 @@ JITServerNoSCCAOTDeserializer::getRAMClass(uintptr_t id, TR::Compilation *comp, } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getClassChainMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _classChainMap.find(record->id()); @@ -1620,12 +1626,12 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord * isNew = true; // Get the RAM class chain for the first class referenced in the class chain serialization record - auto firstClass = findInMap(_classIdMap, record->list().ids()[0], getClassMonitor(), comp->fej9(), wasReset)._ramClass; + auto firstClass = findInMap(_classIdMap, record->list().ids()[0], getClassMonitor(), context._fej9, wasReset)._ramClass; if (!firstClass) return false; J9Class *ramClassChain[TR_J9SharedCache::maxClassChainLength]; size_t ramClassChainLength = 0; - getRAMClassChain(comp, firstClass, ramClassChain, ramClassChainLength); + getRAMClassChain(context, firstClass, ramClassChain, ramClassChainLength); // Check that it has the expected length if (record->list().length() != ramClassChainLength) @@ -1641,7 +1647,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord * // Validate each class in the server's chain (which should all be cached by now) for (size_t i = 0; i < ramClassChainLength; ++i) { - auto ramClass = findInMap(_classIdMap, record->list().ids()[i], getClassMonitor(), comp->fej9(), wasReset)._ramClass; + auto ramClass = findInMap(_classIdMap, record->list().ids()[i], getClassMonitor(), context._fej9, wasReset)._ramClass; if (!ramClass) { if (TR::Options::getVerboseOption(TR_VerboseJITServer)) @@ -1686,10 +1692,10 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord * } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { OMR::CriticalSection cs(getWellKnownClassesMonitor()); - if (deserializerWasReset(comp->fej9(), wasReset)) + if (deserializerWasReset(context._fej9, wasReset)) return false; auto it = _wellKnownClassesMap.find(record->id()); @@ -1715,13 +1721,16 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRe } bool -JITServerNoSCCAOTDeserializer::cacheRecord(const ThunkSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) +JITServerNoSCCAOTDeserializer::cacheRecord(const ThunkSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) { + TR_ASSERT_FATAL(context._comp, "Should not be trying to cache a ThunkSerializationRecord outside a compilation\n"); + // Unlike the rest of the cacheRecord functions, we do not need to acquire a monitor here, as we can rely on // the internal synchronization of getJ2IThunk and setJ2IThunk. Since we don't touch any internal caches, we can // skip checking for a reset. - auto fej9vm = comp->fej9vm(); + auto fej9vm = context._fej9; + auto comp = context._comp; void *thunk = fej9vm->getJ2IThunk((char *)record->signature(), record->signatureSize(), comp); if (thunk) return true; @@ -1745,7 +1754,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ThunkSerializationRecord *recor } bool -JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, +JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, const DeserializerContext& context, bool &wasReset, bool &usesSVM) { //NOTE: Defining class chain record is validated by now; there is no corresponding SCC offset to be updated @@ -1756,7 +1765,7 @@ JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR: "Invalid TR_AOTMethodHeader version: %d.%d", header->majorVersion, header->minorVersion); TR_ASSERT_FATAL((header->offsetToRelocationDataItems != 0) || (method->numRecords() == 0), "Unexpected %zu serialization records in serialized method %s with no relocation data", - method->numRecords(), comp->signature()); + method->numRecords(), method->signature()); usesSVM = (header->flags & TR_AOTMethodHeader_UsesSymbolValidationManager) != 0; uint8_t *start = method->data() + header->offsetToRelocationDataItems; @@ -1771,7 +1780,7 @@ JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR: if (serializedOffset.recordType() == AOTSerializationRecordType::Thunk) continue; - if (!revalidateRecord(serializedOffset.recordType(), serializedOffset.recordId(), comp->fej9(), wasReset)) + if (!revalidateRecord(serializedOffset.recordType(), serializedOffset.recordId(), context._fej9, wasReset)) return false; uintptr_t offset = encodeOffset(serializedOffset); @@ -1779,13 +1788,13 @@ JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR: uint8_t *ptr = start + serializedOffset.reloDataOffset(); TR_ASSERT_FATAL((ptr >= start + sizeof(uintptr_t)/*skip the size word*/) && (ptr < end), "Out-of-bounds relocation data offset %zu in serialized method %s", - serializedOffset.reloDataOffset(), comp->signature()); + serializedOffset.reloDataOffset(), method->signature()); #if defined(DEBUG) if (TR::Options::getVerboseOption(TR_VerboseJITServer)) TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Updating offset %zu -> %zu for record type %u ID %zu at relo data offset %zu in serialized method %s", *(uintptr_t *)ptr, offset, serializedOffset.recordType(), serializedOffset.recordId(), - serializedOffset.reloDataOffset(), comp->signature() + serializedOffset.reloDataOffset(), method->signature() ); #endif /* defined(DEBUG) */ *(uintptr_t *)ptr = offset; @@ -1890,9 +1899,9 @@ JITServerNoSCCAOTDeserializer::revalidateRecord(AOTSerializationRecordType type, } J9ROMClass * -JITServerNoSCCAOTDeserializer::romClassFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset) +JITServerNoSCCAOTDeserializer::romClassFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset) { - auto clazz = classFromOffset(offset, comp, wasReset); + auto clazz = classFromOffset(offset, context, wasReset); if (clazz) return clazz->romClass; @@ -1900,16 +1909,16 @@ JITServerNoSCCAOTDeserializer::romClassFromOffsetInSharedCache(uintptr_t offset, } J9Class * -JITServerNoSCCAOTDeserializer::classFromOffset(uintptr_t offset, TR::Compilation *comp, bool &wasReset) +JITServerNoSCCAOTDeserializer::classFromOffset(uintptr_t offset, const DeserializerContext& context, bool &wasReset) { TR_ASSERT_FATAL(offsetType(offset) == AOTSerializationRecordType::Class, "Offset %zu must be to a class", offset); - return findInMap(_classIdMap, offsetId(offset), getClassMonitor(), comp->fej9(), wasReset)._ramClass; + return findInMap(_classIdMap, offsetId(offset), getClassMonitor(), context._fej9, wasReset)._ramClass; } // Return a pointer to the entity referred to by the given offset. Note that for class chains identifying class loaders, // we simply return the cached (J9ClassLoader *) directly. void * -JITServerNoSCCAOTDeserializer::pointerFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset) +JITServerNoSCCAOTDeserializer::pointerFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset) { auto id = offsetId(offset); auto ty = AOTSerializationRecord::getType(offset); @@ -1919,15 +1928,15 @@ JITServerNoSCCAOTDeserializer::pointerFromOffsetInSharedCache(uintptr_t offset, switch (ty) { case AOTSerializationRecordType::ClassLoader: - ptr = findInMap(_classLoaderIdMap, id, getClassLoaderMonitor(), comp->fej9(), wasReset); + ptr = findInMap(_classLoaderIdMap, id, getClassLoaderMonitor(), context._fej9, wasReset); break; case AOTSerializationRecordType::ClassChain: - ptr = findInMap(_classChainMap, id, getClassChainMonitor(), comp->fej9(), wasReset); + ptr = findInMap(_classChainMap, id, getClassChainMonitor(), context._fej9, wasReset); break; case AOTSerializationRecordType::WellKnownClasses: - ptr = findInMap(_wellKnownClassesMap, id, getWellKnownClassesMonitor(), comp->fej9(), wasReset); + ptr = findInMap(_wellKnownClassesMap, id, getWellKnownClassesMonitor(), context._fej9, wasReset); break; default: @@ -1940,10 +1949,10 @@ JITServerNoSCCAOTDeserializer::pointerFromOffsetInSharedCache(uintptr_t offset, } J9ROMMethod * -JITServerNoSCCAOTDeserializer::romMethodFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset) +JITServerNoSCCAOTDeserializer::romMethodFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset) { TR_ASSERT_FATAL(offsetType(offset) == AOTSerializationRecordType::Method, "Offset %zu must be to a method", offset); - auto romMethod = findInMap(_methodIdMap, offsetId(offset), getMethodMonitor(), comp->fej9(), wasReset); + auto romMethod = findInMap(_methodIdMap, offsetId(offset), getMethodMonitor(), context._fej9, wasReset); if (romMethod) return J9_ROM_METHOD_FROM_RAM_METHOD(romMethod); diff --git a/runtime/compiler/runtime/JITServerAOTDeserializer.hpp b/runtime/compiler/runtime/JITServerAOTDeserializer.hpp index a6ec4b20aff..0a69a08db4e 100644 --- a/runtime/compiler/runtime/JITServerAOTDeserializer.hpp +++ b/runtime/compiler/runtime/JITServerAOTDeserializer.hpp @@ -32,6 +32,27 @@ class TR_PersistentClassLoaderTable; namespace TR { class Compilation; } namespace TR { class Monitor; } +struct DeserializerContext + { + DeserializerContext(TR::Compilation *comp) + : _vmThread(comp->j9VMThread()) + , _fej9(comp->fej9()) + , _trMemory(comp->trMemory()) + , _comp(comp) + {} + + DeserializerContext(J9VMThread * vmThread, TR_J9VMBase * fej9, TR_Memory *trMemory) + : _vmThread(vmThread) + , _fej9(fej9) + , _trMemory(trMemory) + , _comp(NULL) + {} + + J9VMThread * _vmThread; + TR_J9VMBase * _fej9; + TR_Memory * _trMemory; + TR::Compilation * _comp; + }; // This class defines the base interface for the deserialization of cached AOT methods received from a JITServer, // and initializes certain elements common to the implementations. Its derived classes contain the actual @@ -69,13 +90,13 @@ class JITServerAOTDeserializer TR_Memory &classLoadTRMemory(); - bool cacheRecords(const uint8_t *records, size_t recordsSize, TR::Compilation *comp, + bool cacheRecords(const uint8_t *records, size_t recordsSize, const DeserializerContext& context, bool ignoreFailures, bool &wasReset); // Deserializes in place a serialized AOT method received from JITServer. Returns true on success. // Caches new serialization records and adds their IDs to the set of new known IDs. bool deserialize(SerializedAOTMethod *method, const std::vector &records, - TR::Compilation *comp, bool &usesSVM); + const DeserializerContext& context, bool &usesSVM); void onClassLoad(J9Class *ramClass, J9VMThread *vmThread); // Invalidation function called from the class unload JIT hook to invalidate class loader pointers @@ -96,12 +117,12 @@ class JITServerAOTDeserializer void reset(TR::CompilationInfoPerThread *compInfoPT); // Adds the given IDs to the set of new known IDs maintained by the deserializer. - void addNewKnownIds(const Vector &newIds, TR::Compilation *comp); + void addNewKnownIds(const Vector &newIds, const DeserializerContext& context); // IDs of records newly cached during deserialization of an AOT method are sent to the JITServer with // the next compilation request, so that the server can update its set of known IDs for this client. // This function returns the list of IDs cached since the last call, and clears the set of new known IDs. - std::vector getNewKnownIds(TR::Compilation *comp); + std::vector getNewKnownIds(const DeserializerContext& context); // 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, @@ -109,7 +130,7 @@ class JITServerAOTDeserializer // 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; + virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, const DeserializerContext& context) = 0; void incNumCacheBypasses() { ++_numCacheBypasses; } void incNumCacheMisses() { ++_numCacheMisses; } @@ -117,7 +138,7 @@ class JITServerAOTDeserializer void printStats(FILE *f) const; - virtual J9Class *getRAMClass(uintptr_t id, TR::Compilation *comp, bool &wasReset) = 0; + virtual J9Class *getRAMClass(uintptr_t id, const DeserializerContext& context, bool &wasReset) = 0; void registerThreadToNotifyOnReset(J9VMThread *vmThread); void unregisterThreadToNotifyOnReset(J9VMThread *vmThread); @@ -137,10 +158,10 @@ class JITServerAOTDeserializer }; bool deserializerWasReset(TR_J9VMBase *vm, bool &wasReset); - bool deserializationFailure(const SerializedAOTMethod *method, TR::Compilation *comp, bool wasReset); + bool deserializationFailure(const SerializedAOTMethod *method, const DeserializerContext& context, bool wasReset); // Returns true if ROMClass hash matches the one in the serialization record - bool isClassMatching(const ClassSerializationRecord *record, J9Class *ramClass, TR::Compilation *comp); + bool isClassMatching(const ClassSerializationRecord *record, J9Class *ramClass, const DeserializerContext& context); template V findInMap(const PersistentUnorderedMap &map, uintptr_t id, TR::Monitor *monitor, TR_J9VMBase *vm, bool &wasReset); @@ -174,34 +195,34 @@ class JITServerAOTDeserializer // and sets isNew to true if the record was newly cached (not already known). // Returns false if the record is invalid (e.g. ROMClass hash doesn't match) // or not yet valid (e.g. class has not been loaded yet). - bool cacheRecord(const AOTSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset); + bool cacheRecord(const AOTSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset); // Cache a ClassLoaderSerializationRecord by looking up a class loader in the current JVM with a first-loaded class name // that matches what was recorded during compilation. This will be used to find candidate J9Classes when deserializing other // records, and isn't guranteed to have any particular relationship with the actual compile-time class loader. - virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Cache a ClassSerializationRecord by looking up a J9Class in the current JVM, using its associated ClassLoaderRecord, that // has a name and ROM class hash that matches what was recorded at compile time. These are used to construct RAM class chains // for class chain serialization records. The J9Classes found may not have any particular relationship with the ones recorded // at compile time. - virtual bool cacheRecord(const ClassSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const ClassSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Cache a MethodSerializationRecord by looking up its defining J9Class using its (already-cached) defining // ClassSerializationRecord. No extra guarantees are provided beyond what the associated ClassSerializationRecord provides. - virtual bool cacheRecord(const MethodSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const MethodSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Cache a ClassChainSerializationRecord by constructing a RAM class chain using its stored ClassSerializationRecord IDs. // We then construct the actual RAM class chain of the first class in the ClassChainSerializationRecord, and make sure that // the constructed and actual RAM class chains match. This ensures that the first class in the chain matches what was recorded // at compile time, giving the same guarantees as J9SharedCache::classMatchesCachedVersion(). - virtual bool cacheRecord(const ClassChainSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const ClassChainSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Cache a WellKnownClassesSerializationRecord. No extra guarantees are provided beyond what the associated // ClassChainSerializationRecords of the individual well-known classes chains provide. - virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Deserialize a ThunkSerializationRecord by installing it in the JVM if one cannot be found through the compilation frontend. // No special validation or caching needs to be performed. - virtual bool cacheRecord(const ThunkSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) = 0; + virtual bool cacheRecord(const ThunkSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) = 0; // Returns false on failure - virtual bool updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, bool &wasReset, bool &usesSVM) = 0; + virtual bool updateSCCOffsets(SerializedAOTMethod *method, const DeserializerContext& context, bool &wasReset, bool &usesSVM) = 0; TR_PersistentClassLoaderTable *const _loaderTable; @@ -264,9 +285,9 @@ class JITServerLocalSCCAOTDeserializer : public JITServerAOTDeserializer virtual void invalidateClassLoader(J9VMThread *vmThread, J9ClassLoader *loader) override; virtual void invalidateClass(J9VMThread *vmThread, J9Class *oldClass, J9Class *newClass = NULL) override; - virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, TR::Compilation *comp) override; + virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, const DeserializerContext& context) override; - virtual J9Class *getRAMClass(uintptr_t id, TR::Compilation *comp, bool &wasReset) override; + virtual J9Class *getRAMClass(uintptr_t id, const DeserializerContext& context, bool &wasReset) override; private: virtual void clearCachedData() override; @@ -284,22 +305,22 @@ class JITServerLocalSCCAOTDeserializer : public JITServerAOTDeserializer uintptr_t _loaderChainSCCOffset; }; - virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ClassSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const MethodSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ClassChainSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ThunkSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const MethodSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassChainSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ThunkSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; // Returns the class loader for given class loader ID, either cached or // looked up using the cached SCC offset if the class loader was unloaded. // The SCC offset of the identifying class chain is returned in loaderSCCOffset. - J9ClassLoader *getClassLoader(uintptr_t id, uintptr_t &loaderSCCOffset, TR::Compilation *comp, bool &wasReset); + J9ClassLoader *getClassLoader(uintptr_t id, uintptr_t &loaderSCCOffset, const DeserializerContext& context, bool &wasReset); - virtual bool updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, bool &wasReset, bool &usesSVM) override; + virtual bool updateSCCOffsets(SerializedAOTMethod *method, const DeserializerContext& context, bool &wasReset, bool &usesSVM) override; // Returns -1 on failure - uintptr_t getSCCOffset(AOTSerializationRecordType type, uintptr_t id, TR::Compilation *comp, bool &wasReset); + uintptr_t getSCCOffset(AOTSerializationRecordType type, uintptr_t id, const DeserializerContext& context, bool &wasReset); TR_J9SharedCache *const _sharedCache; @@ -341,9 +362,9 @@ class JITServerNoSCCAOTDeserializer : public JITServerAOTDeserializer virtual void invalidateClass(J9VMThread *vmThread, J9Class *oldClass, J9Class *newClass = NULL) override; void invalidateMethod(J9Method *method); - virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, TR::Compilation *comp) override; + virtual J9Class *getGeneratedClass(J9ClassLoader *loader, uintptr_t romClassSccOffset, const DeserializerContext& context) override; - virtual J9Class *getRAMClass(uintptr_t id, TR::Compilation *comp, bool &wasReset) override; + virtual J9Class *getRAMClass(uintptr_t id, const DeserializerContext& context, bool &wasReset) override; static uintptr_t offsetId(uintptr_t offset) { return AOTSerializationRecord::getId(offset); } @@ -360,22 +381,22 @@ class JITServerNoSCCAOTDeserializer : public JITServerAOTDeserializer virtual void clearCachedData() override; - virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ClassSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const MethodSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ClassChainSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; - virtual bool cacheRecord(const ThunkSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassLoaderSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const MethodSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ClassChainSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const WellKnownClassesSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; + virtual bool cacheRecord(const ThunkSerializationRecord *record, const DeserializerContext& context, bool &isNew, bool &wasReset) override; - virtual bool updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, bool &wasReset, bool &usesSVM) override; + virtual bool updateSCCOffsets(SerializedAOTMethod *method, const DeserializerContext& context, bool &wasReset, bool &usesSVM) override; bool revalidateRecord(AOTSerializationRecordType type, uintptr_t id, TR_J9VMBase *vm, bool &wasReset); - void getRAMClassChain(TR::Compilation *comp, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength); + void getRAMClassChain(const DeserializerContext& context, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength); - J9ROMClass *romClassFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset); - void *pointerFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset); - J9ROMMethod *romMethodFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset); - J9Class *classFromOffset(uintptr_t offset, TR::Compilation *comp, bool &wasReset); + J9ROMClass *romClassFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset); + void *pointerFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset); + J9ROMMethod *romMethodFromOffsetInSharedCache(uintptr_t offset, const DeserializerContext& context, bool &wasReset); + J9Class *classFromOffset(uintptr_t offset, const DeserializerContext& context, bool &wasReset); static uintptr_t encodeOffset(const AOTSerializationRecord *record) { return AOTSerializationRecord::idAndType(record->id(), record->type()); } diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index 227a5e0ac05..07776b870e7 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -3359,8 +3359,9 @@ TR_RelocationRecordProfiledInlinedMethod::preparePrivateData(TR_RelocationRuntim if (!inlinedCodeClass && reloRuntime->comp()->isDeserializedAOTMethod()) { auto deserializer = TR::CompilationInfo::get()->getJITServerAOTDeserializer(); - inlinedCodeClass = (TR_OpaqueClassBlock *)deserializer->getGeneratedClass(classLoader, romClassOffset, - reloRuntime->comp()); + auto comp = reloRuntime->comp(); + auto context = DeserializerContext(comp); + inlinedCodeClass = (TR_OpaqueClassBlock *)deserializer->getGeneratedClass(classLoader, romClassOffset, context); } #endif /* defined(J9VM_OPT_JITSERVER) */ }