Skip to content

Commit 249f7e6

Browse files
committed
[embedded] Handle retain/retain ops inside deinit in Embedded Swift's swift_release
1 parent bef5841 commit 249f7e6

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,10 @@ func swift_release_n_(object: UnsafeMutablePointer<HeapObject>?, n: UInt32) {
291291

292292
let resultingRefcount = subFetchAcquireRelease(refcount, n: Int(n)) & HeapObject.refcountMask
293293
if resultingRefcount == 0 {
294+
// Set the refcount to immortalRefCount before calling the object destroyer
295+
// to prevent future retains/releases from having any effect.
296+
storeRelaxed(refcount, newValue: HeapObject.immortalRefCount)
297+
294298
_swift_embedded_invoke_heap_object_destroy(object)
295299
} else if resultingRefcount < 0 {
296300
fatalError("negative refcount")
@@ -350,6 +354,9 @@ fileprivate func storeRelease(_ atomic: UnsafeMutablePointer<Int>, newValue: Int
350354
Builtin.atomicstore_release_Word(atomic._rawValue, newValue._builtinWordValue)
351355
}
352356

357+
fileprivate func storeRelaxed(_ atomic: UnsafeMutablePointer<Int>, newValue: Int) {
358+
Builtin.atomicstore_monotonic_Word(atomic._rawValue, newValue._builtinWordValue)
359+
}
353360

354361
/// Exclusivity checking
355362

test/embedded/deinit-release.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -enable-experimental-feature Embedded -O -c -o %t/main.o
3+
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
4+
// RUN: %target-run %t/a.out | %FileCheck %s
5+
6+
// REQUIRES: swift_in_compiler
7+
// REQUIRES: executable_test
8+
// REQUIRES: OS=macosx || OS=linux-gnu
9+
10+
class C {}
11+
12+
struct Foo {
13+
let foo: C = C()
14+
let bar: C = C()
15+
}
16+
17+
class Bar {}
18+
class SubBar: Bar {
19+
var qwe = Foo()
20+
}
21+
22+
var bar: SubBar? = SubBar()
23+
bar = nil
24+
print("OK!")
25+
26+
// CHECK: OK!

0 commit comments

Comments
 (0)