Skip to content

Commit ff25310

Browse files
committed
Make client and server agree on exact permanent loaders
...within each compilation. There will be at least two data structures that are sensitive to the set of permanent loaders. These could potentially allow the precise set of permanent loaders to vary between the client and server, but the reasoning needed to determine whether certain kinds of variation are allowed gets hairy very quickly. It's much simpler if there is only one set of permanent loaders that will be used for all purposes on both the client and the server. This change also simplifies reasoning about which permanent loaders the server already has. The client no longer attempts to keep track of that at all. Instead, that information is purely in the purview of the server, where it's easy to maintain consistency.
1 parent e3451a2 commit ff25310

17 files changed

+170
-152
lines changed

runtime/compiler/compile/Compilation.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ class OMR_EXTENSIBLE Compilation : public J9::CompilationConnector
5050
TR_Memory *memory,
5151
TR_OptimizationPlan *optimizationPlan,
5252
TR_RelocationRuntime *reloRuntime,
53-
TR::Environment *target = NULL) :
53+
TR::Environment *target
54+
#if defined(J9VM_OPT_JITSERVER)
55+
, size_t numPermanentLoaders
56+
#endif
57+
) :
5458
J9::CompilationConnector(
5559
compThreadId,
5660
j9vmThread,
@@ -62,7 +66,11 @@ class OMR_EXTENSIBLE Compilation : public J9::CompilationConnector
6266
memory,
6367
optimizationPlan,
6468
reloRuntime,
65-
target)
69+
target
70+
#if defined(J9VM_OPT_JITSERVER)
71+
, numPermanentLoaders
72+
#endif
73+
)
6674
{}
6775

6876
~Compilation() {}

runtime/compiler/compile/J9Compilation.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ J9::Compilation::Compilation(int32_t id,
150150
TR_Memory *m,
151151
TR_OptimizationPlan *optimizationPlan,
152152
TR_RelocationRuntime *reloRuntime,
153-
TR::Environment *target)
153+
TR::Environment *target
154+
#if defined(J9VM_OPT_JITSERVER)
155+
, size_t numPermanentLoaders
156+
#endif
157+
)
154158
: OMR::CompilationConnector(
155159
id,
156160
j9vmThread->omrVMThread,
@@ -208,6 +212,7 @@ J9::Compilation::Compilation(int32_t id,
208212
_ignoringLocalSCC(false),
209213
_serializationRecords(decltype(_serializationRecords)::allocator_type(heapMemoryRegion)),
210214
_thunkRecords(decltype(_thunkRecords)::allocator_type(heapMemoryRegion)),
215+
_numPermanentLoaders(numPermanentLoaders),
211216
#endif /* defined(J9VM_OPT_JITSERVER) */
212217
#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)
213218
_aotMethodDependencies(decltype(_aotMethodDependencies)::allocator_type(heapMemoryRegion)),
@@ -1612,8 +1617,12 @@ J9::Compilation::permanentLoaders()
16121617
#if defined(J9VM_OPT_JITSERVER)
16131618
if (self()->isOutOfProcessCompilation())
16141619
{
1620+
TR_ASSERT_FATAL(
1621+
_numPermanentLoaders != SIZE_MAX, "missing _numPermanentLoaders");
1622+
16151623
ClientSessionData *clientData = self()->getClientData();
1616-
clientData->getPermanentLoaders(_permanentLoaders);
1624+
clientData->getPermanentLoaders(
1625+
_permanentLoaders, _numPermanentLoaders, getStream());
16171626
}
16181627
else
16191628
#endif

runtime/compiler/compile/J9Compilation.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,11 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
101101
TR_Memory *,
102102
TR_OptimizationPlan *optimizationPlan,
103103
TR_RelocationRuntime *reloRuntime,
104-
TR::Environment *target = NULL);
104+
TR::Environment *target
105+
#if defined(J9VM_OPT_JITSERVER)
106+
, size_t numPermanentLoaders
107+
#endif
108+
);
105109

106110
~Compilation();
107111

