Skip to content

Commit

Permalink
Merge pull request #10245 from dmitry-ten/coalesce-methods-2
Browse files Browse the repository at this point in the history
  • Loading branch information
mpirvu committed Aug 10, 2020
2 parents d7344f2 + 58949a1 commit d3ca26b
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 218 deletions.
65 changes: 29 additions & 36 deletions runtime/compiler/control/JITClientCompilationThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,50 +1847,43 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
break;
case MessageType::ResolvedMethod_getResolvedImplementorMethods:
{
auto recv = client->getRecvData<TR_ResolvedJ9Method *, std::vector<TR_OpaqueClassBlock *>, int32_t, bool>();
auto owningMethod = std::get<0>(recv);
auto &subClasses = std::get<1>(recv);
int32_t cpIndexOrOffset = std::get<2>(recv);
bool isInterface = std::get<3>(recv);
auto recv = client->getRecvData<TR_OpaqueClassBlock *, int32_t, int32_t, TR_ResolvedJ9Method *, TR_YesNoMaybe>();
TR_OpaqueClassBlock *clazz = std::get<0>(recv);
int32_t maxCount = std::get<1>(recv);
int32_t slotOrIndex = std::get<2>(recv);
TR_ResolvedJ9Method *callerMethod = std::get<3>(recv);
TR_YesNoMaybe useGetResolvedInterfaceMethod = std::get<4>(recv);

TR_ResolvedMethod *implArray[maxCount];
TR_PersistentClassInfo *classInfo = comp->getPersistentInfo()->getPersistentCHTable()->findClassInfoAfterLocking(clazz, comp, true);
int32_t implCount =
TR_ClassQueries::collectImplementorsCapped(
classInfo,
implArray,
maxCount,
slotOrIndex,
callerMethod,
comp,
false,
useGetResolvedInterfaceMethod);

int32_t numMethods = subClasses.size();
std::vector<J9Method *> ramMethods;
// pack resolved method infos and send them back to the client
std::vector<TR_ResolvedJ9JITServerMethodInfo> methodInfos;
ramMethods.reserve(numMethods);
methodInfos.reserve(numMethods);

for (int32_t i = 0; i < numMethods; ++i)
std::vector<J9Method *> ramMethods;
if (implCount <= maxCount)
{
J9Method *ramMethod;
TR_ResolvedJ9JITServerMethodInfo methodInfo;
if (isInterface)
// otherwise, collection failed
for (int32_t i = 0; i < implCount; ++i)
{
ramMethod = (J9Method *) fe->getResolvedInterfaceMethod(owningMethod->getPersistentIdentifier(), subClasses[i], cpIndexOrOffset);
bool resolved = ramMethod && J9_BYTECODE_START_FROM_RAM_METHOD(ramMethod);

if (resolved)
TR_ResolvedJ9JITServerMethod::createResolvedMethodFromJ9MethodMirror(methodInfo, (TR_OpaqueMethodBlock *) ramMethod, 0, owningMethod, fe, trMemory);
}
else
{
TR_OpaqueMethodBlock *method = fe->getResolvedVirtualMethod(subClasses[i], cpIndexOrOffset);
ramMethod = reinterpret_cast<J9Method *>(method);
TR_ResolvedJ9JITServerMethodInfo methodInfo;
if (ramMethod)
TR_ResolvedJ9JITServerMethod::createResolvedMethodMirror(methodInfo, method, 0, owningMethod, fe, trMemory);
TR_ResolvedJ9JITServerMethod::packMethodInfo(methodInfo, (TR_ResolvedJ9Method *) implArray[i], fe);
methodInfos.push_back(methodInfo);
ramMethods.push_back(static_cast<TR_ResolvedJ9Method *>(implArray[i])->ramMethod());
}
ramMethods.push_back(ramMethod);
methodInfos.push_back(methodInfo);

// First unresolved method found, stop the walk.
// We will still cache this unresolved method,
// so that server doesn't need to make an extra remote call.
if (!std::get<0>(methodInfo).remoteMirror)
break;
}
client->write(response, ramMethods, methodInfos);
break;
client->write(response, methodInfos, ramMethods, implCount);
}
break;
case MessageType::ResolvedRelocatableMethod_createResolvedRelocatableJ9Method:
{
auto recv = client->getRecvData<TR_ResolvedJ9Method *, J9Method *, int32_t, uint32_t>();
Expand Down
164 changes: 11 additions & 153 deletions runtime/compiler/env/CHTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1011,146 +1011,6 @@ bool CollectCompiledImplementors::visitSubclass(TR_PersistentClassInfo *cl)
return false;
}

#if defined(J9VM_OPT_JITSERVER)
class CollectResolvedImplementors: public CollectImplementors
{
public:
CollectResolvedImplementors(TR::Compilation * comp,
TR_OpaqueClassBlock *topClassId,
TR_ResolvedMethod **implArray,
int32_t maxCount,
TR_ResolvedMethod *callerMethod,
int32_t slotOrIndex,
TR_YesNoMaybe useGetResolvedInterfaceMethod = TR_maybe) :
CollectImplementors(comp, topClassId, implArray, maxCount, callerMethod, slotOrIndex, useGetResolvedInterfaceMethod)
{
TR_ASSERT_FATAL(comp->isOutOfProcessCompilation(), "Must only be called on JITServer server-side");
}

virtual bool visitSubclass(TR_PersistentClassInfo *cl) override;
void cacheResolvedMethods();

private:
std::vector<TR_OpaqueClassBlock *> _subClasses;
};

bool
CollectResolvedImplementors::visitSubclass(TR_PersistentClassInfo *cl)
{
TR_ASSERT_FATAL(comp()->isOutOfProcessCompilation(), "Must only be called on JITServer server-side");
if (_count >= _maxCount)
{
stopTheWalk();
return false;
}

auto callerMethod = static_cast<TR_ResolvedJ9JITServerMethod *>(_callerMethod);

// verify that our subclass meets all conditions
TR_OpaqueClassBlock *classId = cl->getClassId();
if (!TR::Compiler->cls.isAbstractClass(comp(), classId)
&& !TR::Compiler->cls.isInterfaceClass(comp(), classId))
{
++_numVisitedSubClasses;
if (_numVisitedSubClasses > _maxNumVisitedSubClasses)
{
// too many classes visited.
// set count greater than maxCount, to indicate failure and force exit
_count = _maxCount + 1;
stopTheWalk();
return false;
}

// if the implementor hasn't been cached yet,
// add the corresponding subclass to the list
TR_ResolvedMethod *resolvedMethod;
TR_ResolvedMethodType type = isInterface() ?
TR_ResolvedMethodType::Interface :
TR_ResolvedMethodType::VirtualFromOffset;
auto compInfoPT = static_cast<TR::CompilationInfoPerThreadRemote *>(static_cast<TR_J9VMBase *>(fe())->_compInfoPT);
TR_ResolvedMethodKey key =
compInfoPT->getResolvedMethodKey(
type,
reinterpret_cast<TR_OpaqueClassBlock *>(callerMethod->constantPoolHdr()),
_slotOrIndex,
classId);
if (!compInfoPT->getCachedResolvedMethod(
key,
callerMethod,
&resolvedMethod))
{
_subClasses.push_back(classId);
}
else if (resolvedMethod)
{
bool added = addImplementor(resolvedMethod);
if (added && _count >= _maxCount)
stopTheWalk();
}
else
{
// unresolved cached method found.
// set count greater than maxCount, to indicate failure and force exit
_count = _maxCount + 1;
stopTheWalk();
return false;
}
}

return true;
}

void
CollectResolvedImplementors::cacheResolvedMethods()
{
TR_ASSERT_FATAL(comp()->isOutOfProcessCompilation(), "Must only be called on JITServer server-side");
// _count >= _maxCount indicates that either all required implementors
// are already cached or that too many subclasses were visited.
// Remote call not needed.
if (_count >= _maxCount)
{
return;
}

auto callerMethod = static_cast<TR_ResolvedJ9JITServerMethod *>(_callerMethod);
callerMethod->cacheImplementorMethods(
_subClasses,
_slotOrIndex,
isInterface(),
2);

// now, add the cached methods to _implArray
TR_ResolvedMethod *resolvedMethod;
TR_ResolvedMethodType type = isInterface() ?
TR_ResolvedMethodType::Interface :
TR_ResolvedMethodType::VirtualFromOffset;
auto compInfoPT = static_cast<TR::CompilationInfoPerThreadRemote *>(static_cast<TR_J9VMBase *>(fe())->_compInfoPT);
for (auto it = _subClasses.begin(); it != _subClasses.end(); ++it)
{
TR_ResolvedMethodKey key =
compInfoPT->getResolvedMethodKey(
type,
reinterpret_cast<TR_OpaqueClassBlock *>(callerMethod->constantPoolHdr()),
_slotOrIndex,
*it);
if (compInfoPT->getCachedResolvedMethod(
key,
callerMethod,
&resolvedMethod))
{
bool added = addImplementor(resolvedMethod);
if (added && _count >= _maxCount)
break;
if (!resolvedMethod)
{
_count = _maxCount + 1;
break;
}
}
}
}
#endif /* defined(J9VM_OPT_JITSERVER) */

