[swift-dev] Preparing metadata records for ABI stability

John McCall rjmccall at apple.com
Mon Nov 13 13:40:33 CST 2017


> On Nov 7, 2017, at 8:58 PM, Joe Groff via swift-dev <swift-dev at swift.org> wrote:
> 
> I’m trying to plan out changes to our type metadata record formats for ABI stability. I’ll start by looking at the current situation and then make suggestions about things we ought to change. We want to settle on a design that leaves room for future expansion and runtime changes, and still allows efficient access to the most frequently-accessed parts of metadata. I’ll be looking exclusively at metadata records themselves for this message, leaving other data structures for separate scrutiny. I'd appreciate all your feedback.
> 

Overall, I think this is a nice description of the problem.  A few comments:

  - One notable omission here is that you don't discuss nominal type descriptors at all.

  - For the structural types (tuples, functions, existentials, metatypes), I don't think there's any particular reason to abstract access to the component types.  If there are future changes to these types that require additional data to be stored, I don't see any reason that that couldn't be stored compatibly with the current layout.  We should make sure that all of these metadata have some space to encode flags and that reads of those flags are appropriately delimited, as opposed to e.g. assuming that an entire word is used to store a single enum.

  - I think having a single "value type" metadata kind for enums / structs makes sense, assuming we can discriminate them via the NTD.

  - I feel like we're not boxing ourselves in too much to assume a layout of the generic requirements.  Having a base offset already imposes a pretty steep compatibility requirement — e.g. even if we significantly generalized a type's generic signature, we would still need to store old requirements (when actually obeyed) in the appropriate places for the old signature, or else the old pattern just doesn't work at all.  As long as we can extend that with more information later, we don't really suffer from making layout assumptions today.

John.
> Tuple metadata records are accessed by calling the swift_getTupleTypeMetadata* runtime functions.
> 
> The compiler expects access to the following fields:
> 
> Information	Projection strategy
> Element offsets	fixed offset
> If we wanted to be able to satisfy type metadata requirements for element types from tuple metadata, we could also provide access to:
> 
> Information	Projection strategy
> Element types	TBD
> Functions
> 
> Function metadata records are accessed by calling the swift_get*FunctionTypeMetadata* runtime functions.
> 
> The compiler does not currently emit any projections into function type metadata.
> 
> If we wanted to be able to satisfy type metadata requirements for input or output types from function metadata, we could also provide access to:
> 
> Information	Projection strategy
> Return type	TBD
> Argument types	TBD
> Existentials, existential metatypes
> 
> Existential metadata records are accessed by calling the swift_getExistentialTypeMetadata* runtime functions.
> 
> The compiler does not currently generate any code that reaches into existential metadata records.
> 
> If we wanted to be able to satisfy type metadata requirements for input or output types from function metadata, we could also provide access to:
> 
> Information	Projection strategy
> Generic signature	TBD
> Metatypes
> 
> Metatype metadata records are accessed by calling the swift_getMetatypeMetadata function.
> 
> The compiler does not currently generate any code that reaches into metatype metadata records.
> 
> If we wanted to be able to satisfy type metadata requirements for the instance type from metatype metadata, we could also provide access to:
> 
> Information	Projection strategy
> Instance type	TBD
> Objective-C wrappers
> 
> Class objects for natively-Objective-C classes are not Swift metadata by themselves, so need a wrapper metadata record. This wrapper metadata is only produced by the Swift runtime (and could be produced more efficiently by future cooperation with the ObjC runtime). The compiler accesses Objective-C class metadata by calling the swift_getObjCClassMetadata function, which may return either a wrapper or pass through the input class object if it is already valid metadata.
> 
> The compiler generates code against the following:
> 
> Information	Projection strategy
> Class object	runtime call swift_getObjCClassFromMetadata
> Core Foundation class
> 
> Foreign class metadata records are generated by Swift’s Clang importer for imported Core Foundation class types. The records require runtime canonicalization to determine which metadata record uniquely identifies the type, since there is no home Swift module for the CF type. The compiler does not currently generate code against any fields of the metadata.
> 
> Recommended changes
> 
> Abstract away fixed offsets across modules and for structural metadata
> 
> Anything we lock down fixed offsets for in the ABI should justify itself by being necessary for performance or code size reasons. Unspecialized code relies heavily on:
> 
> the value witness table
> stored property offsets
> generic arguments
> and these are the things that nominal type metadata currently makes directly available, for the most part. Anything else we emit direct access to (such as nominal type descriptors) should definitely be abstracted behind a runtime call. For structural type metadata (tuples, functions, existentials, metatypes), we already do so for most of the layout details, with the one exception of tuple element offsets, which are exposed for performance of unspecialized code.
> 
> For concrete nominal types, the compiler also currently generates metadata records that are expected to be directly usable as metadata. This is a nice code size optimization that’d be unfortunate to give up. At least for internal or private types, the emitted metadata format and all of the code that ought to be reaching into it are together in one resilience boundary, so one could say that the precise metadata record format for internal value types is a private contract of the compiler. However, even for public fragile types, it would be beneficial still to be able to directly export the symbol as usable metadata. For the performance-sensitive field offset and generic argument vectors, we could nonetheless avoid hard-coding offsets in the compiler. We could still guarantee that the generic arguments followed by (fragile) stored property offsets are stored contiguously, and abstract the base offset to the contiguous data structure. Possibilities for accessing the base offset include:
> 
> Require a runtime call to get it
> Place the base offset somewhere else in the metadata
> Export the base offset as a separate symbol (possibly an absolute symbol, if it’s knowable at compile time for the home module, or a global variable, if it requires runtime computation).
> For classes with resilient ancestry, we already must have an approach that allows the offset to be computed at instantiation time and efficiently accessed in unspecialized code afterward. Technique (3) is proven by the Objective-C runtime and should be sufficient for our needs. It would impose a two- or three-instruction cost per type to load the base offset, which would sit on the dependency chain for any generic type or field offset loads based on that base offset, but would give us the flexibility to add new information to metadata records in future compilers.
> 
> Make most metadata kinds private to the runtime
> 
> The compiler does not emit any code that looks at metadata kinds for projection purposes. It does, however, use metadata kinds when it builds metadata records for nominal types. However, the metadata kind is already redundantly coded in the nominal type descriptor, so we could conceivably reduce the exposure of metadata kinds to a single “value type” kind (in addition to the “isa-pointer-in-the-kind-field-means-class” kind, imposed by ObjC compatibility).
> 
> 
> -Joe
> _______________________________________________
> swift-dev mailing list
> swift-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20171113/6cad2212/attachment.html>


More information about the swift-dev mailing list