@@ -629,6 +633,9 @@ class OMR_EXTENSIBLE Compilation : public OMR::CompilationConnector
629633
Vector<std::pair<const AOTCacheRecord *, uintptr_t>> _serializationRecords;
630634
// Set of AOT cache thunk records that this compilation depends on; always empty at the client
631635
UnorderedSet<const AOTCacheThunkRecord *> _thunkRecords;
636+
// For the server, the number of permanent loaders the client has specified
637+
// we must use for this compilation.
638+
size_t _numPermanentLoaders;
632639
#endif /* defined(J9VM_OPT_JITSERVER) */
633640

634641
#if !defined(PERSISTENT_COLLECTIONS_UNSUPPORTED)

runtime/compiler/control/CompilationThread.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8375,6 +8375,9 @@ TR::CompilationInfoPerThreadBase::compile(J9VMThread * vmThread,
83758375
trMemory,
83768376
TR::CompileIlGenRequest(entry->getMethodDetails()),
83778377
entry->_checkpointInProgress
8378+
#if defined(J9VM_OPT_JITSERVER)
8379+
, entry->_numPermanentLoaders
8380+
#endif
83788381
);
83798382
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
83808383
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH,
@@ -9254,7 +9257,11 @@ TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void *
92549257
p->trMemory(),
92559258
p->_optimizationPlan,
92569259
reloRuntime,
9257-
&target);
9260+
&target
9261+
#if defined(J9VM_OPT_JITSERVER)
9262+
, p->_numPermanentLoaders
9263+
#endif
9264+
);
92589265

92599266
#if defined(J9VM_OPT_JITSERVER)
92609267
// JITServer TODO: put info in optPlan so that compilation constructor can do this

runtime/compiler/control/CompilationThread.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ struct CompileParameters
103103
TR_Memory &trMemory,
104104
const TR::CompileIlGenRequest &ilGenRequest,
105105
bool checkpointInProgress
106+
#if defined(J9VM_OPT_JITSERVER)
107+
, size_t numPermanentLoaders
108+
#endif
106109
) :
107110
_compilationInfo(compilationInfo),
108111
_vm(vm),
@@ -114,6 +117,9 @@ struct CompileParameters
114117
_trMemory(trMemory),
115118
_ilGenRequest(ilGenRequest),
116119
_checkpointInProgress(checkpointInProgress)
120+
#if defined(J9VM_OPT_JITSERVER)
121+
, _numPermanentLoaders(numPermanentLoaders)
122+
#endif
117123
{}
118124

119125
TR_Memory *trMemory() { return &_trMemory; }
@@ -128,6 +134,10 @@ struct CompileParameters
128134
TR_Memory &_trMemory;
129135
TR::CompileIlGenRequest _ilGenRequest;
130136
bool _checkpointInProgress;
137+
138+
#if defined(J9VM_OPT_JITSERVER)
139+
size_t _numPermanentLoaders;
140+
#endif
131141
};
132142

133143
#if defined(TR_HOST_S390)

runtime/compiler/control/JITClientCompilationThread.cpp

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,6 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
282282
// Do not forbid AOT cache stores or loads (this server might be able to fulfill them)
283283
compInfo->getPersistentInfo()->setDoNotRequestJITServerAOTCacheLoad(false);
284284
compInfo->getPersistentInfo()->setDoNotRequestJITServerAOTCacheStore(false);
285-
286-
auto loaderTable = compInfo->getPersistentInfo()->getPersistentClassLoaderTable();
287-
OMR::CriticalSection lock(compInfo->getSequencingMonitor());
288-
loaderTable->resetPermanentLoadersSentToServer(compInfo);
289285
}
290286

