@@ -745,6 +745,9 @@ class RefCounts {
745
745
LLVM_ATTRIBUTE_NOINLINE
746
746
bool tryIncrementSlow (RefCountBits oldbits);
747
747
748
+ LLVM_ATTRIBUTE_NOINLINE
749
+ bool tryIncrementNonAtomicSlow (RefCountBits oldbits);
750
+
748
751
public:
749
752
enum Initialized_t { Initialized };
750
753
@@ -859,16 +862,17 @@ class RefCounts {
859
862
return true ;
860
863
}
861
864
862
- // Increment the reference count, unless the object is deallocating.
863
865
bool tryIncrementNonAtomic () {
864
- uint32_t oldval = __atomic_load_n (&refCount, __ATOMIC_RELAXED );
865
- if (oldval & RC_DEALLOCATING_FLAG) {
866
+ auto oldbits = refCounts. load (SWIFT_MEMORY_ORDER_CONSUME );
867
+ if (!oldbits. hasSideTable () && oldbits. getIsDeiniting ())
866
868
return false ;
867
- } else {
868
- uint32_t newval = oldval + RC_ONE;
869
- __atomic_store_n (&refCount, newval, __ATOMIC_RELAXED);
870
- return true ;
871
- }
869
+
870
+ auto newbits = oldbits;
871
+ bool fast = newbits.incrementStrongExtraRefCount (1 );
872
+ if (!fast)
873
+ return tryIncrementNonAtomicSlow (oldbits);
874
+ refCounts.store (newbits, std::memory_order_relaxed);
875
+ return true ;
872
876
}
873
877
874
878
// Simultaneously clear the pinned flag and decrement the reference
@@ -1089,6 +1093,18 @@ class RefCounts {
1089
1093
std::memory_order_relaxed));
1090
1094
}
1091
1095
1096
+ void incrementUnownedNonAtomic (uint32_t inc) {
1097
+ auto oldbits = refCounts.load (SWIFT_MEMORY_ORDER_CONSUME);
1098
+ if (oldbits.hasSideTable ())
1099
+ return oldbits.getSideTable ()->incrementUnownedNonAtomic (inc);
1100
+
1101
+ auto newbits = oldbits;
1102
+ assert (newbits.getUnownedRefCount () != 0 );
1103
+ newbits.incrementUnownedRefCount (inc);
1104
+ // FIXME: overflow check?
1105
+ refCounts.store (newbits, std::memory_order_relaxed);
1106
+ }
1107
+
1092
1108
// Decrement the unowned reference count.
1093
1109
// Return true if the caller should free the object.
1094
1110
bool decrementUnownedShouldFree (uint32_t dec) {
@@ -1117,6 +1133,29 @@ class RefCounts {
1117
1133
return performFree;
1118
1134
}
1119
1135
1136
+ bool decrementUnownedShouldFreeNonAtomic (uint32_t dec) {
1137
+ auto oldbits = refCounts.load (SWIFT_MEMORY_ORDER_CONSUME);
1138
+
1139
+ if (oldbits.hasSideTable ())
1140
+ return oldbits.getSideTable ()->decrementUnownedShouldFreeNonAtomic (dec);
1141
+
1142
+ bool performFree;
1143
+ auto newbits = oldbits;
1144
+ newbits.decrementUnownedRefCount (dec);
1145
+ if (newbits.getUnownedRefCount () == 0 ) {
1146
+ // DEINITED -> FREED or DEINITED -> DEAD
1147
+ // Caller will free the object. Weak decrement is handled by
1148
+ // HeapObjectSideTableEntry::decrementUnownedShouldFreeNonAtomic.
1149
+ assert (newbits.getIsDeiniting ());
1150
+ performFree = true ;
1151
+ } else {
1152
+ performFree = false ;
1153
+ }
1154
+ // FIXME: underflow check?
1155
+ refCounts.store (newbits, std::memory_order_relaxed);
1156
+ return performFree;
1157
+ }
1158
+
1120
1159
// Return unowned reference count.
1121
1160
// Note that this is not equal to the number of outstanding unowned pointers.
1122
1161
uint32_t getUnownedCount () const {
@@ -1163,6 +1202,16 @@ class RefCounts {
1163
1202
1164
1203
return performFree;
1165
1204
}
1205
+
1206
+ bool decrementWeakShouldCleanUpNonAtomic () {
1207
+ auto oldbits = refCounts.load (SWIFT_MEMORY_ORDER_CONSUME);
1208
+
1209
+ auto newbits = oldbits;
1210
+ auto performFree = newbits.decrementWeakRefCount ();
1211
+ refCounts.store (newbits, std::memory_order_relaxed);
1212
+
1213
+ return performFree;
1214
+ }
1166
1215
1167
1216
// Return weak reference count.
1168
1217
// Note that this is not equal to the number of outstanding weak pointers.
@@ -1260,6 +1309,14 @@ class HeapObjectSideTableEntry {
1260
1309
return refCounts.tryIncrementAndPin ();
1261
1310
}
1262
1311
1312
+ bool tryIncrementNonAtomic () {
1313
+ return refCounts.tryIncrementNonAtomic ();
1314
+ }
1315
+
1316
+ bool tryIncrementAndPinNonAtomic () {
1317
+ return refCounts.tryIncrementAndPinNonAtomic ();
1318
+ }
1319
+
1263
1320
// Return weak reference count.
1264
1321
// Note that this is not equal to the number of outstanding weak pointers.
1265
1322
uint32_t getCount () const {
@@ -1276,6 +1333,10 @@ class HeapObjectSideTableEntry {
1276
1333
return refCounts.incrementUnowned (inc);
1277
1334
}
1278
1335
1336
+ void incrementUnownedNonAtomic (uint32_t inc) {
1337
+ return refCounts.incrementUnownedNonAtomic (inc);
1338
+ }
1339
+
1279
1340
bool decrementUnownedShouldFree (uint32_t dec) {
1280
1341
bool shouldFree = refCounts.decrementUnownedShouldFree (dec);
1281
1342
if (shouldFree) {
@@ -1287,6 +1348,17 @@ class HeapObjectSideTableEntry {
1287
1348
return shouldFree;
1288
1349
}
1289
1350
1351
+ bool decrementUnownedShouldFreeNonAtomic (uint32_t dec) {
1352
+ bool shouldFree = refCounts.decrementUnownedShouldFreeNonAtomic (dec);
1353
+ if (shouldFree) {
1354
+ // DEINITED -> FREED
1355
+ // Caller will free the object.
1356
+ decrementWeakNonAtomic ();
1357
+ }
1358
+
1359
+ return shouldFree;
1360
+ }
1361
+
1290
1362
uint32_t getUnownedCount () const {
1291
1363
return refCounts.getUnownedCount ();
1292
1364
}
@@ -1320,6 +1392,19 @@ class HeapObjectSideTableEntry {
1320
1392
delete this ;
1321
1393
}
1322
1394
1395
+ void decrementWeakNonAtomic () {
1396
+ // FIXME: assertions
1397
+ // FIXME: optimize barriers
1398
+ bool cleanup = refCounts.decrementWeakShouldCleanUpNonAtomic ();
1399
+ if (!cleanup)
1400
+ return ;
1401
+
1402
+ // Weak ref count is now zero. Delete the side table entry.
1403
+ // FREED -> DEAD
1404
+ assert (refCounts.getUnownedCount () == 0 );
1405
+ delete this ;
1406
+ }
1407
+
1323
1408
uint32_t getWeakCount () const {
1324
1409
return refCounts.getWeakCount ();
1325
1410
}
0 commit comments