-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SILOptimizer: make vtable pruning less aggressive #33770
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
Conversation
CC: @jckarter |
@swift-ci please test |
Before this goes in I would like to understand more what is happening here. |
Also note that @jckarter is on vacation right now as I understand it. |
void runOnVTable(SILModule *M, | ||
SILVTable *vtable) { | ||
void runOnVTable(SILModule *M, SILVTable *vtable) { | ||
if (!vtable->getClass()->isOutermostPrivateOrFilePrivateScope()) { |
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.
Turning this off for everything is not appropriate, we at least should be using the tools that we already have that handle this sort of thing. There are ways of checking this visibility while handling wmo/non-wmo that we should be using rather than referring to the ast.
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.
Reading SILVTable, it seems that there is a query that tells you if the vtable will be serialized or was serialized. Given that we seem to not have SILLinkage here, I imagine that is what one would want to use.
@eeckstein what are your thoughts?
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.
Can you point me to what you have in mind for checking here? I think that the WMO doesn't guarantee that every single reference is going to get fully monomorphized right? But, sure WMO with internal visibility should allow additional cases.
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 problem can only occur in non-WMO mode or for "open" classes in WMO mode, right?
Can we disable this optimization just for "open" classes and for non-WMO mode (which is not so important)?
The class vtable is stored in the metadata, not the VWT. I think a better fix would be to disable vtable pruning entirely in non-WMO mode. A more precise check would be to use vtable pruning only for fileprivate classes in non-WMO mode. |
Background for this PR is SR-13449. |
Correct. The effective VWT in the metadata is what is being pruned.
Yes, I agree with you, and that is what I would prefer to do:
I suppose that we could disable vtable pruning entirely in non-WMO mode, but if we can do it safely, why not? |
Build failed |
@slavapestov question. I imagine the issue here in the design space is that we never have given vtables a SILLinkage and the infrastructure around isExternallyUsedSymbol. Your thoughts? My thought is given that this causes a real crash, I think it makes sense to just disable this in this way for now. Really we should just fix the vtable to have VTables. |
Build failed |
3400f86
to
e5770ab
Compare
@slavapestov, @eeckstein - okay, the pass always runs under WMO now and only scans private classes on non-WMO mode. |
@swift-ci please test |
Build failed |
A class which is marked as internal or public can be visible outside of the current file, where the use of the VWT indirectly is possible. If the VWT is modified and inlined, it is possible that the offsets will no longer match resulting in an invalid dispatch. Limit the pass to when WMO is enabled or the type is private in non-WMO cases.
e5770ab
to
a92e9b3
Compare
@swift-ci please test |
Build failed |
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.
lgtm!
LLVM_DEBUG(llvm::dbgs() << "PruneVTables inspecting table:\n"; | ||
vtable->print(llvm::dbgs())); | ||
if (!M->isWholeModule() && | ||
vtable->getClass()->getEffectiveAccess() >= AccessLevel::FilePrivate) { |
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.
Shouldn't it be >
not >=
then?
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.
Oops, I thought Id fixed that. #33808
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 change is unnecessarily pessimistic. The check for calleesAreStaticallyKnowable
below should already prevent us from pruning nonfinal internal vtable entries. We should still be able to prune entries for final methods as long as the final method is not itself an override, because it should never need a vtable entry for originally-final methods to begin with, and we can reliably check whether a method is final across modules without an optimization pass. I suppose that means we could set the nonoverridden
bit in SILGen for final methods.
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 looks like if a method is originally final we already don't give it a vtable entry at all. So, we should be able to remove the if (!methodDecl->isFinal())
precondition below and get the same effect. I think that's better than reimplementing calleesAreStaticallyKnowable
here.
A class which is marked as
internal
orpublic
can be visible outsideof the current file, where the use of the VWT indirectly is possible.
If the VWT is modified and inlined, it is possible that the offsets will
no longer match resulting in an invalid dispatch. Although this change
drastically reduces the efficacy of this pass, it ensures correctness as
a temporary measure.
Thanks to Alexander Smarus for the basis for the test case!
https://bugs.swift.org/browse/SR-13449
rdar://problem/68170038