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
This PR replaces our use of `__dso_handle` and (indirectly) `dladdr()`
when figuring out the base address of loaded Swift images on ELF-based
platforms. Instead, we use `__ehdr_start` which refers to the start of
the image's ELF header (i.e. the start of the file) and is provided by
the compiler/linker for this purpose.
This pointer is consumed by `swift_addNewDSOImage()` and, later, by
Swift Testing when running tests, but is otherwise unused, so the less
work we do on it at runtime, the better.
A fallback path is present that, for images that do not contain
`__ehdr_start`, derives the address by calling `dladdr()` on the section
structure's address.
Resolves#84997.
OpenBSD 7.8 snapshots hide the type information for FILE. Therefore, the
types for the standard stdio streams should (regrettably) be
OpaquePointer, due to the well-discussed issue of losing type
information for forward-declared C types.
We explicitly drop to void * in the LibcOverlayShims for backwards
compatibility, since OpenBSD 7.8 is not yet released.
CMake 3.30 passes linker flags to the Swift invocation when it is used
as the linker driver. However, Swift cannot parse the linker arguments,
so they need to be passed with the `-Xlinker` prefix. This cannot be
done uncondtionally as the same arguments are also used with the MSVC
toolchain.
CMake 4.0 introduces the CMP0181 policy, which allows CMake to parse the
`LINKER:` syntax on the linker flags passed on the command line, which
simplifies handling of flags.
Note that building for Android still requires CMake 3.29 for the time
being as we pass a linker driver argument to the CMake linker flags to
override the linker used.
Resolves the following warnings:
```
stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h:86:1: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
86 | const _swift_shims_NSUInteger
| ^~~~~
stdlib/public/stubs/FoundationHelpers.mm:110:1: warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
110 | const _swift_shims_NSUInteger
| ^~~~~
```
When using the Swift static build on Windows, projects like Foundation
use the clang headers from the toolchain build `lib` directory. No
target in the toolchain build depends on the static clang headers, so
they do not get installed. As a workaround, this makes the static clang
headers symlink target a dependency of the regular dynamic version of
the headers, ensuring they are installed as part of the toolchainb
build.
This commit adds required conditional compilation blocks to enable bulding on
FreeBSD (tested on x86_64 FreeBSD 14.1-RELEASE-p6). Also implements FreeBSD
synchronization shims using `_umtx_op(2)`
The condition previously depended on the specific OS, but the image
boundary is the same for all platforms using Wasm as image format. This
fixes the Emscripten build.
When building the standard library statically on Windows, we should not
use any __declspec(dllimport) or __declspec(dllexport) on the runtime
functions or data. Furthermore, we should internalise all of the
standard library functions so that they are not re-exported if used to
build a shared library. The code generation changes required for this
are easier to identify once a static SDK is available for Windows.
Darwin defines memcmp with optional pointers. Update SwiftShims to
define it to the same type to avoid deserialization failures where we
get one over the other and the types don't match anymore.
rdar://140596571
macOS 15.0, iOS 18.0, et al has started unconditionally declaring `lgamma_r` in <math.h>, add a __has_include in SwiftShims to detect that and not redeclare it when building against those SDK versions.
rdar://115192929
PR #74394 removed a field from `struct MetadataSections` whose layout is ABI.
So restore that field as an unused padding field to preserve the layout of all
the other fields in that struct.
without relying on spare bit information in the reflection metadata
(which was added in #40906). As a result, we can remove the
code from #40906.
This is the first step in such removal. It removes the RemoteMirror
code for looking up such metadata. It leaves behind:
* Sufficient stubs for LLDB to continue to build. Once LLDB is updated, these stubs can be removed as well.
* The compiler code to emit such metadata. This allows new binaries to still reflect MPEs on older runtimes. This will need to be kept for a transitional period.
Mostly this just means adding `Musl` as a module dependency of various
things and making sure that we build things for `swift_static` even
if `SWIFT_BUILD_STATIC_STDLIB` isn't enabled.
There's also a slight difference in the declaration of `memcmp()`;
musl's declaration is more like the one we have on Darwin.
rdar://123508245