Skip to content

Commit 0c0cdc7

Browse files
authored
Merge pull request swiftlang#37952 from jckarter/actor-hop-objc-async-5.5
[5.5] SILGen: Hop to the executor for actor-constrained methods in their @objc async thunks
2 parents 5f8726b + e5f928b commit 0c0cdc7

File tree

3 files changed

+33
-7
lines changed

3 files changed

+33
-7
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "ArgumentScope.h"
1414
#include "Callee.h"
15+
#include "ExecutorBreadcrumb.h"
1516
#include "RValue.h"
1617
#include "ResultPlan.h"
1718
#include "SILGenFunction.h"
@@ -1478,10 +1479,11 @@ SILFunction *SILGenFunction::emitNativeAsyncToForeignThunk(SILDeclRef thunk) {
14781479
}
14791480

14801481
// Create the closure implementation function. It has the same signature,
1481-
// but is just swiftcc and async.
1482+
// but is swiftcc and async.
14821483
auto closureExtInfo = objcFnTy->getExtInfo().intoBuilder()
14831484
.withRepresentation(SILFunctionTypeRepresentation::Thin)
14841485
.withAsync()
1486+
.withConcurrent()
14851487
.build();
14861488
auto closureTy = objcFnTy->getWithExtInfo(closureExtInfo);
14871489

@@ -1555,6 +1557,22 @@ void SILGenFunction::emitNativeToForeignThunk(SILDeclRef thunk) {
15551557
auto loc = thunk.getAsRegularLocation();
15561558
loc.markAutoGenerated();
15571559
Scope scope(Cleanups, CleanupLocation(loc));
1560+
1561+
// Hop to the actor for the method's actor constraint, if any.
1562+
// Note that, since an async native-to-foreign thunk only ever runs in a
1563+
// task purpose-built for running the Swift async code triggering the
1564+
// completion handler, there is no need for us to hop back to the existing
1565+
// executor, since the task will end after we invoke the completion handler.
1566+
if (F.isAsync()) {
1567+
Optional<ActorIsolation> isolation;
1568+
if (thunk.hasDecl()) {
1569+
isolation = getActorIsolation(thunk.getDecl());
1570+
}
1571+
1572+
if (isolation) {
1573+
emitHopToTargetActor(loc, *isolation, None);
1574+
}
1575+
}
15581576

15591577
// If we are bridging a Swift method with an Any return value, create a
15601578
// stack allocation to hold the result, since Any is address-only.

stdlib/public/Concurrency/Task.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -897,12 +897,8 @@ func _getCurrentThreadPriority() -> Int
897897
@available(SwiftStdlib 5.5, *)
898898
@_alwaysEmitIntoClient
899899
@usableFromInline
900-
internal func _runTaskForBridgedAsyncMethod(_ body: @escaping () async -> Void) {
901-
#if compiler(>=5.5) && $Sendable && $InheritActorContext && $ImplicitSelfCapture
902-
Task { await body() }
903-
#else
904-
Task.runDetached { await body() }
905-
#endif
900+
internal func _runTaskForBridgedAsyncMethod(@_inheritActorContext _ body: __owned @Sendable @escaping () async -> Void) {
901+
Task(operation: body)
906902
}
907903

908904
#endif

test/SILGen/objc_async_from_swift.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,15 @@ class SlowServerlet: SlowServer {
108108
}
109109
}
110110

111+
@globalActor actor FooActor {
112+
static var shared = FooActor()
113+
}
114+
115+
@FooActor
116+
class ActorConstrained: NSObject {
117+
// CHECK-LABEL: sil shared [thunk] [ossa] @$s{{.*}}16ActorConstrainedC3foo{{.*}}U_To
118+
// CHECK: hop_to_executor {{%.*}} : $FooActor
119+
@objc func foo() async -> Bool {
120+
return true
121+
}
122+
}

0 commit comments

Comments
 (0)