Commit Graph

226 Commits

Author SHA1 Message Date
Alejandro Alonso
bc04d6dcf7 Don't check suppressed protocols when the extended existential is metatype constrained 2025-10-15 10:57:52 -07:00
Dmitrii Galimzianov
091b005a60 Protocol conformance cache for generic types
This change adds a new type of cache (cache by type descriptor) to the protocol conformance lookup system. This optimization is beneficial for generic types, where the
same conformance can be reused across different instantiations of the generic type.

Key changes:
- Add a `GetOrInsertManyScope` class to `ConcurrentReadableHashMap` for performing
  multiple insertions under a single lock
- Add type descriptor-based caching for protocol conformances
- Add environment variables for controlling and debugging the conformance cache
- Add tests to verify the behavior of the conformance cache
- Fix for https://github.com/swiftlang/swift/issues/82889

The implementation is controlled by the `SWIFT_DEBUG_ENABLE_CACHE_PROTOCOL_CONFORMANCES_BY_TYPE_DESCRIPTOR`
environment variable, which is enabled by default.

This reapplies https://github.com/swiftlang/swift/pull/82818 after it's been reverted in https://github.com/swiftlang/swift/pull/83770.
2025-08-30 00:12:52 +02:00
Dmitrii Galimzianov
4509b22415 Revert "Protocol conformance cache for generic types"
This reverts commit 7989dbe24e merged in https://github.com/swiftlang/swift/pull/82818
2025-08-16 01:39:16 +02:00
Dmitrii Galimzianov
7989dbe24e Protocol conformance cache for generic types
This change adds a new type of cache (cache by type descriptor) to the protocol conformance lookup system. This optimization is beneficial for generic types, where the
same conformance can be reused across different instantiations of the generic type.

Key changes:
- Add a `GetOrInsertManyScope` class to `ConcurrentReadableHashMap` for performing
  multiple insertions under a single lock
- Add type descriptor-based caching for protocol conformances
- Add environment variables for controlling and debugging the conformance cache
- Add tests to verify the behavior of the conformance cache
- Fix for https://github.com/swiftlang/swift/issues/82889

The implementation is controlled by the `SWIFT_DEBUG_ENABLE_CACHE_PROTOCOL_CONFORMANCES_BY_TYPE_DESCRIPTOR`
environment variable, which is enabled by default.
2025-07-11 03:54:42 +02:00
Doug Gregor
15123f5771 [Runtime] Don't fail conformances when the global actor hook is missing
When the concurrency library's "is current global actor" hook is not
available, assume that we are already executing on the right global
actor. This mimics the behavior of earlier standard libraries when
faced with an isolated conformance, as well as dealing with odd
configurations where the code might not load the concurrency library
yet

At the moment, WebAssembly ends up in this configuration because we
don't run the initialization for the concurrency library. That makes
this also a workaround for issue #82682 / rdar://154762027.
2025-07-05 08:50:26 -07:00
Doug Gregor
885f829a63 [Conformance cache] Add allocated extended-storage for entries to the free list
This memory is part of the conformance cache concurrent hash map, so
when we clear the conformance cache, record each of the allocated
pointers within the concurrent map's free list. This way, it'll be
freed with the rest of the concurrent map when it's safe to do so.
2025-04-16 15:11:59 -07:00
Doug Gregor
d576fa30c9 [Runtime] Replace use of C++ new with malloc() 2025-04-16 14:04:14 -07:00
Doug Gregor
9eebee8b7c Merge pull request #80844 from DougGregor/conformance-cache-entry-stole-the-wrong-bit
[Runtime] Don't use the low bit of a WitnessTable pointer in the conformance cache
2025-04-16 13:45:16 -07:00
Doug Gregor
5f0043711c [Conformance cache] Handle missing protocol descriptors
This can happen when running against an older version of a library that
doesn't have the protocol defined.
2025-04-15 21:11:19 -07:00
Doug Gregor
aeb7056991 [Runtime] Don't use the low bit of a WitnessTable pointer in the conformance cache
With relative witness tables, the low bit of a witness table pointer is
an indicator that we need to load from the given pointer. We were also
using the low bit of the witness table pointer in the conformance
cache entry as part of a pointer union. Hilarity ensures [*].

Switch to another low bit by exploding the conformance cache key
into separate fields and taking the low bit of one of those pointers
that isn't reserved.

Fixes the remainder of rdar://149326058, I hope.

[*] No, I am not laughing.
2025-04-15 18:12:18 -07:00
Doug Gregor
663ef8aa2e [Runtime] Handle relative witness tables in _getIsolationCheckingOptionsFromExecutorWitnessTable
Part of rdar://148687148.
2025-04-15 13:47:26 -07:00
Mike Ash
f01d46ce38 [Runtime] Handle relative witness tables in _checkWitnessTableIsolation.
We need to use lookThroughOptionalConditionalWitnessTable when relative witness tables are being used.

rdar://148687148
2025-04-08 16:14:48 -04:00
Ben Barham
a1a8bde65d [Runtime] Return ConformanceLookupResult from findConformanceWithDyld 2025-03-11 21:30:28 -07:00
Doug Gregor
d7f687619e Revert "[WebAssembly] Temporarily work around lack of __attribute__((constructor))"
This reverts commit 8ef9f7fcad.
2025-03-08 08:06:28 -08:00
Doug Gregor
8ef9f7fcad [WebAssembly] Temporarily work around lack of __attribute__((constructor))
We don't have a great way to ensure that the current-global-actor hook
will get installed by the concurrency library with WebAssembly, so
temporarily work around the issue by relying on the fact that we also
aren't doing actual concurrency with WebAssembly.
2025-03-07 23:52:25 -08:00
Doug Gregor
296e14662a Rework runtime entrypoints for isolated conformance checking
Replace the pair of global actor type/conformance we are passing around with
a general "conformance execution context" that could grow new functionality
over time. Add three external symbols to the runtime:

* swift_conformsToProtocolWithExecutionContext: a conforms-to-protocol check
  that also captures the execution context that should be checked before
  using the conformance for anything. The only execution context right now
  is for an isolated conformance.
* swift_isInConformanceExecutionContext: checks whether the function is
  being executed in the given execution context, i.e., running on the
  executor for the given global actor.
* swift_ConformanceExecutionContextSize: the size of the conformance
  execution context. Client code outside of the Swift runtime can allocate
  a pointer-aligned region of memory of this size to use with the runtime
  functions above.
2025-03-07 23:52:20 -08:00
Doug Gregor
48aa75d86f [Isolated conformances] Cache resolved global actor for conformances
In the prior implementation of runtime resolution of isolated conformances,
the runtime had to look in both the protocol conformance descriptor and
in all conditional conformance requirements (recursively) to find any
isolated conformances. If it found one, it had to demangle the global
actor type to metadata. Since swift_conformsToProtocol is a hot path through
the runtime, we can't afford this non-constant-time work in the common
case.

Instead, cache the resolved global actor and witness table as part of the
conformance cache, so that we have access to this information every time
we look up a witness table for a conformance. Propagate this up through
various callers (e.g., generic requirement checking) to the point where
we either stash it in the cache or check it at runtime. This gets us down
to a very quick check (basically, NULL-or-not) for nonisolated conformances,
and just one check for isolated conformances.
2025-03-07 23:51:46 -08:00
Doug Gregor
6dd141ad54 Replace dlsym of swift_task_isCurrentGlobalActor with a constructor hook
Following the approach taken with the concurrency-specific type
descriptors, register a hook function for the "is current global actor"
check used for isolated conformances.
2025-03-07 23:51:43 -08:00
Doug Gregor
c266a0965f [Isolated conformances] Check witness tables for conditional requirements
When establishing whether a given conformance is isolated, look through
the witness tables used to satisfy conditional requirements as well. This
is because an otherwise-nonisolated conditional conformance can become
isolated if one of its associated conformance requirements is satisfied
by an isolated conformance.

While here, make sure this code works with variadic generics, too.
2025-03-07 23:51:39 -08:00
Doug Gregor
951b535608 Metadata and runtime support for checking isolated conformances at runtime
Extend the metadata representation of protocol conformance descriptors
to include information about the global actor to which the conformance is
isolated (when there is one), as well as the conformance of that type to
the GlobalActor protocol. Emit this metadata whenever a conformance is
isolated.

When performing a conforms-to-protocol check at runtime, check whether
the conformance that was found is isolated. If so, extract the serial
executor for the global actor and check whether we are running on that
executor. If not, the conformance fails.
2025-03-07 23:51:25 -08:00
Allan Shortlidge
806c60020c stdlib: Resolve an unused variable warning. 2024-11-13 09:51:29 -08:00
Joe Groff
a184782a38 Introduce a Builtin.FixedArray type.
`Builtin.FixedArray<let N: Int, T: ~Copyable & ~Escapable>` has the layout of `N` elements of type `T` laid out
sequentially in memory (with the tail padding of every element occupied by the array). This provides a primitive
on which the standard library `Vector` type can be built.
2024-10-22 16:21:45 -07:00
Michael Gottesman
cb8e8b505a Fix syntax highlighting by changing how we include COMPATIBILITY_OVERRIDE_INCLUDE_PATH.
The way that we include COMPATIBILITY_OVERRIDE_INCLUDE_PATH freaks out the
syntax highlighting of editors like emacs. It causes the whole file to be
highlighted like it is part of the include string.

To work around this, this patch creates a separate file called
CompatibilityOverrideIncludePath.h that just includes
COMPATIBILITY_OVERRIDE_INCLUDE_PATH. So its syntax highlighting is borked, but
at least in the actual files that contain real code, the syntax highlighting is
restored.
2024-10-01 16:17:16 -07:00
Alejandro Alonso
3d8a9d4554 Implement same type checking at runtime 2024-09-04 15:13:51 -07:00
Alejandro Alonso
7c85261a77 Add runtime support 2024-09-04 15:13:27 -07:00
Alejandro Alonso
75c2cbf593 Implement value generics
Some requirement machine work

Rename requirement to Value

Rename more things to Value

Fix integer checking for requirement

some docs and parser changes

Minor fixes
2024-09-04 15:13:25 -07:00
Mike Ash
b86fe88c43 [Runtime] Fix key argument indexing when checking invertible protocols.
Track the key argument index separately from the generic parameter index when performing the invertible protocol checking in _checkGenericRequirements. This keeps the indexing correct when a non-key argument is followed by a key argument.

rdar://128774651
2024-06-11 12:39:23 -04:00
Doug Gregor
ae01d20428 Runtime checking for associated types conforming to invertible protocols
Emit metadata for runtime checks of conformances of associated types to
invertible protocols, e.g., `T.Assoc: Copyable`. This allows us to
correctly handle, e.g., dynamic casting involving conditional
conformances that have such constraints.

The model we use here is to emit an invertible-protocol constraint
that leaves only the specific bit clear in the invertible protocol
set.
2024-04-02 16:42:16 -07:00
Doug Gregor
b84f8ab080 Rename "suppressible protocols" to "invertible protocols".
We've decided to use the "invertible protocols" terminology throughout
the runtime and compiler, so move over to that terminology
consistently.
2024-03-29 11:31:48 -07:00
Doug Gregor
cd20dbafbf [Runtime] Don't check suppressible protocols for non-key generic arguments 2024-03-26 21:33:53 -07:00
Doug Gregor
af38d88ba3 Fix typos spotted by code review, thank you! 2024-03-22 08:28:45 -07:00
Doug Gregor
11774e5d17 [Runtime] Check function types against suppressible protocols
Form a set of suppressed protocols for a function type based on
the extended flags (where future compilers can start recording
suppressible protocols) and the existing "noescape" bit. Compare
that against the "ignored" suppressible protocol requirements, as we
do for other types.

This involves a behavior change if any client has managed to evade the
static checking for noescape function types, but it's unlikely that
existing code has done so (and it was unsafe anyway).
2024-03-22 07:45:50 -07:00
Doug Gregor
5b020068c5 Extend runtime checking for suppressible protocols
Add more runtime support for checking suppressible protocol requirements:
* Parameter packs now check all of the arguments appropriately
* Most structural types now implement checking (these are hard to test).
2024-03-21 19:22:28 -07:00
Doug Gregor
b167eece42 Metadata and runtime support for suppressible protocol requirements
Introduce metadata and runtime support for describing conformances to
"suppressible" protocols such as `Copyable`. The metadata changes occur
in several different places:

* Context descriptors gain a flag bit to indicate when the type itself has
  suppressed one or more suppressible protocols (e.g., it is `~Copyable`).
  When the bit is set, the context will have a trailing
  `SuppressibleProtocolSet`, a 16-bit bitfield that records one bit for
  each suppressed protocol. Types with no suppressed conformances will
  leave the bit unset (so the metadata is unchanged), and older runtimes
  don't look at the bit, so they will ignore the extra data.
* Generic context descriptors gain a flag bit to indicate when the type
  has conditional conformances to suppressible protocols. When set,
  there will be trailing metadata containing another
  `SuppressibleProtocolSet` (a subset of the one in the main context
  descriptor) indicating which suppressible protocols have conditional
  conformances, followed by the actual lists of generic requirements
  for each of the conditional conformances. Again, if there are no
  conditional conformances to suppressible protocols, the bit won't be
  set. Old runtimes ignore the bit and any trailing metadata.
* Generic requirements get a new "kind", which provides an ignored
  protocol set (another `SuppressibleProtocolSet`) stating which
  suppressible protocols should *not* be checked for the subject type
  of the generic requirement. For example, this encodes a requirement
  like `T: ~Copyable`. These generic requirements can occur anywhere
  that there is a generic requirement list, e.g., conditional
  conformances and extended existentials. Older runtimes handle unknown
  generic requirement kinds by stating that the requirement isn't
  satisfied.

Extend the runtime to perform checking of the suppressible
conformances on generic arguments as part of checking generic
requirements. This checking follows the defaults of the language, which
is that every generic argument must conform to each of the suppressible
protocols unless there is an explicit generic requirement that states
which suppressible protocols to ignore. Thus, a generic parameter list
`<T, Y where T: ~Escapable>` will check that `T` is `Copyable` but
not that it is `Escapable`, and check that `U` is both `Copyable` and
`Escapable`. To implement this, we collect the ignored protocol sets
from these suppressed requirements while processing the generic
requirements, then check all of the generic arguments against any
conformances not suppressed.

