This is currently disabled by default. Building the client library can be enabled with the CMake option SWIFT_BUILD_CLIENT_RETAIN_RELEASE, and using the library can be enabled with the flags -Xfrontend -enable-client-retain-release.
To improve retain/release performance, we build a static library containing optimized implementations of the fast paths of swift_retain, swift_release, and the corresponding bridgeObject functions. This avoids going through a stub to make a cross-library call.
IRGen gains awareness of these new functions and emits calls to them when the functionality is enabled and the target supports them. Two options are added to force use of them on or off: -enable-client-retain-release and -disable-client-retain-release. When enabled, the compiler auto-links the static library containing the implementations.
The new calls also use LLVM's preserve_most calling convention. Since retain/release doesn't need a large number of scratch registers, this is mostly harmless for the implementation, while allowing callers to improve code size and performance by spilling fewer registers around refcounting calls. (Experiments with an even more aggressive calling convention preserving x2 and up showed an insignificant savings in code size, so preserve_most seems to be a good middle ground.)
Since the implementations are embedded into client binaries, any change in the runtime's refcounting implementation needs to stay compatible with this new fast path implementation. This is ensured by having the implementation use a runtime-provided mask to check whether it can proceed into its fast path. The mask is provided as the address of the absolute symbol _swift_retainRelease_slowpath_mask_v1. If that mask ANDed with the object's current refcount field is non-zero, then we take the slow path. A future runtime that changes the refcounting implementation can adjust this mask to match, or set the mask to all 1s to disable the old embedded fast path entirely (as long as the new representation never uses 0 as a valid refcount field value).
As part of this work, the overall approach for bridgeObjectRetain is changed slightly. Previously, it would mask off the spare bits from the native pointer and then call through to swift_retain. This either lost the spare bits in the return value (when tail calling swift_retain) which is problematic since it's supposed to return its parameter, or it required pushing a stack frame which is inefficient. Now, swift_retain takes on the responsibility of masking off spare bits from the parameter and preserving them in the return value. This is a trivial addition to the fast path (just a quick mask and an extra register for saving the original value) and makes bridgeObjectRetain quite a bit more efficient when implemented correctly to return the exact value it was passed.
The runtime's implementations of swift_retain/release are now also marked as preserve_most so that they can be tail called from the client library. preserve_most is compatible with callers expecting the standard calling convention so this doesn't break any existing clients. Some ugly tricks were needed to prevent the compiler from creating unnecessary stack frames with the new calling convention. Avert your eyes.
To allow back deployment, the runtime now has aliases for these functions called swift_retain_preservemost and swift_release_preservemost. The client library brings weak definitions of these functions that save the extra registers and call through to swift_retain/release. This allows them to work correctly on older runtimes, with a small performance penalty, while still running at full speed on runtimes that have the new preservemost symbols.
Although this is only supported on Darwin at the moment, it shouldn't be too much work to adapt it to other ARM64 targets. We need to ensure the assembly plays nice with the other platforms' assemblers, and make sure the implementation is correct for the non-ObjC-interop case.
rdar://122595871
We could encode local archetypes in reflection info by performing the
local archetype transform, to get an extended generic signature together
with substitutions for the added generic parameters.
However, for now, let's just not crash. This generalizes an earlier hack
for opened existential archetypes. Instead of replacing them with
nonsensical type parameters though, let's just not emit the whole
descriptor.
- Fixes https://github.com/swiftlang/swift/issues/83539.
- Fixes rdar://157554723.
Noncopyable types may have user-defined code in their `deinit`s that requires
passing the type's generic parameters, so a box for a captured noncopyable type
needs to capture the generic environment even when the captured type is fixed-
layout. Fixes rdar://138958210.
This was never implemented properly, but it works sometimes.
When the protocol is parameterized, it started crashing in a new way,
because the interface type of an existential is now derived from the
generalization signature, which will have nothing to do with the
signature that IRGen is passing in here.
Tweak the workaround to keep things limping along.
Fixes rdar://problem/139745699
The generality of the `AvailabilityContext` name made it seem like it
encapsulates more than it does. Really it just augments `VersionRange` with
additional set algebra operations that are useful for availability
computations. The `AvailabilityContext` name should be reserved for something
pulls together more than just a single version.
So call the destroy on the closing type instead.
Amends the concepts areFieldsABIAccessible/isABIAccessible to take metadata
accessibility of non-copyable types into account.
rdar://133990500
Although I don't plan to bring over new assertions wholesale
into the current qualification branch, it's entirely possible
that various minor changes in main will use the new assertions;
having this basic support in the release branch will simplify that.
(This is why I'm adding the includes as a separate pass from
rewriting the individual assertions)
Call `swift_clearSensitive` after destroying or taking "sensitive" struct types.
Also, support calling C-functions with "sensitive" parameters or return values. In SIL, sensitive types are address-only and so are sensitive parameters/return values.
Though, (small) sensitive C-structs are passed directly to/from C-functions. We need re-abstract such parameter and return values for C-functions.
The instructions related to producing DynamicSelf metadata are always placed at
the start of the function. This creates an issue: which debug location should be
used in order to preserve a sane line table? The current implementation just
uses w/e debug location is present in the new insertion point, which could, for
example, be a debug_declare whose location is not suitable for these purposes.
This patch addresses the issue by removing the debug location of instructions
associated with producing DynamicSelfMetadata.
rdar://120408665
`ReadOnly`/`ArgMemOnly` were mostly moved over, but a few were missed.
Update them all. Also default to `unknown` for no memory effects rather
than none (ie. we should be conservative).
Reformatting everything now that we have `llvm` namespaces. I've
separated this from the main commit to help manage merge-conflicts and
for making it a bit easier to read the mega-patch.
This is phase-1 of switching from llvm::Optional to std::optional in the
next rebranch. llvm::Optional was removed from upstream LLVM, so we need
to migrate off rather soon. On Darwin, std::optional, and llvm::Optional
have the same layout, so we don't need to be as concerned about ABI
beyond the name mangling. `llvm::Optional` is only returned from one
function in
```
getStandardTypeSubst(StringRef TypeName,
bool allowConcurrencyManglings);
```
It's the return value, so it should not impact the mangling of the
function, and the layout is the same as `std::optional`, so it should be
mostly okay. This function doesn't appear to have users, and the ABI was
already broken 2 years ago for concurrency and no one seemed to notice
so this should be "okay".
I'm doing the migration incrementally so that folks working on main can
cherry-pick back to the release/5.9 branch. Once 5.9 is done and locked
away, then we can go through and finish the replacement. Since `None`
and `Optional` show up in contexts where they are not `llvm::None` and
`llvm::Optional`, I'm preparing the work now by going through and
removing the namespace unwrapping and making the `llvm` namespace
explicit. This should make it fairly mechanical to go through and
replace llvm::Optional with std::optional, and llvm::None with
std::nullopt. It's also a change that can be brought onto the
release/5.9 with minimal impact. This should be an NFC change.
- Renames ExperimentalPlatformCCallingConvention to
PlatformCCallingConvention.
- Removes non-arm calling convention support as this feature is working
around a clang bug for some arm triples which we hope to see resolved.
- Removes misleading MetaVarName from platform-c-calling-convention
argument.
- Replaces other uses of LLVM::CallingConv::C with
IGM.getOptions().PlatformCCallingConvention().
And use the new bit to ensure we don't try to lower move-only types
with common layout value witness surrogates. Take a bit in the runtime
value witness flags to represent types that are not copyable.
Noncopyable types aren't really "POD", but the bit is still useful to track
whether a noncopyable type has a no-op destroy operation, so rename the
existing bit to be more specific within IRGen's implementation.
Don't rename it in the runtime or Builtin names yet, since doing so will
require a naming transition for compatibility.
rdar://105837040
* WIP: Store layout string in type metadata
* WIP: More cases working
* WIP: Layout strings almost working
* Add layout string pointer to struct metadata
* Fetch bytecode layout strings from metadata in runtime
* More efficient bytecode layout
* Add support for interpreted generics in layout strings
* Layout string instantiation, take and more
* Remove duplicate information from layout strings
* Include size of previous object in next objects offset to reduce number of increments at runtime
* Add support for existentials
* Build type layout strings with StructBuilder to support target sizes and metadata pointers
* Add support for resilient types
* Properly cache layout strings in compiler
* Generic resilient types working
* Non-generic resilient types working
* Instantiate resilient type in layout when possible
* Fix a few issues around alignment and signing
* Disable generics, fix static alignment
* Fix MultiPayloadEnum size when no extra tag is necessary
* Fixes after rebase
* Cleanup
* Fix most tests
* Fix objcImplementattion and non-Darwin builds
* Fix BytecodeLayouts on non-Darwin
* Fix Linux build
* Fix sizes in linux tests
* Sign layout string pointers
* Use nullptr instead of debug value
* Introduce TypeLayout Strings
Layout strings encode the structure of a type into a byte string that can be
interpreted by a runtime function to achieve a destroy or copy. Rather than
generating ir for a destroy/assignWithCopy/etc, we instead generate a layout
string which encodes enough information for a called runtime function to
perform the operation for us. Value witness functions tend to be quite large,
so this allows us to replace them with a single call instead. This gives us the
option of making a codesize/runtime cost trade off.
* Added Attribute @_GenerateLayoutBytecode
This marks a type definition that should use generic bytecode based
value witnesses rather than generating the standard suite of
value witness functions. This should reduce the codesize of the binary
for a runtime interpretation of the bytecode cost.
* Statically link in implementation
Summary:
This creates a library to store the runtime functions in to deploy to
runtimes that do not implement bytecode layouts. Right now, that is
everything. Once these are added to the runtime itself, it can be used
to deploy to old runtimes.
* Implement Destroy at Runtime Using LayoutStrings
If GenerateLayoutBytecode is enabled, Create a layout string and use it
to call swift_generic_destroy
* Add Resilient type and Archetype Support for BytecodeLayouts
Add Resilient type and Archetype Support to Bytecode Layouts
* Implement Bytecode assign/init with copy/take
Implements swift_generic_initialize and swift_generic_assign to allow copying
types using bytecode based witnesses.
* Add EnumTag Support
* Add IRGen Bytecode Layouts Test
Added a test to ensure layouts are correct and getting generated
* Implement BytecodeLayouts ObjC retain/release
* Fix for Non static alignments in aligned groups
* Disable MultiEnums
MultiEnums currently have some correctness issues with non fixed multienum
types. Disabling them for now then going to attempt a correct implementation in
a follow up patch
* Fixes after merge
* More fixes
* Possible fix for native unowned
* Use TypeInfoeBasedTypeLayoutEntry for all scalars when ForceStructTypeLayouts is disabled
* Remove @_GenerateBytecodeLayout attribute
* Fix typelayout_based_value_witness.swift
Co-authored-by: Gwen Mittertreiner <gwenm@fb.com>
Co-authored-by: Gwen Mittertreiner <gwen.mittertreiner@gmail.com>
In preparation for moving to llvm's opaque pointer representation
replace getPointerElementType and CreateCall/CreateLoad/Store uses that
dependent on the address operand's pointer element type.
This means an `Address` carries the element type and we use
`FunctionPointer` in more places or read the function type off the
`llvm::Function`.
Pass the correct type to `emitHeapMetadataRefForHeapObject()`.
Fixes a runtime crash in case a class protocol is cast to a final swift class, where the actual object is an ObjectiveC class instance.
rdar://99626888
`PointerType::getElementType` has been removed entirely as part of the
opaque pointers migration. Update to `getPointerElementType` for now
until we've also migrated.
* [IRGen] Return null reference from IRGenFunction::emitUnmanagedAlloc when layout isKnownEmpty
rdar://92418090
This fixes a runtime crash on x86 caused by allocations of size 0, which are later deallocated with swift_deallocObjectImpl, but are missing the object header.
* Fix test compiler arguments
* Add IRGen test case
* Add assert to FixedBoxTypeInfoBase does not get created with known empty layout