@@ -38,20 +38,21 @@ public struct HeapObject {
38
38
// to think about supporting (or banning) weak and/or unowned references.
39
39
var refcount : Int
40
40
41
+ // Note: The immortalRefCount value is also hard-coded in IRGen in `irgen::emitConstantObject`.
41
42
#if _pointerBitWidth(_64)
42
- static let doNotFreeBit = Int ( bitPattern: 0x8000_0000_0000_0000 )
43
- static let refcountMask = Int ( bitPattern: 0x7fff_ffff_ffff_ffff )
43
+ static let doNotFreeBit = Int ( bitPattern: 0x8000_0000_0000_0000 )
44
+ static let refcountMask = Int ( bitPattern: 0x7fff_ffff_ffff_ffff )
45
+ static let immortalRefCount = Int ( bitPattern: 0x7fff_ffff_ffff_ffff ) // Make sure we don't have doNotFreeBit set
44
46
#elseif _pointerBitWidth(_32)
45
- static let doNotFreeBit = Int ( bitPattern: 0x8000_0000 )
46
- static let refcountMask = Int ( bitPattern: 0x7fff_ffff )
47
+ static let doNotFreeBit = Int ( bitPattern: 0x8000_0000 )
48
+ static let refcountMask = Int ( bitPattern: 0x7fff_ffff )
49
+ static let immortalRefCount = Int ( bitPattern: 0x7fff_ffff ) // Make sure we don't have doNotFreeBit set
47
50
#elseif _pointerBitWidth(_16)
48
- static let doNotFreeBit = Int ( bitPattern: 0x8000 )
49
- static let refcountMask = Int ( bitPattern: 0x7fff )
51
+ static let doNotFreeBit = Int ( bitPattern: 0x8000 )
52
+ static let refcountMask = Int ( bitPattern: 0x7fff )
53
+ static let immortalRefCount = Int ( bitPattern: 0x7fff ) // Make sure we don't have doNotFreeBit set
50
54
#endif
51
55
52
- // Note: The immortalRefCount value of -1 is also hard-coded in IRGen in `irgen::emitConstantObject`.
53
- static let immortalRefCount = - 1
54
-
55
56
#if _pointerBitWidth(_64)
56
57
static let immortalObjectPointerBit = UInt ( 0x8000_0000_0000_0000 )
57
58
#endif
@@ -158,7 +159,7 @@ public func swift_initStaticObject(metadata: Builtin.RawPointer, object: Builtin
158
159
159
160
func swift_initStaticObject( metadata: UnsafeMutablePointer < ClassMetadata > , object: UnsafeMutablePointer < HeapObject > ) -> UnsafeMutablePointer < HeapObject > {
160
161
_swift_embedded_set_heap_object_metadata_pointer ( object, metadata)
161
- object. pointee. refcount = HeapObject . immortalRefCount
162
+ object. pointee. refcount = HeapObject . immortalRefCount | HeapObject . doNotFreeBit
162
163
return object
163
164
}
164
165
@@ -251,7 +252,7 @@ public func swift_retain_n(object: Builtin.RawPointer, n: UInt32) -> Builtin.Raw
251
252
252
253
func swift_retain_n_( object: UnsafeMutablePointer < HeapObject > , n: UInt32 ) -> UnsafeMutablePointer < HeapObject > {
253
254
let refcount = refcountPointer ( for: object)
254
- if loadRelaxed ( refcount) == HeapObject . immortalRefCount {
255
+ if loadRelaxed ( refcount) & HeapObject . refcountMask == HeapObject . immortalRefCount {
255
256
return object
256
257
}
257
258
@@ -294,7 +295,8 @@ func swift_release_n_(object: UnsafeMutablePointer<HeapObject>?, n: UInt32) {
294
295
}
295
296
296
297
let refcount = refcountPointer ( for: object)
297
- if loadRelaxed ( refcount) == HeapObject . immortalRefCount {
298
+ let loadedRefcount = loadRelaxed ( refcount)
299
+ if loadedRefcount & HeapObject . refcountMask == HeapObject . immortalRefCount {
298
300
return
299
301
}
300
302
@@ -309,7 +311,8 @@ func swift_release_n_(object: UnsafeMutablePointer<HeapObject>?, n: UInt32) {
309
311
// There can only be one thread with a reference at this point (because
310
312
// we're releasing the last existing reference), so a relaxed store is
311
313
// enough.
312
- storeRelaxed ( refcount, newValue: HeapObject . immortalRefCount)
314
+ let doNotFree = ( loadedRefcount & HeapObject . doNotFreeBit) != 0
315
+ storeRelaxed ( refcount, newValue: HeapObject . immortalRefCount | ( doNotFree ? HeapObject . doNotFreeBit : 0 ) )
313
316
314
317
_swift_embedded_invoke_heap_object_destroy ( object)
315
318
} else if resultingRefcount < 0 {
0 commit comments