Skip to content

Commit 2741535

Browse files
committed
Add non-atomic variants to SideTable
1 parent e0fd2d5 commit 2741535

File tree

1 file changed

+66
-7
lines changed

1 file changed

+66
-7
lines changed

stdlib/public/SwiftShims/RefCount.h

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,12 @@ class RefCounts {
10001000
// object may have a side table entry.
10011001
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
10021002
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+
10041009
// First slow path of doDecrement, where the object may need to be deinited.
10051010
// Side table is handled in the second slow path, doDecrementSideTable().
10061011
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1042,6 +1047,42 @@ class RefCounts {
10421047

10431048
return deinitNow;
10441049
}
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+
}
10451086

10461087
public: // FIXME: access control hack
10471088

@@ -1066,8 +1107,6 @@ class RefCounts {
10661107

10671108
return false; // don't deinit
10681109
}
1069-
1070-
private:
10711110

10721111
// This is independently specialized below for inline and out-of-line use.
10731112
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
@@ -1292,9 +1331,13 @@ class HeapObjectSideTableEntry {
12921331
return refCounts.doDecrement<clearPinnedFlag, performDeinit>(dec);
12931332
}
12941333

1334+
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
1335+
bool decrementNonAtomicStrong(uint32_t dec) {
1336+
return refCounts.doDecrementNonAtomic<clearPinnedFlag, performDeinit>(dec);
1337+
}
1338+
12951339
void decrementFromOneNonAtomic() {
1296-
// FIXME: can there be a non-atomic implementation?
1297-
decrementStrong<DontClearPinnedFlag, DontPerformDeinit>(1);
1340+
decrementNonAtomicStrong<DontClearPinnedFlag, DontPerformDeinit>(1);
12981341
}
12991342

13001343
bool isDeiniting() const {
@@ -1431,12 +1474,12 @@ inline bool RefCounts<InlineRefCountBits>::doDecrementNonAtomic(uint32_t dec) {
14311474

14321475
// Use slow path if we can't guarantee atomicity.
14331476
if (oldbits.hasSideTable() || oldbits.getUnownedRefCount() != 1)
1434-
return doDecrementSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
1477+
return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
14351478

14361479
auto newbits = oldbits;
14371480
bool fast = newbits.decrementStrongExtraRefCount(dec, clearPinnedFlag);
14381481
if (!fast)
1439-
return doDecrementSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
1482+
return doDecrementNonAtomicSlow<clearPinnedFlag, performDeinit>(oldbits, dec);
14401483

14411484
refCounts.store(newbits, std::memory_order_relaxed);
14421485
return false; // don't deinit
@@ -1461,6 +1504,14 @@ doDecrementSideTable(InlineRefCountBits oldbits, uint32_t dec) {
14611504
return side->decrementStrong<clearPinnedFlag, performDeinit>(dec);
14621505
}
14631506

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+
14641515
template <>
14651516
template <ClearPinnedFlag clearPinnedFlag, PerformDeinit performDeinit>
14661517
inline bool RefCounts<SideTableRefCountBits>::
@@ -1469,6 +1520,14 @@ doDecrementSideTable(SideTableRefCountBits oldbits, uint32_t dec) {
14691520
"a side table entry of its own");
14701521
}
14711522

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+
14721531

14731532
template <> inline
14741533
HeapObject* RefCounts<InlineRefCountBits>::getHeapObject() const {

0 commit comments

Comments
 (0)