diff --git a/stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h b/stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h index ccf4146483ab9..6dabf75e390ab 100644 --- a/stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h +++ b/stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h @@ -48,6 +48,11 @@ typedef struct __swift_shims_builtin_CFString { unsigned long length; } _swift_shims_builtin_CFString; +SWIFT_RUNTIME_STDLIB_API +void * _Nullable +_swift_stdlib_createTaggedPointerString(const _swift_shims_UInt8 * _Nonnull bytes, + _swift_shims_CFIndex length); + SWIFT_RUNTIME_STDLIB_API __swift_uint8_t _swift_stdlib_isNSString(id _Nonnull obj); diff --git a/stdlib/public/core/StringBridge.swift b/stdlib/public/core/StringBridge.swift index 528e584302079..6d7d0bda4b270 100644 --- a/stdlib/public/core/StringBridge.swift +++ b/stdlib/public/core/StringBridge.swift @@ -58,10 +58,6 @@ internal typealias _CocoaString = AnyObject options: UInt, range: _SwiftNSRange, locale: AnyObject?) -> Int - - @objc(newTaggedNSStringWithASCIIBytes_:length_:) - func createTaggedString(bytes: UnsafePointer, - count: Int) -> AnyObject? } /* @@ -316,24 +312,26 @@ internal enum _KnownCocoaString { #if !(arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32)) case tagged #endif -#if arch(arm64) - case constantTagged -#endif +//Constant tagged strings are disabled for now +//#if arch(arm64) +// case constantTagged +//#endif @inline(__always) init(_ str: _CocoaString) { #if !(arch(i386) || arch(arm) || arch(arm64_32)) if _isObjCTaggedPointer(str) { -#if arch(arm64) - if let _ = getConstantTaggedCocoaContents(str) { - self = .constantTagged - } else { - self = .tagged - } -#else +//Constant tagged strings are disabled for now +//#if arch(arm64) +// if let _ = getConstantTaggedCocoaContents(str) { +// self = .constantTagged +// } else { +// self = .tagged +// } +//#else self = .tagged -#endif +//#endif return } #endif @@ -504,21 +502,22 @@ private var expectedConstantTagValue:UInt { private func formConstantTaggedCocoaString( untaggedCocoa: _CocoaString ) -> AnyObject? { -#if !arch(arm64) +//constant tagged strings are currently disabled +//#if !arch(arm64) return nil -#else - - let constantPtr:UnsafeRawPointer = Builtin.reinterpretCast(untaggedCocoa) - - // Check if what we're pointing to is actually a valid tagged constant - guard _swift_stdlib_dyld_is_objc_constant_string(constantPtr) == 1 else { - return nil - } - - let retaggedPointer = UInt(bitPattern: constantPtr) | expectedConstantTagValue - - return unsafeBitCast(retaggedPointer, to: AnyObject.self) -#endif +//#else +// +// let constantPtr:UnsafeRawPointer = Builtin.reinterpretCast(untaggedCocoa) +// +// // Check if what we're pointing to is actually a valid tagged constant +// guard _swift_stdlib_dyld_is_objc_constant_string(constantPtr) == 1 else { +// return nil +// } +// +// let retaggedPointer = UInt(bitPattern: constantPtr) | expectedConstantTagValue +// +// return unsafeBitCast(retaggedPointer, to: AnyObject.self) +//#endif } @inline(__always) @@ -526,45 +525,46 @@ private func getConstantTaggedCocoaContents(_ cocoaString: _CocoaString) -> (utf16Length: Int, asciiContentsPointer: UnsafePointer, untaggedCocoa: _CocoaString)? { -#if !arch(arm64) +//constant tagged strings are currently disabled +//#if !arch(arm64) return nil -#else - - guard _isObjCTaggedPointer(cocoaString) else { - return nil - } - - let taggedValue = unsafeBitCast(cocoaString, to: UInt.self) - - - - guard taggedValue & constantTagMask == expectedConstantTagValue else { - return nil - } - - let payloadMask = ~constantTagMask - let payload = taggedValue & payloadMask - let ivarPointer = UnsafePointer<_swift_shims_builtin_CFString>( - bitPattern: payload - )! +//#else - guard _swift_stdlib_dyld_is_objc_constant_string( - UnsafeRawPointer(ivarPointer) - ) == 1 else { - return nil - } - - 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 - let contentsPtr = ivarPointer.pointee.str - return ( - utf16Length: Int(length), - asciiContentsPointer: contentsPtr, - untaggedCocoa: Builtin.reinterpretCast(ivarPointer) - ) -#endif +// guard _isObjCTaggedPointer(cocoaString) else { +// return nil +// } +// +// let taggedValue = unsafeBitCast(cocoaString, to: UInt.self) +// +// +// +// guard taggedValue & constantTagMask == expectedConstantTagValue else { +// return nil +// } +// +// let payloadMask = ~constantTagMask +// let payload = taggedValue & payloadMask +// let ivarPointer = UnsafePointer<_swift_shims_builtin_CFString>( +// bitPattern: payload +// )! +// +// guard _swift_stdlib_dyld_is_objc_constant_string( +// UnsafeRawPointer(ivarPointer) +// ) == 1 else { +// return nil +// } +// +// 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 +// let contentsPtr = ivarPointer.pointee.str +// return ( +// utf16Length: Int(length), +// asciiContentsPointer: contentsPtr, +// untaggedCocoa: Builtin.reinterpretCast(ivarPointer) +// ) +//#endif } @usableFromInline @@ -579,21 +579,18 @@ internal func _bridgeCocoaString(_ cocoaString: _CocoaString) -> _StringGuts { cocoaString, to: __SharedStringStorage.self).asString._guts #if !(arch(i386) || arch(arm) || arch(arm64_32)) case .tagged: - // Foundation should be taking care of tagged pointer strings before they - // reach here, so the only ones reaching this point should be back deployed, - // which will never have tagged pointer strings that aren't small, hence - // the force unwrap here. return _StringGuts(_SmallString(taggedCocoa: cocoaString)!) -#if arch(arm64) - case .constantTagged: - let taggedContents = getConstantTaggedCocoaContents(cocoaString)! - return _StringGuts( - cocoa: taggedContents.untaggedCocoa, - providesFastUTF8: false, //TODO: if contentsPtr is UTF8 compatible, use it - isASCII: true, - length: taggedContents.utf16Length - ) -#endif +//Constant tagged strings are disabled for now +//#if arch(arm64) +// case .constantTagged: +// let taggedContents = getConstantTaggedCocoaContents(cocoaString)! +// return _StringGuts( +// cocoa: taggedContents.untaggedCocoa, +// providesFastUTF8: false, //TODO: if contentsPtr is UTF8 compatible, use it +// isASCII: true, +// length: taggedContents.utf16Length +// ) +//#endif #endif case .cocoa: // "Copy" it into a value to be sure nobody will modify behind @@ -642,27 +639,14 @@ extension String { } @_effects(releasenone) -private func _createNSString( - _ receiver: _StringSelectorHolder, +private func _createTaggedNSString( _ ptr: UnsafePointer, - _ count: Int, - _ encoding: UInt32 + _ count: Int ) -> AnyObject? { - return receiver.createTaggedString(bytes: ptr, count: count) -} - -@_effects(releasenone) -private func _createCFString( - _ ptr: UnsafePointer, - _ count: Int, - _ encoding: UInt32 -) -> AnyObject? { - return _createNSString( - unsafeBitCast(__StringStorage.self as AnyClass, to: _StringSelectorHolder.self), - ptr, - count, - encoding - ) + if let str = _swift_stdlib_createTaggedPointerString(ptr, count) { + return Unmanaged.fromOpaque(str).takeRetainedValue() + } + return nil } extension String { @@ -675,10 +659,9 @@ extension String { // Smol ASCII a) may bridge to tagged pointers, b) can't contain a BOM if _guts.isSmallASCII { let maybeTagged = _guts.asSmall.withUTF8 { bufPtr in - return _createCFString( + return _createTaggedNSString( bufPtr.baseAddress._unsafelyUnwrappedUnchecked, - bufPtr.count, - kCFStringEncodingUTF8 + bufPtr.count ) } if let tagged = maybeTagged { return tagged } diff --git a/stdlib/public/stubs/FoundationHelpers.mm b/stdlib/public/stubs/FoundationHelpers.mm index 66382c677e004..7e44169d2c933 100644 --- a/stdlib/public/stubs/FoundationHelpers.mm +++ b/stdlib/public/stubs/FoundationHelpers.mm @@ -33,38 +33,44 @@ static CFHashCode(*_CFStringHashCString)(const uint8_t *bytes, CFIndex len); static CFHashCode(*_CFStringHashNSString)(id str); -static CFTypeID(*_CFGetTypeID)(CFTypeRef obj); -static CFTypeID _CFStringTypeID = 0; -static swift_once_t initializeBridgingFuncsOnce; - -extern "C" bool _dyld_is_objc_constant(DyldObjCConstantKind kind, - const void *addr) SWIFT_RUNTIME_WEAK_IMPORT; +static id(*_CFStringCreateTaggedPointerString)(const uint8_t *bytes, CFIndex numBytes); +static __swift_uint8_t(*_NSIsNSString)(id arg); +static once_t initializeBridgingFuncsOnce; static void _initializeBridgingFunctionsImpl(void *ctxt) { - auto getStringTypeID = - (CFTypeID(*)(void)) - dlsym(RTLD_DEFAULT, "CFStringGetTypeID"); - assert(getStringTypeID); - _CFStringTypeID = getStringTypeID(); - - _CFGetTypeID = (CFTypeID(*)(CFTypeRef obj))dlsym(RTLD_DEFAULT, "CFGetTypeID"); - _CFStringHashNSString = (CFHashCode(*)(id))dlsym(RTLD_DEFAULT, - "CFStringHashNSString"); - _CFStringHashCString = (CFHashCode(*)(const uint8_t *, CFIndex))dlsym( - RTLD_DEFAULT, - "CFStringHashCString"); + void *cf = dlopen("/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", RTLD_LAZY | RTLD_NOLOAD | RTLD_LOCAL | RTLD_FIRST); + _NSIsNSString = (__swift_uint8_t(*)(id))dlsym(cf ? cf : RTLD_DEFAULT, "_NSIsNSString"); + _CFStringHashNSString = (CFHashCode(*)(id))dlsym(cf ? cf : RTLD_DEFAULT, "CFStringHashNSString"); + _CFStringHashCString = (CFHashCode(*)(const uint8_t *, CFIndex))dlsym(cf ? cf : RTLD_DEFAULT, "CFStringHashCString"); + _CFStringCreateTaggedPointerString = (id(*)(const uint8_t *, CFIndex))dlsym(cf ? cf : RTLD_DEFAULT, "_CFStringCreateTaggedPointerString"); + if (cf) { + dlclose(cf); + } } static inline void initializeBridgingFunctions() { - swift_once(&initializeBridgingFuncsOnce, - _initializeBridgingFunctionsImpl, - nullptr); + once(initializeBridgingFuncsOnce, + _initializeBridgingFunctionsImpl, + nullptr); +} + +void * +_swift_stdlib_createTaggedPointerString(const _swift_shims_UInt8 * _Nonnull bytes, + _swift_shims_CFIndex length) { + initializeBridgingFunctions(); + // if (_CFStringCreateTaggedPointerString != NULL) { + return (void *)_CFStringCreateTaggedPointerString(bytes, length); + // } + // return nil; } __swift_uint8_t _swift_stdlib_isNSString(id obj) { initializeBridgingFunctions(); - return _CFGetTypeID((CFTypeRef)obj) == _CFStringTypeID ? 1 : 0; + if (_NSIsNSString != NULL) { + return _NSIsNSString(obj); + } + return [obj isKindOfClass: objc_lookUpClass("NSString")]; } _swift_shims_CFHashCode @@ -106,10 +112,15 @@ typedef __swift_uint8_t (*getCStringImplPtr)(id, } +//extern "C" bool _dyld_is_objc_constant(DyldObjCConstantKind kind, +// const void *addr) SWIFT_RUNTIME_WEAK_IMPORT; + __swift_uint8_t _swift_stdlib_dyld_is_objc_constant_string(const void *addr) { - return (SWIFT_RUNTIME_WEAK_CHECK(_dyld_is_objc_constant) - && SWIFT_RUNTIME_WEAK_USE(_dyld_is_objc_constant(dyld_objc_string_kind, addr))) ? 1 : 0; + return false; + //This currently always return false +// return (SWIFT_RUNTIME_WEAK_CHECK(_dyld_is_objc_constant) +// && SWIFT_RUNTIME_WEAK_USE(_dyld_is_objc_constant(dyld_objc_string_kind, addr))) ? 1 : 0; } #endif