void
TR_ClassQueries::getSubClasses(TR_PersistentClassInfo *clazz,
TR_ScratchList<TR_PersistentClassInfo> &list, TR_FrontEnd *fe, bool locked)
Expand Down Expand Up @@ -1179,20 +1039,18 @@ TR_ClassQueries::collectImplementorsCapped(TR_PersistentClassInfo *clazz,
#if defined(J9VM_OPT_JITSERVER)
if (comp->isOutOfProcessCompilation())
{
CollectResolvedImplementors collector(comp, clazz->getClassId(), implArray, maxCount, callerMethod, slotOrIndex, useGetResolvedInterfaceMethod);
collector.visitSubclass(clazz);
collector.visit(clazz->getClassId(), locked);
collector.cacheResolvedMethods();
return collector.getCount();
}
else
#endif /* defined(J9VM_OPT_JITSERVER) */
{
CollectImplementors collector(comp, clazz->getClassId(), implArray, maxCount, callerMethod, slotOrIndex, useGetResolvedInterfaceMethod);
collector.visitSubclass(clazz);
collector.visit(clazz->getClassId(), locked);
return collector.getCount(); // return the number of implementers in the implArray
return static_cast<TR_ResolvedJ9JITServerMethod *>(callerMethod)->collectImplementorsCapped(
clazz->getClassId(),
maxCount,
slotOrIndex,
useGetResolvedInterfaceMethod,
implArray);
}
#endif
CollectImplementors collector(comp, clazz->getClassId(), implArray, maxCount, callerMethod, slotOrIndex, useGetResolvedInterfaceMethod);
collector.visitSubclass(clazz);
collector.visit(clazz->getClassId(), locked);
return collector.getCount(); // return the number of implementers in the implArray
}

int32_t
Expand Down
81 changes: 55 additions & 26 deletions runtime/compiler/env/j9methodServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1954,37 +1954,66 @@ TR_ResolvedJ9JITServerMethod::cacheFields()
}
}

