Skip to content

WalkUtils: handle unsafe_ref_cast which casts between AnyObject and a class #75434

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
Jul 24, 2024

Conversation

eeckstein
Copy link
Contributor

We need to ignore such casts because otherwise the constructed walking path wouldn't contain the right existential field kind. Fixes a miscompile caused by redundant load elimination.

rdar://132364917

… a class

We need to ignore such casts because otherwise the constructed walking path wouldn't contain the right `existential` field kind.
Fixes a miscompile caused by redundant load elimination.

rdar://132364917
@eeckstein eeckstein requested a review from jckarter as a code owner July 24, 2024 09:35
@eeckstein
Copy link
Contributor Author

@swift-ci test

@eeckstein
Copy link
Contributor Author

@swift-ci benchmark

@eeckstein eeckstein requested review from atrick and removed request for jckarter July 24, 2024 09:36
@eeckstein eeckstein merged commit 384d7f7 into swiftlang:main Jul 24, 2024
6 checks passed
@eeckstein eeckstein deleted the fix-walkutils branch July 24, 2024 15:51
Copy link
Contributor

@atrick atrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved for 5.10 and 6.0 CCC, because the change seems conservative.

But I don't understand what problem is being fixed. Surely this test already reported "may alias" before this change, because the use-def walk from both ref_element_addr instructions would have found the same root.
Was the problem that the def-use walk did not match the use-def walk because the path did not include the correct type? Did it optimistically assume that AnyObject cannot have a field of type s? I just wonder how that failure to match the type happened and how it ended up being optimistic instead of pessimistic.

 CHECK-LABEL: Address escape information for test_anyobject_cast:
// CHECK:       pair 0 - 1
// CHECK-NEXT:    %3 = ref_element_addr %2 : $X, #X.s
// CHECK-NEXT:    %5 = ref_element_addr %2 : $X, #X.s
// CHECK-NEXT:  may alias
// CHECK:       End function test_anyobject_cast
sil @test_anyobject_cast : $@convention(thin) () -> () {
bb0:
  %0 = alloc_ref $X
  %1 = init_existential_ref %0 : $X : $X, $AnyObject
  %2 = unchecked_ref_cast %1 : $AnyObject to $X
  %3 = ref_element_addr %2 : $X, #X.s
  fix_lifetime %3 : $*Str
  %5 = ref_element_addr %2 : $X, #X.s
  fix_lifetime %5 : $*Str
  %r = tuple ()
  return %r : $()
}

@eeckstein
Copy link
Contributor Author

This test did not report "may alias" before this change. The reason was a mismatch of init- and open existential instructions (unchecked_ref_cast was not considered as potentially "open" the AnyObject existential).
The EscapeInfo walkers push an existential field onto the walking path when walking up an open_existential_ref instruction. And try to pop it when seeing an init_existential_ref. But if there is no such field type in the path, it's considered a path mismatch which aborts the walk and the result is a no-escape.

@atrick
Copy link
Contributor

atrick commented Jul 25, 2024

Thanks. I understand. What is the purpose of creating a path component for init_existential_ref %0 : $X : $X, $AnyObject if it's not because of the type change? Converting to AnyObject from a class can't change the representation right? Then you could continue ignoring unchecked_ref_cast

@eeckstein
Copy link
Contributor Author

Yes, ignoring creating AnyObject existentials would be a possibility. Currently we don't treat AnyObject different than other existentials.

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.

2 participants