Skip to content

Commit 77bf535

Browse files
committed
[stdlib] Set, Dictionary: Flatten switch statements
The optimizer dislikes nested switch statements; flatten them out to simplify optimization and to hopefully speed things up a little.
1 parent df7744e commit 77bf535

File tree

10 files changed

+338
-362
lines changed

10 files changed

+338
-362
lines changed

stdlib/public/core/Dictionary.swift

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1513,20 +1513,14 @@ extension Dictionary {
15131513
@inlinable
15141514
public mutating func swapAt(_ i: Index, _ j: Index) {
15151515
guard i != j else { return }
1516-
let (a, b): (_HashTable.Bucket, _HashTable.Bucket)
1517-
switch _variant {
1518-
case .native(let native):
1519-
a = native.validatedBucket(for: i)
1520-
b = native.validatedBucket(for: j)
15211516
#if _runtime(_ObjC)
1522-
case .cocoa(let cocoa):
1523-
_variant.cocoaPath()
1524-
let native = _NativeDictionary<Key, Value>(cocoa)
1525-
a = native.validatedBucket(for: i)
1526-
b = native.validatedBucket(for: j)
1527-
_variant = .native(native)
1528-
#endif
1517+
if !_variant.isNative {
1518+
_variant = .native(_NativeDictionary<Key, Value>(_variant.asCocoa))
15291519
}
1520+
#endif
1521+
let native = _variant.asNative
1522+
let a = native.validatedBucket(for: i)
1523+
let b = native.validatedBucket(for: j)
15301524
let isUnique = _variant.isUniquelyReferenced()
15311525
_variant.asNative.swapValuesAt(a, b, isUnique: isUnique)
15321526
}
@@ -1850,6 +1844,17 @@ extension Dictionary.Index {
18501844
var handle = _asCocoa.handleBitPattern
18511845
return handle == 0 || _isUnique_native(&handle)
18521846
}
1847+
1848+
@usableFromInline @_transparent
1849+
internal var _isNative: Bool {
1850+
switch _variant {
1851+
case .native:
1852+
return true
1853+
case .cocoa:
1854+
_cocoaPath()
1855+
return false
1856+
}
1857+
}
18531858
#endif
18541859

18551860
@usableFromInline @_transparent
@@ -1935,19 +1940,17 @@ extension Dictionary.Index: Comparable {
19351940
extension Dictionary.Index: Hashable {
19361941
public // FIXME(cocoa-index): Make inlinable
19371942
func hash(into hasher: inout Hasher) {
1938-
#if _runtime(_ObjC)
1939-
switch _variant {
1940-
case .native(let nativeIndex):
1941-
hasher.combine(0 as UInt8)
1942-
hasher.combine(nativeIndex.bucket.offset)
1943-
case .cocoa(let cocoaIndex):
1944-
_cocoaPath()
1943+
#if _runtime(_ObjC)
1944+
guard _isNative else {
19451945
hasher.combine(1 as UInt8)
1946-
hasher.combine(cocoaIndex.storage.currentKeyIndex)
1946+
hasher.combine(_asCocoa.storage.currentKeyIndex)
1947+
return
19471948
}
1948-
#else
1949+
hasher.combine(0 as UInt8)
19491950
hasher.combine(_asNative.bucket.offset)
1950-
#endif
1951+
#else
1952+
hasher.combine(_asNative.bucket.offset)
1953+
#endif
19511954
}
19521955
}
19531956

@@ -2011,6 +2014,17 @@ extension Dictionary.Iterator {
20112014
_conditionallyUnreachable()
20122015
}
20132016
}
2017+
2018+
@usableFromInline @_transparent
2019+
internal var _isNative: Bool {
2020+
switch _variant {
2021+
case .native:
2022+
return true
2023+
case .cocoa:
2024+
_cocoaPath()
2025+
return false
2026+
}
2027+
}
20142028
#endif
20152029

20162030
@usableFromInline @_transparent
@@ -2029,6 +2043,21 @@ extension Dictionary.Iterator {
20292043
self._variant = .native(newValue)
20302044
}
20312045
}
2046+
2047+
#if _runtime(_ObjC)
2048+
@usableFromInline @_transparent
2049+
internal var _asCocoa: _CocoaDictionary.Iterator {
2050+
get {
2051+
switch _variant {
2052+
case .native:
2053+
_sanityCheckFailure("internal error: does not contain a Cocoa index")
2054+
case .cocoa(let cocoa):
2055+
return cocoa
2056+
}
2057+
}
2058+
}
2059+
#endif
2060+
20322061
}
20332062

20342063
extension Dictionary.Iterator: IteratorProtocol {
@@ -2039,20 +2068,17 @@ extension Dictionary.Iterator: IteratorProtocol {
20392068
@inlinable
20402069
@inline(__always)
20412070
public mutating func next() -> (key: Key, value: Value)? {
2042-
switch _variant {
2043-
case .native:
2044-
return _asNative.next()
20452071
#if _runtime(_ObjC)
2046-
case .cocoa(let cocoaIterator):
2047-
_cocoaPath()
2048-
if let (cocoaKey, cocoaValue) = cocoaIterator.next() {
2072+
guard _isNative else {
2073+
if let (cocoaKey, cocoaValue) = _asCocoa.next() {
20492074
let nativeKey = _forceBridgeFromObjectiveC(cocoaKey, Key.self)
20502075
let nativeValue = _forceBridgeFromObjectiveC(cocoaValue, Value.self)
20512076
return (nativeKey, nativeValue)
20522077
}
20532078
return nil
2054-
#endif
20552079
}
2080+
#endif
2081+
return _asNative.next()
20562082
}
20572083
}
20582084

stdlib/public/core/DictionaryBridging.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -797,12 +797,10 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
797797
extension Dictionary {
798798
@inlinable
799799
public __consuming func _bridgeToObjectiveCImpl() -> _NSDictionaryCore {
800-
switch _variant {
801-
case .native(let nativeDictionary):
802-
return nativeDictionary.bridged()
803-
case .cocoa(let cocoaDictionary):
804-
return cocoaDictionary.object
800+
guard _variant.isNative else {
801+
return _variant.asCocoa.object
805802
}
803+
return _variant.asNative.bridged()
806804
}
807805

808806
/// Returns the native Dictionary hidden inside this NSDictionary;

stdlib/public/core/DictionaryCasting.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ public func _dictionaryDownCast<BaseKey, BaseValue, DerivedKey, DerivedValue>(
5656
&& _isClassOrObjCExistential(DerivedKey.self)
5757
&& _isClassOrObjCExistential(DerivedValue.self) {
5858

59-
switch source._variant {
60-
case .native(let native):
61-
// Note: it is safe to treat the buffer as immutable here because
62-
// Dictionary will not mutate buffer with reference count greater than 1.
63-
return Dictionary(_immutableCocoaDictionary: native.bridged())
64-
case .cocoa(let cocoa):
65-
return Dictionary(_immutableCocoaDictionary: cocoa.object)
59+
guard source._variant.isNative else {
60+
return Dictionary(
61+
_immutableCocoaDictionary: source._variant.asCocoa.object)
6662
}
63+
// Note: it is safe to treat the buffer as immutable here because
64+
// Dictionary will not mutate buffer with reference count greater than 1.
65+
return Dictionary(
66+
_immutableCocoaDictionary: source._variant.asNative.bridged())
6767
}
6868
#endif
6969
return _dictionaryDownCastConditional(source)!

0 commit comments

Comments
 (0)