Skip to content

Commit fa09001

Browse files
mikeashDougGregor
authored andcommitted
Fix actor/job/task leaks in the back deployment runtime.
When initializing an actor, job, or task, use _swift_instantiateInertHeapObject to have the OS's libswiftCore set up the object's refcounts field, to ensure we get a valid initial state. There is no equivalent for immortal objects, but by a stroke of luck the new representation for immortal refcounts happens to set the immortal bit in the old representation. rdar://93087343
1 parent b43e864 commit fa09001

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

stdlib/public/BackDeployConcurrency/Actor.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,23 @@ class alignas(Alignment_DefaultActor) DefaultActor : public HeapObject {
3131
// destructor does not destroy the actor instance; you must call
3232
// swift_defaultActor_{initialize,destroy} yourself.
3333
constexpr DefaultActor(const HeapMetadata *metadata)
34-
: HeapObject(metadata), PrivateData{} {}
34+
: HeapObject(metadata), PrivateData{} {
35+
initHeapObject();
36+
}
3537

3638
constexpr DefaultActor(const HeapMetadata *metadata,
3739
InlineRefCounts::Immortal_t immortal)
38-
: HeapObject(metadata, immortal), PrivateData{} {}
40+
: HeapObject(metadata, immortal), PrivateData{} {
41+
// By a lucky coincidence, the modern bit pattern for immortal objects also
42+
// sets the immortal bit for older runtimes, so we don't need an immortal
43+
// equivalent to initHeapObject().
44+
}
45+
46+
void initHeapObject() {
47+
#ifdef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
48+
_swift_instantiateInertHeapObject(this, metadata);
49+
#endif
50+
}
3951

4052
void *PrivateData[NumWords_DefaultActor];
4153
};

stdlib/public/BackDeployConcurrency/Task.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class alignas(2 * alignof(void*)) Job :
9595
Job(JobFlags flags, JobInvokeFunction *invoke,
9696
const HeapMetadata *metadata = &jobHeapMetadata)
9797
: HeapObject(metadata), Flags(flags), RunJob(invoke) {
98+
initHeapObject();
9899
Voucher = voucher_copy();
99100
assert(!isAsyncTask() && "wrong constructor for a task");
100101
}
@@ -103,6 +104,7 @@ class alignas(2 * alignof(void*)) Job :
103104
const HeapMetadata *metadata = &jobHeapMetadata,
104105
bool captureCurrentVoucher = true)
105106
: HeapObject(metadata), Flags(flags), ResumeTask(invoke) {
107+
initHeapObject();
106108
if (captureCurrentVoucher)
107109
Voucher = voucher_copy();
108110
assert(isAsyncTask() && "wrong constructor for a non-task job");
@@ -114,11 +116,20 @@ class alignas(2 * alignof(void*)) Job :
114116
const HeapMetadata *metadata, InlineRefCounts::Immortal_t immortal,
115117
bool captureCurrentVoucher = true)
116118
: HeapObject(metadata, immortal), Flags(flags), ResumeTask(invoke) {
119+
// By a lucky coincidence, the modern bit pattern for immortal objects also
120+
// sets the immortal bit for older runtimes, so we don't need an immortal
121+
// equivalent to initHeapObject().
117122
if (captureCurrentVoucher)
118123
Voucher = voucher_copy();
119124
assert(isAsyncTask() && "wrong constructor for a non-task job");
120125
}
121126

127+
void initHeapObject() {
128+
#ifdef SWIFT_CONCURRENCY_BACK_DEPLOYMENT
129+
_swift_instantiateInertHeapObject(this, metadata);
130+
#endif
131+
}
132+
122133
~Job() { swift_voucher_release(Voucher); }
123134

124135
bool isAsyncTask() const {

0 commit comments

Comments
 (0)