Answering the actual question "does `X` conform to `Copyable`?" (for
any suppressible protocol) looks at the context descriptor metadata to
answer the question, e.g.,

1. If there is no "suppressed protocol set", then the type conforms.
This covers types that haven't suppressed any conformances, including
all types that predate noncopyable generics.
2. If the suppressed protocol set doesn't contain `Copyable`, then the
type conforms.
3. If the type is generic and has a conditional conformance to
`Copyable`, evaluate the generic requirements for that conditional
conformance to answer whether it conforms.

The procedure above handles the bits of a `SuppressibleProtocolSet`
opaquely, with no mapping down to specific protocols. Therefore, the
same implementation will work even with future suppressible protocols,
including back deployment.

The end result of this is that we can dynamically evaluate conditional
conformances to protocols that depend on conformances to suppressible
protocols.

Implements rdar://123466649.
2024-03-21 14:57:47 -07:00
Ben Barham
ef8825bfe6 Migrate llvm::Optional to std::optional
LLVM has removed llvm::Optional, move over to std::optional. Also
clang-format to fix up all the renamed #includes.
2024-02-21 11:20:06 -08:00
Allan Shortlidge
3a3a2460df NFC: Resolve -Wformat warning in ProtocolConformance.cpp. 2024-01-12 17:41:50 -08:00
Alejandro Alonso
de8233a5d6 Revert "Merge pull request #68844 from Azoy/gather-no-parameters"
This reverts commit ccaf427fc3, reversing
changes made to bf45c55530.
2023-10-10 19:36:20 -07:00
Alejandro Alonso
3ddec4fd83 Wrap _checkGenericRequirements instead for _instantiateCheckedGenericMetadata 2023-10-09 15:02:29 -07:00
Saleem Abdulrasool
da314bc7d7 runtime: silence some -Wformat warnings (NFC)
Use `z` rather than `l` for the modifier as the values are `size_t`
rather than `long`.  This fixes a bit of warning spew on Windows.
2023-08-04 08:47:23 -07:00
Mike Ash
fe7e13bba5 [Runtime][IRGen] Sign type context descriptor pointers.
Ensure that context descriptor pointers are signed in the runtime by putting the ptrauth_struct attribute on the types.

We use the new __builtin_ptrauth_struct_key/disc to conditionally apply ptrauth_struct to TrailingObjects based on the signing of the base type, so that pointers to TrailingObjects get signed when used with a context descriptor pointer.

We add new runtime entrypoints that take signed pointers where appropriate, and have the compiler emit calls to the new entrypoints when targeting a sufficiently new OS.

rdar://111480914
2023-07-07 18:10:35 -04:00
Slava Pestov
8742b1a1e2 Runtime: Fix shape requirement handling in _checkGenericRequirements()
We would say the shape requirement was always satisfied since we
incorrectly checked the left-hand side type twice.
2023-06-21 15:03:53 -04:00
Slava Pestov
3052e36f7e Runtime: Fix dynamic casts of variadic types that conditionally conform 2023-06-21 13:42:57 -04:00
Mike Ash
110f428780 [Runtime] Add tracing for section scans.
Section scans (for metadata, protocols, etc.) can be costly. This change adds tracing calls to those scans so we can more easily see how much time is spent in these scans and where they're initiated.

This adds an os_signpost implementation controlled by SWIFT_STDLIB_TRACING, and a default empty implementation for when that's disabled.

rdar://110266743
2023-06-14 12:07:44 -04:00
Slava Pestov
c50e8bb5de Runtime: Check same-type pack requirements in checkGenericPackRequirement() 2023-03-17 22:19:18 -04:00
Slava Pestov
a21b0d9749 Runtime: Check layout pack requirements in checkGenericPackRequirement() 2023-03-17 22:19:18 -04:00
Slava Pestov
d17baed985 Runtime: Check superclass pack requirements in checkGenericPackRequirement() 2023-03-17 22:19:17 -04:00
Slava Pestov
d776f71b4f Runtime: Teach checkGenericRequirements() to check same-shape and conformance pack requirements 2023-03-09 09:42:00 -05:00
Slava Pestov
2cf1241a7c Runtime: Extract checkGenericRequirement() from checkGenericRequirements() 2023-03-09 01:54:51 -05:00
Slava Pestov
32caa17b11 Runtime: Finish removing the 'extra argument' notion 2023-03-03 02:21:08 -05:00
Slava Pestov
d5b75fe7d2 Runtime: Add GenericRequirementKind::SameShape and stub out cases 2023-02-28 17:33:06 -05:00