SR-4355 Update standard library to use memory ownership features
Exclusivity is currently supported in Debug builds but not in Release builds.
We need to make sure the optimizer works with access markers to support the mode. Further, we would need to evaluate performance impact and minimize it. For example, we will need to fix the optimization passes to handle access markers without missing optimization opportunities. We might also want to add new optimizations to merge and eliminate access scopes.
The text was updated successfully, but these errors were encountered:
Enabling run-time exclusivity checking in release mode
It's time to change the compiler default for run-time exclusivity
checks. This will expose the feature to more testing and allow the
compiler team to gather performance feedback from users. Until now,
I've been waiting until the most obvious bottlenecks are
resolved--there's no sense having a slew of performance bugs for
issues that are about to be fixed. Recent optimizations landed by Joe
Shajrawi have brought performance where I think it needs to be for
adoption. More optimizations are planned, and some benchmarks should
be further improved, but at this point we're ready to begin receiving
bug reports. That will help prioritize the remaining work for Swift 5.
Compile-time (static) diagnostics catch many common exclusivity
violations, but run-time (dynamic) diagnostics are also required to
catch violations involving escaping closures, class properties, and
globals. Swift 4.0 provided both static and dynamic enforcement, but
dynamic enforcement was only enabled in debug builds.
In Swift 4.1 and 4.2, compiler diagnostics were gradually strengthened
to catch more and more of the cases in which programmers could skirt
exclusivity rules--most notably, by capturing variables in nonescaping
closures or by converting nonescaping closures to escaping closures.
The goal for Swift 5 is to fix the remaining holes in the language
model and to fully enforce that model. All of the known language
deficiencies have been fixed, with the exception of [[SR-8546]: Enforce @escaping for nested functions named inside conditional
expressions](https://bugs.swift.org/browse/SR-8546). Run-time enforcement will be enabled for release builds by
default in [PR 20302](#20302
This change could impact Swift programs that previously appeared
well-behaved, but weren't fully tested in debug mode. Now, when running
in release mode, they may trap with the message "error: overlapping
1. Adherence to exclusivity rules removes a common class of
programming bugs involving mutable state and action at a distance.
As programs scale in size, it becomes increasingly likely for routines
to interact in unexpected ways. Exclusivity rules eliminate dangerous
interactions involving mutable state. In this simple example, note
that exclusivity prevents the programmer from passing the same
instance of `Names` as `src` and `dest`, which would otherwise cause
an infinite loop:
2. Enforcement eliminates an unspecified behavior rule from the language.
Prior to Swift 4, these memory rules were unenforced, making it the
programmer's responsibility to adhere to them. In practice, it was
easy for programmers to violate these rules in subtle ways, leaving
their programs vulnerable to unspecified behavior.
3. Enforcement legalizes performance optimization while protecting
A guarantee of exclusivity on `inout` parameters and `mutating`
methods provides important information to the compiler, which it can
use to optimize memory access and reference counting
operations. Declaring an unspecified behavior rule, as mentioned
above, does not provide this guarantee. An "undefined behavior" rule
is required to support optimization, but such a rule would, by
definition, compromise the memory safety of the language. Full
exclusivity enforcement allows the compiler to optimize based on
memory exclusivity without introducing undefined behavior.
4. Exclusivity rules are needed to give programmer control of
ownership and move-only types.
The common pattern in these benchmarks is to define an array of data
as a class property and to repeatedly access that array through the
class reference. Each of those class property accesses now incurs a
runtime call. Naturally, introducing a runtime call in a loop that
otherwise does almost no work incurs substantial overhead. This is
similar to the issue caused by automatic reference counting. In some
cases, more sophistacated optimization will be able to determine the
same object is repeatedly accessed. Furthermore, the overhead of the
runtime call can be improved. But regardless of how well we optimize,
there will always a class of microbenchmarks in which the runtime
check has a noticeable impact.
As a general guideline, avoid performing class property access within
the most performance critical loops, particularly on different objects
in each loop iteration. If that isn't possible, it may help if the
visibility of those class properties is private or internal.