Skip to content

Commit

Permalink
Use the dependency table as class loader fallback
Browse files Browse the repository at this point in the history
The dependency table tracks currently-loaded RAM classes with valid
class chains by their offset, so it can be used as a fallback during
relocation if a class cannot be found in its associated loader.

Signed-off-by: Christian Despres <[email protected]>
  • Loading branch information
cjjdespres committed Nov 11, 2024
1 parent 3cac37b commit 9cc270d
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 19 deletions.
3 changes: 3 additions & 0 deletions runtime/compiler/compile/J9Compilation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,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; }
Expand Down
9 changes: 8 additions & 1 deletion runtime/compiler/env/DependencyTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*******************************************************************************/


#include "compile/Compilation.hpp"
#include "control/CompilationThread.hpp"
#include "env/DependencyTable.hpp"
#include "env/J9SharedCache.hpp"
Expand Down Expand Up @@ -202,8 +203,14 @@ TR_AOTDependencyTable::invalidateRedefinedClass(TR_PersistentCHTable *table, TR_
}

TR_OpaqueClassBlock *
TR_AOTDependencyTable::findClassCandidate(uintptr_t romClassOffset)
TR_AOTDependencyTable::findCandidateFromChainOffset(TR::Compilation *comp, uintptr_t chainOffset)
{
if (comp->isDeserializedAOTMethod() || comp->ignoringLocalSCC())
return NULL;

void *chain = _sharedCache->pointerFromOffsetInSharedCache(chainOffset);
uintptr_t romClassOffset = _sharedCache->startingROMClassOffsetOfClassChain(chain);

OMR::CriticalSection cs(_tableMonitor);

if (!isActive())
Expand Down
6 changes: 3 additions & 3 deletions runtime/compiler/env/DependencyTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ class TR_AOTDependencyTable
// Invalidate a redefined class
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 offset in the local SCC, return an initialized class
// with a valid class chain starting with that offset.
TR_OpaqueClassBlock *findCandidateFromChainOffset(TR::Compilation *comp, uintptr_t chainOffset);

private:
bool isActive() const { return _isActive; }
Expand Down
13 changes: 9 additions & 4 deletions runtime/compiler/env/J9SharedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -981,11 +981,16 @@ TR_J9SharedCache::isPtrToROMClassesSectionInSharedCache(void *ptr, uintptr_t *ca
J9ROMClass *
TR_J9SharedCache::startingROMClassOfClassChain(UDATA *classChain)
{
UDATA lengthInBytes = classChain[0];
TR_ASSERT_FATAL(lengthInBytes >= 2 * sizeof (UDATA), "class chain is too short!");
return romClassFromOffsetInSharedCache(startingROMClassOffsetOfClassChain(classChain));
}

UDATA romClassOffset = classChain[1];
return romClassFromOffsetInSharedCache(romClassOffset);
uintptr_t
TR_J9SharedCache::startingROMClassOffsetOfClassChain(void *chain)
{
auto classChain = (uintptr_t *)chain;
uintptr_t lengthInBytes = classChain[0];
TR_ASSERT_FATAL(lengthInBytes >= 2 * sizeof (UDATA), "class chain is too short!");
return classChain[1];
}

// convert an offset into a string of 8 characters
Expand Down
2 changes: 2 additions & 0 deletions runtime/compiler/env/J9SharedCache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,8 @@ class TR_J9SharedCache : public TR_SharedCache

J9ROMClass *startingROMClassOfClassChain(UDATA *classChain);

uintptr_t startingROMClassOffsetOfClassChain(void *chain);

virtual uintptr_t getClassChainOffsetIdentifyingLoader(TR_OpaqueClassBlock *clazz, uintptr_t **classChain = NULL);

#if defined(J9VM_OPT_JITSERVER)
Expand Down
40 changes: 32 additions & 8 deletions runtime/compiler/runtime/RelocationRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,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"
Expand Down Expand Up @@ -3303,6 +3304,7 @@ TR_RelocationRecordProfiledInlinedMethod::preparePrivateData(TR_RelocationRuntim
classChainIdentifyingLoader);
J9ClassLoader *classLoader = (J9ClassLoader *)sharedCache->lookupClassLoaderAssociatedWithClassChain(classChainIdentifyingLoader);
RELO_LOG(reloRuntime->reloLogger(), 6, "\tpreparePrivateData: classLoader %p\n", classLoader);
auto compInfo = TR::CompilationInfo::get();

if (classLoader)
{
Expand All @@ -3316,12 +3318,20 @@ TR_RelocationRecordProfiledInlinedMethod::preparePrivateData(TR_RelocationRuntim
// class is runtime-generated (e.g., a lambda). Try to look it up in the AOT deserializer cache instead.
if (!inlinedCodeClass && reloRuntime->comp()->isDeserializedAOTMethod())
{
auto deserializer = TR::CompilationInfo::get()->getJITServerAOTDeserializer();
auto deserializer = compInfo->getJITServerAOTDeserializer();
inlinedCodeClass = (TR_OpaqueClassBlock *)deserializer->getGeneratedClass(classLoader, romClassOffset,
reloRuntime->comp());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
}
if (!inlinedCodeClass)
{
// TODO: if we get a candidate class from the dependency table, we
// already know it has a valid chain, so we can skip some later chain
// lookups/validation. This applies to other dependency table lookups.
if (auto dependencyTable = compInfo->getPersistentInfo()->getAOTDependencyTable())
inlinedCodeClass = dependencyTable->findCandidateFromChainOffset(reloRuntime->comp(), classChainForInlinedMethod(reloTarget));
}
}

if (inlinedCodeClass && checkInlinedClassValidity(reloRuntime, inlinedCodeClass))
Expand Down Expand Up @@ -3823,18 +3833,25 @@ TR_RelocationRecordValidateArbitraryClass::applyRelocation(TR_RelocationRuntime
J9ClassLoader *classLoader = (J9ClassLoader *)sharedCache->lookupClassLoaderAssociatedWithClassChain(classChainIdentifyingLoader);
RELO_LOG(reloRuntime->reloLogger(), 6, "\t\tpreparePrivateData: classLoader %p\n", classLoader);

TR_OpaqueClassBlock *clazz = NULL;
if (classLoader)
{
uintptr_t *classChainForClassBeingValidated = (uintptr_t *)sharedCache->pointerFromOffsetInSharedCache(
classChainOffsetForClassBeingValidated(reloTarget));
TR_OpaqueClassBlock *clazz = sharedCache->lookupClassFromChainAndLoader(classChainForClassBeingValidated,
classLoader, reloRuntime->comp());
RELO_LOG(reloRuntime->reloLogger(), 6, "\t\tpreparePrivateData: clazz %p\n", clazz);
clazz = sharedCache->lookupClassFromChainAndLoader(classChainForClassBeingValidated,
classLoader, reloRuntime->comp());
}

if (clazz)
return TR_RelocationErrorCode::relocationOK;
if (!clazz)
{
if (auto dependencyTable = TR::CompilationInfo::get()->getPersistentInfo()->getAOTDependencyTable())
clazz = dependencyTable->findCandidateFromChainOffset(reloRuntime->comp(), classChainIdentifyingLoaderOffset(reloTarget));
}

RELO_LOG(reloRuntime->reloLogger(), 6, "\t\tpreparePrivateData: clazz %p\n", clazz);
if (clazz)
return TR_RelocationErrorCode::relocationOK;

if (aotStats)
aotStats->numClassValidationsFailed++;

Expand Down Expand Up @@ -3920,7 +3937,7 @@ TR_RelocationRecordValidateProfiledClass::applyRelocation(TR_RelocationRuntime *
uintptr_t classChainOffset = this->classChainOffset(reloTarget);
void *classChain = reloRuntime->fej9()->sharedCache()->pointerFromOffsetInSharedCache(classChainOffset);

if (reloRuntime->comp()->getSymbolValidationManager()->validateProfiledClassRecord(classID, classChainForCL, classChain))
if (reloRuntime->comp()->getSymbolValidationManager()->validateProfiledClassRecord(classID, classChainForCL, classChain, classChainOffset))
return TR_RelocationErrorCode::relocationOK;
else
return TR_RelocationErrorCode::profiledClassValidationFailure;
Expand Down Expand Up @@ -5664,8 +5681,15 @@ TR_RelocationRecordPointer::preparePrivateData(TR_RelocationRuntime *reloRuntime
uintptr_t *classChain = (uintptr_t *)sharedCache->pointerFromOffsetInSharedCache(classChainForInlinedMethod(reloTarget));
RELO_LOG(reloRuntime->reloLogger(), 6,"\tpreparePrivateData: classChain %p\n", classChain);
classPointer = (J9Class *)sharedCache->lookupClassFromChainAndLoader(classChain, (void *) classLoader, reloRuntime->comp());
RELO_LOG(reloRuntime->reloLogger(), 6,"\tpreparePrivateData: classPointer %p\n", classPointer);
}

if (classPointer == NULL)
{
if (auto dependencyTable = TR::CompilationInfo::get()->getPersistentInfo()->getAOTDependencyTable())
classPointer = (J9Class *)dependencyTable->findCandidateFromChainOffset(reloRuntime->comp(), classChainForInlinedMethod(reloTarget));
}

RELO_LOG(reloRuntime->reloLogger(), 6,"\tpreparePrivateData: classPointer %p\n", classPointer);
}
else
RELO_LOG(reloRuntime->reloLogger(), 6,"\tpreparePrivateData: inlined site invalid\n");
Expand Down
10 changes: 8 additions & 2 deletions runtime/compiler/runtime/SymbolValidationManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <string.h>
#include "env/VMJ9.h"
#include "env/ClassLoaderTable.hpp"
#include "env/DependencyTable.hpp"
#include "env/PersistentCHTable.hpp"
#include "env/VMAccessCriticalSection.hpp"
#include "exceptions/AOTFailure.hpp"
Expand Down Expand Up @@ -850,7 +851,7 @@ TR::SymbolValidationManager::addStaticClassFromCPRecord(TR_OpaqueClassBlock *cla
SVM_ASSERT_ALREADY_VALIDATED(this, beholder);
if (skipFieldRefClassRecord(clazz, beholder, cpIndex))
return true;
else
else
return addClassRecord(clazz, new (_region) StaticClassFromCPRecord(clazz, beholder, cpIndex));
}

Expand Down Expand Up @@ -1210,7 +1211,7 @@ TR::SymbolValidationManager::validateClassByNameRecord(uint16_t classID, uint16_

bool
TR::SymbolValidationManager::validateProfiledClassRecord(uint16_t classID, void *classChainIdentifyingLoader,
void *classChainForClassBeingValidated)
void *classChainForClassBeingValidated, uintptr_t classChainOffsetForClassBeingValidated)
{
J9ClassLoader *classLoader = (J9ClassLoader *)_fej9->sharedCache()->lookupClassLoaderAssociatedWithClassChain(classChainIdentifyingLoader);
if (classLoader == NULL)
Expand All @@ -1219,6 +1220,11 @@ TR::SymbolValidationManager::validateProfiledClassRecord(uint16_t classID, void
TR_OpaqueClassBlock *clazz = _fej9->sharedCache()->lookupClassFromChainAndLoader(
static_cast<uintptr_t *>(classChainForClassBeingValidated), classLoader, _comp
);
if (!clazz)
{
if (auto dependencyTable = _fej9->_compInfo->getPersistentInfo()->getAOTDependencyTable())
clazz = dependencyTable->findCandidateFromChainOffset(_comp, classChainOffsetForClassBeingValidated);
}
return validateSymbol(classID, clazz);
}

Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/runtime/SymbolValidationManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ class SymbolValidationManager


bool validateClassByNameRecord(uint16_t classID, uint16_t beholderID, uintptr_t *classChain);
bool validateProfiledClassRecord(uint16_t classID, void *classChainIdentifyingLoader, void *classChainForClassBeingValidated);
bool validateProfiledClassRecord(uint16_t classID, void *classChainIdentifyingLoader, void *classChainForClassBeingValidated, uintptr_t classChainOffsetForClassBeingValidated);
bool validateClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex);
bool validateDefiningClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex, bool isStatic);
bool validateStaticClassFromCPRecord(uint16_t classID, uint16_t beholderID, uint32_t cpIndex);
Expand Down

0 comments on commit 9cc270d

Please sign in to comment.