291287
client->write(response, ranges, unloadedClasses->getMaxRanges(), serializedCHTable, dltedMethods);
@@ -298,6 +294,21 @@ handleServerMessage(JITServer::ClientStream *client, TR_J9VM *fe, JITServer::Mes
298294
}
299295
}
300296
break;
297+
case MessageType::ClientSessionData_getPermanentLoaders:
298+
{
299+
auto recv = client->getRecvData<size_t>();
300+
size_t serverCount = std::get<0>(recv);
301+
auto permanentLoaders = comp->permanentLoaders();
302+
std::vector<J9ClassLoader*> newPermanentLoaders;
303+
newPermanentLoaders.reserve(permanentLoaders.size() - serverCount);
304+
newPermanentLoaders.insert(
305+
newPermanentLoaders.end(),
306+
permanentLoaders.begin() + serverCount,
307+
permanentLoaders.end());
308+
309+
client->write(response, newPermanentLoaders);
310+
}
311+
break;
301312
case MessageType::VM_isClassLibraryMethod:
302313
{
303314
auto tup = client->getRecvData<TR_OpaqueMethodBlock*, bool>();
@@ -3454,11 +3465,9 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod
34543465
std::vector<uintptr_t> newKnownIds = deserializer ? deserializer->getNewKnownIds(context) : std::vector<uintptr_t>();
34553466

34563467
auto chTable = (JITClientPersistentCHTable *)persistentInfo->getPersistentCHTable();
3457-
auto permanentLoaders = compiler->permanentLoaders();
34583468
std::vector<TR_OpaqueClassBlock *> unloadedClasses;
34593469
std::vector<TR_OpaqueClassBlock *> illegalModificationList;
34603470
std::pair<std::string, std::string> chtableUpdates("", "");
3461-
std::vector<J9ClassLoader *> newPermanentLoaders; // doesn't affect critical seq. no.
34623471
uint32_t seqNo = 0;
34633472
uint32_t lastCriticalSeqNo = 0;
34643473

@@ -3495,29 +3504,30 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod
34953504
{
34963505
compInfo->setLastCriticalSeqNo(seqNo);
34973506
}
3498-
3499-
// Determine which permanent loaders (if any) to send to the server.
3500-
auto loaderTable = persistentInfo->getPersistentClassLoaderTable();
3501-
size_t numPermanentLoadersSent =
3502-
loaderTable->numPermanentLoadersSentToServer(compInfo);
3503-
3504-
// It's possible to have numPermanentLoadersSent > permanentLoaders.size()
3505-
// in some interleavings. Only send loaders if our permanentLoaders contains
3506-
// entries that haven't been sent yet. This also prevents the subtraction
3507-
// from overflowing.
3508-
if (numPermanentLoadersSent < permanentLoaders.size())
3509-
{
3510-
size_t n = permanentLoaders.size() - numPermanentLoadersSent;
3511-
newPermanentLoaders.reserve(n);
3512-
newPermanentLoaders.insert(
3513-
newPermanentLoaders.end(),
3514-
permanentLoaders.begin() + numPermanentLoadersSent,
3515-
permanentLoaders.end());
3516-
3517-
loaderTable->addPermanentLoadersSentToServer(n, compInfo);
3518-
}
35193507
}
35203508

3509+
// Determine the loaders to consider permanent for this compilation. From
3510+
// this point on, they are fixed.
3511+
//
3512+
// There will be at least two data structures that are sensitive to the
3513+
// set of permanent loaders. These could potentially allow the precise set
3514+
// of permanent loaders to vary between the client and server, but the
3515+
// reasoning needed to determine whether certain kinds of variation are
3516+
// allowed gets hairy very quickly. It's much simpler if there is only one
3517+
// set of permanent loaders that will be used for all purposes on both the
3518+
// client and the server.
3519+
//
3520+
// To ensure that for this compilation the server will use exactly the
3521+
// permanent loaders determined here, it suffices to tell the server how
3522+
// many there are, let's call it n. The server will know that this
3523+
// compilation is using the first n permanent loaders for this client. If it
3524+
// doesn't yet have all of the first n, then it will send a message to
3525+
// request the ones it's missing, and the response will preserve the
3526+
// ordering so that the first n on the server are the same as the first n on
3527+
// the client.
3528+
//
3529+
size_t numPermanentLoaders = compiler->permanentLoaders().size();
3530+
35213531
uint32_t statusCode = compilationFailure;
35223532
std::string codeCacheStr;
35233533
std::string dataCacheStr;
@@ -3549,7 +3559,7 @@ remoteCompile(J9VMThread *vmThread, TR::Compilation *compiler, TR_ResolvedMethod
35493559
detailsStr, details.getType(), unloadedClasses, illegalModificationList, classInfoTuple, optionsStr,
35503560
recompMethodInfoStr, chtableUpdates.first, chtableUpdates.second, useAotCompilation,
35513561
TR::Compiler->vm.isVMInStartupPhase(compInfoPT->getJitConfig()), aotCacheStore, aotCacheLoad, methodIndex,
3552-
classChainOffset, ramClassChain, uncachedRAMClasses, uncachedClassInfos, newKnownIds, newPermanentLoaders
3562+
classChainOffset, ramClassChain, uncachedRAMClasses, uncachedClassInfos, newKnownIds, numPermanentLoaders
35533563
);
35543564

