Skip to content

Commit 64a53b4

Browse files
authored
Merge pull request #83084 from gottesmm/release/6.2-rdar155905383
[6.2][concurrency] Make optimize hop to executor more conservative for 6.2 around caller isolation inheriting functions.
2 parents f8ca0f0 + 82b0ec3 commit 64a53b4

File tree

14 files changed

+696
-59
lines changed

14 files changed

+696
-59
lines changed

include/swift/SIL/ApplySite.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -894,6 +894,21 @@ class FullApplySite : public ApplySite {
894894
getNumIndirectSILErrorResults();
895895
}
896896

897+
std::optional<ActorIsolation> getActorIsolation() const {
898+
if (auto isolation = getIsolationCrossing();
899+
isolation && isolation->getCalleeIsolation())
900+
return isolation->getCalleeIsolation();
901+
auto *calleeFunction = getCalleeFunction();
902+
if (!calleeFunction)
903+
return {};
904+
return calleeFunction->getActorIsolation();
905+
}
906+
907+
bool isCallerIsolationInheriting() const {
908+
auto isolation = getActorIsolation();
909+
return isolation && isolation->isCallerIsolationInheriting();
910+
}
911+
897912
static FullApplySite getFromOpaqueValue(void *p) { return FullApplySite(p); }
898913

