|
28 | 28 | │ Immortal, Small ║ 1 │ASCII│ 1 │ 0 │ |
29 | 29 | ├─────────────────────╫─────┼─────┼─────┼─────┤ |
30 | 30 | │ Immortal, Large ║ 1 │ 0 │ 0 │ 0 │ |
| 31 | + ├─────────────────────╫─────┼─────┼─────┼─────┤ |
| 32 | + │ Immortal, Bridged ║ 1 │ 1 │ 0 │ 0 │ |
31 | 33 | ╞═════════════════════╬═════╪═════╪═════╪═════╡ |
32 | 34 | │ Native ║ 0 │ 0 │ 0 │ 0 │ |
33 | 35 | ├─────────────────────╫─────┼─────┼─────┼─────┤ |
@@ -436,6 +438,10 @@ extension _StringObject.Nibbles { |
436 | 438 | internal static func largeCocoa(providesFastUTF8: Bool) -> UInt64 { |
437 | 439 | return providesFastUTF8 ? 0x4000_0000_0000_0000 : 0x5000_0000_0000_0000 |
438 | 440 | } |
| 441 | + |
| 442 | + internal static func largeFastImmortalCocoa() -> UInt64 { |
| 443 | + 0xC000_0000_0000_0000 |
| 444 | + } |
439 | 445 | } |
440 | 446 |
|
441 | 447 | extension _StringObject { |
@@ -549,6 +555,15 @@ extension _StringObject { |
549 | 555 | return (discriminatedObjectRawBits & 0x4000_0000_0000_0000) != 0 |
550 | 556 | #endif |
551 | 557 | } |
| 558 | + |
| 559 | + @inline(__always) |
| 560 | + internal var largeFastIsConstantCocoa: Bool { |
| 561 | +#if os(Android) && arch(arm64) |
| 562 | + false |
| 563 | +#else |
| 564 | + (discriminatedObjectRawBits & 0xF000_0000_0000_0000) == 0xC000_0000_0000_0000 |
| 565 | +#endif |
| 566 | + } |
552 | 567 |
|
553 | 568 | // Whether this string is in one of our fastest representations: |
554 | 569 | // small or tail-allocated (i.e. mortal/immortal native) |
@@ -952,6 +967,11 @@ extension _StringObject { |
952 | 967 | internal func getSharedUTF8Start() -> UnsafePointer<UInt8> { |
953 | 968 | _internalInvariant(largeFastIsShared) |
954 | 969 | #if _runtime(_ObjC) |
| 970 | + if largeFastIsConstantCocoa { |
| 971 | + return withCocoaObject { |
| 972 | + _getNSCFConstantStringContentsPointer($0) |
| 973 | + } |
| 974 | + } |
955 | 975 | if largeIsCocoa { |
956 | 976 | return withCocoaObject { |
957 | 977 | stableCocoaUTF8Pointer($0)._unsafelyUnwrappedUnchecked |
@@ -1075,7 +1095,9 @@ extension _StringObject { |
1075 | 1095 | #if $Embedded |
1076 | 1096 | fatalError("unreachable in embedded Swift") |
1077 | 1097 | #elseif _pointerBitWidth(_64) |
1078 | | - _internalInvariant(largeIsCocoa && !isImmortal) |
| 1098 | + _internalInvariant( |
| 1099 | + (largeIsCocoa && !isImmortal) || largeFastIsConstantCocoa |
| 1100 | + ) |
1079 | 1101 | let unmanaged = Unmanaged<AnyObject>.fromOpaque(largeAddress) |
1080 | 1102 | return unmanaged._withUnsafeGuaranteedRef { body($0) } |
1081 | 1103 | #elseif _pointerBitWidth(_32) |
@@ -1168,7 +1190,7 @@ extension _StringObject { |
1168 | 1190 | internal var hasObjCBridgeableObject: Bool { |
1169 | 1191 | @_effects(releasenone) get { |
1170 | 1192 | // Currently, all mortal objects can zero-cost bridge |
1171 | | - return !self.isImmortal |
| 1193 | + return !self.isImmortal || self.largeFastIsConstantCocoa |
1172 | 1194 | } |
1173 | 1195 | } |
1174 | 1196 |
|
@@ -1291,6 +1313,33 @@ extension _StringObject { |
1291 | 1313 | countAndFlags: countAndFlags) |
1292 | 1314 | #else |
1293 | 1315 | #error("Unknown platform") |
| 1316 | +#endif |
| 1317 | + } |
| 1318 | + |
| 1319 | + @_unavailableInEmbedded |
| 1320 | + internal init( |
| 1321 | + constantCocoa cocoa: AnyObject, |
| 1322 | + providesFastUTF8: Bool, |
| 1323 | + isASCII: Bool, |
| 1324 | + length: Int |
| 1325 | + ) { |
| 1326 | + let countAndFlags = CountAndFlags(sharedCount: length, isASCII: isASCII) |
| 1327 | + let discriminator = Nibbles.largeFastImmortalCocoa() |
| 1328 | +#if $Embedded |
| 1329 | + fatalError("unreachable in embedded Swift") |
| 1330 | +#elseif _pointerBitWidth(_64) |
| 1331 | + self.init( |
| 1332 | + object: cocoa, discriminator: discriminator, countAndFlags: countAndFlags) |
| 1333 | + _internalInvariant(self.largeAddressBits == Builtin.reinterpretCast(cocoa)) |
| 1334 | + _internalInvariant(self.providesFastUTF8 == providesFastUTF8) |
| 1335 | + _internalInvariant(self.largeCount == length) |
| 1336 | +#elseif _pointerBitWidth(_32) |
| 1337 | + self.init( |
| 1338 | + variant: .bridged(cocoa), |
| 1339 | + discriminator: discriminator, |
| 1340 | + countAndFlags: countAndFlags) |
| 1341 | +#else |
| 1342 | +#error("Unknown platform") |
1294 | 1343 | #endif |
1295 | 1344 | } |
1296 | 1345 | } |
@@ -1357,7 +1406,7 @@ extension _StringObject { |
1357 | 1406 | _internalInvariant(nativeStorage.count == self.count) |
1358 | 1407 | } |
1359 | 1408 | } |
1360 | | - if largeIsCocoa { |
| 1409 | + if largeFastIsConstantCocoa || largeIsCocoa { |
1361 | 1410 | _internalInvariant(hasObjCBridgeableObject) |
1362 | 1411 | _internalInvariant(!isSmall) |
1363 | 1412 | _internalInvariant(!_countAndFlags.isNativelyStored) |
|
0 commit comments