35553565
JITServer::MessageType response;

runtime/compiler/control/JITServerCompilationThread.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ TR::CompilationInfoPerThreadRemote::processCompilationRequest(CompilationRequest
591591
auto &uncachedRAMClasses = std::get<22>(req);
592592
auto &uncachedClassInfos = std::get<23>(req);
593593
auto &newKnownIds = std::get<24>(req);
594-
auto &newPermanentLoaders = std::get<25>(req);
594+
size_t numPermanentLoaders = std::get<25>(req);
595595

596596
TR_ASSERT_FATAL(TR::Compiler->persistentMemory() == compInfo->persistentMemory(),
597597
"per-client persistent memory must not be set at this point");
@@ -669,8 +669,6 @@ TR::CompilationInfoPerThreadRemote::processCompilationRequest(CompilationRequest
669669
clientSession->getAOTCacheKnownIds().insert(newKnownIds.begin(), newKnownIds.end());
670670
}
671671

672-
clientSession->addPermanentLoaders(newPermanentLoaders);
673-
674672
// We must process unloaded classes lists in the same order they were generated at the client
675673
// Use a sequencing scheme to re-order compilation requests
676674
//
@@ -909,6 +907,7 @@ TR::CompilationInfoPerThreadRemote::processCompilationRequest(CompilationRequest
909907
// If we want something then we need to increaseQueueWeightBy(weight) while holding compilation monitor
910908
entry._weight = 0;
911909
entry._jitStateWhenQueued = compInfo->getPersistentInfo()->getJitState();
910+
entry._numPermanentLoaders = numPermanentLoaders;
912911
entry._stream = stream; // Add the stream to the entry
913912

914913
auto aotCache = clientSession->getOrCreateAOTCache(stream);

runtime/compiler/control/JITServerCompilationThread.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ using CompilationRequest = std::tuple<
4141
J9::IlGeneratorMethodDetailsType, std::vector<TR_OpaqueClassBlock *>, std::vector<TR_OpaqueClassBlock *>,
4242
JITServerHelpers::ClassInfoTuple, std::string, std::string, std::string, std::string,
4343
bool, bool, bool, bool, uint32_t, uintptr_t, std::vector<J9Class *>, std::vector<J9Class *>,
44-
std::vector<JITServerHelpers::ClassInfoTuple>, std::vector<uintptr_t>, std::vector<J9ClassLoader *>
44+
std::vector<JITServerHelpers::ClassInfoTuple>, std::vector<uintptr_t>, size_t
4545
>;
4646

4747
void outOfProcessCompilationEnd(TR_MethodToBeCompiled *entry, TR::Compilation *comp);

runtime/compiler/control/MethodToBeCompiled.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ void TR_MethodToBeCompiled::initialize(TR::IlGeneratorMethodDetails &details, vo
9797
_doNotLoadFromJITServerAOTCache = false;
9898
_useAOTCacheCompilation = false;
9999
_origOptLevel = unknownHotness;
100+
_numPermanentLoaders = SIZE_MAX;
100101
_stream = NULL;
101102
#endif /* defined(J9VM_OPT_JITSERVER) */
102103

runtime/compiler/control/MethodToBeCompiled.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,8 @@ struct TR_MethodToBeCompiled
171171
bool _useAOTCacheCompilation;
172172
// Cache original optLevel when transforming a remote sync compilation to a local cheap one
173173
TR_Hotness _origOptLevel;
174+
// On the server, the number of permanent loaders specified by the client for this compilation.
175+
size_t _numPermanentLoaders;
174176
// A non-NULL field denotes an out-of-process compilation request
175177
JITServer::ServerStream *_stream;
176178
#endif /* defined(J9VM_OPT_JITSERVER) */

0 commit comments

Comments
 (0)