Skip to content

Commit 4967393

Browse files
authored
Merge pull request #19688 from lorentey/hashed-bridgeobject
[stdlib] Set, Dictionary: Replace _Variant enums with _BridgeStorage
2 parents cc16ddf + aba15a1 commit 4967393

21 files changed

+595
-597
lines changed

stdlib/public/core/Bitset.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ extension _UnsafeBitset {
6464
@inline(__always)
6565
internal static func join(word: Int, bit: Int) -> Int {
6666
_sanityCheck(bit >= 0 && bit < Word.capacity)
67-
return word &* Word.capacity + bit
67+
return word &* Word.capacity &+ bit
6868
}
6969
}
7070

7171
extension _UnsafeBitset {
7272
@inlinable
7373
@inline(__always)
7474
internal static func wordCount(forCapacity capacity: Int) -> Int {
75-
return word(for: capacity + Word.capacity - 1)
75+
return word(for: capacity &+ Word.capacity &- 1)
7676
}
7777

7878
@inlinable

stdlib/public/core/BridgeStorage.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,15 @@ struct _BridgeStorage<
6060
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
6161
rawValue = Builtin.reinterpretCast(native)
6262
}
63-
63+
64+
#if !(arch(i386) || arch(arm))
65+
@inlinable
66+
@inline(__always)
67+
internal init(taggedPayload: UInt) {
68+
rawValue = _bridgeObject(taggingPayload: taggedPayload)
69+
}
70+
#endif
71+
6472
@inlinable // FIXME(sil-serialize-all)
6573
public // @testable
6674
var spareBits: Int {

stdlib/public/core/Dictionary.swift

Lines changed: 86 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -396,13 +396,13 @@ public struct Dictionary<Key: Hashable, Value> {
396396

397397
@inlinable
398398
internal init(_native: __owned _NativeDictionary<Key, Value>) {
399-
_variant = .native(_native)
399+
_variant = _Variant(native: _native)
400400
}
401401

402402
#if _runtime(_ObjC)
403403
@inlinable
404404
internal init(_cocoa: __owned _CocoaDictionary) {
405-
_variant = .cocoa(_cocoa)
405+
_variant = _Variant(cocoa: _cocoa)
406406
}
407407

408408
/// Private initializer used for bridging.
@@ -444,7 +444,7 @@ public struct Dictionary<Key: Hashable, Value> {
444444
/// reallocating its storage buffer.
445445
public // FIXME(reserveCapacity): Should be inlinable
446446
init(minimumCapacity: Int) {
447-
_variant = .native(_NativeDictionary(capacity: minimumCapacity))
447+
_variant = _Variant(native: _NativeDictionary(capacity: minimumCapacity))
448448
}
449449

450450
/// Creates a new dictionary from the key-value pairs in the given sequence.
@@ -1316,8 +1316,12 @@ extension Dictionary {
13161316
return Values(_dictionary: self)
13171317
}
13181318
_modify {
1319-
var values = Values(_dictionary: self)
1320-
_variant = .native(_NativeDictionary())
1319+
var values: Values
1320+
do {
1321+
var temp = _Variant(dummy: ())
1322+
swap(&temp, &_variant)
1323+
values = Values(_variant: temp)
1324+
}
13211325
yield &values
13221326
self._variant = values._variant
13231327
}
@@ -1404,10 +1408,26 @@ extension Dictionary {
14041408
@inlinable
14051409
public static func ==(lhs: Keys, rhs: Keys) -> Bool {
14061410
// Equal if the two dictionaries share storage.
1407-
if case (.native(let ln), .native(let rn)) = (lhs._variant, rhs._variant),
1408-
ln._storage === rn._storage {
1411+
#if _runtime(_ObjC)
1412+
if
1413+
lhs._variant.isNative,
1414+
rhs._variant.isNative,
1415+
lhs._variant.asNative._storage === rhs._variant.asNative._storage
1416+
{
1417+
return true
1418+
}
1419+
if
1420+
!lhs._variant.isNative,
1421+
!rhs._variant.isNative,
1422+
lhs._variant.asCocoa.object === rhs._variant.asCocoa.object
1423+
{
1424+
return true
1425+
}
1426+
#else
1427+
if lhs._variant.asNative._storage === rhs._variant.asNative._storage {
14091428
return true
14101429
}
1430+
#endif
14111431

14121432
// Not equal if the dictionaries are different sizes.
14131433
if lhs.count != rhs.count {
@@ -1517,21 +1537,15 @@ extension Dictionary {
15171537
@inlinable
15181538
public mutating func swapAt(_ i: Index, _ j: Index) {
15191539
guard i != j else { return }
1520-
let (a, b): (_HashTable.Bucket, _HashTable.Bucket)
1521-
switch _variant {
1522-
case .native(let native):
1523-
a = native.validatedBucket(for: i)
1524-
b = native.validatedBucket(for: j)
15251540
#if _runtime(_ObjC)
1526-
case .cocoa(let cocoa):
1527-
_variant.cocoaPath()
1528-
let native = _NativeDictionary<Key, Value>(cocoa)
1529-
a = native.validatedBucket(for: i)
1530-
b = native.validatedBucket(for: j)
1531-
_variant = .native(native)
1532-
#endif
1541+
if !_variant.isNative {
1542+
_variant = .init(native: _NativeDictionary(_variant.asCocoa))
15331543
}
1544+
#endif
15341545
let isUnique = _variant.isUniquelyReferenced()
1546+
let native = _variant.asNative
1547+
let a = native.validatedBucket(for: i)
1548+
let b = native.validatedBucket(for: j)
15351549
_variant.asNative.swapValuesAt(a, b, isUnique: isUnique)
15361550
}
15371551
}
@@ -1606,51 +1620,20 @@ extension Dictionary.Values {
16061620
extension Dictionary: Equatable where Value: Equatable {
16071621
@inlinable
16081622
public static func == (lhs: [Key: Value], rhs: [Key: Value]) -> Bool {
1609-
switch (lhs._variant, rhs._variant) {
1610-
case (.native(let lhsNative), .native(let rhsNative)):
1611-
1612-
if lhsNative._storage === rhsNative._storage {
1613-
return true
1614-
}
1615-
1616-
if lhsNative.count != rhsNative.count {
1617-
return false
1618-
}
1619-
1620-
for (k, v) in lhs {
1621-
let (bucket, found) = rhsNative.find(k)
1622-
guard found, rhsNative.uncheckedValue(at: bucket) == v else {
1623-
return false
1624-
}
1625-
}
1626-
return true
1627-
1628-
#if _runtime(_ObjC)
1629-
case (.cocoa(let lhsCocoa), .cocoa(let rhsCocoa)):
1630-
return lhsCocoa == rhsCocoa
1631-
1632-
case (.native(let lhsNative), .cocoa(let rhsCocoa)):
1633-
if lhsNative.count != rhsCocoa.count {
1634-
return false
1635-
}
1636-
1637-
defer { _fixLifetime(lhsNative) }
1638-
for bucket in lhsNative.hashTable {
1639-
let key = lhsNative.uncheckedKey(at: bucket)
1640-
let value = lhsNative.uncheckedValue(at: bucket)
1641-
guard
1642-
let rhsValue = rhsCocoa.lookup(_bridgeAnythingToObjectiveC(key)),
1643-
value == _forceBridgeFromObjectiveC(rhsValue, Value.self)
1644-
else {
1645-
return false
1646-
}
1647-
}
1648-
return true
1649-
1650-
case (.cocoa, .native):
1651-
return rhs == lhs
1652-
#endif
1653-
}
1623+
#if _runtime(_ObjC)
1624+
switch (lhs._variant.isNative, rhs._variant.isNative) {
1625+
case (true, true):
1626+
return lhs._variant.asNative.isEqual(to: rhs._variant.asNative)
1627+
case (false, false):
1628+
return lhs._variant.asCocoa.isEqual(to: rhs._variant.asCocoa)
1629+
case (true, false):
1630+
return lhs._variant.asNative.isEqual(to: rhs._variant.asCocoa)
1631+
case (false, true):
1632+
return rhs._variant.asNative.isEqual(to: lhs._variant.asCocoa)
1633+
}
1634+
#else
1635+
return lhs._variant.asNative.isEqual(to: rhs._variant.asNative)
1636+
#endif
16541637
}
16551638
}
16561639

@@ -1860,20 +1843,18 @@ extension Dictionary.Index {
18601843
var handle = _asCocoa.handleBitPattern
18611844
return handle == 0 || _isUnique_native(&handle)
18621845
}
1863-
#endif
18641846

18651847
@usableFromInline @_transparent
18661848
internal var _isNative: Bool {
18671849
switch _variant {
18681850
case .native:
18691851
return true
1870-
#if _runtime(_ObjC)
18711852
case .cocoa:
18721853
_cocoaPath()
18731854
return false
1874-
#endif
18751855
}
18761856
}
1857+
#endif
18771858

18781859
@usableFromInline @_transparent
18791860
internal var _asNative: _HashTable.Index {
@@ -1958,19 +1939,17 @@ extension Dictionary.Index: Comparable {
19581939
extension Dictionary.Index: Hashable {
19591940
public // FIXME(cocoa-index): Make inlinable
19601941
func hash(into hasher: inout Hasher) {
1961-
#if _runtime(_ObjC)
1962-
switch _variant {
1963-
case .native(let nativeIndex):
1964-
hasher.combine(0 as UInt8)
1965-
hasher.combine(nativeIndex.bucket.offset)
1966-
case .cocoa(let cocoaIndex):
1967-
_cocoaPath()
1942+
#if _runtime(_ObjC)
1943+
guard _isNative else {
19681944
hasher.combine(1 as UInt8)
1969-
hasher.combine(cocoaIndex.storage.currentKeyIndex)
1945+
hasher.combine(_asCocoa.storage.currentKeyIndex)
1946+
return
19701947
}
1971-
#else
1948+
hasher.combine(0 as UInt8)
19721949
hasher.combine(_asNative.bucket.offset)
1973-
#endif
1950+
#else
1951+
hasher.combine(_asNative.bucket.offset)
1952+
#endif
19741953
}
19751954
}
19761955

@@ -2034,6 +2013,17 @@ extension Dictionary.Iterator {
20342013
_conditionallyUnreachable()
20352014
}
20362015
}
2016+
2017+
@usableFromInline @_transparent
2018+
internal var _isNative: Bool {
2019+
switch _variant {
2020+
case .native:
2021+
return true
2022+
case .cocoa:
2023+
_cocoaPath()
2024+
return false
2025+
}
2026+
}
20372027
#endif
20382028

20392029
@usableFromInline @_transparent
@@ -2052,6 +2042,21 @@ extension Dictionary.Iterator {
20522042
self._variant = .native(newValue)
20532043
}
20542044
}
2045+
2046+
#if _runtime(_ObjC)
2047+
@usableFromInline @_transparent
2048+
internal var _asCocoa: _CocoaDictionary.Iterator {
2049+
get {
2050+
switch _variant {
2051+
case .native:
2052+
_sanityCheckFailure("internal error: does not contain a Cocoa index")
2053+
case .cocoa(let cocoa):
2054+
return cocoa
2055+
}
2056+
}
2057+
}
2058+
#endif
2059+
20552060
}
20562061

20572062
extension Dictionary.Iterator: IteratorProtocol {
@@ -2062,20 +2067,17 @@ extension Dictionary.Iterator: IteratorProtocol {
20622067
@inlinable
20632068
@inline(__always)
20642069
public mutating func next() -> (key: Key, value: Value)? {
2065-
switch _variant {
2066-
case .native:
2067-
return _asNative.next()
20682070
#if _runtime(_ObjC)
2069-
case .cocoa(let cocoaIterator):
2070-
_cocoaPath()
2071-
if let (cocoaKey, cocoaValue) = cocoaIterator.next() {
2071+
guard _isNative else {
2072+
if let (cocoaKey, cocoaValue) = _asCocoa.next() {
20722073
let nativeKey = _forceBridgeFromObjectiveC(cocoaKey, Key.self)
20732074
let nativeValue = _forceBridgeFromObjectiveC(cocoaValue, Value.self)
20742075
return (nativeKey, nativeValue)
20752076
}
20762077
return nil
2077-
#endif
20782078
}
2079+
#endif
2080+
return _asNative.next()
20792081
}
20802082
}
20812083

stdlib/public/core/DictionaryBridging.swift

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -434,13 +434,10 @@ internal struct _CocoaDictionary {
434434
}
435435
}
436436

437-
extension _CocoaDictionary: Equatable {
437+
extension _CocoaDictionary {
438438
@usableFromInline
439-
internal static func ==(
440-
lhs: _CocoaDictionary,
441-
rhs: _CocoaDictionary
442-
) -> Bool {
443-
return _stdlib_NSObject_isEqual(lhs.object, rhs.object)
439+
internal func isEqual(to other: _CocoaDictionary) -> Bool {
440+
return _stdlib_NSObject_isEqual(self.object, other.object)
444441
}
445442
}
446443

@@ -805,12 +802,10 @@ extension _CocoaDictionary.Iterator: IteratorProtocol {
805802
extension Dictionary {
806803
@inlinable
807804
public __consuming func _bridgeToObjectiveCImpl() -> _NSDictionaryCore {
808-
switch _variant {
809-
case .native(let nativeDictionary):
810-
return nativeDictionary.bridged()
811-
case .cocoa(let cocoaDictionary):
812-
return cocoaDictionary.object
805+
guard _variant.isNative else {
806+
return _variant.asCocoa.object
813807
}
808+
return _variant.asNative.bridged()
814809
}
815810

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

stdlib/public/core/DictionaryBuilder.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ struct _DictionaryBuilder<Key: Hashable, Value> {
3030

3131
@inlinable
3232
public mutating func add(key newKey: Key, value: Value) {
33-
_target.insertNew(key: newKey, value: value)
33+
_precondition(_target.count < _requestedCount,
34+
"Can't add more members than promised")
35+
_target._unsafeInsertNew(key: newKey, value: value)
3436
}
3537

3638
@inlinable

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)