@@ -4427,27 +4427,6 @@ class FixLifetimeDestroyCleanup : public Cleanup {
44274427#endif
44284428 }
44294429};
4430-
4431- class EmitBreadcrumbCleanup : public Cleanup {
4432- ExecutorBreadcrumb breadcrumb;
4433-
4434- public:
4435- EmitBreadcrumbCleanup (ExecutorBreadcrumb &&breadcrumb)
4436- : breadcrumb(std::move(breadcrumb)) {}
4437-
4438- void emit (SILGenFunction &SGF, CleanupLocation l,
4439- ForUnwind_t forUnwind) override {
4440- breadcrumb.emit (SGF, l);
4441- }
4442-
4443- void dump (SILGenFunction &SGF) const override {
4444- #ifndef NDEBUG
4445- llvm::errs () << " EmitBreadcrumbCleanup "
4446- << " State:" << getState ()
4447- << " NeedsEmit:" << breadcrumb.needsEmit ();
4448- #endif
4449- }
4450- };
44514430} // end anonymous namespace
44524431
44534432// ===----------------------------------------------------------------------===//
@@ -4607,7 +4586,7 @@ RValue SILGenFunction::emitApply(
46074586 // generates `await_async_continuation`.
46084587 // Lifetime is extended by creating unmanaged copies here and by pushing the
46094588 // cleanups required just before the result plan is generated.
4610- SmallVector<SILValue , 8 > unmanagedCopies;
4589+ SmallVector<ManagedValue , 8 > unmanagedCopies;
46114590 if (calleeTypeInfo.foreign .async ) {
46124591 for (auto arg : args) {
46134592 if (arg.hasCleanup ()) {
@@ -4694,23 +4673,32 @@ RValue SILGenFunction::emitApply(
46944673 *foreignError, calleeTypeInfo.foreign .async );
46954674 }
46964675
4697- // For objc async calls, push cleanups to be used on
4698- // both result and throw paths prior to finishing the result plan.
4699- if (calleeTypeInfo.foreign .async ) {
4700- for (auto unmanagedCopy : unmanagedCopies) {
4701- Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(unmanagedCopy);
4702- }
4703- // save breadcrumb as a clean-up so it is emitted in result / throw cases.
4704- Cleanups.pushCleanup <EmitBreadcrumbCleanup>(std::move (breadcrumb));
4705- } else {
4706- assert (unmanagedCopies.empty ());
4676+ // For objc async calls, push cleanup to be used on throw paths in the result
4677+ // planner.
4678+ for (unsigned i : indices (unmanagedCopies)) {
4679+ SILValue value = unmanagedCopies[i].getValue ();
4680+ Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(value);
4681+ unmanagedCopies[i] = ManagedValue (value, Cleanups.getTopCleanup ());
47074682 }
47084683
47094684 auto directResultsArray = makeArrayRef (directResults);
47104685 RValue result = resultPlan->finish (*this , loc, substResultType,
47114686 directResultsArray, bridgedForeignError);
47124687 assert (directResultsArray.empty () && " didn't claim all direct results" );
47134688
4689+ // For objc async calls, generate cleanup on the resume path here and forward
4690+ // the previously pushed cleanups.
4691+ if (calleeTypeInfo.foreign .async ) {
4692+ for (auto unmanagedCopy : unmanagedCopies) {
4693+ auto value = unmanagedCopy.forward (*this );
4694+ B.emitFixLifetime (loc, value);
4695+ B.emitDestroyOperation (loc, value);
4696+ }
4697+
4698+ // hop back to the current executor
4699+ breadcrumb.emit (*this , loc);
4700+ }
4701+
47144702 return result;
47154703}
47164704
0 commit comments