Skip to content

[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

Merged

Conversation

DougGregor
Copy link
Member

@DougGregor DougGregor commented Jan 3, 2018

This pull request improves the runtime representation of protocol conformance records and type metadata records in several ways:

  • Move conformance kind into the low bits of the witness table reference, and be explicit about the remaining reserved kind
  • Reference Objective-C class objects indirectly, so the runtime can fix them up
  • Eliminate TypeMetadataRecordKind::UniqueDirectClass, which is no longer necessary
  • Use nominal type descriptors whenever we can, reducing the number of TypeMetadataRecordKind 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.
  • Eliminate the "flags" word from protocol conformance records, but leave the word reserved for conditional requirements.

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().
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor DougGregor requested a review from jckarter January 3, 2018 06:59
@swift-ci
Copy link
Contributor

swift-ci commented Jan 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - b6b0697ffc2a465d637a904d2e69d26f0c861526

Effectively NFC, because the compiler is not likely to ever notice the
aliasing violation here.
@DougGregor DougGregor force-pushed the protocol-conformance-record-cleanup branch from b6b0697 to b25dc44 Compare January 3, 2018 07:04
@DougGregor
Copy link
Member Author

@swift-ci please test

2 similar comments
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please test

@swift-ci
Copy link
Contributor

swift-ci commented Jan 3, 2018

Build failed
Swift Test Linux Platform
Git Sha - b6b0697ffc2a465d637a904d2e69d26f0c861526

@swift-ci
Copy link
Contributor

swift-ci commented Jan 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - b6b0697ffc2a465d637a904d2e69d26f0c861526

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.
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility

@DougGregor
Copy link
Member Author

@swift-ci please test

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility

1 similar comment
@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility

@swift-ci
Copy link
Contributor

swift-ci commented Jan 3, 2018

Build failed
Swift Test Linux Platform
Git Sha - 29a1ede93177a39eb2301b437ddcdd6f562c9a7a

@swift-ci
Copy link
Contributor

swift-ci commented Jan 3, 2018

Build failed
Swift Test OS X Platform
Git Sha - 29a1ede93177a39eb2301b437ddcdd6f562c9a7a

@DougGregor
Copy link
Member Author

@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.
@DougGregor DougGregor force-pushed the protocol-conformance-record-cleanup branch from 29a1ede to 310bd6b Compare January 3, 2018 18:50
@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please test

@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility

2 similar comments
@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility

@DougGregor
Copy link
Member Author

@swift-ci please test source compatibility


/// The conformance is for a nominal type referenced directly;
/// getNominalTypeDescriptor() points to the nominal type descriptor.
IndirectNominalTypeDescriptor = 0x01,
Copy link
Contributor

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.

/// platforms, the class object always is the type metadata.
UniqueDirectClass = 0xF,
/// and classes are emitted as UniqueDirectType.
UniqueIndirectClass = 0x03,
Copy link
Contributor

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.

/// 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,
Copy link
Contributor

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.

RelativeIndirectablePointer<TargetNominalTypeDescriptor<Runtime>>
TypeDescriptor;
RelativeIndirectablePointerIntPair<TargetNominalTypeDescriptor<Runtime>,
/*always clear=*/bool> TypeDescriptor;
Copy link
Contributor

@jckarter jckarter Jan 3, 2018

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.)

Copy link
Member Author

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!

@DougGregor
Copy link
Member Author

@swift-ci please smoke test

/// an additional tiny integer value.
template<typename ValueTy, typename IntTy, bool Nullable = false,
typename Offset = int32_t>
class RelativeIndirectablePointerIntPair {
Copy link
Contributor

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?

Copy link
Contributor

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.)

@DougGregor
Copy link
Member Author

@swift-ci please smoke test and merge

@DougGregor DougGregor merged commit 0632d87 into swiftlang:master Jan 3, 2018
@DougGregor DougGregor deleted the protocol-conformance-record-cleanup branch January 3, 2018 22:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants