-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Runtime] Improve representation of protocol conformance records #13685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Runtime] Improve representation of protocol conformance records #13685
Conversation
The protocol conformance record has two bits to describe how the witness table will be produced. There are currently three states (direct reference to witness table, witness table accessor, and conditional witness table accessor). Add a reserved case for the fourth state so the Swift 5 runtime will (silently) ignore conformances using that fourth state, when/if some future Swift uses it.
The format of protocol conformance records will be changing in Swift 5, so rename the segment (from, e.g., __swift2_proto to __swift5_proto) to allow Swift < 5 and Swift 5+ runtimes to coexist.
…nce. Move the 2-bit conformance reference kind from the conformance flags (which is meant to go away) into the lower two bits of the witness table offset.
…rds. Within conformance records, reference Objective-C class objects indirectly so the runtime can update those references appropriately. We don't need to do this for classes with Swift metadata.
Now that references to Objective-C class objects are indirected (via UniqueIndirectClass), classes with Swift type metadata can be directly referenced (via UniqueDirectType) rather than hopping through swift_getObjCClassMetadata().
@swift-ci please test |
Build failed |
Effectively NFC, because the compiler is not likely to ever notice the aliasing violation here.
b6b0697
to
b25dc44
Compare
@swift-ci please test |
Build failed |
Build failed |
Rather than emitting unique, direct type metadata for non-foreign types, emit a reference to the nominal type descriptor. This collapses the set of type metadata reference kinds to 3: nominal type descriptor, (indirect) Objective-C class object, and nonuniqued foreign type metadata.
@swift-ci please test |
@swift-ci please test source compatibility |
@swift-ci please test |
1 similar comment
@swift-ci please test |
@swift-ci please test source compatibility |
1 similar comment
@swift-ci please test source compatibility |
Build failed |
Build failed |
@jckarter, I suggest holding off on reviewing for a little bit. I have a cleaner solution coming. |
…formances Use the spare bits within the type reference field to describe the kinds of type metadata records, so that we no longer need to rely on a separate "flags" field.
Eliminate the separate flags field in protocol conformance records, now that all of the information is stored in spare bits elsewhere. Reserve this 32-bit value for future use to describe conditional requirements.
…erences. The separate section of type references uses the same type reference format as in protocol conformance records. As with protocol conformance records, mangle the type reference kind into the lower two bits. Then, eliminate the separate "flags" field from the type metadata record. Finally, rename the section because the Swift 5 stable format for this section is different from prior formats, and the two runtimes need to be able to coexist.
29a1ede
to
310bd6b
Compare
@swift-ci please test |
@swift-ci please test |
@swift-ci please test source compatibility |
2 similar comments
@swift-ci please test source compatibility |
@swift-ci please test source compatibility |
include/swift/ABI/MetadataValues.h
Outdated
|
||
/// The conformance is for a nominal type referenced directly; | ||
/// getNominalTypeDescriptor() points to the nominal type descriptor. | ||
IndirectNominalTypeDescriptor = 0x01, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to update the comment here.
include/swift/ABI/MetadataValues.h
Outdated
/// platforms, the class object always is the type metadata. | ||
UniqueDirectClass = 0xF, | ||
/// and classes are emitted as UniqueDirectType. | ||
UniqueIndirectClass = 0x03, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name and comment here could be updated to indicate this kind is necessary for ObjC classes, since they don't have nominal type descriptors.
include/swift/ABI/MetadataValues.h
Outdated
/// The conformance is for a nongeneric foreign struct or enum type. | ||
/// getDirectType() points to a nonunique metadata record for the type, which | ||
/// needs to be uniqued by the runtime. | ||
NonuniqueDirectType, | ||
NonuniqueDirectType = 0x02, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this case goes away if CF class metadata gets nominal type descriptors (and we'd want to reserve at least one case for future expansion, for a "mangled name" representation perhaps), but the comment could be updated here too.
include/swift/Runtime/Metadata.h
Outdated
RelativeIndirectablePointer<TargetNominalTypeDescriptor<Runtime>> | ||
TypeDescriptor; | ||
RelativeIndirectablePointerIntPair<TargetNominalTypeDescriptor<Runtime>, | ||
/*always clear=*/bool> TypeDescriptor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we're using the spare bits to encode the type metadata kind, and we have separate kinds for direct and indirect type descriptor references, I think it might be clearer to use two union members here:
RelativeDirectPointerIntPair<const TargetNominalTypeDescriptor<Runtime> *,
TypeMetadataRecordKind> DirectTypeDescriptor;
RelativeDirectPointerIntPair<const TargetNominalTypeDescriptor<Runtime> * const *,
TypeMetadataRecordKind> IndirectTypeDescriptor;
since that avoids the cleverness of the TypeMetadataRecordKind
's kinds for nominal type descriptors just happening to line up with the way RelativeIndirectablePointerIntPair
indicates indirection. (Furthermore, it keeps RelativeIndirectablePointerIntPair from being necessary at all.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree that's clearer. Thanks!
…ceRecord. Per JoeG's comments, thanks!
@swift-ci please smoke test |
/// an additional tiny integer value. | ||
template<typename ValueTy, typename IntTy, bool Nullable = false, | ||
typename Offset = int32_t> | ||
class RelativeIndirectablePointerIntPair { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can go away now, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Nevermind, I see it's still used to reserve the unused bit in the protocol reference.)
@swift-ci please smoke test and merge |
This pull request improves the runtime representation of protocol conformance records and type metadata records in several ways:
TypeMetadataRecordKind::UniqueDirectClass
, which is no longer necessaryTypeMetadataRecordKind
cases to 3 (nominal type descriptor, indirect Objective-C class object, and nonuniqued foreign type metadata). Pack the kind into the lower bits of type references in protocol conformance records and type metadata records.