Skip to content

Commit 62a2e82

Browse files
lorenteyairspeedswift
authored andcommitted
[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 b8c9d8f commit 62a2e82

10 files changed

+336
-360
lines changed

stdlib/public/core/Dictionary.swift

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1498,20 +1498,14 @@ extension Dictionary {
14981498
@inlinable
14991499
public mutating func swapAt(_ i: Index, _ j: Index) {
15001500
guard i != j else { return }
1501-
let (a, b): (_HashTable.Bucket, _HashTable.Bucket)
1502-
switch _variant {
1503-
case .native(let native):
1504-
a = native.validatedBucket(for: i)
1505-
b = native.validatedBucket(for: j)
15061501
#if _runtime(_ObjC)
1507-
case .cocoa(let cocoa):
1508-
_variant.cocoaPath()
1509-
let native = _NativeDictionary<Key, Value>(cocoa)
1510-
a = native.validatedBucket(for: i)
1511-
b = native.validatedBucket(for: j)
1512-
_variant = .native(native)
1513-
#endif
1502+
if !_variant.isNative {
1503+
_variant = .native(_NativeDictionary<Key, Value>(_variant.asCocoa))
15141504
}
1505+
#endif
1506+
let native = _variant.asNative
1507+
let a = native.validatedBucket(for: i)
1508+
let b = native.validatedBucket(for: j)
15151509
let isUnique = _variant.isUniquelyReferenced()
15161510
_variant.asNative.swapValuesAt(a, b, isUnique: isUnique)
15171511
}
@@ -1827,6 +1821,17 @@ extension Dictionary.Index {
18271821
_conditionallyUnreachable()
18281822
}
18291823
}
1824+
1825+
@usableFromInline @_transparent
1826+
internal var _isNative: Bool {
1827+
switch _variant {
1828+
case .native:
1829+
return true
1830+
case .cocoa:
1831+
_cocoaPath()
1832+
return false
1833+
}
1834+
}
18301835
#endif
18311836

18321837
@usableFromInline @_transparent
@@ -1899,16 +1904,14 @@ extension Dictionary.Index: Comparable {
18991904
extension Dictionary.Index: Hashable {
19001905
@_effects(readonly) // FIXME(cocoa-index): Make inlinable
19011906
public func hash(into hasher: inout Hasher) {
1902-
#if _runtime(_ObjC)
1903-
switch _variant {
1904-
case .native(let nativeIndex):
1905-
hasher.combine(0 as UInt8)
1906-
hasher.combine(nativeIndex.bucket.offset)
1907-
case .cocoa(let cocoaIndex):
1908-
_cocoaPath()
1907+
#if _runtime(_ObjC)
1908+
guard _isNative else {
19091909
hasher.combine(1 as UInt8)
1910-
hasher.combine(cocoaIndex.storage.currentKeyIndex)
1910+
hasher.combine(_asCocoa.storage.currentKeyIndex)
1911+
return
19111912
}
1913+
hasher.combine(0 as UInt8)
1914+
hasher.combine(_asNative.bucket.offset)
19121915
#else
19131916
hasher.combine(_asNative.bucket.offset)
19141917
#endif
@@ -1975,6 +1978,17 @@ extension Dictionary.Iterator {
19751978
_conditionallyUnreachable()
19761979
}
19771980
}
1981+
1982+
@usableFromInline @_transparent
1983+
internal var _isNative: Bool {
1984+
switch _variant {
1985+
case .native:
1986+
return true
1987+
case .cocoa:
1988+
_cocoaPath()
1989+
return false
1990+
}
1991+
}
19781992
#endif
19791993

19801994
@usableFromInline @_transparent
@@ -1993,6 +2007,21 @@ extension Dictionary.Iterator {
19932007
self._variant = .native(newValue)
19942008
}
19952009
}
2010+
2011+
#if _runtime(_ObjC)
2012+
@usableFromInline @_transparent
2013+
internal var _asCocoa: _CocoaDictionary.Iterator {
2014+
get {
2015+
switch _variant {
2016+
case .native:
2017+
_sanityCheckFailure("internal error: does not contain a Cocoa index")
2018+
case .cocoa(let cocoa):
2019+
return cocoa
2020+
}
2021+
}
2022+
}
2023+
#endif
2024+
19962025
}
19972026

19982027
extension Dictionary.Iterator: IteratorProtocol {
@@ -2003,20 +2032,17 @@ extension Dictionary.Iterator: IteratorProtocol {
20032032
@inlinable
20042033
@inline(__always)
20052034
public mutating func next() -> (key: Key, value: Value)? {
2006-
switch _variant {
2007-
case .native:
2008-
return _asNative.next()
20092035
#if _runtime(_ObjC)
2010-
case .cocoa(let cocoaIterator):
2011-
_cocoaPath()
2012-
if let (cocoaKey, cocoaValue) = cocoaIterator.next() {
2036+
guard _isNative else {
2037+
if let (cocoaKey, cocoaValue) = _asCocoa.next() {
20132038
let nativeKey = _forceBridgeFromObjectiveC(cocoaKey, Key.self)
20142039
let nativeValue = _forceBridgeFromObjectiveC(cocoaValue, Value.self)
20152040
return (nativeKey, nativeValue)
20162041
}
20172042
return nil
2018-
#endif
20192043
}
2044+
#endif
2045+
return _asNative.next()
20202046
}
20212047
}
20222048

stdlib/public/core/DictionaryBridging.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -776,12 +776,10 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
776776
extension Dictionary {
777777
@inlinable
778778
public __consuming func _bridgeToObjectiveCImpl() -> _NSDictionaryCore {
779-
switch _variant {
780-
case .native(let nativeDictionary):
781-
return nativeDictionary.bridged()
782-
case .cocoa(let cocoaDictionary):
783-
return cocoaDictionary.object
779+
guard _variant.isNative else {
780+
return _variant.asCocoa.object
784781
}
782+
return _variant.asNative.bridged()
785783
}
786784

787785
/// 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)