Skip to content

Commit 15f4b91

Browse files
committed
[stdlib] Set, Dictionary: Hide Cocoa index storage classes
Replace the single typed storage reference with two _BridgeObjects; this should give us plenty of space to play around with alternative representations.
1 parent 41bedbe commit 15f4b91

File tree

2 files changed

+65
-14
lines changed

2 files changed

+65
-14
lines changed

stdlib/public/core/DictionaryBridging.swift

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,8 @@ extension _CocoaDictionary: _DictionaryBuffer {
487487
internal func formIndex(after index: inout Index) {
488488
validate(index)
489489
let isUnique = index.isUniquelyReferenced()
490-
if !isUnique { index.storage = index.copy() }
490+
if !isUnique { index = index.copy() }
491+
_sanityCheck(index.isUniquelyReferenced())
491492
let storage = index.storage // FIXME: rdar://problem/44863751
492493
storage.currentKeyIndex += 1
493494
}
@@ -575,17 +576,34 @@ extension _CocoaDictionary {
575576
@usableFromInline
576577
internal struct Index {
577578
@usableFromInline
578-
internal var storage: Storage
579+
internal var _object: Builtin.BridgeObject
580+
@usableFromInline
581+
internal var _storage: Builtin.BridgeObject
582+
583+
internal var object: AnyObject {
584+
@inline(__always)
585+
get {
586+
return _bridgeObject(toNonTaggedObjC: _object)
587+
}
588+
}
589+
590+
internal var storage: Storage {
591+
@inline(__always)
592+
get {
593+
let storage = _bridgeObject(toNative: _storage)
594+
return unsafeDowncast(storage, to: Storage.self)
595+
}
596+
}
579597

580598
internal init(_ storage: Storage) {
581-
self.storage = storage
599+
self._object = _bridgeObject(fromNonTaggedObjC: storage.base.object)
600+
self._storage = _bridgeObject(fromNative: storage)
582601
}
583602
}
584603
}
585604

586605
extension _CocoaDictionary.Index {
587606
// FIXME(cocoa-index): Try using an NSEnumerator to speed this up.
588-
@usableFromInline
589607
internal class Storage {
590608
// Assumption: we rely on NSDictionary.getObjects when being
591609
// repeatedly called on the same NSDictionary, returning items in the same
@@ -620,13 +638,21 @@ extension _CocoaDictionary.Index {
620638
extension _CocoaDictionary.Index {
621639
@inlinable
622640
internal mutating func isUniquelyReferenced() -> Bool {
641+
defer { _fixLifetime(self) }
642+
guard _isNativePointer(_storage) else {
643+
return false
644+
}
645+
unowned(unsafe) var storage = _bridgeObject(toNative: _storage)
623646
return _isUnique_native(&storage)
624647
}
625648

626649
@usableFromInline
627-
internal mutating func copy() -> Storage {
650+
internal mutating func copy() -> _CocoaDictionary.Index {
628651
let storage = self.storage
629-
return Storage(storage.base, storage.allKeys, storage.currentKeyIndex)
652+
return _CocoaDictionary.Index(Storage(
653+
storage.base,
654+
storage.allKeys,
655+
storage.currentKeyIndex))
630656
}
631657
}
632658

@@ -647,7 +673,7 @@ extension _CocoaDictionary.Index {
647673
internal var age: Int32 {
648674
@_effects(readonly)
649675
get {
650-
return _HashTable.age(for: storage.base.object)
676+
return _HashTable.age(for: object)
651677
}
652678
}
653679
}

stdlib/public/core/SetBridging.swift

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ extension _CocoaSet: _SetBuffer {
362362
internal func formIndex(after index: inout Index) {
363363
validate(index)
364364
let isUnique = index.isUniquelyReferenced()
365-
if !isUnique { index.storage = index.copy() }
365+
if !isUnique { index = index.copy() }
366366
let storage = index.storage // FIXME: rdar://problem/44863751
367367
storage.currentKeyIndex += 1
368368
}
@@ -412,17 +412,34 @@ extension _CocoaSet {
412412
@usableFromInline
413413
internal struct Index {
414414
@usableFromInline
415-
internal var storage: Storage
415+
internal var _object: Builtin.BridgeObject
416+
@usableFromInline
417+
internal var _storage: Builtin.BridgeObject
418+
419+
internal var object: AnyObject {
420+
@inline(__always)
421+
get {
422+
return _bridgeObject(toNonTaggedObjC: _object)
423+
}
424+
}
425+
426+
internal var storage: Storage {
427+
@inline(__always)
428+
get {
429+
let storage = _bridgeObject(toNative: _storage)
430+
return unsafeDowncast(storage, to: Storage.self)
431+
}
432+
}
416433

417434
internal init(_ storage: __owned Storage) {
418-
self.storage = storage
435+
self._object = _bridgeObject(fromNonTaggedObjC: storage.base.object)
436+
self._storage = _bridgeObject(fromNative: storage)
419437
}
420438
}
421439
}
422440

423441
extension _CocoaSet.Index {
424442
// FIXME(cocoa-index): Try using an NSEnumerator to speed this up.
425-
@usableFromInline
426443
internal class Storage {
427444
// Assumption: we rely on NSDictionary.getObjects when being
428445
// repeatedly called on the same NSDictionary, returning items in the same
@@ -457,13 +474,21 @@ extension _CocoaSet.Index {
457474
extension _CocoaSet.Index {
458475
@inlinable
459476
internal mutating func isUniquelyReferenced() -> Bool {
477+
defer { _fixLifetime(self) }
478+
guard _isNativePointer(_storage) else {
479+
return false
480+
}
481+
unowned(unsafe) var storage = _bridgeObject(toNative: _storage)
460482
return _isUnique_native(&storage)
461483
}
462484

463485
@usableFromInline
464-
internal mutating func copy() -> Storage {
486+
internal mutating func copy() -> _CocoaSet.Index {
465487
let storage = self.storage
466-
return Storage(storage.base, storage.allKeys, storage.currentKeyIndex)
488+
return _CocoaSet.Index(Storage(
489+
storage.base,
490+
storage.allKeys,
491+
storage.currentKeyIndex))
467492
}
468493
}
469494

@@ -484,7 +509,7 @@ extension _CocoaSet.Index {
484509
internal var age: Int32 {
485510
@_effects(releasenone)
486511
get {
487-
return _HashTable.age(for: storage.base.object)
512+
return _HashTable.age(for: object)
488513
}
489514
}
490515
}

0 commit comments

Comments
 (0)