Skip to content

Commit 40817e8

Browse files
authored
Merge pull request #19472 from cjjdespres/deserializer-fixes
Ensure all necessary cached JITServer AOT cache records are valid during deserialization
2 parents f4d4782 + 8419f37 commit 40817e8

File tree

2 files changed

+114
-68
lines changed

2 files changed

+114
-68
lines changed

runtime/compiler/runtime/JITServerAOTDeserializer.cpp

Lines changed: 113 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,14 @@ JITServerLocalSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *re
460460
uintptr_t loaderOffset = (uintptr_t)-1;
461461
J9ClassLoader *loader = getClassLoader(record->classLoaderId(), loaderOffset, comp, wasReset);
462462
if (!loader)
463+
{
464+
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
465+
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
466+
"ERROR: Class loader for class %.*s ID %zu was marked invalid",
467+
RECORD_NAME(record), record->id()
468+
);
463469
return false;
470+
}
464471

465472
// Lookup the RAMClass by name in the class loader
466473
J9Class *ramClass = jitGetClassInClassloaderFromUTF8(comp->j9VMThread(), loader, (char *)record->name(),
@@ -1072,7 +1079,14 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassSerializationRecord *recor
10721079
// we simply fail to deserialize here.
10731080
auto loader = findInMap(_classLoaderIdMap, record->classLoaderId(), getClassLoaderMonitor(), comp, wasReset);
10741081
if (!loader)
1082+
{
1083+
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
1084+
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
1085+
"ERROR: Class loader for class %.*s ID %zu was marked invalid",
1086+
RECORD_NAME(record), record->id()
1087+
);
10751088
return false;
1089+
}
10761090

10771091
// Lookup the RAMClass by name in the class loader
10781092
J9Class *ramClass = jitGetClassInClassloaderFromUTF8(comp->j9VMThread(), loader, (char *)record->name(),
@@ -1156,24 +1170,6 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const MethodSerializationRecord *reco
11561170
return true;
11571171
}
11581172

1159-
// We confirmed that the first class in the chain had a RAM class chain that was equal to
1160-
// what was recorded at compile time, but that may have changed (due to class redefinition or
1161-
// invalidation somewhere along the chain). Since we don't support class reloading, we only
1162-
// have to check that the individual class entries remain valid.
1163-
bool
1164-
JITServerNoSCCAOTDeserializer::revalidateClassChain(uintptr_t *classChain, TR::Compilation *comp, bool &wasReset)
1165-
{
1166-
size_t chainLength = classChain[0] / sizeof(classChain[0]) - 1;
1167-
uintptr_t *chainData = classChain + 1;
1168-
for (size_t i = 0; i < chainLength; ++i)
1169-
{
1170-
auto ramClass = findInMap(_classIdMap, offsetId(chainData[i]), getClassMonitor(), comp, wasReset)._ramClass;
1171-
if (!ramClass)
1172-
return false;
1173-
}
1174-
return true;
1175-
}
1176-
11771173
void
11781174
JITServerNoSCCAOTDeserializer::getRAMClassChain(TR::Compilation *comp, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength)
11791175
{
@@ -1214,22 +1210,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *
12141210

12151211
auto it = _classChainMap.find(record->id());
12161212
if (it != _classChainMap.end())
1217-
{
1218-
if (revalidateClassChain(it->second, comp, wasReset))
1219-
{
1220-
return true;
1221-
}
1222-
else
1223-
{
1224-
TR::Compiler->persistentGlobalMemory()->freePersistentMemory(it->second);
1225-
it->second = NULL;
1226-
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
1227-
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
1228-
"Invalidated cached class chain record ID %zu", record->id()
1229-
);
1230-
return false;
1231-
}
1232-
}
1213+
return true;
12331214
isNew = true;
12341215

12351216
// Get the RAM class chain for the first class referenced in the class chain serialization record
@@ -1298,21 +1279,6 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const ClassChainSerializationRecord *
12981279
return true;
12991280
}
13001281

1301-
// See revalidateClassChain()
1302-
bool
1303-
JITServerNoSCCAOTDeserializer::revalidateWellKnownClasses(uintptr_t *wellKnownClassesChain, TR::Compilation *comp, bool &wasReset)
1304-
{
1305-
size_t chainLength = wellKnownClassesChain[0];
1306-
uintptr_t *chainData = wellKnownClassesChain + 1;
1307-
for (size_t i = 0; i < chainLength; ++i)
1308-
{
1309-
auto classChain = findInMap(_classChainMap, offsetId(chainData[i]), getClassChainMonitor(), comp, wasReset);
1310-
if (!classChain)
1311-
return false;
1312-
}
1313-
return true;
1314-
}
1315-
13161282
bool
13171283
JITServerNoSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset)
13181284
{
@@ -1322,22 +1288,7 @@ JITServerNoSCCAOTDeserializer::cacheRecord(const WellKnownClassesSerializationRe
13221288

13231289
auto it = _wellKnownClassesMap.find(record->id());
13241290
if (it != _wellKnownClassesMap.end())
1325-
{
1326-
if (revalidateWellKnownClasses(it->second, comp, wasReset))
1327-
{
1328-
return true;
1329-
}
1330-
else
1331-
{
1332-
TR::Compiler->persistentGlobalMemory()->freePersistentMemory(it->second);
1333-
it->second = NULL;
1334-
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
1335-
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
1336-
"Invalidated cached well-known classes record ID %zu", record->id()
1337-
);
1338-
return false;
1339-
}
1340-
}
1291+
return true;
13411292
isNew = true;
13421293

13431294
// Initialize the "well-known classes" object (see SymbolValidationManager::populateWellKnownClasses()).
@@ -1414,6 +1365,8 @@ JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR:
14141365
if (serializedOffset.recordType() == AOTSerializationRecordType::Thunk)
14151366
continue;
14161367

1368+
if (!revalidateRecord(serializedOffset.recordType(), serializedOffset.recordId(), comp, wasReset))
1369+
return false;
14171370
uintptr_t offset = encodeOffset(serializedOffset);
14181371

14191372
// Update the SCC offset stored in AOT method relocation data
@@ -1435,6 +1388,101 @@ JITServerNoSCCAOTDeserializer::updateSCCOffsets(SerializedAOTMethod *method, TR:
14351388
return true;
14361389
}
14371390

1391+
bool
1392+
JITServerNoSCCAOTDeserializer::revalidateRecord(AOTSerializationRecordType type, uintptr_t id, TR::Compilation *comp, bool &wasReset)
1393+
{
1394+
switch (type)
1395+
{
1396+
case ClassLoader:
1397+
{
1398+
auto loader = findInMap(_classLoaderIdMap, id, getClassLoaderMonitor(), comp, wasReset);
1399+
return !wasReset && (loader != NULL);
1400+
}
1401+
case Class:
1402+
{
1403+
auto clazz = findInMap(_classIdMap, id, getClassMonitor(), comp, wasReset)._ramClass;
1404+
return !wasReset && (clazz != NULL);
1405+
}
1406+
case Method:
1407+
{
1408+
auto method = findInMap(_methodIdMap, id, getMethodMonitor(), comp, wasReset);
1409+
return !wasReset && (method != NULL);
1410+
}
1411+
case ClassChain:
1412+
{
1413+
// Why do we need to revalidate the entire chain here?
1414+
// Note that only serialization records the server thinks the client needs are sent to the client,
1415+
// and only offsets used in the method's relocation records get serialized SCC offsets. That means
1416+
// that we aren't guaranteed to have revalidated every class mentioned in this class chain, and so
1417+
// we must check the entire chain here.
1418+
OMR::CriticalSection cs(getClassChainMonitor());
1419+
if (deserializerWasReset(comp, wasReset))
1420+
return false;
1421+
1422+
auto it = _classChainMap.find(id);
1423+
if (it == _classChainMap.end() || !it->second)
1424+
return false;
1425+
1426+
size_t chainLength = it->second[0] / sizeof(it->second[0]) - 1;
1427+
uintptr_t *chainData = it->second + 1;
1428+
for (size_t i = 0; i < chainLength; ++i)
1429+
{
1430+
auto ramClass = findInMap(_classIdMap, offsetId(chainData[i]), getClassMonitor(), comp, wasReset)._ramClass;
1431+
if (!ramClass)
1432+
{
1433+
TR::Compiler->persistentGlobalMemory()->freePersistentMemory(it->second);
1434+
it->second = NULL;
1435+
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
1436+
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
1437+
"Invalidated cached class chain record ID %zu", id
1438+
);
1439+
return false;
1440+
}
1441+
}
1442+
return true;
1443+
}
1444+
case WellKnownClasses:
1445+
{
1446+
// See the note for case ClassChain
1447+
OMR::CriticalSection cs(getWellKnownClassesMonitor());
1448+
if (deserializerWasReset(comp, wasReset))
1449+
return false;
1450+
1451+
auto it = _wellKnownClassesMap.find(id);
1452+
if ((it == _wellKnownClassesMap.end()) || !it->second)
1453+
return false;
1454+
1455+
size_t chainLength = it->second[0];
1456+
uintptr_t *chainData = it->second + 1;
1457+
for (size_t i = 0; i < chainLength; ++i)
1458+
{
1459+
auto classChain = findInMap(_classChainMap, offsetId(chainData[i]), getClassChainMonitor(), comp, wasReset);
1460+
if (!classChain)
1461+
{
1462+
TR::Compiler->persistentGlobalMemory()->freePersistentMemory(it->second);
1463+
it->second = NULL;
1464+
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
1465+
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
1466+
"Invalidated cached well-known classes record ID %zu", id
1467+
);
1468+
return false;
1469+
}
1470+
}
1471+
return true;
1472+
}
1473+
case Thunk:
1474+
{
1475+
// Thunks are not cached, so do not need to be revalidated
1476+
return true;
1477+
}
1478+
default:
1479+
{
1480+
TR_ASSERT_FATAL(false, "Invalid record type: %u", type);
1481+
return false;
1482+
}
1483+
}
1484+
}
1485+
14381486
J9ROMClass *
14391487
JITServerNoSCCAOTDeserializer::romClassFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset)
14401488
{

runtime/compiler/runtime/JITServerAOTDeserializer.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,10 @@ class JITServerNoSCCAOTDeserializer : public JITServerAOTDeserializer
296296
virtual bool cacheRecord(const ThunkSerializationRecord *record, TR::Compilation *comp, bool &isNew, bool &wasReset) override;
297297

298298
virtual bool updateSCCOffsets(SerializedAOTMethod *method, TR::Compilation *comp, bool &wasReset, bool &usesSVM) override;
299+
bool revalidateRecord(AOTSerializationRecordType type, uintptr_t id, TR::Compilation *comp, bool &wasReset);
299300

300-
bool revalidateClassChain(uintptr_t *classChain, TR::Compilation *comp, bool &wasReset);
301301
void getRAMClassChain(TR::Compilation *comp, J9Class *clazz, J9Class **chainBuffer, size_t &chainLength);
302302

303-
bool revalidateWellKnownClasses(uintptr_t *wellKnownClassesChain, TR::Compilation *comp, bool &wasReset);
304-
305303
J9ROMClass *romClassFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset);
306304
void *pointerFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset);
307305
J9ROMMethod *romMethodFromOffsetInSharedCache(uintptr_t offset, TR::Compilation *comp, bool &wasReset);

0 commit comments

Comments
 (0)