@@ -1000,7 +1000,12 @@ class RefCounts {
1000
1000
// object may have a side table entry.
1001
1001
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1002
1002
bool doDecrementSideTable (RefCountBits oldbits, uint32_t dec);
1003
-
1003
+
1004
+ // Second slow path of doDecrementNonAtomic, where the
1005
+ // object may have a side table entry.
1006
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1007
+ bool doDecrementNonAtomicSideTable (RefCountBits oldbits, uint32_t dec);
1008
+
1004
1009
// First slow path of doDecrement, where the object may need to be deinited.
1005
1010
// Side table is handled in the second slow path, doDecrementSideTable().
1006
1011
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1042,6 +1047,42 @@ class RefCounts {
1042
1047
1043
1048
return deinitNow;
1044
1049
}
1050
+
1051
+ // First slow path of doDecrementNonAtomic, where the object may need to be deinited.
1052
+ // Side table is handled in the second slow path, doDecrementNonAtomicSideTable().
1053
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1054
+ bool doDecrementNonAtomicSlow (RefCountBits oldbits, uint32_t dec) {
1055
+ bool deinitNow;
1056
+ auto newbits = oldbits;
1057
+
1058
+ bool fast = newbits.decrementStrongExtraRefCount (dec, clearPinnedFlag);
1059
+ if (fast) {
1060
+ // Decrement completed normally. New refcount is not zero.
1061
+ deinitNow = false ;
1062
+ }
1063
+ else if (oldbits.hasSideTable ()) {
1064
+ // Decrement failed because we're on some other slow path.
1065
+ return doDecrementNonAtomicSideTable<clearPinnedFlag,
1066
+ performDeinit>(oldbits, dec);
1067
+ }
1068
+ else {
1069
+ // Decrement underflowed. Begin deinit.
1070
+ // LIVE -> DEINITING
1071
+ deinitNow = true ;
1072
+ assert (!oldbits.getIsDeiniting ()); // FIXME: make this an error?
1073
+ newbits = oldbits; // Undo failed decrement of newbits.
1074
+ newbits.setStrongExtraRefCount (0 );
1075
+ newbits.setIsDeiniting (true );
1076
+ if (clearPinnedFlag)
1077
+ newbits.setIsPinned (false );
1078
+ }
1079
+ refCounts.store (newbits, std::memory_order_relaxed);
1080
+ if (performDeinit && deinitNow) {
1081
+ _swift_release_dealloc (getHeapObject ());
1082
+ }
1083
+
1084
+ return deinitNow;
1085
+ }
1045
1086
1046
1087
public: // FIXME: access control hack
1047
1088
@@ -1066,8 +1107,6 @@ class RefCounts {
1066
1107
1067
1108
return false ; // don't deinit
1068
1109
}
1069
-
1070
- private:
1071
1110
1072
1111
// This is independently specialized below for inline and out-of-line use.
1073
1112
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1292,9 +1331,13 @@ class HeapObjectSideTableEntry {
1292
1331
return refCounts.doDecrement <clearPinnedFlag, performDeinit>(dec);
1293
1332
}
1294
1333
1334
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1335
+ bool decrementNonAtomicStrong (uint32_t dec) {
1336
+ return refCounts.doDecrementNonAtomic <clearPinnedFlag, performDeinit>(dec);
1337
+ }
1338
+
1295
1339
void decrementFromOneNonAtomic () {
1296
- // FIXME: can there be a non-atomic implementation?
1297
- decrementStrong<DontClearPinnedFlag, DontPerformDeinit>(1 );
1340
+ decrementNonAtomicStrong<DontClearPinnedFlag, DontPerformDeinit>(1 );
1298
1341
}
1299
1342
1300
1343
bool isDeiniting () const {
@@ -1431,12 +1474,12 @@ inline bool RefCounts<InlineRefCountBits>::doDecrementNonAtomic(uint32_t dec) {
1431
1474
1432
1475
// Use slow path if we can't guarantee atomicity.
1433
1476
if (oldbits.hasSideTable () || oldbits.getUnownedRefCount () != 1 )
1434
- return doDecrementSlow <clearPinnedFlag, performDeinit>(oldbits, dec);
1477
+ return doDecrementNonAtomicSlow <clearPinnedFlag, performDeinit>(oldbits, dec);
1435
1478
1436
1479
auto newbits = oldbits;
1437
1480
bool fast = newbits.decrementStrongExtraRefCount (dec, clearPinnedFlag);
1438
1481
if (!fast)
1439
- return doDecrementSlow <clearPinnedFlag, performDeinit>(oldbits, dec);
1482
+ return doDecrementNonAtomicSlow <clearPinnedFlag, performDeinit>(oldbits, dec);
1440
1483
1441
1484
refCounts.store (newbits, std::memory_order_relaxed);
1442
1485
return false ; // don't deinit
@@ -1461,6 +1504,14 @@ doDecrementSideTable(InlineRefCountBits oldbits, uint32_t dec) {
1461
1504
return side->decrementStrong <clearPinnedFlag, performDeinit>(dec);
1462
1505
}
1463
1506
1507
+ template <>
1508
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1509
+ inline bool RefCounts<InlineRefCountBits>::
1510
+ doDecrementNonAtomicSideTable (InlineRefCountBits oldbits, uint32_t dec) {
1511
+ auto side = oldbits.getSideTable ();
1512
+ return side->decrementNonAtomicStrong <clearPinnedFlag, performDeinit>(dec);
1513
+ }
1514
+
1464
1515
template <>
1465
1516
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1466
1517
inline bool RefCounts<SideTableRefCountBits>::
@@ -1469,6 +1520,14 @@ doDecrementSideTable(SideTableRefCountBits oldbits, uint32_t dec) {
1469
1520
" a side table entry of its own" );
1470
1521
}
1471
1522
1523
+ template <>
1524
+ template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1525
+ inline bool RefCounts<SideTableRefCountBits>::
1526
+ doDecrementNonAtomicSideTable (SideTableRefCountBits oldbits, uint32_t dec) {
1527
+ swift::crash (" side table refcount must not have "
1528
+ " a side table entry of its own" );
1529
+ }
1530
+
1472
1531
1473
1532
template <> inline
1474
1533
HeapObject* RefCounts<InlineRefCountBits>::getHeapObject() const {
0 commit comments