-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[sil] Ban casting AnyObject with a guaranteed ownership forwarding checked_cast_br and fix up semantic-arc-opts given that. #40287
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
@swift-ci smoke test |
Turns out libswift hit the verification. I put a fix in SILGenBuilder to ensure that if we create a checked_cast_br, we ensurePlusOne if the source type is AnyObject. |
4c9ab1c
to
9862ae6
Compare
@swift-ci test |
@swift-ci test source compatibility |
@swift-ci benchmark |
Performance (x86_64): -O
Code size: -O
Performance (x86_64): -Osize
Code size: -OsizePerformance (x86_64): -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
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.
Thanks. Look great except...
swift::findOwnershipReferenceAggregate
needs to be fixed to check for direct forwarding. Maybe there are other places?
The canOpcodeForwardGuaranteedValues
APIs are the problem. They're completely misleading. Can they be fixed to be canDirectlyForwardValue
and canDirectlyForwardOperand
? That would be much better than adding a check to OwnershipLiveRange
I probably would have opted for custom logic in isDirectlyForwarding
that checks for checked_cast_br
, then calls CheckedCastBranch::isDirectlyForwarding
, but the flag is cleaner so that's up to your judgement.
…ecked_cast_br and fix up semantic-arc-opts given that. The reason why I am doing this is that currently checked_cast_br of an AnyObject may return a different value due to boxing. As an example, this can occur when performing a checked_cast_br of a __SwiftValue(AnyHashable(Klass())). To model this in SIL, I added to OwnershipForwardingMixin a bit of information that states if the instruction directly forwards ownership with a default value of true. In checked_cast_br's constructor though I specialize this behavior if the source type is AnyObject and thus mark the checked_cast_br as not directly forwarding its operand. If an OwnershipForwardingMixin directly forwards ownership, one can assume that if it forwards ownership, it will always do so in a way that ensures that each forwarded value is rc-identical to whatever result it algebraically forwards ownership to. So in the context of checked_cast_br, it means that the source value is rc-identical to the argument of the success and default blocks. I added a verifier check to CheckedCastBr that makes sure that it can never forward guaranteed ownership and have a source type of AnyObject. In SemanticARCOpts, I modified the code that builds extended live ranges of owned values (*) to check if a OwnershipForwardingMixin is directly forwarding. If it is not directly forwarding, then we treat the use just as an unknown consuming use. This will then prevent us from converting such an owned value to guaranteed appropriately in such a case. I also in SILGen needed to change checked_cast_br emission in SILGenBuilder to perform an ensurePlusOne on the input operand (converting it to +1 with an appropriate cleanup) if the source type is an AnyObject. I found this via the verifier check catching this behavior from SILGen when compiling libswift. This just shows how important IR verification of invariants can be. (*) For those unaware, SemanticARCOpts contains a model of an owned value and all forwarding uses of it called an OwnershipLiveRange. rdar://85710101
9862ae6
to
8e5fb21
Compare
@swift-ci smoke test |
@swift-ci test |
I believe the concept here is correct: The optimization that assumes a successful cast of a reference type returns the same pointer does need to be avoided if the source is AnyObject, since AnyObject can hold references to various box types that can be unboxed to get at a contained class object reference. |
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 believe the concept is sound; I'll let @atrick weigh in on the implementation.
Build failed |
Build failed |
I asked Mishal to kill the linux/macOS job since I am already running the smoke test. |
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.
Looks great!
if (ti->isDirectlyForwarding()) { | ||
root = term->getOperand(0); | ||
continue; | ||
} |
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.
Not critical in this PR, but it seems that 6 lines above should now have an assert:
assert(cast<OwnershipForwardingTermInst>(root)->isDirectlyForwarding());
root = root->getDefiningInstruction()->getOperand(0);
The reason why I am doing this is that currently checked_cast_br of an AnyObject
may return a different value due to boxing. As an example, this can occur when
performing a checked_cast_br of a __SwiftValue(AnyHashable(Klass())).
To model this in SIL, I added to OwnershipForwardingMixin a bit of information
that states if the instruction directly forwards ownership with a default value
of true. In checked_cast_br's constructor though I specialize this behavior if
the source type is AnyObject and thus mark the checked_cast_br as not directly
forwarding its operand. If an OwnershipForwardingMixin directly forwards
ownership, one can assume that if it forwards ownership, it will always do so in
a way that ensures that each forwarded value is rc-identical to whatever result
it algebraically forwards ownership to. So in the context of checked_cast_br, it
means that the source value is rc-identical to the argument of the success and
default blocks.
I added a verifier check to CheckedCastBr that makes sure that it can never
forward guaranteed ownership and have a source type of AnyObject.
In SemanticARCOpts, I modified the code that builds extended live ranges of
owned values (*) to check if a OwnershipForwardingMixin is directly
forwarding. If it is not directly forwarding, then we treat the use just as an
unknown consuming use. This will then prevent us from converting such an owned
value to guaranteed appropriately in such a case.
(*) For those unaware, SemanticARCOpts contains a model of an owned value and
all forwarding uses of it called an OwnershipLiveRange.
rdar://85710101
Replace this paragraph with a description of your changes and rationale. Provide links to external references/discussions if appropriate.
Resolves SR-NNNN.