Since these types have an implicit stored property, this requires
adding an abstraction over fields to IRGen, at least throughout
the class code. In some ways I think this significantly improves
the code, especially in how we approach missing members.
Fixes rdar://72202671.
A formally virtual method still needs to provide the ABI of an overridable
method, including a dispatch thunk, method descriptor, and support in the
method lookup function for the class to handle `super.` calls from clients.
Private and internal classes shouldn't have ABI constraints on their concrete vtable layout, so if methods
don't have overrides in practice, we can elide their vtable entries.
Previously, the trailing flags field of runtime instantiated generic
metadata for types which had prespecialization enabled were not zeroed.
Consequently, the field always contained garbage. Often, metadata was
instantiated on new (and so, zeroed) pages, so the garbage happened to
be zero as is appropriate. However, when the metadata was instantiated
on pages which had previously been dirtied, the garbage value would
sometimes indicate that the metadata was canonical statically
specialized. When that occurred, swift_checkMetadataState would
incorrectly return a metadata state of complete, despite the fact that
the metadata might not in fact be complete. As a result, the runtime
was trafficking in incomplete metadata as if it were complete, resulting
in various crashes that would arise from for example missing a witness
table or a value witness table.
Here the problem is corrected. The trailing flags field of structs and
enums that have the field is set to 0.
For structs, this is accomplished by modifying the extra data pattern to
exist not only when there is fixed type info for the type but also when
the type is being prespecialized. Specifically, the extra data for a
struct is, rather than an i32 array of field offsets, a struct
consisting of none, one, or both of the following: (1) the array of
field offsets, (2) the trailing flags.
Similarly, enums now have an extra data pattern which consists of none,
one, or both of the following: (1) the payload size, (2) the trailing
flags. Enum metadata extra data setting was previously achieved by
customizing the metadata allocation function; that customization is now
eliminated, being replaced with the shared runtime code for copying
extra data into place, a modest code size savings.
rdar://problem/61465515
Previously, the various generic builders implemented the methods
addGenericArgument and addGenericWitnessTable without being provided
what argument or witness table they were to add (because it was not
previously needed). Now, the GenericRequirement is passed along to both
methods.
We don't need to substitute the superclass type as we walk up a
class hierarchy, or look up the generic parameters and conformances
to check if they're concrete, since we're always just emitting
null pointers in place of the generic parameters and requirements,
to be filled at runtime.
Also, don't leave space for generic parameters and requirements from
Objective-C superclasses, since that's not how they're represented.
- `swift_getForeignTypeMetadata` is now a request/response function.
- The initialization function is now a completion function, and the
pointer to it has moved into the type descriptor.
- The cache variable is no longer part of the ABI; it's an
implementation detail of the access function.
- The two points above mean that there is no special header on foreign
type metadata and therefore that they can be marked constant when
there isn't something about them that needs to be initialized.
The only foreign-metadata initialization we actually do right now is
of the superclass field of a foreign class, and since that relationship
is a proper DAG, it's not actually possible to have recursive
initialization problems. But this is the right long-term thing to do,
and it removes one of the last two clients of once-based initialization.
The resilient methods will all be keyed by their dispatch thunks, so for methods of local subclasses, we can use the offsets relative to the dynamic base as identifiers without having to adjust for that dynamic base.
Type of elements contained by field offsets vector can be adjusted
to 32-bit integers (from being pointer sized) to safe space in the
binary since segment size is limited to 4 GB.
Resolves: rdar://problem/36560486
Abstract type/heap metadata access goes into MetadataRequest.
Metadata access starting from a heap object goes into GenHeap.
Accessing various components of class metadata goes into GenClass
or MetadataLayout.
The layout changes to become relative-address based. For this to be
truly immutable (at least on Darwin), things like the RO data patterns
must be moved out of the pattern header. Additionally, compress the
pattern header so that we do not include metadata about patterns that
are not needed for the type.
Value metadata patterns just include the metadata kind and VWT.
The design here is meant to accomodate non-default instantiation
patterns should that become an interesting thing to support in the
future, e.g. for v-table specialization.
Change the "metadata base offset" variable into a "class metadata bounds"
variable that contains the base offset and the +/- bounds on the class.
Link this variable from the class descriptor when the class has a resilient
superclass; otherwise, store the +/- bounds there. Use this variable to
compute the immediate-members offset for various runtime queries. Teach the
runtime to fill it in lazily and remove the code to compute it from the
generated code for instantiation. Identify generic arguments with the start
of the immediate class metadata members / end of the {struct,enum} metadata
header and remove the generic-arguments offset from generic type descriptors.
When emitting foreign class metadata (e.g., for an imported CF type), fill
in the superclass when we have one. The superclass will itself be a foreign
metadata candidate, so also register an initialization function that uniques
the superclass metadata once we've picked the canonical foreign class
metadata.
If a generic class has non-resilient ancestry, we cannot use
the template size so far as the constant value of the base offset
variable, because the template will not contain entries for all
metadata members; instead, use metadata layout as with everything
else.
We no longer need this for anything, so remove it from metadata
altogether. This simplifies logic for emitting type metadata and
makes type metadata smaller.
We still pass the parent metadata pointer to type constructors;
removing that is a separate change.