Rename the funnel points for demangling strings/nodes to metadata to
swift_getTypeByMangled(Name|Node) and make them overridable. This will let
us back-deploy mangling improvements and bug fixes.
Clean up the interfaces used to go from a mangled name or demangle tree to
metadata. Parameterize these interfaces for generic parameter substitutions
(already in use) and dependent conformance substitutions (speculative).
When we emit "false" symbolic references to accesors for conformances or
type metadata, ensure that we end up with two-byte-aligned symbolic
references. This addresses a problem with ARM+Thumb compilation where the
low bit wasn't getting set for Thumb code.
Fixes rdar://problem/46067353.
Split these two functions into a fast path (for the cached case) and a slow
path. Make the slow path overridable, so we can patch it in the future if
needed.
When we are looking for the specific type for a protocol conformance (e.g.,
because we may have a subclass of the type that declared conformances), don't
go back through swift_conformsToProtocol() multiple times, which
requires more lookups in the global conformance table. Instead, use
the (known) protocol conformance descriptor.
The current representation of an associated conformance in a witness
tables (e.g., Iterator: IteratorProtocol within a witness table for
Sequence) is a function that the client calls.
Replace this with something more like what we do for associated types:
an associated conformance is either a pointer to the witness table (once
it is known) or a pointer to a mangled name that describes that
conformance. On first access, demangle the mangled name and replace the
entry with the resulting witness table. This will give us a more compact
representation of associated conformances, as well as always caching
them.
For now, the mangled name is a sham: it’s a mangled relative reference to
the existing witness table accessors, not a true mangled name. In time,
we’ll extend the support here to handle proper mangled names.
Part of rdar://problem/38038799.
Introduce a new runtime entry point, swift_getAssociatedConformanceWitness(),
which extracts an associated conformance witness from a witness table.
Teach IRGen to use this entry point rather than loading the witness
from the witness table and calling it directly.
There’s no advantage to doing this now, but it is staging for changing the
representation of associated conformances in witness tables.
Previously we were only doing this in assert builds, or if the
new Objective-C runtime metadata update hook mechanism was
available.
However, swift_checkMetadataState() gets called on the superclass
of a class, and it assumes that the metadata entry for the
superclass already exists in the singleton cache.
So even on an older runtime when there's no initialization work
to be done, we have to realize the superclass to populate the
singleton cache so that the check can succeed.
Fixes <rdar://problem/45569020>.
This runtime function doesn’t always perform instantiation; it’s how we
get a witness table given a conformance, type, and set of instantiation
arguments. Name it accordingly.
Witness table accessors return a witness table for a given type's
conformance to a protocol. They are called directly from IRGen
(when we need the witness table instance) and from runtime conformance
checking (swift_conformsToProtocol digs the access function out of the
protocol conformance record). They have two interesting functions:
1) For witness tables requiring instantiation, they call
swift_instantiateWitnessTable directly.
2) For synthesized witness tables that might not be unique, they call
swift_getForeignWitnessTable.
Extend swift_instantiateWitnessTable() to handle both runtime
uniquing (for #2) as well as handling witness tables that don't have
a "generic table", i.e., don't need any actual instantiation. Use it
as the universal entry point for "get a witness table given a specific
conformance descriptor and type", eliminating witness table accessors
entirely.
Make a few related simplifications:
* Drop the "pattern" from the generic witness table. Instead, store
the pattern in the main part of the conformance descriptor, always.
* Drop the "conformance kind" from the protocol conformance
descriptor, since it was only there to distinguish between witness
table (pattern) vs. witness table accessor.
* Internalize swift_getForeignWitnessTable(); IRGen no longer needs to
call it.
Reduces the code size of the standard library (+assertions build) by
~149k.
Addresses rdar://problem/45489388.
Collapse the generic witness table, which was used only as a uniquing
data structure during witness table instantiation, into the protocol
conformance record. This colocates all of the constant protocol conformance
metadata and makes it possible for us to recover the generic witness table
from the conformance descriptor (including looking at the pattern itself).
Rename swift_getGenericWitnessTable() to swift_instantiateWitnessTable()
to make it clearer what its purpose is, and take the conformance descriptor
directly.
When performing the round-tripping verification for mangled type names,
make sure we resolve symbolic references to something
user-comprehensible that can be meaningfully rem angled.
Part of rdar://problem/37551850.
Place resilient witnesses in the protocol conformance descriptor,
tail-allocated after the conditional requirements, so they can be found by
reflection. Drop the resilient witness table and protocol descriptor from
the generic witness table.
Addresses rdar://problem/45228582.
Have clients pass the requirement base descriptor to
swift_getAssociatedTypeWitness(), so that the witness index is just one
subtraction away, avoiding several dependent loads (witness table ->
conformance descriptor -> protocol descriptor -> requirement offset)
in the hot path.
Rather than rely on the metadata initialization function to compute and
fill in the superclass, use the mangled superclass name to construct the
superclass metadata.
Introduce a sanity check verifying that we can demangle the superclass
of a class when forming type metadata, and that the result matches the
compiler-provided superclass metadata.
The superclass descriptor reference in class context descriptors is only used
for metadata bound computations when the superclass is resilient. Only
include the superclass descriptor reference when the class has a resilient
superclass, using a trailing record. It’s a tiny space savings for
classes that don’t have resilient superclasses.
This is the scheme used for metadata caches elsewhere, and it
eliminates the need to check the metadata state along the hot path of
swift_getAssociatedTypeWitness().
Encode default associated type witnesses using a sentinel prefix byte
(0xFF) in the mangled name rather than as a second low bit on the
reference. Align all of the mangled names used for type references to
2 bytes (so we get that low bit regardless) and separate the symbol
names for default associated type witnesses vs. other kinds of
metadata or reflection metadata.
Indicate whether a particular associated type witness is a default (whose
mangled name is relative to the protocol) vs. being supplied as part of the
conformance (whose mangled name is relative to the conforming type). The
use of pointer identity to distinguish these cases can fail due to the
coalescing of these linker symbols.
When producing an associated type witness from a mangled name, adjust the
conforming type metadata to find the original conforming type, which may
be a superclass of the conforming type given.
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.
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.
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 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.