Skip to content

Fix a crash in StackPromotion; case not handled in EscapeAnalysis. #28917

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
merged 1 commit into from
Dec 21, 2019
Merged

Fix a crash in StackPromotion; case not handled in EscapeAnalysis. #28917

merged 1 commit into from
Dec 21, 2019

Conversation

atrick
Copy link
Contributor

@atrick atrick commented Dec 21, 2019

StackPromotion queries EscapeAnalysis. The escape information for the
result of an array semantic was missing because it was an ill-formed
call. This fix introduces a new check to determine whether a call is
well formed so it can be handled consistently everywhere.

Fixes rdar://problem/58113508
Interpreter/SDK/objc_fast_enumeration.swift failed on
iphonesimulator-i386

The bug was introduced here:
commit 8b926af
Author: Andrew Trick atrick@apple.com
Date: Mon Dec 16 16:04:09 2019 -0800

EscapeAnalysis: Add PointerKind and interior/reference flags

The bug can occur when a semantic "array.ininitialized"
call (Array.adoptStorage) at the SIL level has direct "release_value"
instructions that don't use the tuple_extract values corresponding to
the call's returned value. This is part of the tragedy of not
supporting multiple call results. When users of the call's result can
use either the entire tuple (which is a meaningless value), or the
individual tuple extracts, then there's no way to handle calls
uniformly.

The change that broke this was to remove the special handling of
TupleExtract instructions. That special handling was identical to the
way that any normal pointer projection is handled. So, as a
simplification, the new code just expects that case to be handled
naturally as a pointer projection. This case was already guarded by a
check to determine whether the TupleExtract was actually the result of
an array.uninitialized call, in which case the normal handling does
not apply. However, because of the weirdness mentioned above, the
handling of "array.ininitialized" may silently bail out. When that
happens, the TupleExtract gets neither the special handling, nor the
normal handling.

Note that the old special handling of TupleExtract was bizarre and
relied on corresponding weirdness in the code that handles
"array.uninitialized". The new code simply creates a separate graph
node for each result of the call, and creates the edges that exactly
correspond to load and stores on those results. So, rather than
reinstating the previous code, which I can't quite reason about, this
fix creates a single check to determine whether a TupleExtract is
treated as an "array.uninitialized" result or not, and use that check
in both places.

@atrick atrick requested a review from eeckstein December 21, 2019 04:01
@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

@swift-ci test

@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

@swift-ci test source compatibility

@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

@slavapestov this fixes our i386 stdlib/asserts bot

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - f9e3c9859dbc51c08d780c45af047e0d9e3ecaaa

@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

The first fix I pushed simply checked ArraySemanticCall.getKind() == kArrayUninitialized. Apparently, an exact match on the kind is not actually an exact match, so it started trying to optimize "array.uninitialize_intrinsic". And apparently that function's count argument can sometimes look like a pointer. So it did something less than conservative and broke the stdlib/nonasserts tests.

The rebase should fix it.

@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - f9e3c9859dbc51c08d780c45af047e0d9e3ecaaa

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - f9e3c9859dbc51c08d780c45af047e0d9e3ecaaa

StackPromotion queries EscapeAnalysis. The escape information for the
result of an array semantic was missing because it was an ill-formed
call. This fix introduces a new check to determine whether a call is
well formed so it can be handled consistently everywhere.

Fixes <rdar://problem/58113508>
Interpreter/SDK/objc_fast_enumeration.swift failed on
iphonesimulator-i386

The bug was introduced here:
commit 8b926af
Author: Andrew Trick <atrick@apple.com>
Date:   Mon Dec 16 16:04:09 2019 -0800

    EscapeAnalysis: Add PointerKind and interior/reference flags

The bug can occur when a semantic "array.ininitialized"
call (Array.adoptStorage) at the SIL level has direct "release_value"
instructions that don't use the tuple_extract values corresponding to
the call's returned value. This is part of the tragedy of not
supporting multiple call results. When users of the call's result can
use either the entire tuple (which is a meaningless value), or the
individual tuple extracts, then there's no way to handle calls
uniformly.

The change that broke this was to remove the special handling of
TupleExtract instructions. That special handling was identical to the
way that any normal pointer projection is handled. So, as a
simplification, the new code just expects that case to be handled
naturally as a pointer projection. This case was already guarded by a
check to determine whether the TupleExtract was actually the result of
an array.uninitialized call, in which case the normal handling does
not apply. However, because of the weirdness mentioned above, the
handling of "array.ininitialized" may silently bail out. When that
happens, the TupleExtract gets neither the special handling, nor the
normal handling.

Note that the old special handling of TupleExtract was bizarre and
relied on corresponding weirdness in the code that handles
"array.uninitialized". The new code simply creates a separate graph
node for each result of the call, and creates the edges that exactly
correspond to load and stores on those results. So, rather than
reinstating the previous code, which I can't quite reason about, this
fix creates a single check to determine whether a TupleExtract is
treated as an "array.uninitialized" result or not, and use that check
in both places.
@atrick
Copy link
Contributor Author

atrick commented Dec 21, 2019

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 18acef017e82db731017f9dab6572c7c6f8763ea

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 18acef017e82db731017f9dab6572c7c6f8763ea

@slavapestov slavapestov merged commit 746b58e into swiftlang:master Dec 21, 2019
@atrick atrick deleted the fix-escape branch December 23, 2019 03:03
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