Skip to content

Avoid losing the high bits of bridged constant tagged pointers #31110

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
Apr 23, 2020

Conversation

Catfish-Man
Copy link
Contributor

@Catfish-Man Catfish-Man commented Apr 17, 2020

Fixes rdar://problem/61273899

@Catfish-Man Catfish-Man requested review from milseman and removed request for milseman April 17, 2020 23:01
@Catfish-Man
Copy link
Contributor Author

This is not the right approach actually

@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 253472260f320066ea993fc7d493857d6510d1b1

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 253472260f320066ea993fc7d493857d6510d1b1

@Catfish-Man Catfish-Man changed the title Assume constant tagged strings are ASCII and act accordingly Avoid losing the high bits of bridged constant tagged pointers Apr 18, 2020
@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 0d719fcea4adfee7c4ca9885d69f18d2e84e6fa8

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 0d719fcea4adfee7c4ca9885d69f18d2e84e6fa8

@Catfish-Man Catfish-Man requested a review from milseman April 20, 2020 22:30
@Catfish-Man Catfish-Man self-assigned this Apr 20, 2020
@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - 90328222cc4bb1f493b80d1478f9c83a7b6b718a

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - 90328222cc4bb1f493b80d1478f9c83a7b6b718a

@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - c6100f8279ec3eeca36a5d3625351f394aa509c3

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - c6100f8279ec3eeca36a5d3625351f394aa509c3

providesFastUTF8: false, //TODO: if contentsPtr is UTF8 compatible, use it
isASCII: taggedContents.asciiContentsPointer != nil,
isASCII: true,
length: taggedContents.utf16Length
Copy link
Member

Choose a reason for hiding this comment

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

Is this what we want, or do we want to bring it in as an immortal string? Have you tested that ref counting and message sending Swift-side works on that untagged object?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we want to, but I'm trying to be conservative about the changes initially both to unblock people and to reduce risk. This limits the changes to just the bridging paths.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(and yes, that's been tested, it's an ordinary NSCFConstantString)

Copy link
Member

Choose a reason for hiding this comment

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

They'd also have be null-terminated.

@@ -590,7 +619,8 @@ extension String {

_internalInvariant(_guts._object.hasObjCBridgeableObject,
"Unknown non-bridgeable object case")
return _guts._object.objCBridgeableObject
let result = _guts._object.objCBridgeableObject
return formConstantTaggedCocoaString(untaggedCocoa: result) ?? result
Copy link
Member

Choose a reason for hiding this comment

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

Here we'd be checking a spare perf flag on the second word instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah. I think that's ultimately where we want to end up.

@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@Catfish-Man
Copy link
Contributor Author

…git failed to push, so that previous test run was useless

@Catfish-Man
Copy link
Contributor Author

@swift-ci please test

@swift-ci
Copy link
Contributor

Build failed
Swift Test Linux Platform
Git Sha - bf4fd69cf69b0efb5785f0784f99165868e0fa75

@swift-ci
Copy link
Contributor

Build failed
Swift Test OS X Platform
Git Sha - bf4fd69cf69b0efb5785f0784f99165868e0fa75

Copy link
Member

@milseman milseman left a comment

Choose a reason for hiding this comment

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

Definitely get someone to look at that potential lifetime management issue

let retaggedPointer = UInt(bitPattern: constantPtr) | expectedConstantTagValue

return unsafeBitCast(retaggedPointer, to: AnyObject.self)
#endif
Copy link
Member

Choose a reason for hiding this comment

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

This still seems a little sketchy without at least a defer { _fixLifetime(untaggedCocoa) }. Make sure to check with @atrick or @eeckstein.

In practice, would ref counting always be disabled here? How are the retain/release counts balanced?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

These objects are in immutable memory, so can't be refcounted

Copy link
Contributor

Choose a reason for hiding this comment

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

👍

let payload = taggedValue & payloadMask
let ivarPointer = UnsafePointer<_swift_shims_builtin_CFString>(
bitPattern: payload
)!

guard _swift_stdlib_dyld_is_objc_constant_string(
unsafeBitCast(ivarPointer, to: UnsafeRawPointer.self)
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if going through ObjectIdentifier is more sanctioned. @lorentey , thoughts?

let length = ivarPointer.pointee.length
let isUTF16Mask:UInt = 0x0000_0000_0000_0004 //CFStringFlags bit 4: isUnicode
let isASCII = ivarPointer.pointee.flags & isUTF16Mask == 0
precondition(isASCII) // we don't currently support non-ASCII here
Copy link
Member

Choose a reason for hiding this comment

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

What should be the behavior if this check fails? Should we trap in the stdlib?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think so. It's pretty much "assert the world is as we expected"

@Catfish-Man Catfish-Man merged commit a4d3261 into swiftlang:master Apr 23, 2020
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.

4 participants