Skip to content

Commit

Permalink
Merge pull request #20686 from cjjdespres/class-from-sig-cp
Browse files Browse the repository at this point in the history
Add support for class lookup by name in CP for JITServer/AOT
  • Loading branch information
mpirvu authored Nov 28, 2024
2 parents d1adf51 + f8a959b commit ff7e742
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 187 deletions.
26 changes: 3 additions & 23 deletions runtime/compiler/compile/J9SymbolReferenceTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -826,30 +826,10 @@ J9::SymbolReferenceTable::findOrFabricateShadowSymbol(
qualifiedFieldName,
TR::Symbol::UnknownField);

// As yet JITServer does not support getClassFromSignature() based directly
// on J9ConstantPool*, but it does support it using TR_OpaqueMethodBlock*.
// Find an arbitrary method (if there is one) defined by the same class that
// declares the field, and use that method to getClassFromSignature(), since
// it will have the desired constant pool.
//
// The class containing the field is highly likely to declare at least a
// constructor, and if it doesn't, then it seems that it's not possible to
// instantiate it in the usual way (new, dup, invokespecial <init>), so the
// performance of accesses to its instance fields is especially unlikely to
// matter.
//
TR_J9VM *fej9 = reinterpret_cast<TR_J9VM *>(fe());
if (fej9->getNumMethods(containingClass) > 0)
{
auto *firstMethod =
static_cast<TR_OpaqueMethodBlock*>(fej9->getMethods(containingClass));

TR_OpaqueClassBlock *declaredClass = fej9->getClassFromSignature(
signature, (int32_t)strlen(signature), firstMethod);

if (declaredClass != NULL)
sym->setDeclaredClass(declaredClass);
}
TR_OpaqueClassBlock *declaredClass = fej9->getClassFromSignature(signature, (int32_t)strlen(signature), containingClass);
if (declaredClass != NULL)
sym->setDeclaredClass(declaredClass);

mcount_t methodIndex = mcount_t::valueOf(0);
int32_t cpIndex = -1;
Expand Down
14 changes: 6 additions & 8 deletions runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,15 +308,13 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
{
// Need to get a non-AOT frontend because the AOT frontend also
// performs some class validation which we want to do at the server
TR_J9VMBase *fej9 = TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread);
auto recv = client->getRecvData<std::string, TR_OpaqueMethodBlock *, bool>();
auto fej9 = (TR_J9VM *)TR_J9VMBase::get(vmThread->javaVM->jitConfig, vmThread);
auto recv = client->getRecvData<std::string, J9ConstantPool *>();
auto &sig = std::get<0>(recv);
auto method = std::get<1>(recv);
bool isVettedForAOT = std::get<2>(recv);
auto clazz = fej9->getClassFromSignature(sig.data(), sig.length(), method, isVettedForAOT);
J9ClassLoader *cl = clazz ? reinterpret_cast<J9ClassLoader *>(fej9->getClassLoader(clazz)) : NULL;
J9ClassLoader *methodCL = reinterpret_cast<J9ClassLoader *>(fej9->getClassLoader(fej9->getClassOfMethod(method)));
client->write(response, clazz, cl, methodCL);
auto constantPool = std::get<1>(recv);
auto clazz = fej9->getClassFromSignature(sig.data(), sig.length(), constantPool, true);
J9ClassLoader *cl = clazz ? reinterpret_cast<J9ClassLoader *>(fej9->getClassLoader((TR_OpaqueClassBlock *)clazz)) : NULL;
client->write(response, clazz, cl);
}
break;
case MessageType::VM_jitFieldsOrStaticsAreSame:
Expand Down
40 changes: 16 additions & 24 deletions runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7422,12 +7422,20 @@ TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedM
TR_OpaqueClassBlock *
TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock * method, bool isVettedForAOT)
{
J9ConstantPool * constantPool = (J9ConstantPool *) (J9_CP_FROM_METHOD((J9Method*)method));
return getClassFromSignature(sig, sigLength, constantPool);
auto constantPool = (J9ConstantPool *)getConstantPoolFromMethod(method);
return getClassFromSignature(sig, sigLength, constantPool, isVettedForAOT);
}


TR_OpaqueClassBlock *
TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueClassBlock *clazz, bool isVettedForAOT)
{
auto constantPool = (J9ConstantPool *)getConstantPoolFromClass(clazz);
return getClassFromSignature(sig, sigLength, constantPool, isVettedForAOT);
}