void
TR_ResolvedJ9JITServerMethod::cacheImplementorMethods(
std::vector<TR_OpaqueClassBlock *> &subClasses,
int32_t
TR_ResolvedJ9JITServerMethod::collectImplementorsCapped(
TR_OpaqueClassBlock *topClass,
int32_t maxCount,
int32_t cpIndexOrOffset,
bool isInterface,
int32_t ttlForUnresolved)
TR_YesNoMaybe useGetResolvedInterfaceMethod,
TR_ResolvedMethod **implArray)
{
auto compInfoPT = (TR::CompilationInfoPerThreadRemote *) _fe->_compInfoPT;
int32_t numMethods = subClasses.size();

_stream->write(JITServer::MessageType::ResolvedMethod_getResolvedImplementorMethods, (TR_ResolvedJ9Method *) _remoteMirror, subClasses, cpIndexOrOffset, isInterface);
auto recv = _stream->read<std::vector<J9Method *>, std::vector<TR_ResolvedJ9JITServerMethodInfo>>();
auto compInfoPT = static_cast<TR::CompilationInfoPerThreadRemote *>(_fe->_compInfoPT);
JITServer::ServerStream *stream = compInfoPT->getMethodBeingCompiled()->_stream;
stream->write(
JITServer::MessageType::ResolvedMethod_getResolvedImplementorMethods,
topClass,
maxCount,
cpIndexOrOffset,
_remoteMirror,
useGetResolvedInterfaceMethod);
auto recv = stream->read<std::vector<TR_ResolvedJ9JITServerMethodInfo>, std::vector<J9Method *>, int32_t>();
auto &methodInfos = std::get<0>(recv);
auto &ramMethods = std::get<1>(recv);

bool isInterface = TR::Compiler->cls.isInterfaceClass(compInfoPT->getCompilation(), topClass);

// refine if requested by a caller
if (useGetResolvedInterfaceMethod != TR_maybe)
isInterface = useGetResolvedInterfaceMethod == TR_yes ? true : false;
for (int32_t i = 0; i < methodInfos.size(); ++i)
{
TR_ResolvedMethodType type = isInterface ?
TR_ResolvedMethodType::Interface :
TR_ResolvedMethodType::VirtualFromOffset;

// Note: the number of received methods can be smaller
// than the requsted number, because client will abort after
// the first unresolved method.
auto &ramMethods = std::get<0>(recv);
auto &methodInfos = std::get<1>(recv);
for (int32_t i = 0; i < ramMethods.size(); ++i)
{
TR_ResolvedMethodType type = isInterface ? TR_ResolvedMethodType::Interface : TR_ResolvedMethodType::VirtualFromOffset;
TR_ResolvedMethod *resolvedMethod;
TR_ResolvedMethodKey key = compInfoPT->getResolvedMethodKey(type, (TR_OpaqueClassBlock *) _ramClass, cpIndexOrOffset, subClasses[i]);
// Assume that we already checked that none of the methods have already been cached
compInfoPT->cacheResolvedMethod(
key,
(TR_OpaqueMethodBlock *) ramMethods[i],
0,
methodInfos[i],
ttlForUnresolved);
TR_ResolvedMethodKey key =
compInfoPT->getResolvedMethodKey(
type,
reinterpret_cast<TR_OpaqueClassBlock *>(_ramClass),
cpIndexOrOffset,
reinterpret_cast<TR_OpaqueClassBlock *>(std::get<0>(methodInfos[i]).ramClass));

bool success;
if (!(success = compInfoPT->getCachedResolvedMethod(
key,
this,
&resolvedMethod)))
{
compInfoPT->cacheResolvedMethod(
key,
(TR_OpaqueMethodBlock *) ramMethods[i],
cpIndexOrOffset,
methodInfos[i],
0); // all received methods should be resolved
success = compInfoPT->getCachedResolvedMethod(key, this, &resolvedMethod);
}

TR_ASSERT_FATAL(success && resolvedMethod, "method must be cached and resolved");
implArray[i] = resolvedMethod;
}

return std::get<2>(recv);
}

bool
Expand Down
4 changes: 2 additions & 2 deletions runtime/compiler/env/j9methodServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,12 +223,12 @@ class TR_ResolvedJ9JITServerMethod : public TR_ResolvedJ9Method
bool addValidationRecordForCachedResolvedMethod(const TR_ResolvedMethodKey &key, TR_OpaqueMethodBlock *method);
void cacheResolvedMethodsCallees(int32_t ttlForUnresolved = 2);
void cacheFields();
void cacheImplementorMethods(std::vector<TR_OpaqueClassBlock *> &subClasses, int32_t cpIndexOrOffset, bool isInterface, int32_t ttlForUnresolved = 2);
int32_t collectImplementorsCapped(TR_OpaqueClassBlock *topClass, int32_t maxCount, int32_t cpIndexOrOffset, TR_YesNoMaybe useGetResolvedInterfaceMethod, TR_ResolvedMethod **implArray);
static void packMethodInfo(TR_ResolvedJ9JITServerMethodInfo &methodInfo, TR_ResolvedJ9Method *resolvedMethod, TR_FrontEnd *fe);

protected:
JITServer::ServerStream *_stream;
J9Class *_ramClass; // client pointer to RAM class
static void packMethodInfo(TR_ResolvedJ9JITServerMethodInfo &methodInfo, TR_ResolvedJ9Method *resolvedMethod, TR_FrontEnd *fe);
static void setAttributeResultFromResolvedMethodFieldAttributes(const TR_J9MethodFieldAttributes &attributes, U_32 * fieldOffset, void **address, TR::DataType * type, bool * volatileP, bool * isFinal, bool * isPrivate, bool * unresolvedInCP, bool *result, bool isStatic);
virtual bool getCachedFieldAttributes(int32_t cpIndex, TR_J9MethodFieldAttributes &attributes, bool isStatic);
virtual void cacheFieldAttributes(int32_t cpIndex, const TR_J9MethodFieldAttributes &attributes, bool isStatic);
Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/net/CommunicationStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ class CommunicationStream
ClientMessage _cMsg;

static const uint8_t MAJOR_NUMBER = 1;
static const uint16_t MINOR_NUMBER = 8;
static const uint16_t MINOR_NUMBER = 9;
static const uint8_t PATCH_NUMBER = 0;
static uint32_t CONFIGURATION_FLAGS;

Expand Down

0 comments on commit d3ca26b

Please sign in to comment.