Associated type witnesses in a witness table are cache entries, which are
updated by the runtime when the associated types are first accessed. The
presence of an associated type witness that involves type parameters requires
the runtime to instantiate the witness table; account for that in the runtime.
The presence of any associated type witness makes the witness table
non-constant.
Rather than storing associated type metadata access functions in
witness tables, initially store a pointer to a mangled type name.
On first access, demangle that type name and replace the witness
table entry with the resulting type metadata.
This reduces the code size of protocol conformances, because we no
longer need to create associated type metadata access functions for
every associated type, and the mangled names are much smaller (and
sharable). The same code size improvements apply to defaulted
associated types for resilient protocols, although those are more
rare. Witness tables themselves are slightly smaller, because we
don’t need separate private entries in them to act as caches.
On the caller side, associated type metadata is always produced via
a call to swift_getAssociatedTypeWitness(), which handles the demangling
and caching behavior.
In all, this reduces the size of the standard library by ~70k. There
are additional code-size wins that are possible with follow-on work:
* We can stop emitting type metadata access functions for non-resilient
types that have constant metadata (like `Int`), because they’re only
currently used as associated type metadata access functions.
* We can stop emitting separate associated type reflection metadata,
because the reflection infrastructure can use these mangled names
directly.
When demangling a symbolic reference to a nested generic type, the
demangle-to-metadata path will be given all levels of generic arguments at
once. Cope with this in the demangling-to-metadata path.
Eventually, we would like to switch all clients over to take all
levels of generic arguments at once.
When forming metadata for a nested generic type, gather all of the
generic arguments from the parent type “as written”, so that we can directly
map generic parameters to those generic arguments when they occur within
requirements. This allows us to demangle nested types within extensions
that have same-type constraints on generic parameters into type metadata.
Fixes rdar://problem/37170296.
At the moment the location being reported is inside the standard
library, which is not very helpful. Instead, the location should point
at the `try!` expression in the application code.
Fixes: rdar://problem/21407683
When mapping from type metadata to a demangle tree, fill in the complete
set of generic arguments. Most of the effort here is in dealing with
extensions that involve same-type constraints on a generic parameter, e.g.,
extension Array where String == Element { }
extension Dictionary where Key == Value { }
In such cases, the metadata won’t contain generic arguments for every
generic parameter. Rather, the generic arguments for non-key generic
parameters will need to be computed based on the same-type requirements
of the context. Do so, and eliminate the old hacks that put the generic
arguments on the innermost type. We don’t need them any more.
Part of rdar://problem/37170296.
If a class has a backward deployment layout:
- We still want to emit it using the FixedClassMetadataBuilder.
- We still want it to appear in the objc_classes section, and get an
OBJC_CLASS_$_ symbol if its @objc.
- However, we want to use the singleton metadata initialization pattern
in the metadata accessor.
- We want to emit metadata for all field types, and call the
swift_updateClassMetadata() function to initialize the class
metadata.
For now, this function just performs the idempotent initialization of
invoking a static method on the class, causing it to be realized with
the Objective-C runtime.
- Rename _swift_initializeSuperclass() to copySuperclassMetadataToSubclass(),
- Factor out initClassFieldOffsetVector()
- Factor out initClassVTable()
- Factor out initGenericObjCClass()
Otherwise, we emitted a static reference to its metaclass, so there's
no need to overwrite it here. This doesn't really improve anything,
it was just something I noticed while auditing this code in
preparation for a refactoring, so may as well fix it.
Reimplement SubstGenericParametersFromMetadata to cope with non-key
generic parameters, which are counted when referring to generic parameters
from metadata but do not have corresponding generic arguments.
Use SubstGenericParametersFromMetadata to handle substitutions when
checking generic requirements, extending SubstGenericParametersFromMetadata
for this purpose.
The field metadata translation has a great little lambda for extracting
generic arguments from metadata when demangling. Extract it into a
reusable function object.
The resolution of generic parameter references, which is used for
checking generic requirements at runtime, was written in terms of an
outdated signature for associated type access functions that did not
account for the MetadataRequest parameter or MetadataResponse result.
Use the existing AssociatedTypeAccessFunction typedef instead.
Fixes SR-7553 / rdar://problem/39769906
When SWIFT_ENABLE_MANGLED_NAME_VERIFICATION is set, we would end up
deadlocking when we encounter a metadata cycle. The demangling code only
requires abstract metadata, because at most it needs type identity and
filling in the type arguments of generics. Update clients of
_getTypeByMangledName to assert the kind of metadata they require.
Update the instances of checks for architectures to be more broad for different
spellings of the architecture macro. Certain targets use `_M_ARM` and others
use `__arm__`. Similarly, arm64/aarch64 has `_M_ARM64`, `__arm64__` and
`__aarch64__` as spellings. This just mechanically goes through and encodes the
various spellings.
Take the opportunity to replace some raw checks with `defined` checks which
avoids a pedantic warning due to the undefined macro when performing the check
as the preprocessor may warn about an undefined condition evaluating to `0`.
(instead of using dlsym)
The original use went in before <objc/runtime.h> was updated, but now
it should be present in all Xcode 10 SDKs.
rdar://problem/42137765
Like we did for structs, make it so that tuple types can also get extra inhabitants from whichever element with the most, not only the first. This lets us move all of the extra inhabitant handling functionality between structs and tuples in IRGen up to the common RecordTypeInfo CRTP base.
The use of `__APPLE__` is unnecessary as the case is guarded by the
`SWIFT_DARWIN_ENABLE_STABLE_ABI_BIT` preprocessor guard which is implicitly
specific to that environment. Additionally, flip the condition around so that
the positive (which is the future) appears ahead of the negative case.
Describe the consequences of missing metadata instead of just posting a scary
message about a bug. Furthermore, since these warnings tend to show up in
playgrounds, and probably aren't relevant to the user of a playground, suppress
them when running in a playground. rdar://problem/44642942
The witness table for an empty, resilient protocol might need to be
instantiated, if a newer version of the protocol contains defaulted
associated type requirements. In such cases, we would either fail to
instantiate or assert in the runtime. Replace the assertion with a
proper check (to require instantiation in such cases) and cope with
filling in defaults even when the provided generic witness table has
no resilient witnesses.
Replace the quadratic algorithm (currently O(m*n) where m is the number of requirements and n is the number of witnesses) with an O(m+n) algorithm.
Harden the algorithm a against bad and unexpected inputs:
* Fail if the requirement descriptor is out-of-bounds for the protocol
* Skip the witness if the requirement descriptor is null; this can happen
when the witness table was compiled against a newer version of the
protocol, but is deployed to a library containing an older version of the
protocol. It is expected.
* In debug builds of the runtime, complain if an entry is initialized twice
* In debug builds of the runtime, complain if an entry is NULL
Fixes rdar://problem/44434793, which covers the second bullet (backward
deployment).
For a resilient conformance, emit the associated conformance accessor
functions into the resilient witness table (keyed on the associated
conformance descriptor) rather than in the fixed part of the witness
table. This is another part of resilience for associated conformances,
and a step toward defaults for associated conformances.