@@ -4430,6 +4430,27 @@ class FixLifetimeDestroyCleanup : public Cleanup {
44304430#endif
44314431 }
44324432};
4433+
4434+ class EmitBreadcrumbCleanup : public Cleanup {
4435+ ExecutorBreadcrumb breadcrumb;
4436+
4437+ public:
4438+ EmitBreadcrumbCleanup (ExecutorBreadcrumb &&breadcrumb)
4439+ : breadcrumb(std::move(breadcrumb)) {}
4440+
4441+ void emit (SILGenFunction &SGF, CleanupLocation l,
4442+ ForUnwind_t forUnwind) override {
4443+ breadcrumb.emit (SGF, l);
4444+ }
4445+
4446+ void dump (SILGenFunction &SGF) const override {
4447+ #ifndef NDEBUG
4448+ llvm::errs () << " EmitBreadcrumbCleanup "
4449+ << " State:" << getState ()
4450+ << " NeedsEmit:" << breadcrumb.needsEmit ();
4451+ #endif
4452+ }
4453+ };
44334454} // end anonymous namespace
44344455
44354456// ===----------------------------------------------------------------------===//
@@ -4589,7 +4610,7 @@ RValue SILGenFunction::emitApply(
45894610 // generates `await_async_continuation`.
45904611 // Lifetime is extended by creating unmanaged copies here and by pushing the
45914612 // cleanups required just before the result plan is generated.
4592- SmallVector<ManagedValue , 8 > unmanagedCopies;
4613+ SmallVector<SILValue , 8 > unmanagedCopies;
45934614 if (calleeTypeInfo.foreign .async ) {
45944615 for (auto arg : args) {
45954616 if (arg.hasCleanup ()) {
@@ -4676,32 +4697,23 @@ RValue SILGenFunction::emitApply(
46764697 *foreignError, calleeTypeInfo.foreign .async );
46774698 }
46784699
4679- // For objc async calls, push cleanup to be used on throw paths in the result
4680- // planner.
4681- for (unsigned i : indices (unmanagedCopies)) {
4682- SILValue value = unmanagedCopies[i].getValue ();
4683- Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(value);
4684- unmanagedCopies[i] = ManagedValue (value, Cleanups.getTopCleanup ());
4700+ // For objc async calls, push cleanups to be used on
4701+ // both result and throw paths prior to finishing the result plan.
4702+ if (calleeTypeInfo.foreign .async ) {
4703+ for (auto unmanagedCopy : unmanagedCopies) {
4704+ Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(unmanagedCopy);
4705+ }
4706+ // save breadcrumb as a clean-up so it is emitted in result / throw cases.
4707+ Cleanups.pushCleanup <EmitBreadcrumbCleanup>(std::move (breadcrumb));
4708+ } else {
4709+ assert (unmanagedCopies.empty ());
46854710 }
46864711
46874712 auto directResultsArray = makeArrayRef (directResults);
46884713 RValue result = resultPlan->finish (*this , loc, substResultType,
46894714 directResultsArray, bridgedForeignError);
46904715 assert (directResultsArray.empty () && " didn't claim all direct results" );
46914716
4692- // For objc async calls, generate cleanup on the resume path here and forward
4693- // the previously pushed cleanups.
4694- if (calleeTypeInfo.foreign .async ) {
4695- for (auto unmanagedCopy : unmanagedCopies) {
4696- auto value = unmanagedCopy.forward (*this );
4697- B.emitFixLifetime (loc, value);
4698- B.emitDestroyOperation (loc, value);
4699- }
4700-
4701- // hop back to the current executor
4702- breadcrumb.emit (*this , loc);
4703- }
4704-
47054717 return result;
47064718}
47074719
0 commit comments