Skip to content

Commit 7eb29e3

Browse files
authored
Merge pull request swiftlang#36995 from DougGregor/data-race-checking-flags-5.5
[5.5] [SILGen] Put actor data-race checking behind a flag.
2 parents 61c60e8 + 817a2c0 commit 7eb29e3

File tree

17 files changed

+138
-17
lines changed

17 files changed

+138
-17
lines changed

include/swift/AST/Attr.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,11 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(_unsafeMainActor, UnsafeMainActor,
647647
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove,
648648
114)
649649

650+
SIMPLE_DECL_ATTR(_implicitSelfCapture, ImplicitSelfCapture,
651+
OnParam | UserInaccessible |
652+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIBreakingToRemove,
653+
115)
654+
650655
#undef TYPE_ATTR
651656
#undef DECL_ATTR_ALIAS
652657
#undef CONTEXTUAL_DECL_ATTR_ALIAS

include/swift/AST/Expr.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,14 @@ class alignas(8) Expr {
292292
Kind : 2
293293
);
294294

295-
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1,
295+
SWIFT_INLINE_BITFIELD(ClosureExpr, AbstractClosureExpr, 1+1,
296296
/// True if closure parameters were synthesized from anonymous closure
297297
/// variables.
298-
HasAnonymousClosureVars : 1
298+
HasAnonymousClosureVars : 1,
299+
300+
/// True if "self" can be captured implicitly without requiring "self."
301+
/// on each member reference.
302+
ImplicitSelfCapture : 1
299303
);
300304

