Skip to content

Commit 6400df4

Browse files
committed
[IRGen] Balance out a retain count for createAsyncTask's context.
The `createAsyncTask` entry point expects the parent task to be "guaranteed" and the function to be "owned". However, that's not easy to model in the operand ownership map, so we consider all operands to be "guaranteed" and balance out the reference count when lowering the builtin. This is an egregious hack that will create a little extra reference count traffic.
1 parent 4c2c2f3 commit 6400df4

File tree

2 files changed

+8
-1
lines changed

2 files changed

+8
-1
lines changed

lib/IRGen/GenBuiltin.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ void irgen::emitBuiltinCall(IRGenFunction &IGF, const BuiltinInfo &Builtin,
230230
auto parentTask = args.claimNext();
231231
auto taskFunction = args.claimNext();
232232
auto taskContext = args.claimNext();
233+
234+
// FIXME: SIL treats the function/context parameter as "guaranteed", but
235+
// the runtime entry point assumes it is owned. Introduce an extra retain
236+
// of the context to balance things out.
237+
IGF.emitNativeStrongRetain(taskContext, IGF.getDefaultAtomicity());
238+
233239
auto newTaskAndContext = emitTaskCreate(
234240
IGF, flags, parentTask, taskFunction, taskContext);
235241

test/IRGen/async/builtins.sil

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@ bb0(%0 : @guaranteed $Builtin.NativeObject):
3333
sil hidden [ossa] @launch_task : $@convention(method) @async (Int, Optional<Builtin.NativeObject>, @guaranteed @async @callee_guaranteed () -> (@error Error)) -> () {
3434
bb0(%0 : $Int, %1: @unowned $Optional<Builtin.NativeObject>, %2: @guaranteed $@async @callee_guaranteed () -> (@error Error)):
3535
%3 = begin_borrow %1 : $Optional<Builtin.NativeObject>
36+
// CHECK: call %swift.refcounted* @swift_retain(%swift.refcounted* returned [[FN_CONTEXT:%.*]])
3637
// CHECK: [[NEW_TASK_AND_CONTEXT:%.*]] = call swiftcc %swift.async_task_and_context @swift_task_create_f
3738
// CHECK-NEXT: [[NEW_CONTEXT_RAW:%.*]] = extractvalue %swift.async_task_and_context [[NEW_TASK_AND_CONTEXT]], 1
3839
// CHECK-NEXT: [[NEW_CONTEXT:%.*]] = bitcast %swift.context* [[NEW_CONTEXT_RAW]] to
3940
// CHECK-NEXT: [[CONTEXT_INFO_LOC:%.*]] = getelementptr inbounds <{{.*}}>* [[NEW_CONTEXT]]
40-
// CHECK-NEXT: store %swift.refcounted* %{{.*}}, %swift.refcounted** [[CONTEXT_INFO_LOC]]
41+
// CHECK-NEXT: store %swift.refcounted* [[FN_CONTEXT]], %swift.refcounted** [[CONTEXT_INFO_LOC]]
4142
%20 = builtin "createAsyncTask"(%0 : $Int, %3 : $Optional<Builtin.NativeObject>, %2 : $@async @callee_guaranteed () -> (@error Error)) : $(Builtin.NativeObject, Builtin.RawPointer)
4243
end_borrow %3 : $Optional<Builtin.NativeObject>
4344
destroy_value %20 : $(Builtin.NativeObject, Builtin.RawPointer)

0 commit comments

Comments
 (0)