@@ -413,10 +413,42 @@ private func _getCocoaStringPointer(
413
413
return . none
414
414
}
415
415
416
+ #if arch(arm64)
417
+ //11000000..payload..111
418
+ private var constantTagMask : UInt {
419
+ 0b1111_1111_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0111
420
+ }
421
+ private var expectedConstantTagValue : UInt {
422
+ 0b1100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0111
423
+ }
424
+ #endif
425
+
426
+ @inline ( __always)
427
+ private func formConstantTaggedCocoaString(
428
+ untaggedCocoa: _CocoaString
429
+ ) -> AnyObject ? {
430
+ #if !arch(arm64)
431
+ return nil
432
+ #else
433
+
434
+ let constantPtr : UnsafeRawPointer = Builtin . reinterpretCast ( untaggedCocoa)
435
+
436
+ // Check if what we're pointing to is actually a valid tagged constant
437
+ guard _swift_stdlib_dyld_is_objc_constant_string ( constantPtr) == 1 else {
438
+ return nil
439
+ }
440
+
441
+ let retaggedPointer = UInt ( bitPattern: constantPtr) | expectedConstantTagValue
442
+
443
+ return unsafeBitCast ( retaggedPointer, to: AnyObject . self)
444
+ #endif
445
+ }
416
446
417
447
@inline ( __always)
418
448
private func getConstantTaggedCocoaContents( _ cocoaString: _CocoaString ) ->
419
- ( utf16Length: Int , asciiContentsPointer: UnsafePointer < UInt8 > ? ) ? {
449
+ ( utf16Length: Int ,
450
+ asciiContentsPointer: UnsafePointer < UInt8 > ,
451
+ untaggedCocoa: _CocoaString ) ? {
420
452
#if !arch(arm64)
421
453
return nil
422
454
#else
@@ -427,34 +459,33 @@ private func getConstantTaggedCocoaContents(_ cocoaString: _CocoaString) ->
427
459
428
460
let taggedValue = unsafeBitCast ( cocoaString, to: UInt . self)
429
461
430
- //11000000..payload..111
431
- let tagMask : UInt =
432
- 0b1111_1111_1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0111
433
- let expectedValue : UInt =
434
- 0b1100_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0111
435
462
436
- guard taggedValue & tagMask == expectedValue else {
437
- return nil
438
- }
439
463
440
- guard _swift_stdlib_dyld_is_objc_constant_string (
441
- cocoaString as! UnsafeRawPointer
442
- ) == 1 else {
464
+ guard taggedValue & constantTagMask == expectedConstantTagValue else {
443
465
return nil
444
466
}
445
467
446
- let payloadMask = ~ tagMask
468
+ let payloadMask = ~ constantTagMask
447
469
let payload = taggedValue & payloadMask
448
470
let ivarPointer = UnsafePointer < _swift_shims_builtin_CFString > (
449
471
bitPattern: payload
450
472
) !
473
+
474
+ guard _swift_stdlib_dyld_is_objc_constant_string (
475
+ unsafeBitCast ( ivarPointer, to: UnsafeRawPointer . self)
476
+ ) == 1 else {
477
+ return nil
478
+ }
479
+
451
480
let length = ivarPointer. pointee. length
452
481
let isUTF16Mask : UInt = 0x0000_0000_0000_0004 //CFStringFlags bit 4: isUnicode
453
482
let isASCII = ivarPointer. pointee. flags & isUTF16Mask == 0
483
+ precondition ( isASCII) // we don't currently support non-ASCII here
454
484
let contentsPtr = ivarPointer. pointee. str
455
485
return (
456
486
utf16Length: Int ( length) ,
457
- asciiContentsPointer: isASCII ? contentsPtr : nil
487
+ asciiContentsPointer: contentsPtr,
488
+ untaggedCocoa: Builtin . reinterpretCast ( ivarPointer)
458
489
)
459
490
#endif
460
491
}
@@ -476,9 +507,9 @@ internal func _bridgeCocoaString(_ cocoaString: _CocoaString) -> _StringGuts {
476
507
case . constantTagged:
477
508
let taggedContents = getConstantTaggedCocoaContents ( cocoaString) !
478
509
return _StringGuts (
479
- cocoa: cocoaString ,
510
+ cocoa: taggedContents . untaggedCocoa ,
480
511
providesFastUTF8: false , //TODO: if contentsPtr is UTF8 compatible, use it
481
- isASCII: taggedContents . asciiContentsPointer != nil ,
512
+ isASCII: true ,
482
513
length: taggedContents. utf16Length
483
514
)
484
515
#endif
@@ -590,7 +621,8 @@ extension String {
590
621
591
622
_internalInvariant ( _guts. _object. hasObjCBridgeableObject,
592
623
" Unknown non-bridgeable object case " )
593
- return _guts. _object. objCBridgeableObject
624
+ let result = _guts. _object. objCBridgeableObject
625
+ return formConstantTaggedCocoaString ( untaggedCocoa: result) ?? result
594
626
}
595
627
}
596
628
0 commit comments