@@ -107,6 +107,8 @@ internal func _cocoaCStringUsingEncodingTrampoline(
107107}
108108
109109
110+
111+
110112@_effects ( releasenone)
111113internal func _cocoaGetCStringTrampoline(
112114 _ string: _CocoaString ,
@@ -131,6 +133,40 @@ private var kCFStringEncodingUTF8 : _swift_shims_CFStringEncoding {
131133 @inline ( __always) get { return 0x8000100 }
132134}
133135
136+ @_effects ( readonly)
137+ private func _unsafeAddressOfCocoaStringClass( _ str: _CocoaString ) -> UInt {
138+ return _swift_stdlib_unsafeAddressOfClass ( str)
139+ }
140+
141+ internal enum _KnownCocoaString {
142+ case storage
143+ case shared
144+ case cocoa
145+ #if !(arch(i386) || arch(arm))
146+ case tagged
147+ #endif
148+
149+ @inline ( __always)
150+ init ( _ str: _CocoaString ) {
151+
152+ #if !(arch(i386) || arch(arm))
153+ if _isObjCTaggedPointer ( str) {
154+ self = . tagged
155+ return
156+ }
157+ #endif
158+
159+ switch _unsafeAddressOfCocoaStringClass ( str) {
160+ case unsafeBitCast ( _StringStorage. self, to: UInt . self) :
161+ self = . storage
162+ case unsafeBitCast ( _SharedStringStorage. self, to: UInt . self) :
163+ self = . shared
164+ default :
165+ self = . cocoa
166+ }
167+ }
168+ }
169+
134170#if !(arch(i386) || arch(arm))
135171// Resiliently write a tagged cocoa string's contents into a buffer
136172@_effects ( releasenone) // @opaque
@@ -185,47 +221,49 @@ private func _getCocoaStringPointer(
185221@usableFromInline
186222@_effects ( releasenone) // @opaque
187223internal func _bridgeCocoaString( _ cocoaString: _CocoaString ) -> _StringGuts {
188- if let abstract = cocoaString as? _AbstractStringStorage {
189- return abstract. asString. _guts
190- }
224+ switch _KnownCocoaString ( cocoaString) {
225+ case . storage:
226+ return _unsafeUncheckedDowncast ( cocoaString, to: _StringStorage. self) . asString. _guts
227+ case . shared:
228+ return _unsafeUncheckedDowncast ( cocoaString, to: _SharedStringStorage. self) . asString. _guts
191229#if !(arch(i386) || arch(arm))
192- if _isObjCTaggedPointer ( cocoaString) {
193- return _StringGuts ( _SmallString ( taggedCocoa: cocoaString) )
194- }
230+ case . tagged:
231+ return _StringGuts ( _SmallString ( taggedCocoa: cocoaString) )
195232#endif
196-
197- // "copy" it into a value to be sure nobody will modify behind
198- // our backs. In practice, when value is already immutable, this
199- // just does a retain.
200- //
201- // TODO: Only in certain circumstances should we emit this call:
202- // 1) If it's immutable, just retain it.
203- // 2) If it's mutable with no associated information, then a copy must
204- // happen; might as well eagerly bridge it in.
205- // 3) If it's mutable with associated information, must make the call
206- //
207- let immutableCopy
208- = _stdlib_binary_CFStringCreateCopy ( cocoaString) as AnyObject
209-
210- #if !(arch(i386) || arch(arm))
211- if _isObjCTaggedPointer ( immutableCopy) {
212- return _StringGuts ( _SmallString ( taggedCocoa: immutableCopy) )
213- }
214- #endif
215-
216- let ( fastUTF8, isASCII) : ( Bool , Bool )
217- switch _getCocoaStringPointer ( immutableCopy) {
233+ case . cocoa :
234+ // "copy" it into a value to be sure nobody will modify behind
235+ // our backs. In practice, when value is already immutable, this
236+ // just does a retain.
237+ //
238+ // TODO: Only in certain circumstances should we emit this call:
239+ // 1) If it's immutable, just retain it.
240+ // 2) If it's mutable with no associated information, then a copy must
241+ // happen; might as well eagerly bridge it in.
242+ // 3) If it's mutable with associated information, must make the call
243+ //
244+ let immutableCopy
245+ = _stdlib_binary_CFStringCreateCopy ( cocoaString) as AnyObject
246+
247+ #if !(arch(i386) || arch(arm))
248+ if _isObjCTaggedPointer ( immutableCopy) {
249+ return _StringGuts ( _SmallString ( taggedCocoa: immutableCopy) )
250+ }
251+ #endif
252+
253+ let ( fastUTF8, isASCII) : ( Bool , Bool )
254+ switch _getCocoaStringPointer ( immutableCopy) {
218255 case . ascii( _) : ( fastUTF8, isASCII) = ( true , true )
219256 case . utf8( _) : ( fastUTF8, isASCII) = ( true , false )
220257 default : ( fastUTF8, isASCII) = ( false , false )
258+ }
259+ let length = _stdlib_binary_CFStringGetLength ( immutableCopy)
260+
261+ return _StringGuts (
262+ cocoa: immutableCopy,
263+ providesFastUTF8: fastUTF8,
264+ isASCII: isASCII,
265+ length: length)
221266 }
222- let length = _stdlib_binary_CFStringGetLength ( immutableCopy)
223-
224- return _StringGuts (
225- cocoa: immutableCopy,
226- providesFastUTF8: fastUTF8,
227- isASCII: isASCII,
228- length: length)
229267}
230268
231269extension String {
0 commit comments