-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
[embedded] Introduce class-bound existentials into Embedded Swift #76572
[embedded] Introduce class-bound existentials into Embedded Swift #76572
Conversation
Motivated by need for protocol-based dynamic dispatch, which hasn't been possible in Embedded Swift due to a full ban on existentials. This lifts that restriction but only for class-bound existentials: Class-bound existentials are already (even in desktop Swift) much more lightweight than full existentials, as they don't need type metadata, their containers are typically 2 words only (reference + wtable pointer), don't incur copies (only retains+releases). Included in this PR: [x] Non-generic class-bound existentials, executable tests for those. [x] Extension methods on protocols and using those from a class-bound existential. [x] RuntimeEffects now differentiate between Existential and ExistentialClassBound. [x] PerformanceDiagnostics don't flag ExistentialClassBound in Embedded Swift. [x] WTables are generated in IRGen when needed. Left for follow-up PRs: [ ] Generic classes support
lib/SIL/Utils/InstructionUtils.cpp
Outdated
@@ -963,7 +961,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) | |||
rt |= RuntimeEffect::ObjectiveC | RuntimeEffect::MetaData; | |||
break; | |||
case SILFunctionTypeRepresentation::WitnessMethod: | |||
rt |= RuntimeEffect::MetaData | RuntimeEffect::Existential; | |||
rt |= RuntimeEffect::MetaData; // ??? |
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.
@eeckstein Do you have a suggestion what to check here? I think we want this to be RuntimeEffect::ExistentialClassBound if the witness method is for a class-bound protocol, and RuntimeEffect::Existential otherwise?
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.
yes, I think this makes sense
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.
Right, but do you have any hints on how to implement this? We have an ApplySite and an ApplyInst here, how do we go from that to the protocol that's in used?
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.
You could do it as in hasValidSignatureForEmbedded
: check if all generic parameters are class bound. The function type you can get from ApplySite::getOrigCalleeType()
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.
It's even simpler: you can use SILFunctionType::getWitnessMethodConformanceOrInvalid
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.
Ok, done!
// in embedded Swift mode, running the existential specializer might introduce | ||
// more generic calls from non-generic functions, which breaks the assumptions | ||
// of embedded Swift. | ||
P.addExistentialSpecializer(); |
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.
@eeckstein Any better ideas what to do here? Or is this reasonable to keep? Temporarily?
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 think this is fine
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.
nice!
lib/SIL/Utils/InstructionUtils.cpp
Outdated
@@ -963,7 +961,7 @@ RuntimeEffect swift::getRuntimeEffect(SILInstruction *inst, SILType &impactType) | |||
rt |= RuntimeEffect::ObjectiveC | RuntimeEffect::MetaData; | |||
break; | |||
case SILFunctionTypeRepresentation::WitnessMethod: | |||
rt |= RuntimeEffect::MetaData | RuntimeEffect::Existential; | |||
rt |= RuntimeEffect::MetaData; // ??? |
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.
yes, I think this makes sense
// in embedded Swift mode, running the existential specializer might introduce | ||
// more generic calls from non-generic functions, which breaks the assumptions | ||
// of embedded Swift. | ||
P.addExistentialSpecializer(); |
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 think this is fine
…assBound based on the callee type
@swift-ci please test |
@swift-ci please test Linux platform |
Motivated by need for protocol-based dynamic dispatch, which hasn't been possible in Embedded Swift due to a full ban on existentials. This lifts that restriction but only for class-bound existentials: Class-bound existentials are already (even in desktop Swift) much more lightweight than full existentials, as they don't need type metadata, their containers are typically 2 words only (reference + wtable pointer), don't incur copies (only retains+releases).
Included in this PR:
Left for follow-up PRs: