@@ -1221,13 +1221,15 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
1221
1221
++searchTries;
1222
1222
1223
1223
Item* candidate = itr.get ();
1224
+ mmContainer.remove (itr);
1225
+ itr.destroy ();
1226
+
1224
1227
// for chained items, the ownership of the parent can change. We try to
1225
1228
// evict what we think as parent and see if the eviction of parent
1226
1229
// recycles the child we intend to.
1227
- auto toReleaseHandle =
1228
- itr->isChainedItem ()
1229
- ? advanceIteratorAndTryEvictChainedItem (itr)
1230
- : advanceIteratorAndTryEvictRegularItem (mmContainer, itr);
1230
+ auto toReleaseHandle = candidate->isChainedItem ()
1231
+ ? tryEvictChainedItem (*candidate)
1232
+ : tryEvictRegularItem (mmContainer, *candidate);
1231
1233
1232
1234
if (toReleaseHandle) {
1233
1235
if (toReleaseHandle->hasChainedItem ()) {
@@ -1236,10 +1238,6 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
1236
1238
(*stats_.regularItemEvictions )[pid][cid].inc ();
1237
1239
}
1238
1240
1239
- // Invalidate iterator since later on we may use this mmContainer
1240
- // again, which cannot be done unless we drop this iterator
1241
- itr.destroy ();
1242
-
1243
1241
// we must be the last handle and for chained items, this will be
1244
1242
// the parent.
1245
1243
XDCHECK (toReleaseHandle.get () == candidate || candidate->isChainedItem ());
@@ -1263,11 +1261,9 @@ CacheAllocator<CacheTrait>::findEviction(PoolId pid, ClassId cid) {
1263
1261
}
1264
1262
}
1265
1263
1266
- // If we destroyed the itr to possibly evict and failed, we restart
1267
- // from the beginning again
1268
- if (!itr) {
1269
- itr.resetToBegin ();
1270
- }
1264
+ // Insert item back to the mmContainer if eviction failed.
1265
+ mmContainer.add (*candidate);
1266
+ itr.resetToBegin ();
1271
1267
}
1272
1268
return nullptr ;
1273
1269
}
@@ -1322,19 +1318,17 @@ bool CacheAllocator<CacheTrait>::shouldWriteToNvmCacheExclusive(
1322
1318
1323
1319
template <typename CacheTrait>
1324
1320
typename CacheAllocator<CacheTrait>::WriteHandle
1325
- CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
1326
- MMContainer& mmContainer, EvictionIterator& itr ) {
1321
+ CacheAllocator<CacheTrait>::tryEvictRegularItem(MMContainer& mmContainer,
1322
+ Item& item ) {
1327
1323
// we should flush this to nvmcache if it is not already present in nvmcache
1328
1324
// and the item is not expired.
1329
- Item& item = *itr;
1330
1325
const bool evictToNvmCache = shouldWriteToNvmCache (item);
1331
1326
1332
1327
auto token = evictToNvmCache ? nvmCache_->createPutToken (item.getKey ())
1333
1328
: typename NvmCacheT::PutToken{};
1334
1329
// record the in-flight eviciton. If not, we move on to next item to avoid
1335
1330
// stalling eviction.
1336
1331
if (evictToNvmCache && !token.isValid ()) {
1337
- ++itr;
1338
1332
stats_.evictFailConcurrentFill .inc ();
1339
1333
return WriteHandle{};
1340
1334
}
@@ -1346,12 +1340,10 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
1346
1340
auto evictHandle = accessContainer_->removeIf (item, &itemEvictionPredicate);
1347
1341
1348
1342
if (!evictHandle) {
1349
- ++itr;
1350
1343
stats_.evictFailAC .inc ();
1351
1344
return evictHandle;
1352
1345
}
1353
1346
1354
- mmContainer.remove (itr);
1355
1347
XDCHECK_EQ (reinterpret_cast <uintptr_t >(evictHandle.get ()),
1356
1348
reinterpret_cast <uintptr_t >(&item));
1357
1349
XDCHECK (!evictHandle->isInMMContainer ());
@@ -1366,15 +1358,6 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
1366
1358
return WriteHandle{};
1367
1359
}
1368
1360
1369
- // Invalidate iterator since later on if we are not evicting this
1370
- // item, we may need to rely on the handle we created above to ensure
1371
- // proper cleanup if the item's raw refcount has dropped to 0.
1372
- // And since this item may be a parent item that has some child items
1373
- // in this very same mmContainer, we need to make sure we drop this
1374
- // exclusive iterator so we can gain access to it when we're cleaning
1375
- // up the child items
1376
- itr.destroy ();
1377
-
1378
1361
// Ensure that there are no accessors after removing from the access
1379
1362
// container
1380
1363
XDCHECK (evictHandle->getRefCount () == 1 );
@@ -1388,12 +1371,10 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictRegularItem(
1388
1371
1389
1372
template <typename CacheTrait>
1390
1373
typename CacheAllocator<CacheTrait>::WriteHandle
1391
- CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
1392
- EvictionIterator& itr) {
1393
- XDCHECK (itr->isChainedItem ());
1374
+ CacheAllocator<CacheTrait>::tryEvictChainedItem(Item& item) {
1375
+ XDCHECK (item.isChainedItem ());
1394
1376
1395
- ChainedItem* candidate = &itr->asChainedItem ();
1396
- ++itr;
1377
+ ChainedItem* candidate = &item.asChainedItem ();
1397
1378
1398
1379
// The parent could change at any point through transferChain. However, if
1399
1380
// that happens, we would realize that the releaseBackToAllocator return
@@ -1420,23 +1401,11 @@ CacheAllocator<CacheTrait>::advanceIteratorAndTryEvictChainedItem(
1420
1401
return parentHandle;
1421
1402
}
1422
1403
1423
- // Invalidate iterator since later on we may use the mmContainer
1424
- // associated with this iterator which cannot be done unless we
1425
- // drop this iterator
1426
- //
1427
- // This must be done once we know the parent is not nullptr.
1428
- // Since we can very well be the last holder of this parent item,
1429
- // which may have a chained item that is linked in this MM container.
1430
- itr.destroy ();
1431
-
1432
1404
// Ensure we have the correct parent and we're the only user of the
1433
1405
// parent, then free it from access container. Otherwise, we abort
1434
1406
XDCHECK_EQ (reinterpret_cast <uintptr_t >(&parent),
1435
1407
reinterpret_cast <uintptr_t >(parentHandle.get ()));
1436
1408
XDCHECK_EQ (1u , parent.getRefCount ());
1437
-
1438
- removeFromMMContainer (*parentHandle);
1439
-
1440
1409
XDCHECK (!parent.isInMMContainer ());
1441
1410
XDCHECK (!parent.isAccessible ());
1442
1411
0 commit comments