899914
static bool classof(const SILInstruction *inst) {

lib/SIL/IR/SILPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ llvm::cl::opt<bool> SILPrintGenericSpecializationInfo(
9595
llvm::cl::desc("Include generic specialization"
9696
"information info in SIL output"));
9797

98+
llvm::cl::opt<bool> SILPrintFunctionIsolationInfo(
99+
"sil-print-function-isolation-info", llvm::cl::init(false),
100+
llvm::cl::desc("Print out isolation info on functions in a manner that SIL "
101+
"understands [e.x.: not in comments]"));
102+
98103
static std::string demangleSymbol(StringRef Name) {
99104
if (SILFullDemangle)
100105
return Demangle::demangleSymbolAsString(Name);
@@ -3627,6 +3632,15 @@ void SILFunction::print(SILPrintContext &PrintCtx) const {
36273632
OS << "[available " << availability.getVersionString() << "] ";
36283633
}
36293634

3635+
// This is here only for testing purposes.
3636+
if (SILPrintFunctionIsolationInfo) {
3637+
if (auto isolation = getActorIsolation()) {
3638+
OS << "[isolation \"";
3639+
isolation->printForSIL(OS);
3640+
OS << "\"] ";
3641+
}
3642+
}
3643+
36303644
switch (getInlineStrategy()) {
36313645
case NoInline: OS << "[noinline] "; break;
36323646
case AlwaysInline: OS << "[always_inline] "; break;

lib/SIL/Parser/ParseSIL.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,8 @@ static bool parseDeclSILOptional(
685685
AvailabilityRange *availability, bool *isWithoutActuallyEscapingThunk,
686686
SmallVectorImpl<std::string> *Semantics,
687687
SmallVectorImpl<ParsedSpecAttr> *SpecAttrs, ValueDecl **ClangDecl,
688-
EffectsKind *MRK, SILParser &SP, SILModule &M) {
688+
EffectsKind *MRK, ActorIsolation *actorIsolation, SILParser &SP,
689+
SILModule &M) {
689690
while (SP.P.consumeIf(tok::l_square)) {
690691
if (isLet && SP.P.Tok.is(tok::kw_let)) {
691692
*isLet = true;
@@ -784,7 +785,27 @@ static bool parseDeclSILOptional(
784785
*isPerformanceConstraint = true;
785786
else if (markedAsUsed && SP.P.Tok.getText() == "used")
786787
*markedAsUsed = true;
787-
else if (section && SP.P.Tok.getText() == "section") {
788+
else if (actorIsolation && SP.P.Tok.getText() == "isolation") {
789+
SP.P.consumeToken(tok::identifier);
790+
if (SP.P.Tok.getKind() != tok::string_literal) {
791+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
792+
return true;
793+
}
794+
StringRef rawString = SP.P.Tok.getText().drop_front().drop_back();
795+
// TODO: By using a raw string here, we can perhaps put in a simple string
796+
// representation of an actor that can be parsed back. For now this is
797+
// just a quick hack so we can write tests.
798+
auto optIsolation = ActorIsolation::forSILString(
799+
SP.P.Context.getIdentifier(rawString).str());
800+
if (!optIsolation) {
801+
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
802+
return true;
803+
}
804+
*actorIsolation = *optIsolation;
805+
SP.P.consumeToken(tok::string_literal);
806+
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
807+
continue;
808+
} else if (section && SP.P.Tok.getText() == "section") {
788809
SP.P.consumeToken(tok::identifier);
789810
if (SP.P.Tok.getKind() != tok::string_literal) {
790811
SP.P.diagnose(SP.P.Tok, diag::expected_in_attribute_list);
@@ -798,8 +819,7 @@ static bool parseDeclSILOptional(
798819

799820
SP.P.parseToken(tok::r_square, diag::expected_in_attribute_list);
800821
continue;
801-
}
802-
else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
822+
} else if (inlineStrategy && SP.P.Tok.getText() == "always_inline")
803823
*inlineStrategy = AlwaysInline;
804824
else if (MRK && SP.P.Tok.getText() == "readnone")
805825
*MRK = EffectsKind::ReadNone;
@@ -7333,6 +7353,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73337353
SILFunction *DynamicallyReplacedFunction = nullptr;
73347354
SILFunction *AdHocWitnessFunction = nullptr;
73357355
Identifier objCReplacementFor;
7356+
ActorIsolation actorIsolation;
73367357
if (parseSILLinkage(FnLinkage, P) ||
73377358
parseDeclSILOptional(
73387359
&isTransparent, &isSerialized, &isCanonical, &hasOwnershipSSA,
@@ -7344,7 +7365,7 @@ bool SILParserState::parseDeclSIL(Parser &P) {
73447365
&optimizationMode, &perfConstr, &isPerformanceConstraint,
73457366
&markedAsUsed, &section, nullptr, &isWeakImported,
73467367
&needStackProtection, &availability, &isWithoutActuallyEscapingThunk,
7347-
&Semantics, &SpecAttrs, &ClangDecl, &MRK, FunctionState, M) ||
7368+
&Semantics, &SpecAttrs, &ClangDecl, &MRK, &actorIsolation, FunctionState, M) ||
73487369
P.parseToken(tok::at_sign, diag::expected_sil_function_name) ||
73497370
P.parseIdentifier(FnName, FnNameLoc, /*diagnoseDollarPrefix=*/false,
73507371
diag::expected_sil_function_name) ||
@@ -7404,6 +7425,8 @@ bool SILParserState::parseDeclSIL(Parser &P) {
74047425
for (auto &Attr : Semantics) {
74057426
FunctionState.F->addSemanticsAttr(Attr);
74067427
}
7428+
if (actorIsolation)
7429+
FunctionState.F->setActorIsolation(actorIsolation);
74077430
// Now that we have a SILFunction parse the body, if present.
74087431

74097432
bool isDefinition = false;
@@ -7593,11 +7616,11 @@ bool SILParserState::parseSILGlobal(Parser &P) {
75937616

75947617
SILParser State(P);
75957618
if (parseSILLinkage(GlobalLinkage, P) ||
7596-
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr,
7619+
parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
75977620
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
75987621
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7622+
nullptr, nullptr, nullptr, nullptr, nullptr, &isLet,
75997623
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7600-
&isLet, nullptr, nullptr, nullptr, nullptr, nullptr,
76017624
nullptr, nullptr, nullptr, State, M) ||
76027625
P.parseToken(tok::at_sign, diag::expected_sil_value_name) ||
76037626
P.parseIdentifier(GlobalName, NameLoc, /*diagnoseDollarPrefix=*/false,
@@ -7651,7 +7674,7 @@ bool SILParserState::parseSILProperty(Parser &P) {
76517674
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76527675
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
76537676
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7654-
nullptr, nullptr, SP, M))
7677+
nullptr, nullptr, nullptr, SP, M))
76557678
return true;
76567679

76577680
ValueDecl *VD;
@@ -7721,7 +7744,7 @@ bool SILParserState::parseSILVTable(Parser &P) {
77217744
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77227745
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
77237746
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7724-
nullptr, nullptr, VTableState, M))
7747+
nullptr, nullptr, nullptr, VTableState, M))
77257748
return true;
77267749

77277750

@@ -7844,7 +7867,8 @@ bool SILParserState::parseSILMoveOnlyDeinit(Parser &parser) {
78447867
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78457868
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
78467869
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
7847-
nullptr, nullptr, moveOnlyDeinitTableState, M))
7870+
nullptr, nullptr, nullptr,
7871+
moveOnlyDeinitTableState, M))
78487872
return true;
78497873

78507874
// Parse the class name.
@@ -8373,12 +8397,12 @@ bool SILParserState::parseSILWitnessTable(Parser &P) {
83738397
parseSILLinkage(Linkage, P);
83748398

83758399
SerializedKind_t isSerialized = IsNotSerialized;
8376-
if (parseDeclSILOptional(nullptr, &isSerialized, nullptr, nullptr, nullptr,
8377-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8378-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8379-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8380-
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8381-
nullptr, nullptr, WitnessState, M))
8400+
if (parseDeclSILOptional(
8401+
nullptr, &isSerialized, nullptr, nullptr, nullptr, nullptr, nullptr,
8402+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8403+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8404+
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
8405+
nullptr, nullptr, nullptr, nullptr, nullptr, WitnessState, M))
83828406
return true;
83838407

83848408
// Parse the protocol conformance.

lib/SILGen/SILGenConcurrency.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,6 +680,35 @@ SILGenFunction::emitHopToTargetActor(SILLocation loc,
680680
}
681681
}
682682

683+
namespace {
684+
685+
class HopToActorCleanup : public Cleanup {
686+
SILValue value;
687+
688+
public:
689+
HopToActorCleanup(SILValue value) : value(value) {}
690+
691+
void emit(SILGenFunction &SGF, CleanupLocation l,
692+
ForUnwind_t forUnwind) override {
693+
SGF.B.createHopToExecutor(l, value, false /*mandatory*/);
694+
}
695+
696+
void dump(SILGenFunction &) const override {
697+
#ifndef NDEBUG
698+
llvm::errs() << "HopToExecutorCleanup\n"
699+
<< "State:" << getState() << "\n"
700+
<< "Value:" << value << "\n";
701+
#endif
702+
}
703+
};
704+
} // end anonymous namespace
705+
706+
CleanupHandle SILGenFunction::emitScopedHopToTargetActor(SILLocation loc,
707+
SILValue actor) {
708+
Cleanups.pushCleanup<HopToActorCleanup>(actor);
709+
return Cleanups.getTopCleanup();
710+
}
711+
683712
ExecutorBreadcrumb SILGenFunction::emitHopToTargetExecutor(
684713
SILLocation loc, SILValue executor) {
685714
// Record that we need to hop back to the current executor.

lib/SILGen/SILGenFunction.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1333,6 +1333,12 @@ class LLVM_LIBRARY_VISIBILITY SILGenFunction
13331333
emitHopToTargetActor(SILLocation loc, std::optional<ActorIsolation> actorIso,
13341334
std::optional<ManagedValue> actorSelf);
13351335

1336+
/// Emit a cleanup for a hop back to a target actor.
1337+
///
1338+
/// Used to ensure that along error paths and normal scope exit paths we hop
1339+
/// back automatically.
1340+
CleanupHandle emitScopedHopToTargetActor(SILLocation loc, SILValue actor);
1341+
13361342
/// Emit a hop to the target executor, returning a breadcrumb with enough
13371343
/// enough information to hop back.
13381344
///

0 commit comments

Comments
 (0)