Skip to content

Commit ba16448

Browse files
authored
Merge pull request #38768 from DougGregor/foreign-async-hop-back-5.5
Emit `hop_to_executor` instructors for foreign `async` calls.
2 parents e94440a + ac3c024 commit ba16448

File tree

2 files changed

+37
-4
lines changed

2 files changed

+37
-4
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4414,7 +4414,7 @@ RValue SILGenFunction::emitApply(
44144414
}
44154415

44164416
ExecutorBreadcrumb breadcrumb;
4417-
4417+
44184418
// The presence of `implicitActorHopTarget` indicates that the callee is a
44194419
// synchronous function isolated to an actor other than our own.
44204420
// Such functions require the caller to hop to the callee's executor
@@ -4440,7 +4440,8 @@ RValue SILGenFunction::emitApply(
44404440
}
44414441

44424442
breadcrumb = emitHopToTargetExecutor(loc, executor);
4443-
} else if (ExpectedExecutor && substFnType->isAsync()) {
4443+
} else if (ExpectedExecutor &&
4444+
(substFnType->isAsync() || calleeTypeInfo.foreign.async)) {
44444445
// Otherwise, if we're in an actor method ourselves, and we're calling into
44454446
// any sort of async function, we'll want to make sure to hop back to our
44464447
// own executor afterward, since the callee could have made arbitrary hops
@@ -4457,8 +4458,10 @@ RValue SILGenFunction::emitApply(
44574458
rawDirectResult = rawDirectResults[0];
44584459
}
44594460

4460-
// hop back to the current executor
4461-
breadcrumb.emit(*this, loc);
4461+
if (!calleeTypeInfo.foreign.async) {
4462+
// hop back to the current executor
4463+
breadcrumb.emit(*this, loc);
4464+
}
44624465

44634466
// For objc async calls, lifetime extend the args until the result plan which
44644467
// generates `await_async_continuation`.
@@ -4570,6 +4573,9 @@ RValue SILGenFunction::emitApply(
45704573
B.emitFixLifetime(loc, value);
45714574
B.emitDestroyOperation(loc, value);
45724575
}
4576+
4577+
// hop back to the current executor
4578+
breadcrumb.emit(*this, loc);
45734579
}
45744580

45754581
return result;

test/SILGen/objc_async.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,30 @@ func testGeneric2<T: AnyObject, U>(x: GenericObject<T>, y: U) async throws {
161161
// CHECK: [[RESULT_1_BUF:%.*]] = tuple_element_addr [[RESULT_BUF]] {{.*}}, 1
162162
// CHECK: store %2 to [trivial] [[RESULT_1_BUF]]
163163

164+
// CHECK-LABEL: sil {{.*}}@${{.*}}22testSlowServerFromMain
165+
@MainActor
166+
func testSlowServerFromMain(slowServer: SlowServer) async throws {
167+
// CHECK: hop_to_executor %6 : $MainActor
168+
// CHECK: [[RESUME_BUF:%.*]] = alloc_stack $Int
169+
// CHECK: [[STRINGINIT:%.*]] = function_ref @$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF :
170+
// CHECK: [[ARG:%.*]] = apply [[STRINGINIT]]
171+
// CHECK: [[METHOD:%.*]] = objc_method {{.*}} $@convention(objc_method) (NSString, @convention(block) (Int) -> (), SlowServer) -> ()
172+
// CHECK: [[CONT:%.*]] = get_async_continuation_addr Int, [[RESUME_BUF]]
173+
// CHECK: [[WRAPPED:%.*]] = struct $UnsafeContinuation<Int, Never> ([[CONT]] : $Builtin.RawUnsafeContinuation)
174+
// CHECK: [[BLOCK_STORAGE:%.*]] = alloc_stack $@block_storage UnsafeContinuation<Int, Never>
175+
// CHECK: [[CONT_SLOT:%.*]] = project_block_storage [[BLOCK_STORAGE]]
176+
// CHECK: store [[WRAPPED]] to [trivial] [[CONT_SLOT]]
177+
// CHECK: [[BLOCK_IMPL:%.*]] = function_ref @[[INT_COMPLETION_BLOCK:.*]] : $@convention(c) (@inout_aliasable @block_storage UnsafeContinuation<Int, Never>, Int) -> ()
178+
// CHECK: [[BLOCK:%.*]] = init_block_storage_header [[BLOCK_STORAGE]] {{.*}}, invoke [[BLOCK_IMPL]]
179+
// CHECK: apply [[METHOD]]([[ARG]], [[BLOCK]], %0)
180+
// CHECK: [[COPY:%.*]] = copy_value [[ARG]]
181+
// CHECK: destroy_value [[ARG]]
182+
// CHECK: await_async_continuation [[CONT]] {{.*}}, resume [[RESUME:bb[0-9]+]]
183+
// CHECK: [[RESUME]]:
184+
// CHECK: [[RESULT:%.*]] = load [trivial] [[RESUME_BUF]]
185+
// CHECK: fix_lifetime [[COPY]]
186+
// CHECK: destroy_value [[COPY]]
187+
// CHECK: hop_to_executor %6 : $MainActor
188+
// CHECK: dealloc_stack [[RESUME_BUF]]
189+
let _: Int = await slowServer.doSomethingSlow("mail")
190+
}

0 commit comments

Comments
 (0)