@@ -107,6 +107,8 @@ internal func _cocoaCStringUsingEncodingTrampoline(
107
107
}
108
108
109
109
110
+
111
+
110
112
@_effects ( releasenone)
111
113
internal func _cocoaGetCStringTrampoline(
112
114
_ string: _CocoaString ,
@@ -131,6 +133,40 @@ private var kCFStringEncodingUTF8 : _swift_shims_CFStringEncoding {
131
133
@inline ( __always) get { return 0x8000100 }
132
134
}
133
135
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
+
134
170
#if !(arch(i386) || arch(arm))
135
171
// Resiliently write a tagged cocoa string's contents into a buffer
136
172
@_effects ( releasenone) // @opaque
@@ -185,47 +221,49 @@ private func _getCocoaStringPointer(
185
221
@usableFromInline
186
222
@_effects ( releasenone) // @opaque
187
223
internal 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
191
229
#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) )
195
232
#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) {
218
255
case . ascii( _) : ( fastUTF8, isASCII) = ( true , true )
219
256
case . utf8( _) : ( fastUTF8, isASCII) = ( true , false )
220
257
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)
221
266
}
222
- let length = _stdlib_binary_CFStringGetLength ( immutableCopy)
223
-
224
- return _StringGuts (
225
- cocoa: immutableCopy,
226
- providesFastUTF8: fastUTF8,
227
- isASCII: isASCII,
228
- length: length)
229
267
}
230
268
231
269
extension String {
0 commit comments