[embedded] Handle retain/retain ops inside deinit in Embedded Swift's swift_release

This commit is contained in:
Kuba Mracek
2024-09-03 14:38:03 -07:00
parent bef5841697
commit 249f7e6073
2 changed files with 33 additions and 0 deletions

View File

@@ -291,6 +291,10 @@ func swift_release_n_(object: UnsafeMutablePointer<HeapObject>?, n: UInt32) {
let resultingRefcount = subFetchAcquireRelease(refcount, n: Int(n)) & HeapObject.refcountMask
if resultingRefcount == 0 {
// Set the refcount to immortalRefCount before calling the object destroyer
// to prevent future retains/releases from having any effect.
storeRelaxed(refcount, newValue: HeapObject.immortalRefCount)
_swift_embedded_invoke_heap_object_destroy(object)
} else if resultingRefcount < 0 {
fatalError("negative refcount")
@@ -350,6 +354,9 @@ fileprivate func storeRelease(_ atomic: UnsafeMutablePointer<Int>, newValue: Int
Builtin.atomicstore_release_Word(atomic._rawValue, newValue._builtinWordValue)
}
fileprivate func storeRelaxed(_ atomic: UnsafeMutablePointer<Int>, newValue: Int) {
Builtin.atomicstore_monotonic_Word(atomic._rawValue, newValue._builtinWordValue)
}
/// Exclusivity checking

View File

@@ -0,0 +1,26 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -O -c -o %t/main.o
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
// RUN: %target-run %t/a.out | %FileCheck %s
// REQUIRES: swift_in_compiler
// REQUIRES: executable_test
// REQUIRES: OS=macosx || OS=linux-gnu
class C {}
struct Foo {
let foo: C = C()
let bar: C = C()
}
class Bar {}
class SubBar: Bar {
var qwe = Foo()
}
var bar: SubBar? = SubBar()
bar = nil
print("OK!")
// CHECK: OK!