@@ -4427,6 +4427,27 @@ 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+ };
44304451} // end anonymous namespace
44314452
44324453// ===----------------------------------------------------------------------===//
@@ -4586,7 +4607,7 @@ RValue SILGenFunction::emitApply(
45864607 // generates `await_async_continuation`.
45874608 // Lifetime is extended by creating unmanaged copies here and by pushing the
45884609 // cleanups required just before the result plan is generated.
4589- SmallVector<ManagedValue , 8 > unmanagedCopies;
4610+ SmallVector<SILValue , 8 > unmanagedCopies;
45904611 if (calleeTypeInfo.foreign .async ) {
45914612 for (auto arg : args) {
45924613 if (arg.hasCleanup ()) {
@@ -4673,32 +4694,23 @@ RValue SILGenFunction::emitApply(
46734694 *foreignError, calleeTypeInfo.foreign .async );
46744695 }
46754696
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 ());
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 ());
46824707 }
46834708
46844709 auto directResultsArray = makeArrayRef (directResults);
46854710 RValue result = resultPlan->finish (*this , loc, substResultType,
46864711 directResultsArray, bridgedForeignError);
46874712 assert (directResultsArray.empty () && " didn't claim all direct results" );
46884713
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-
47024714 return result;
47034715}
47044716
0 commit comments