@@ -4425,6 +4425,27 @@ class FixLifetimeDestroyCleanup : public Cleanup {
44254425#endif
44264426 }
44274427};
4428+
4429+ class EmitBreadcrumbCleanup : public Cleanup {
4430+ ExecutorBreadcrumb breadcrumb;
4431+
4432+ public:
4433+ EmitBreadcrumbCleanup (ExecutorBreadcrumb &&breadcrumb)
4434+ : breadcrumb(std::move(breadcrumb)) {}
4435+
4436+ void emit (SILGenFunction &SGF, CleanupLocation l,
4437+ ForUnwind_t forUnwind) override {
4438+ breadcrumb.emit (SGF, l);
4439+ }
4440+
4441+ void dump (SILGenFunction &SGF) const override {
4442+ #ifndef NDEBUG
4443+ llvm::errs () << " EmitBreadcrumbCleanup "
4444+ << " State:" << getState ()
4445+ << " NeedsEmit:" << breadcrumb.needsEmit ();
4446+ #endif
4447+ }
4448+ };
44284449} // end anonymous namespace
44294450
44304451// ===----------------------------------------------------------------------===//
@@ -4584,7 +4605,7 @@ RValue SILGenFunction::emitApply(
45844605 // generates `await_async_continuation`.
45854606 // Lifetime is extended by creating unmanaged copies here and by pushing the
45864607 // cleanups required just before the result plan is generated.
4587- SmallVector<ManagedValue , 8 > unmanagedCopies;
4608+ SmallVector<SILValue , 8 > unmanagedCopies;
45884609 if (calleeTypeInfo.foreign .async ) {
45894610 for (auto arg : args) {
45904611 if (arg.hasCleanup ()) {
@@ -4671,32 +4692,23 @@ RValue SILGenFunction::emitApply(
46714692 *foreignError, calleeTypeInfo.foreign .async );
46724693 }
46734694
4674- // For objc async calls, push cleanup to be used on throw paths in the result
4675- // planner.
4676- for (unsigned i : indices (unmanagedCopies)) {
4677- SILValue value = unmanagedCopies[i].getValue ();
4678- Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(value);
4679- unmanagedCopies[i] = ManagedValue (value, Cleanups.getTopCleanup ());
4695+ // For objc async calls, push cleanups to be used on
4696+ // both result and throw paths prior to finishing the result plan.
4697+ if (calleeTypeInfo.foreign .async ) {
4698+ for (auto unmanagedCopy : unmanagedCopies) {
4699+ Cleanups.pushCleanup <FixLifetimeDestroyCleanup>(unmanagedCopy);
4700+ }
4701+ // save breadcrumb as a clean-up so it is emitted in result / throw cases.
4702+ Cleanups.pushCleanup <EmitBreadcrumbCleanup>(std::move (breadcrumb));
4703+ } else {
4704+ assert (unmanagedCopies.empty ());
46804705 }
46814706
46824707 auto directResultsArray = makeArrayRef (directResults);
46834708 RValue result = resultPlan->finish (*this , loc, substResultType,
46844709 directResultsArray, bridgedForeignError);
46854710 assert (directResultsArray.empty () && " didn't claim all direct results" );
46864711
4687- // For objc async calls, generate cleanup on the resume path here and forward
4688- // the previously pushed cleanups.
4689- if (calleeTypeInfo.foreign .async ) {
4690- for (auto unmanagedCopy : unmanagedCopies) {
4691- auto value = unmanagedCopy.forward (*this );
4692- B.emitFixLifetime (loc, value);
4693- B.emitDestroyOperation (loc, value);
4694- }
4695-
4696- // hop back to the current executor
4697- breadcrumb.emit (*this , loc);
4698- }
4699-
47004712 return result;
47014713}
47024714
0 commit comments