TR_OpaqueClassBlock *
TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool)
TR_J9VM::getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool, bool isVettedForAOT)
{
// Primitive types don't have a class associated with them
if (isSignatureForPrimitiveType(sig, sigLength))
Expand Down Expand Up @@ -9056,34 +9064,18 @@ TR_J9SharedCacheVM::isInstanceOf(TR_OpaqueClassBlock * a, TR_OpaqueClassBlock *b
}

TR_OpaqueClassBlock *
TR_J9SharedCacheVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedMethod * method, bool isVettedForAOT)
TR_J9SharedCacheVM::getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool *constantPool, bool isVettedForAOT)
{
return getClassFromSignature(sig, sigLength, (TR_OpaqueMethodBlock *)method->getPersistentIdentifier(), isVettedForAOT);
}

TR_OpaqueClassBlock *
TR_J9SharedCacheVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock * method, bool isVettedForAOT)
{
TR_OpaqueClassBlock* j9class = TR_J9VM::getClassFromSignature(sig, sigLength, method, true);
TR_OpaqueClassBlock* j9class = TR_J9VM::getClassFromSignature(sig, sigLength, constantPool, isVettedForAOT);
bool validated = false;
TR::Compilation* comp = TR::comp();

if (j9class)
{
if (comp->getOption(TR_UseSymbolValidationManager))
{
TR::SymbolValidationManager *svm = comp->getSymbolValidationManager();
SVM_ASSERT_ALREADY_VALIDATED(svm, method);
validated = svm->addClassByNameRecord(j9class, getClassFromMethodBlock(method));
}
else
{
if (isVettedForAOT)
{
if (((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class))
validated = true;
}
}
validated = comp->getSymbolValidationManager()->addClassByNameRecord(j9class, getClassFromCP(constantPool));
else if (isVettedForAOT)
validated = ((TR_ResolvedRelocatableJ9Method *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class);
}

if (validated)
Expand Down
11 changes: 5 additions & 6 deletions runtime/compiler/env/VMJ9.h
Original file line number Diff line number Diff line change
Expand Up @@ -1573,8 +1573,10 @@ class TR_J9VM : public TR_J9VMBase
virtual TR_OpaqueClassBlock * getNullRestrictedArrayClassFromComponentClass(TR_OpaqueClassBlock *componentClass);
virtual TR_OpaqueClassBlock * getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayClass);
virtual int32_t getNewArrayTypeFromClass(TR_OpaqueClassBlock *clazz);
virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, TR_ResolvedMethod *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, TR_OpaqueMethodBlock *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock *getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedMethod *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock *getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock *getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueClassBlock *clazz, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock *getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool, bool isVettedForAOT=false);

virtual TR_OpaqueClassBlock *getBaseComponentClass(TR_OpaqueClassBlock *clazz, int32_t &numDims)
{
Expand Down Expand Up @@ -1615,8 +1617,6 @@ class TR_J9VM : public TR_J9VMBase

virtual TR_StaticFinalData dereferenceStaticFinalAddress(void *staticAddress, TR::DataType addressType);

TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t sigLength, J9ConstantPool * constantPool);

private:
void transformJavaLangClassIsArrayOrIsPrimitive( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop, int32_t andMask);
void transformJavaLangClassIsArray( TR::Compilation *, TR::Node * callNode, TR::TreeTop * treeTop);
Expand Down Expand Up @@ -1715,8 +1715,7 @@ class TR_J9SharedCacheVM : public TR_J9VM
virtual bool isClassVisible(TR_OpaqueClassBlock * sourceClass, TR_OpaqueClassBlock * destClass);
virtual bool isPrimitiveArray(TR_OpaqueClassBlock *);
virtual bool isReferenceArray(TR_OpaqueClassBlock *);
virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, TR_ResolvedMethod *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, TR_OpaqueMethodBlock *method, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock * getClassFromSignature(const char * sig, int32_t length, J9ConstantPool *constantPool, bool isVettedForAOT=false);
virtual TR_OpaqueClassBlock * getSystemClassFromClassName(const char * name, int32_t length, bool isVettedForAOT=false);

virtual intptr_t methodTrampolineLookup( TR::Compilation *, TR::SymbolReference *symRef, void *callSite);
Expand Down
160 changes: 42 additions & 118 deletions runtime/compiler/env/VMJ9Server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,26 +348,49 @@ TR_J9ServerVM::getLeafComponentClassFromArrayClass(TR_OpaqueClassBlock * arrayCl
}

TR_OpaqueClassBlock *
TR_J9ServerVM::getClassFromSignature(const char *sig, int32_t length, TR_ResolvedMethod *method, bool isVettedForAOT)
TR_J9ServerVM::getClassFromSignature(const char *sig, int32_t sigLength, J9ConstantPool *constantPool, bool isVettedForAOT)
{
// Primitive types don't have a class associated with them
if (isSignatureForPrimitiveType(sig, length))
if (isSignatureForPrimitiveType(sig, sigLength))
return NULL;

TR_OpaqueClassBlock * clazz = NULL;
J9ClassLoader * cl = ((TR_ResolvedJ9Method *)method)->getClassLoader();
ClassLoaderStringPair key = {cl, std::string(sig, length)};
PersistentUnorderedMap<ClassLoaderStringPair, TR_OpaqueClassBlock*> & classBySignatureMap = _compInfoPT->getClientData()->getClassBySignatureMap();
auto cpClass = getClassFromCP(constantPool);
auto cpClassLoader = (J9ClassLoader *)getClassLoader(cpClass);

ClassLoaderStringPair key = {cpClassLoader, std::string(sig, sigLength)};
PersistentUnorderedMap<ClassLoaderStringPair, TR_OpaqueClassBlock *> & classBySignatureMap = _compInfoPT->getClientData()->getClassBySignatureMap();
{
OMR::CriticalSection classFromSigCS(_compInfoPT->getClientData()->getClassMapMonitor());
auto it = classBySignatureMap.find(key);
if (it != classBySignatureMap.end())
return it->second;
}

// classname not found; ask the client and cache the answer
clazz = getClassFromSignature(sig, length, (TR_OpaqueMethodBlock *)method->getPersistentIdentifier(), isVettedForAOT);
JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream;
std::string str(sig, sigLength);
stream->write(JITServer::MessageType::VM_getClassFromSignature, str, constantPool);
auto recv = stream->read<TR_OpaqueClassBlock *, J9ClassLoader *>();
TR_OpaqueClassBlock *clazz = std::get<0>(recv);
J9ClassLoader *cl = std::get<1>(recv);
if (clazz)
{
if (cl != cpClassLoader)
{
// make sure that the class is cached
J9ROMClass *romClass = TR::Compiler->cls.romClassOf((TR_OpaqueClassBlock *)clazz);
TR_ASSERT_FATAL(romClass, "class %p could not be cached", clazz);
OMR::CriticalSection getRemoteROMClass(_compInfoPT->getClientData()->getROMMapMonitor());
auto it = _compInfoPT->getClientData()->getROMClassMap().find(reinterpret_cast<J9Class *>(clazz));
if (it != _compInfoPT->getClientData()->getROMClassMap().end())
{
// remember that we cached this class by cp class loader
// so that the cache entry is removed if the cached class gets unloaded
// if the class loaders are not identical
it->second._referencingClassLoaders.insert(cpClassLoader);
}
}

OMR::CriticalSection classFromSigCS(_compInfoPT->getClientData()->getClassMapMonitor());
classBySignatureMap[key] = clazz;
}
Expand All @@ -383,39 +406,6 @@ TR_J9ServerVM::getClassFromSignature(const char *sig, int32_t length, TR_Resolve
return clazz;
}


TR_OpaqueClassBlock *
TR_J9ServerVM::getClassFromSignature(const char *sig, int32_t length, TR_OpaqueMethodBlock *method, bool isVettedForAOT)
{
// Primitive types don't have a class associated with them
if (isSignatureForPrimitiveType(sig, length))
return NULL;

JITServer::ServerStream *stream = _compInfoPT->getMethodBeingCompiled()->_stream;
std::string str(sig, length);
stream->write(JITServer::MessageType::VM_getClassFromSignature, str, method, isVettedForAOT);
auto recv = stream->read<TR_OpaqueClassBlock *, J9ClassLoader *, J9ClassLoader *>();
TR_OpaqueClassBlock *clazz = std::get<0>(recv);
J9ClassLoader *cl = std::get<1>(recv);
J9ClassLoader *methodClassLoader = std::get<2>(recv);
if (clazz && cl != methodClassLoader)
{
// make sure that the class is cached
J9ROMClass *romClass = TR::Compiler->cls.romClassOf(clazz);
TR_ASSERT_FATAL(romClass, "class %p could not be cached", clazz);
OMR::CriticalSection getRemoteROMClass(_compInfoPT->getClientData()->getROMMapMonitor());
auto it = _compInfoPT->getClientData()->getROMClassMap().find(reinterpret_cast<J9Class *>(clazz));
if (it != _compInfoPT->getClientData()->getROMClassMap().end())
{
// remember that we cached this class by method class loader
// so that the cache entry is removed if the cached class gets unloaded
// if the class loaders are not identical
it->second._referencingClassLoaders.insert(methodClassLoader);
}
}
return clazz;
}

void *
TR_J9ServerVM::getSystemClassLoader()
{
Expand Down Expand Up @@ -2817,91 +2807,25 @@ TR_J9SharedCacheServerVM::supportAllocationInlining(TR::Compilation *comp, TR::N
}

TR_OpaqueClassBlock *
TR_J9SharedCacheServerVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_ResolvedMethod * method, bool isVettedForAOT)
TR_J9SharedCacheServerVM::getClassFromSignature(const char *sig, int32_t sigLength, J9ConstantPool *constantPool, bool isVettedForAOT)
{
// Primitive types don't have a class associated with them
if (isSignatureForPrimitiveType(sig, sigLength))
return NULL;

TR_ResolvedRelocatableJ9JITServerMethod* resolvedJITServerMethod = (TR_ResolvedRelocatableJ9JITServerMethod *)method;
TR_OpaqueClassBlock* clazz = NULL;
J9ClassLoader * cl = ((TR_ResolvedJ9Method *)method)->getClassLoader();
ClassLoaderStringPair key = {cl, std::string(sig, sigLength)};
PersistentUnorderedMap<ClassLoaderStringPair, TR_OpaqueClassBlock*> & classBySignatureMap = _compInfoPT->getClientData()->getClassBySignatureMap();
{
OMR::CriticalSection classFromSigCS(_compInfoPT->getClientData()->getClassMapMonitor());
auto it = classBySignatureMap.find(key);
if (it != classBySignatureMap.end())
clazz = it->second;
}
if (!clazz)
{
// classname not found; ask the client and cache the answer
clazz = TR_J9ServerVM::getClassFromSignature(sig, sigLength, (TR_OpaqueMethodBlock *)resolvedJITServerMethod->getPersistentIdentifier(), isVettedForAOT);
if (clazz)
{
{
OMR::CriticalSection classFromSigCS(_compInfoPT->getClientData()->getClassMapMonitor());
classBySignatureMap[key] = clazz;
}
if (!validateClass((TR_OpaqueMethodBlock *)resolvedJITServerMethod->getPersistentIdentifier(), clazz, isVettedForAOT))
{
clazz = NULL;
}
}
else
{
// Class with given name does not exist yet, but it could be
// loaded in the future, thus we should not cache NULL pointers.
// Note: many times we get in here due to Ljava/lang/String$StringCompressionFlag;
// In theory we could consider this a special case and watch the CHTable updates
// for a class load event for Ljava/lang/String$StringCompressionFlag, but it may not
// be worth the trouble.
//printf("ErrorSystem %lu for cl=%p\tclassName=%.*s\n", ++errorsSystem, cl, length, sig);
}
}
else
{
if (!validateClass((TR_OpaqueMethodBlock *)resolvedJITServerMethod->getPersistentIdentifier(), clazz, isVettedForAOT))
clazz = NULL;
}
return clazz;
}
auto comp = _compInfoPT->getCompilation();
auto j9class = TR_J9ServerVM::getClassFromSignature(sig, sigLength, constantPool, isVettedForAOT);
bool validated = false;

TR_OpaqueClassBlock *
TR_J9SharedCacheServerVM::getClassFromSignature(const char * sig, int32_t sigLength, TR_OpaqueMethodBlock * method, bool isVettedForAOT)
{
TR_OpaqueClassBlock* j9class = TR_J9ServerVM::getClassFromSignature(sig, sigLength, method, true);
if (j9class)
{
if (!validateClass(method, j9class, isVettedForAOT))
j9class = NULL;
if (comp->getOption(TR_UseSymbolValidationManager))
validated = comp->getSymbolValidationManager()->addClassByNameRecord(j9class, getClassFromCP(constantPool));
else if (isVettedForAOT)
validated = ((TR_ResolvedRelocatableJ9JITServerMethod *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class);
}

return j9class;
}

bool
TR_J9SharedCacheServerVM::validateClass(TR_OpaqueMethodBlock * method, TR_OpaqueClassBlock* j9class, bool isVettedForAOT)
{
TR::Compilation* comp = _compInfoPT->getCompilation();
bool validated = false;

if (comp->getOption(TR_UseSymbolValidationManager))
{
TR::SymbolValidationManager *svm = comp->getSymbolValidationManager();
SVM_ASSERT_ALREADY_VALIDATED(svm, method);
validated = svm->addClassByNameRecord(j9class, getClassFromMethodBlock(method));
}
if (validated)
return j9class;
else
{
if (isVettedForAOT)
{
if (((TR_ResolvedRelocatableJ9JITServerMethod *) comp->getCurrentMethod())->validateArbitraryClass(comp, (J9Class *) j9class))
validated = true;
}
}
return validated;
return NULL;

}

bool
Expand Down
Loading

0 comments on commit ff7e742

Please sign in to comment.