Without this hack the call will leave a stack frame around (not tail
call optimized) and blow the stack if we call switch_task often enough.
Ideally, clang would emit this call as `musttail` but currently it does
not.
rdar://76652421
Actor inheritance was removed in the second revision of SE-0306. Remove
the ability to inherit actors.
Note that this doesn't fully eliminate all vestigates of inheritance
from actors. There are simplifications that need to be performed
still, e.g., there's no need to distinguish
designated/convenience/required initializers. That will follow.
Commit the platform definition and build script work necessary to
cross-compile for arm64_32.
arm64_32 is a variant of AARCH64 that supports an ILP32 architecture.
Problem: We continue to uncover code that assumes either precise local
variable lifetimes (to the end of the lexical scope) or extended
temporary lifetimes (to the end of the statement). These bugs require
heroic debugging to find the root cause. Because they only show up in
Release builds, they often manifest just before the affected project
“ships” under an impending deadline.
We now have enough information from projects that have been tested
with copy propagation that we can both understand common patterns and
identify some specific APIs that may cause trouble. We know what API
annotations the compiler will need for helpful warnings and can begin
adding those annotations.
Disabling copy propagation now is only a temporary deferral, we will
still need to bring it back by default. However, by then we should
have:
- LLDB and runtime support for debugging deinitialized objects
- A variant of lifetime sortening that can run in Debug builds to
catch problems before code ships
- Static compiler warnings for likely invalid lifetime assumptions
- Source annotations that allow those warnings to protect programmers
against existing dangerous APIs
In the meantime...
Projects can experiment with the behavior and gradually migrate.
Copy propagation will automatically be enabled in -enable-ossa-modules
mode. It is important to work toward a single performance
target. Supporting full OSSA and improving ARC performance without
copy propagation would be prohibitively complicated.
rdar://76438920 (Temporarily disable -O copy propagation by default)
This feature degrades the debugging experience and causes a large
number of unit test failures.
These were both known issues, but our planned debugger improvements
won't be ready for a while. Until then, we'll leave the feature under
a compiler option, and developers can adopt it at there own speed for
now when they are ready to fix lifetime issues in their code.
rdar://76177280 (Disable mandatory-copy-propagation (-Onone only))
This shortens -Onone lifetimes.
To eliminate ARC traffic, the optimizer reorders object
destruction. This changes observable program behavior. If a custom
deinitializer produces side effects, code may observe those side
effects earlier after optimization. Similarly, code that dereferences
a weak reference may observe a 'nil' reference after optimization,
while the unoptimized code observed a valid object.
Developers have overwhelmingly requested that object lifetimes have
similar behavior in -Onone and -O builds in order to find and diagnose
program bugs involving weak references and other lifetime assumptions.
Enabling the copy propagation at -Onone is simply a matter of flipping
a switch. -Onone runtime and code size will improve. By design, copy
propagation, has no direct affect on compile time. It will indirectly
improve optimized compile times, but in debug builds, it simply isn't
a factor.
To support debugging, a "poison" flag was (in prior commits) added to
new destroy_value instructions generated by copy propagation. When
OwnershipModelEliminator lowers destroy_value [poison] it will
generate new debug_value instructions with a “poison” flag.
These additional poison stores to the stack could increase both code
size and -Onone runtime.
rdar://75012368 (-Onone compiler support for early object deinitialization with sentinel dead references)
This patch updates the `actor class` spelling to `actor` in almost all
of the tests. There are places where I verify that we sanely handle
`actor` as an attribute though. These include:
- test/decl/class/actor/basic.swift
- test/decl/protocol/special/Actor.swift
- test/SourceKit/CursorInfo/cursor_info_concurrency.swift
- test/attr/attr_objc_async.swift
- test/ModuleInterface/actor_protocol.swift
Swift allows a method override to be more visible than the base method.
In practice, this means that since it might be possible for client
code to see the override but not the base method, we have to take
extra care when emitting the override.
Specifically, the override always receives a new vtable entry, and
a vtable thunk is emitted in place of the base method's vtable entry
which re-dispatches via the override's vtable entry.
This allows client code to further override the method without any
knowledge of the base method's vtable entry, which may be inaccessible
to the client.
In order for the above to work, three places in the code perform
co-ordinated checks:
- needsNewVTableEntry() determines whether the override is more
visible than the base, in which case it receives a new vtable
entry
- SILGenModule::emitVTableMethod() performs the same check in order
to emit the re-dispatching vtable thunk in place of the base
method's entry
- in the client, SILVTableVisitor then skips the base method's
vtable entry entirely when emitting the derived class, since no
thunk is to be emitted.
The problem was that the first two used effective access (where
internal declarations become public with -enable-testing), while
the last check used formal access. As a result, it was possible
for the method override vtable entry to never be emitted in the
client.
Consistently using either effective access or formal access would
fix the problem. I fixed the first two to rely on formal access;
the reason is that using effective access makes vtable layout
depend on whether the library was built with -enable-testing or
not, which is undesirable since we do not want -enable-testing to
impact the ABI, even for non-resilient frameworks.
Fixes rdar://problem/74108928.
For now simply run the pass before SemanticARCOpts. This will probably
be called as a utility from within SemanticARCOpts so it can be
iteratively applied after other ARC-related transformations.
There's no reason to use -m${platform}-version-min as of clang-11/Xcode 11. Clang is now smart enough to parse -target and provide Apple's ld with the appropriate -platform_version argument string.
For the following discussion, let OP be the switch's operand. This is
implemented by:
* Modeling switch_enum_addr as not forwarding OP and instead delegate the
forwarding of OP to be done by each enum case. This matches what SILGen is
actually doing since the actual taking of the address in SIL is done in each
enum case block by an unchecked_take_enum_data_addr.
* In each enum case, I treat OP as being forwarded into an irrefutable
sub-tree. I follow the pattern of other places this is done by creating a
CleanupStateRestorationScope and using forwardIntoIrrefutableSubTree. This
ensures that if I forward OP in the enum case, it just becomes dormant instead
of being thrown away.
* Inside each case, there is a bunch of code that does some final preparations
to src before dispatching to the inner dispatch. This code was written using
old low-level SILValue APIs where ownership is done by hand. I replaced all of
that by hand ownership with higher level Managed Value APIs that automatically
handle ownership for the user. This simplified the implementation and ensured
correctness via SILGenBuilder API invariants.
The end result of all of these together is that:
1. The cleanup on OP is still live when we emit the default case later than the
cleanups. This eliminates the leak that I am fixing.
2. We have greater correctness since the SILGenBuilder APIs automatically handle
ownership for us.
3. We have eliminated some brittle logic that could in the future introduce
bugs. Specifically, I noticed that if we were ever given a
ConsumableManagedValue that was CopyOnSuccess or BorrowAlways but its
ManagedValue was a +1 value, we would leak. I could not figure out how to
create a Swift test case that would go down this code path though = (. But
that being said, it is one new language feature away from being broken. I
added some asserts to ConsumableManagedValue that ensures this invariant, so
we are safe. If it is inconvenient, we can also cause ConsumableManagedValue
to create a new ManagedValue when it detects this condition without the
cleanup. But lets see how difficult it is to keep this invariant.
In terms of testing, I put in both a SILGen test and also an end<->end
interpreter test to ensure this doesn't break again.
rdar://71992652
SR-13926
We expect to iterate on this quite a bit, both publicly
and internally, but this is a fine starting-point.
I've renamed runAsync to runAsyncAndBlock to underline
very clearly what it does and why it's not long for this
world. I've also had to give it a radically different
implementation in an effort to make it continue to work
given an actor implementation that is no longer just
running all work synchronously.
The major remaining bit of actor-scheduling work is to
make swift_task_enqueue actually do something sensible
based on the executor it's been given; currently it's
expecting a flag that IRGen simply doesn't know to set.
of adding a property.
This better matches what the actual implementation expects,
and it avoids some possibilities of weird mismatches. However,
it also requires special-case initialization, destruction, and
dynamic-layout support, none of which I've added yet.
In order to get NSObject default actor subclasses to use Swift
refcounting (and thus avoid the need for the default actor runtime
to generally use ObjC refcounting), I've had to introduce a
SwiftNativeNSObject which we substitute as the superclass when
inheriting directly from NSObject. This is something we could
do in all NSObject subclasses; for now, I'm just doing it in
actors, although it's all actors and not just default actors.
We are not yet taking advantage of our special knowledge of this
class anywhere except the reference-counting code.
I went around in circles exploring a number of alternatives for
doing this; at one point I basically had a completely parallel
"ForImplementation" superclass query. That proved to be a lot
of added complexity and created more problems than it solved.
We also don't *really* get any benefit from this subclassing
because there still wouldn't be a consistent superclass for all
actors. So instead it's very ad-hoc.
Associated objects are actively dangerous there because they’re non-isolated
actor state, and it’s “new” code wher no backward compatibility concerns that
make it more difficult to ban this on other forms of classes.
rdar://69769048
Tests that need to execute need to be marked as such so they can be
skipped in platforms that are cross-compiled and do not have a target
platform available.
This situation happens in the Android CI machines.
Introduced in #34746.