@@ -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;
0 commit comments