301305
SWIFT_INLINE_BITFIELD_FULL(BindOptionalExpr, Expr, 16,
@@ -3871,6 +3875,7 @@ class ClosureExpr : public AbstractClosureExpr {
38713875
Body(nullptr) {
38723876
setParameterList(params);
38733877
Bits.ClosureExpr.HasAnonymousClosureVars = false;
3878+
Bits.ClosureExpr.ImplicitSelfCapture = false;
38743879
}
38753880

38763881
SourceRange getSourceRange() const;
@@ -3898,7 +3903,17 @@ class ClosureExpr : public AbstractClosureExpr {
38983903
void setHasAnonymousClosureVars() {
38993904
Bits.ClosureExpr.HasAnonymousClosureVars = true;
39003905
}
3901-
3906+
3907+
/// Whether this closure allows "self" to be implicitly captured without
3908+
/// required "self." on each reference.
3909+
bool allowsImplicitSelfCapture() const {
3910+
return Bits.ClosureExpr.ImplicitSelfCapture;
3911+
}
3912+
3913+
void setAllowsImplicitSelfCapture(bool value = true) {
3914+
Bits.ClosureExpr.ImplicitSelfCapture = value;
3915+
}
3916+
39023917
/// Determine whether this closure expression has an
39033918
/// explicitly-specified result type.
39043919
bool hasExplicitResultType() const { return ArrowLoc.isValid(); }

include/swift/AST/SILOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ class SILOptions {
6565
/// It is turned off by default.
6666
bool EnableSpeculativeDevirtualization = false;
6767

68+
/// Controls whether to emit actor data-race checks.
69+
bool EnableActorDataRaceChecks = false;
70+
6871
/// Should we run any SIL performance optimizations
6972
///
7073
/// Useful when you want to enable -O LLVM opts but not -O SIL opts.

include/swift/AST/Types.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,7 @@ struct ParameterListInfo {
33823382
SmallBitVector propertyWrappers;
33833383
SmallBitVector unsafeSendable;
33843384
SmallBitVector unsafeMainActor;
3385+
SmallBitVector implicitSelfCapture;
33853386

33863387
public:
33873388
ParameterListInfo() { }
@@ -3410,6 +3411,13 @@ struct ParameterListInfo {
34103411
/// part of the type system.
34113412
bool isUnsafeMainActor(unsigned paramIdx) const;
34123413

3414+
/// Whether the given parameter is a closure that should allow capture of
3415+
/// 'self' to be implicit, without requiring "self.".
3416+
bool isImplicitSelfCapture(unsigned paramIdx) const;
3417+
3418+
/// Whether there is any contextual information set on this parameter list.
3419+
bool anyContextualInfo() const;
3420+
34133421
/// Retrieve the number of non-defaulted parameters.
34143422
unsigned numNonDefaultedParameters() const {
34153423
return defaultArguments.count();

include/swift/Option/Options.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,16 @@ def warn_swift3_objc_inference_minimal :
607607
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
608608
HelpText<"Warn about deprecated @objc inference in Swift 3 based on direct uses of the Objective-C entrypoint">;
609609

610+
def enable_actor_data_race_checks :
611+
Flag<["-"], "enable-actor-data-race-checks">,
612+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
613+
HelpText<"Emit runtime checks for actor data races">;
614+
615+
def disable_actor_data_race_checks :
616+
Flag<["-"], "disable-actor-data-race-checks">,
617+
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
618+
HelpText<"Disable runtime checks for actor data races">;
619+
610620
def warn_implicit_overrides :
611621
Flag<["-"], "warn-implicit-overrides">,
612622
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2546,6 +2546,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
25462546
printClosure(E, "closure_expr");
25472547
if (E->hasSingleExpressionBody())
25482548
PrintWithColorRAII(OS, ClosureModifierColor) << " single-expression";
2549+
if (E->allowsImplicitSelfCapture())
2550+
PrintWithColorRAII(OS, ClosureModifierColor) << " implicit-self";
25492551

25502552
if (E->getParameters()) {
25512553
OS << '\n';

lib/AST/Type.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,7 @@ ParameterListInfo::ParameterListInfo(
970970
propertyWrappers.resize(params.size());
971971
unsafeSendable.resize(params.size());
972972
unsafeMainActor.resize(params.size());
973+
implicitSelfCapture.resize(params.size());
973974

974975
// No parameter owner means no parameter list means no default arguments
975976
// - hand back the zeroed bitvector.
@@ -1029,6 +1030,10 @@ ParameterListInfo::ParameterListInfo(
10291030
if (param->getAttrs().hasAttribute<UnsafeMainActorAttr>()) {
10301031
unsafeMainActor.set(i);
10311032
}
1033+
1034+
if (param->getAttrs().hasAttribute<ImplicitSelfCaptureAttr>()) {
1035+
implicitSelfCapture.set(i);
1036+
}
10321037
}
10331038
}
10341039

@@ -1059,6 +1064,17 @@ bool ParameterListInfo::isUnsafeMainActor(unsigned paramIdx) const {
10591064
: false;
10601065
}
10611066

1067+
bool ParameterListInfo::isImplicitSelfCapture(unsigned paramIdx) const {
1068+
return paramIdx < implicitSelfCapture.size()
1069+
? implicitSelfCapture[paramIdx]
1070+
: false;
1071+
}
1072+
1073+
bool ParameterListInfo::anyContextualInfo() const {
1074+
return unsafeSendable.any() || unsafeMainActor.any() ||
1075+
implicitSelfCapture.any();
1076+
}
1077+
10621078
/// Turn a param list into a symbolic and printable representation that does not
10631079
/// include the types, something like (_:, b:, c:)
10641080
std::string swift::getParamListAsString(ArrayRef<AnyFunctionType::Param> params) {

lib/Driver/ToolChains.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ void ToolChain::addCommonFrontendArgs(const OutputInfo &OI,
217217
inputArgs.AddLastArg(arguments,
218218
options::OPT_warn_swift3_objc_inference_minimal,
219219
options::OPT_warn_swift3_objc_inference_complete);
220+
inputArgs.AddLastArg(arguments,
221+
options::OPT_enable_actor_data_race_checks,
222+
options::OPT_disable_actor_data_race_checks);
220223
inputArgs.AddLastArg(arguments, options::OPT_warn_concurrency);
221224
inputArgs.AddLastArg(arguments, options::OPT_warn_implicit_overrides);
222225
inputArgs.AddLastArg(arguments, options::OPT_typo_correction_limit);

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,9 @@ static bool ParseSILArgs(SILOptions &Opts, ArgList &Args,
12221222
Opts.EnableOSSAModules |= Args.hasArg(OPT_enable_ossa_modules);
12231223
Opts.EnableOSSAOptimizations &= !Args.hasArg(OPT_disable_ossa_opts);
12241224
Opts.EnableSpeculativeDevirtualization |= Args.hasArg(OPT_enable_spec_devirt);
1225+
Opts.EnableActorDataRaceChecks |= Args.hasFlag(
1226+
OPT_enable_actor_data_race_checks,
1227+
OPT_disable_actor_data_race_checks, /*default=*/false);
12251228
Opts.DisableSILPerfOptimizations |= Args.hasArg(OPT_disable_sil_perf_optzns);
12261229
Opts.CrossModuleOptimization |= Args.hasArg(OPT_CrossModuleOptimization);
12271230
Opts.VerifyAll |= Args.hasArg(OPT_sil_verify_all);

lib/SILGen/SILGenProlog.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
492492

493493
// Initialize ExpectedExecutor if the function is an actor-isolated
494494
// function or closure.
495+
bool wantDataRaceChecks = getOptions().EnableActorDataRaceChecks &&
496+
!F.isAsync() &&
497+
!isInActorDestructor(FunctionDC);
498+
495499
if (auto *funcDecl =
496500
dyn_cast_or_null<AbstractFunctionDecl>(FunctionDC->getAsDecl())) {
497501
auto actorIsolation = getActorIsolation(funcDecl);
@@ -508,7 +512,7 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
508512
// are prone to dynamic data races in code that does not enforce Sendable
509513
// completely.
510514
if (F.isAsync() ||
511-
(funcDecl->isLocalCapture() && !isInActorDestructor(funcDecl))) {
515+
(wantDataRaceChecks && funcDecl->isLocalCapture())) {
512516
auto loc = RegularLocation::getAutoGeneratedLocation(F.getLocation());
513517
ManagedValue selfArg = ManagedValue::forUnmanaged(F.getSelfArgument());
514518
ExpectedExecutor = emitLoadActorExecutor(loc, selfArg);
@@ -517,14 +521,17 @@ void SILGenFunction::emitProlog(CaptureInfo captureInfo,
517521
}
518522

519523
case ActorIsolation::GlobalActor:
520-
if (F.isAsync() || !isInActorDestructor(funcDecl)) {
524+
if (F.isAsync() || wantDataRaceChecks) {
521525
ExpectedExecutor =
522526
emitLoadGlobalActorExecutor(actorIsolation.getGlobalActor());
523527
}
524528
break;
525529
}
526530
} else if (auto *closureExpr = dyn_cast<AbstractClosureExpr>(FunctionDC)) {
527-
bool wantExecutor = F.isAsync() || !isInActorDestructor(closureExpr);
531+
bool wantExecutor = F.isAsync() ||
532+
(wantDataRaceChecks &&
533+
!(isa<ClosureExpr>(closureExpr) &&
534+
cast<ClosureExpr>(closureExpr)->isUnsafeMainActor()));
528535
auto actorIsolation = closureExpr->getActorIsolation();
529536
switch (actorIsolation.getKind()) {
530537
case ClosureActorIsolation::Independent:

0 commit comments

Comments
 (0)