diff --git a/runtime/compiler/compile/J9Compilation.hpp b/runtime/compiler/compile/J9Compilation.hpp index 17895d5f0aa..bee6f05dec0 100644 --- a/runtime/compiler/compile/J9Compilation.hpp +++ b/runtime/compiler/compile/J9Compilation.hpp @@ -389,6 +389,9 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector // fails serialization by setting _aotCacheStore to false if we are not ignoring the client's SCC, and otherwise // fails the compilation entirely. void addThunkRecord(const AOTCacheThunkRecord *record); +#else + bool isDeserializedAOTMethod() const { return false; } + bool ignoringLocalSCC() const { return false; } #endif /* defined(J9VM_OPT_JITSERVER) */ TR::SymbolValidationManager *getSymbolValidationManager() { return _symbolValidationManager; } diff --git a/runtime/compiler/env/DependencyTable.cpp b/runtime/compiler/env/DependencyTable.cpp index 49ae6c53cfd..665d8ca222a 100644 --- a/runtime/compiler/env/DependencyTable.cpp +++ b/runtime/compiler/env/DependencyTable.cpp @@ -22,6 +22,7 @@ #include "control/CompilationRuntime.hpp" #include "control/CompilationThread.hpp" +#include "env/ClassLoaderTable.hpp" #include "env/DependencyTable.hpp" #include "env/J9SharedCache.hpp" #include "env/PersistentCHTable.hpp" @@ -469,9 +470,32 @@ TR_AOTDependencyTable::resolvePendingLoads() _pendingLoads.clear(); } -TR_OpaqueClassBlock * -TR_AOTDependencyTable::findClassCandidate(uintptr_t romClassOffset) +J9Class * +TR_AOTDependencyTable::findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t classChainOffset, void *classLoaderChain) + { + if (comp->isDeserializedAOTMethod() || comp->ignoringLocalSCC()) + return NULL; + + auto classChain = (uintptr_t *)_sharedCache->pointerFromOffsetInSharedCache(classChainOffset); + return findChainLoaderCandidate(comp, classChain, classLoaderChain); + } + +J9Class * +TR_AOTDependencyTable::findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t *classChain, void *classLoaderChain) + { + if (comp->isDeserializedAOTMethod() || comp->ignoringLocalSCC()) + return NULL; + + return findChainLoaderCandidate(comp, classChain, classLoaderChain); + } + +J9Class * +TR_AOTDependencyTable::findChainLoaderCandidate(TR::Compilation *comp, uintptr_t *classChain, void *classLoaderChain) { + TR_ASSERT_FATAL(classLoaderChain, "Must be given a loader chain"); + + uintptr_t romClassOffset = _sharedCache->startingROMClassOffsetOfClassChain(classChain); + OMR::CriticalSection cs(_tableMonitor); if (!isActive()) @@ -481,7 +505,15 @@ TR_AOTDependencyTable::findClassCandidate(uintptr_t romClassOffset) if (it == _offsetMap.end()) return NULL; - return (TR_OpaqueClassBlock *)findCandidateForDependency(it->second._loadedClasses, true); + for (const auto& clazz: it->second._loadedClasses) + { + // Init condition taken from jitGetClassInClassloaderFromUTF8() + if ((J9ClassInitFailed != clazz->initializeStatus) && + (_sharedCache->persistentClassLoaderTable()->lookupClassChainAssociatedWithClassLoader(clazz->classLoader) == classLoaderChain)) + return clazz; + } + + return NULL; } void diff --git a/runtime/compiler/env/DependencyTable.hpp b/runtime/compiler/env/DependencyTable.hpp index 7c2e2d513ce..365ad00781c 100644 --- a/runtime/compiler/env/DependencyTable.hpp +++ b/runtime/compiler/env/DependencyTable.hpp @@ -39,7 +39,8 @@ class TR_AOTDependencyTable void classLoadEvent(TR_OpaqueClassBlock *ramClass, bool isClassLoad, bool isClassInitialization) {} void invalidateUnloadedClass(TR_OpaqueClassBlock *ramClass) {} void invalidateRedefinedClass(TR_PersistentCHTable *table, TR_J9VMBase *fej9, TR_OpaqueClassBlock *oldClass, TR_OpaqueClassBlock *freshClass) {} - TR_OpaqueClassBlock *findClassCandidate(uintptr_t offset) { return NULL; } + J9Class *findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t classChainOffset, void *classLoaderChain) { return NULL; } + J9Class *findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t *classChain, void *classLoaderChain) { return NULL; } void methodWillBeCompiled(J9Method *method) {} void printStats() {} }; @@ -118,9 +119,11 @@ class TR_AOTDependencyTable // RAM method of ramClass. void invalidateRedefinedClass(TR_PersistentCHTable *table, TR_J9VMBase *fej9, TR_OpaqueClassBlock *oldClass, TR_OpaqueClassBlock *freshClass); - // Given a ROM class offset, return an initialized class with a valid class - // chain starting with that offset. - TR_OpaqueClassBlock *findClassCandidate(uintptr_t offset); + // Given a class chain and class loader chain, return an initialized class + // with a valid class chain starting with that offset and with a class loader + // with that loader chain + J9Class *findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t classChainOffset, void *classLoaderChain); + J9Class *findCandidateWithChainAndLoader(TR::Compilation *comp, uintptr_t *classChain, void *classLoaderChain); static uintptr_t decodeDependencyOffset(uintptr_t offset) { @@ -169,6 +172,7 @@ class TR_AOTDependencyTable OffsetEntry *getOffsetEntry(uintptr_t offset, bool create); J9Class *findCandidateForDependency(const PersistentUnorderedSet &loadedClasses, bool needsInitialization); + J9Class *findChainLoaderCandidate(TR::Compilation *comp, uintptr_t *classChain, void *classLoaderChain); // Stop tracking the given method. This will invalidate the MethodEntryRef // for the method. diff --git a/runtime/compiler/runtime/RelocationRecord.cpp b/runtime/compiler/runtime/RelocationRecord.cpp index b4c601ccfbb..25547fb5c40 100644 --- a/runtime/compiler/runtime/RelocationRecord.cpp +++ b/runtime/compiler/runtime/RelocationRecord.cpp @@ -40,6 +40,7 @@ #include "control/Options_inlines.hpp" #include "env/CHTable.hpp" #include "env/ClassLoaderTable.hpp" +#include "env/DependencyTable.hpp" #include "env/PersistentCHTable.hpp" #include "env/jittypes.h" #include "env/VMAccessCriticalSection.hpp" @@ -3363,6 +3364,12 @@ TR_RelocationRecordProfiledInlinedMethod::preparePrivateData(TR_RelocationRuntim } #endif /* defined(J9VM_OPT_JITSERVER) */ } + if (!inlinedCodeClass) + { + if (auto dependencyTable = reloRuntime->comp()->getPersistentInfo()->getAOTDependencyTable()) + inlinedCodeClass = (TR_OpaqueClassBlock *)dependencyTable->findCandidateWithChainAndLoader(reloRuntime->comp(), classChainForInlinedMethod(reloTarget), + classChainIdentifyingLoader); + } } if (inlinedCodeClass) diff --git a/runtime/compiler/runtime/SymbolValidationManager.cpp b/runtime/compiler/runtime/SymbolValidationManager.cpp index 5ccee9b0c5b..81c63766e3d 100644 --- a/runtime/compiler/runtime/SymbolValidationManager.cpp +++ b/runtime/compiler/runtime/SymbolValidationManager.cpp @@ -23,6 +23,7 @@ #include #include "env/VMJ9.h" #include "env/ClassLoaderTable.hpp" +#include "env/DependencyTable.hpp" #include "env/JSR292Methods.h" #include "env/PersistentCHTable.hpp" #include "env/VMAccessCriticalSection.hpp" @@ -1255,13 +1256,19 @@ bool TR::SymbolValidationManager::validateProfiledClassRecord(uint16_t classID, void *classChainIdentifyingLoader, void *classChainForClassBeingValidated) { + TR_OpaqueClassBlock *clazz = NULL; J9ClassLoader *classLoader = (J9ClassLoader *)_fej9->sharedCache()->lookupClassLoaderAssociatedWithClassChain(classChainIdentifyingLoader); - if (classLoader == NULL) - return false; + if (classLoader) + { + clazz = _fej9->sharedCache()->lookupClassFromChainAndLoader(static_cast(classChainForClassBeingValidated), classLoader, _comp); + } + + if (!clazz) + { + if (auto dependencyTable = _comp->getPersistentInfo()->getAOTDependencyTable()) + clazz = (TR_OpaqueClassBlock *)dependencyTable->findCandidateWithChainAndLoader(_comp, (uintptr_t *)classChainForClassBeingValidated, classChainIdentifyingLoader); + } - TR_OpaqueClassBlock *clazz = _fej9->sharedCache()->lookupClassFromChainAndLoader( - static_cast(classChainForClassBeingValidated), classLoader, _comp - ); return validateSymbol(classID, clazz); }