Skip to content

Commit f8c1df8

Browse files
authored
[6.2] Native implementation of -lengthOfBytesUsingEncoding (#82747)
1 parent 2e0b9d7 commit f8c1df8

File tree

7 files changed

+138
-1
lines changed

7 files changed

+138
-1
lines changed

benchmark/single-source/ObjectiveCBridging.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ public let benchmarks = [
9797
BenchmarkInfo(name: "NSArray.bridged.repeatedBufferAccess",
9898
runFunction: run_BridgedNSArrayRepeatedBufferAccess, tags: t,
9999
setUpFunction: setup_bridgedArrays),
100+
BenchmarkInfo(name: "NSString.bridged.byteCount.ascii.ascii",
101+
runFunction: run_BridgedNSStringLengthASCII_ASCII, tags: ts,
102+
setUpFunction: setup_bridgedStrings),
103+
BenchmarkInfo(name: "NSString.bridged.byteCount.ascii.utf8",
104+
runFunction: run_BridgedNSStringLengthASCII_UTF8, tags: ts,
105+
setUpFunction: setup_bridgedStrings),
106+
BenchmarkInfo(name: "NSString.bridged.byteCount.ascii.utf16",
107+
runFunction: run_BridgedNSStringLengthASCII_UTF16, tags: ts,
108+
setUpFunction: setup_bridgedStrings),
109+
BenchmarkInfo(name: "NSString.bridged.byteCount.ascii.macroman",
110+
runFunction: run_BridgedNSStringLengthASCII_MacRoman, tags: ts,
111+
setUpFunction: setup_bridgedStrings),
112+
BenchmarkInfo(name: "NSString.bridged.byteCount.utf8.utf8",
113+
runFunction: run_BridgedNSStringLengthUTF8_UTF8, tags: ts,
114+
setUpFunction: setup_bridgedStrings),
115+
BenchmarkInfo(name: "NSString.bridged.byteCount.utf8.utf16",
116+
runFunction: run_BridgedNSStringLengthUTF8_UTF16, tags: ts,
117+
setUpFunction: setup_bridgedStrings),
100118
]
101119

102120
#if _runtime(_ObjC)
@@ -797,6 +815,8 @@ var bridgedArray:NSArray! = nil
797815
var bridgedArrayMutableCopy:NSMutableArray! = nil
798816
var nsArray:NSArray! = nil
799817
var nsArrayMutableCopy:NSMutableArray! = nil
818+
var bridgedASCIIString:NSString! = nil
819+
var bridgedUTF8String:NSString! = nil
800820
#endif
801821

802822
public func setup_bridgedArrays() {
@@ -809,6 +829,15 @@ public func setup_bridgedArrays() {
809829
#endif
810830
}
811831

832+
public func setup_bridgedStrings() {
833+
#if _runtime(_ObjC)
834+
let str = Array(repeating: "The quick brown fox jumps over the lazy dog.", count: 100).joined()
835+
bridgedASCIIString = str as NSString
836+
let str2 = Array(repeating: "The quick brown fox jumps over the lazy dög.", count: 100).joined()
837+
bridgedUTF8String = str2 as NSString
838+
#endif
839+
}
840+
812841
@inline(never)
813842
public func run_BridgedNSArrayObjectAtIndex(_ n: Int) {
814843
#if _runtime(_ObjC)
@@ -883,3 +912,40 @@ public func run_RealNSArrayMutableCopyObjectAtIndex(_ n: Int) {
883912
#endif
884913
}
885914

915+
@inline(__always)
916+
fileprivate func run_BridgedNSStringLength(_ asciiBase: Bool, _ enc: UInt, _ n: Int) {
917+
let str = asciiBase ? bridgedASCIIString : bridgedUTF8String
918+
for _ in 0 ..< n * 100 {
919+
blackHole(str!.lengthOfBytes(using: enc))
920+
}
921+
}
922+
923+
@inline(never)
924+
public func run_BridgedNSStringLengthASCII_ASCII(_ n: Int) {
925+
run_BridgedNSStringLength(true, 1 /* NSASCIIStringEncoding */, n)
926+
}
927+
928+
@inline(never)
929+
public func run_BridgedNSStringLengthASCII_UTF8(_ n: Int) {
930+
run_BridgedNSStringLength(true, 4 /* NSUTF8StringEncoding */, n)
931+
}
932+
933+
@inline(never)
934+
public func run_BridgedNSStringLengthASCII_UTF16(_ n: Int) {
935+
run_BridgedNSStringLength(true, 10 /* NSUnicodeStringEncoding */, n)
936+
}
937+
938+
@inline(never)
939+
public func run_BridgedNSStringLengthASCII_MacRoman(_ n: Int) {
940+
run_BridgedNSStringLength(true, 30 /* NSMacOSRomanStringEncoding */, n)
941+
}
942+
943+
@inline(never)
944+
public func run_BridgedNSStringLengthUTF8_UTF8(_ n: Int) {
945+
run_BridgedNSStringLength(false, 4 /* NSUTF8StringEncoding */, n)
946+
}
947+
948+
@inline(never)
949+
public func run_BridgedNSStringLengthUTF8_UTF16(_ n: Int) {
950+
run_BridgedNSStringLength(false, 10 /* NSUnicodeStringEncoding */, n)
951+
}

stdlib/public/SwiftShims/swift/shims/CoreFoundationShims.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ typedef unsigned long _swift_shims_CFHashCode;
3535
typedef signed long _swift_shims_CFIndex;
3636
#endif
3737

38+
typedef unsigned long _swift_shims_NSUInteger;
39+
3840
// Consider creating SwiftMacTypes.h for these
3941
typedef unsigned char _swift_shims_Boolean;
4042
typedef __swift_uint8_t _swift_shims_UInt8;
@@ -80,6 +82,11 @@ const void * _Nullable
8082
_swift_stdlib_CreateIndirectTaggedPointerString(const __swift_uint8_t * _Nonnull bytes,
8183
_swift_shims_CFIndex len);
8284

85+
SWIFT_RUNTIME_STDLIB_API
86+
const _swift_shims_NSUInteger
87+
_swift_stdlib_NSStringLengthOfBytesInEncodingTrampoline(id _Nonnull obj,
88+
unsigned long encoding);
89+
8390
#endif // __OBJC2__
8491

8592
#ifdef __cplusplus

stdlib/public/core/StringBridge.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,13 @@ internal func _cocoaCStringUsingEncodingTrampoline(
287287
return _swift_stdlib_NSStringCStringUsingEncodingTrampoline(string, encoding)
288288
}
289289

290+
@_effects(readonly)
291+
internal func _cocoaLengthOfBytesInEncodingTrampoline(
292+
_ string: _CocoaString, _ encoding: UInt
293+
) -> UInt {
294+
return _swift_stdlib_NSStringLengthOfBytesInEncodingTrampoline(string, encoding)
295+
}
296+
290297
@_effects(releasenone)
291298
internal func _cocoaGetCStringTrampoline(
292299
_ string: _CocoaString,

stdlib/public/core/StringStorageBridge.swift

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import SwiftShims
1616

1717
internal var _cocoaASCIIEncoding:UInt { 1 } /* NSASCIIStringEncoding */
1818
internal var _cocoaUTF8Encoding:UInt { 4 } /* NSUTF8StringEncoding */
19+
internal var _cocoaUTF16Encoding:UInt { 10 } /* NSUTF16StringEncoding and NSUnicodeStringEncoding*/
20+
internal var _cocoaMacRomanEncoding:UInt { 30 } /* NSMacOSRomanStringEncoding */
1921

2022
extension String {
2123
@available(SwiftStdlib 5.6, *)
@@ -69,13 +71,14 @@ extension _AbstractStringStorage {
6971
) -> Int8 {
7072
switch (encoding, isASCII) {
7173
case (_cocoaASCIIEncoding, true),
74+
(_cocoaMacRomanEncoding, true),
7275
(_cocoaUTF8Encoding, _):
7376
guard maxLength >= count + 1 else { return 0 }
7477
unsafe outputPtr.initialize(from: start, count: count)
7578
unsafe outputPtr[count] = 0
7679
return 1
7780
default:
78-
return unsafe _cocoaGetCStringTrampoline(self, outputPtr, maxLength, encoding)
81+
return unsafe _cocoaGetCStringTrampoline(self, outputPtr, maxLength, encoding)
7982
}
8083
}
8184

@@ -84,12 +87,35 @@ extension _AbstractStringStorage {
8487
internal func _cString(encoding: UInt) -> UnsafePointer<UInt8>? {
8588
switch (encoding, isASCII) {
8689
case (_cocoaASCIIEncoding, true),
90+
(_cocoaMacRomanEncoding, true),
8791
(_cocoaUTF8Encoding, _):
8892
return unsafe start
8993
default:
9094
return _cocoaCStringUsingEncodingTrampoline(self, encoding)
9195
}
9296
}
97+
98+
@_effects(readonly)
99+
internal func _lengthOfBytes(using encoding: UInt) -> UInt {
100+
switch encoding {
101+
case _cocoaASCIIEncoding:
102+
if unsafe isASCII || _allASCII(UnsafeBufferPointer(start: start, count: count)) {
103+
return UInt(count)
104+
}
105+
return 0
106+
case _cocoaUTF8Encoding:
107+
return UInt(count)
108+
case _cocoaUTF16Encoding:
109+
return UInt(UTF16Length)
110+
case _cocoaMacRomanEncoding:
111+
if unsafe isASCII || _allASCII(UnsafeBufferPointer(start: start, count: count)) {
112+
return UInt(count)
113+
}
114+
fallthrough
115+
default:
116+
return _cocoaLengthOfBytesInEncodingTrampoline(self, encoding)
117+
}
118+
}
93119

94120
@_effects(readonly)
95121
internal func _nativeIsEqual<T:_AbstractStringStorage>(
@@ -232,6 +258,12 @@ extension __StringStorage {
232258
return _cocoaUTF8Encoding
233259
}
234260
}
261+
262+
@objc(lengthOfBytesUsingEncoding:)
263+
@_effects(readonly)
264+
final internal func lengthOfBytes(using encoding: UInt) -> UInt {
265+
_lengthOfBytes(using: encoding)
266+
}
235267

236268
@objc(isEqualToString:)
237269
@_effects(readonly)
@@ -297,6 +329,12 @@ extension __SharedStringStorage {
297329
return _cocoaUTF8Encoding
298330
}
299331
}
332+
333+
@objc(lengthOfBytesUsingEncoding:)
334+
@_effects(readonly)
335+
final internal func lengthOfBytes(using encoding: UInt) -> UInt {
336+
_lengthOfBytes(using: encoding)
337+
}
300338

301339
@objc(_fastCStringContents:)
302340
@_effects(readonly)

stdlib/public/stubs/FoundationHelpers.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,19 @@ typedef __swift_uint8_t (*getCStringImplPtr)(id,
106106

107107
}
108108

109+
SWIFT_RUNTIME_STDLIB_API
110+
const _swift_shims_NSUInteger
111+
_swift_stdlib_NSStringLengthOfBytesInEncodingTrampoline(id _Nonnull obj,
112+
unsigned long encoding) {
113+
typedef _swift_shims_NSUInteger (*getLengthImplPtr)(id,
114+
SEL,
115+
unsigned long);
116+
SEL sel = @selector(lengthOfBytesUsingEncoding:);
117+
getLengthImplPtr imp = (getLengthImplPtr)class_getMethodImplementation([obj superclass], sel);
118+
119+
return imp(obj, sel, encoding);
120+
}
121+
109122
__swift_uint8_t
110123
_swift_stdlib_dyld_is_objc_constant_string(const void *addr) {
111124
return (SWIFT_RUNTIME_WEAK_CHECK(_dyld_is_objc_constant)

test/abi/macOS/arm64/stdlib.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,3 +1081,6 @@ Added: _$ss6MirrorV12DisplayStyleO16foreignReferenceyA2DmFWC
10811081
// var InlineArray._protectedAddress
10821082
Added: _$ss11InlineArrayVsRi__rlE16_protectedBufferSRyq_GvpMV
10831083
Added: _$ss11InlineArrayVsRi__rlE17_protectedAddressSPyq_GvpMV
1084+
1085+
// lengthOfBytes(using:)
1086+
Added: __swift_stdlib_NSStringLengthOfBytesInEncodingTrampoline

test/abi/macOS/x86_64/stdlib.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,3 +1081,6 @@ Added: _$ss6MirrorV12DisplayStyleO16foreignReferenceyA2DmFWC
10811081
// var InlineArray._protectedAddress
10821082
Added: _$ss11InlineArrayVsRi__rlE16_protectedBufferSRyq_GvpMV
10831083
Added: _$ss11InlineArrayVsRi__rlE17_protectedAddressSPyq_GvpMV
1084+
1085+
// lengthOfBytes(using:)
1086+
Added: __swift_stdlib_NSStringLengthOfBytesInEncodingTrampoline

0 commit comments

Comments
 (0)