[stdlib] Make protocol _NSArrayCore internal

These shadow protocols don’t add any real type safety, and exposing them in the ABI seems unnecessary.
This commit is contained in:
Karoy Lorentey
2018-11-12 15:44:09 +00:00
parent c71abaaf51
commit ee17e975ca
9 changed files with 131 additions and 106 deletions

View File

@@ -43,9 +43,7 @@ extension Array : _ObjectiveCBridgeable {
//
// The bug is fixed in: OS X 10.11.0, iOS 9.0, all versions of tvOS
// and watchOS.
self = Array(
_immutableCocoaArray:
unsafeBitCast(_cocoaArray.copy() as AnyObject, to: _NSArrayCore.self))
self = Array(_immutableCocoaArray: _cocoaArray.copy() as AnyObject)
}
@_semantics("convertToObjectiveC")

View File

@@ -1728,7 +1728,7 @@ extension Array {
// to do the bridging in an ABI safe way. Even though this looks useless,
// DO NOT DELETE!
@usableFromInline internal
func _bridgeCocoaArray<T>(_ _immutableCocoaArray: _NSArrayCore) -> Array<T> {
func _bridgeCocoaArray<T>(_ _immutableCocoaArray: AnyObject) -> Array<T> {
return Array(_buffer: _ArrayBuffer(nsArray: _immutableCocoaArray))
}
@@ -1764,7 +1764,7 @@ extension Array {
/// * `Element` is bridged verbatim to Objective-C (i.e.,
/// is a reference type).
@inlinable
public init(_immutableCocoaArray: _NSArrayCore) {
public init(_immutableCocoaArray: AnyObject) {
self = _bridgeCocoaArray(_immutableCocoaArray)
}
}

View File

@@ -20,7 +20,7 @@ import SwiftShims
@usableFromInline
internal typealias _ArrayBridgeStorage
= _BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>
= _BridgeStorage<__ContiguousArrayStorageBase, AnyObject>
@usableFromInline
@_fixed_layout
@@ -33,7 +33,7 @@ internal struct _ArrayBuffer<Element> : _ArrayBufferProtocol {
}
@inlinable
internal init(nsArray: _NSArrayCore) {
internal init(nsArray: AnyObject) {
_sanityCheck(_isClassOrObjCExistential(Element.self))
_storage = _ArrayBridgeStorage(objC: nsArray)
}
@@ -121,8 +121,8 @@ extension _ArrayBuffer {
///
/// O(1) if the element type is bridged verbatim, O(*n*) otherwise.
@inlinable
internal func _asCocoaArray() -> _NSArrayCore {
return _fastPath(_isNative) ? _native._asCocoaArray() : _nonNative
internal func _asCocoaArray() -> AnyObject {
return _fastPath(_isNative) ? _native._asCocoaArray() : _nonNative.buffer
}
/// If this buffer is backed by a uniquely-referenced mutable
@@ -175,8 +175,7 @@ extension _ArrayBuffer {
)
}
else {
let ns = _nonNative
let element = ns.objectAt(index)
let element = _nonNative[index]
precondition(
element is Element,
"""
@@ -216,26 +215,12 @@ extension _ArrayBuffer {
if _fastPath(_isNative) {
return _native._copyContents(subRange: bounds, initializing: target)
}
let nonNative = _nonNative
let nsSubRange = SwiftShims._SwiftNSRange(
location: bounds.lowerBound,
length: bounds.upperBound - bounds.lowerBound)
let buffer = UnsafeMutableRawPointer(target).assumingMemoryBound(
to: AnyObject.self)
// Copies the references out of the NSArray without retaining them
nonNative.getObjects(buffer, range: nsSubRange)
// Make another pass to retain the copied objects
var result = target
for _ in bounds {
result.initialize(to: result.pointee)
result += 1
}
return result
let buffer = UnsafeMutableRawPointer(target)
.assumingMemoryBound(to: AnyObject.self)
let result = _nonNative._copyContents(
subRange: bounds,
initializing: buffer)
return UnsafeMutableRawPointer(result).assumingMemoryBound(to: Element.self)
}
/// Returns a `_SliceBuffer` containing the given sub-range of elements in
@@ -244,45 +229,10 @@ extension _ArrayBuffer {
internal subscript(bounds: Range<Int>) -> _SliceBuffer<Element> {
get {
_typeCheck(bounds)
if _fastPath(_isNative) {
return _native[bounds]
}
let boundsCount = bounds.count
if boundsCount == 0 {
return _SliceBuffer(
_buffer: _ContiguousArrayBuffer<Element>(),
shiftedToStartIndex: bounds.lowerBound)
}
// Look for contiguous storage in the NSArray
let nonNative = self._nonNative
let cocoa = _CocoaArrayWrapper(nonNative)
let cocoaStorageBaseAddress = cocoa.contiguousStorage(self.indices)
if let cocoaStorageBaseAddress = cocoaStorageBaseAddress {
let basePtr = UnsafeMutableRawPointer(cocoaStorageBaseAddress)
.assumingMemoryBound(to: Element.self)
return _SliceBuffer(
owner: nonNative,
subscriptBaseAddress: basePtr,
indices: bounds,
hasNativeBuffer: false)
}
// No contiguous storage found; we must allocate
let result = _ContiguousArrayBuffer<Element>(
_uninitializedCount: boundsCount, minimumCapacity: 0)
// Tell Cocoa to copy the objects into our storage
cocoa.buffer.getObjects(
UnsafeMutableRawPointer(result.firstElementAddress)
.assumingMemoryBound(to: AnyObject.self),
range: _SwiftNSRange(location: bounds.lowerBound, length: boundsCount))
return _SliceBuffer(
_buffer: result, shiftedToStartIndex: bounds.lowerBound)
return _nonNative[bounds].unsafeCastElements(to: Element.self)
}
set {
fatalError("not implemented")
@@ -392,7 +342,7 @@ extension _ArrayBuffer {
)
} else {
// ObjC arrays do their own subscript checking.
element = _nonNative.objectAt(i)
element = _nonNative[i]
precondition(
element is Element,
"""
@@ -460,7 +410,7 @@ extension _ArrayBuffer {
/// An object that keeps the elements stored in this buffer alive.
@inlinable
internal var owner: AnyObject {
return _fastPath(_isNative) ? _native._storage : _nonNative
return _fastPath(_isNative) ? _native._storage : _nonNative.buffer
}
/// An object that keeps the elements stored in this buffer alive.
@@ -481,7 +431,8 @@ extension _ArrayBuffer {
return _native.identity
}
else {
return UnsafeRawPointer(Unmanaged.passUnretained(_nonNative).toOpaque())
return UnsafeRawPointer(
Unmanaged.passUnretained(_nonNative.buffer).toOpaque())
}
}
@@ -550,11 +501,11 @@ extension _ArrayBuffer {
}
@inlinable
internal var _nonNative: _NSArrayCore {
internal var _nonNative: _CocoaArrayWrapper {
@inline(__always)
get {
_sanityCheck(_isClassOrObjCExistential(Element.self))
return _storage.objCInstance
return _CocoaArrayWrapper(_storage.objCInstance)
}
}
}

View File

@@ -21,29 +21,76 @@
#if _runtime(_ObjC)
import SwiftShims
/// A wrapper around any `_NSArrayCore` that gives it
/// `Collection` conformance. Why not make
/// `_NSArrayCore` conform directly? It's a class, and I
/// don't want to pay for the dynamic dispatch overhead.
/// A wrapper around any `_NSArrayCore` (represented as AnyObject) that gives it
/// `Collection` conformance. Why not make `_NSArrayCore` conform directly?
/// It's a class, and I don't want to pay for the dynamic dispatch overhead.
@usableFromInline
@_fixed_layout
internal struct _CocoaArrayWrapper : RandomAccessCollection {
@usableFromInline
typealias Indices = Range<Int>
@usableFromInline
internal var buffer: AnyObject
@usableFromInline @_transparent
internal init(_ buffer: AnyObject) {
self.buffer = buffer
}
internal var core: _NSArrayCore {
@inline(__always) get {
return unsafeBitCast(buffer, to: _NSArrayCore.self)
}
}
@inlinable
internal var startIndex: Int {
return 0
}
@inlinable
@usableFromInline
internal var endIndex: Int {
return buffer.count
return core.count
}
@inlinable
@usableFromInline
internal subscript(i: Int) -> AnyObject {
return buffer.objectAt(i)
return core.objectAt(i)
}
@usableFromInline
internal subscript(bounds: Range<Int>) -> _SliceBuffer<AnyObject> {
let boundsCount = bounds.count
if boundsCount == 0 {
return _SliceBuffer(
_buffer: _ContiguousArrayBuffer<AnyObject>(),
shiftedToStartIndex: bounds.lowerBound)
}
// Look for contiguous storage in the NSArray
let cocoaStorageBaseAddress = self.contiguousStorage(self.indices)
if let cocoaStorageBaseAddress = cocoaStorageBaseAddress {
return _SliceBuffer(
owner: self.buffer,
subscriptBaseAddress: cocoaStorageBaseAddress,
indices: bounds,
hasNativeBuffer: false)
}
// No contiguous storage found; we must allocate
let result = _ContiguousArrayBuffer<AnyObject>(
_uninitializedCount: boundsCount,
minimumCapacity: 0)
// Tell Cocoa to copy the objects into our storage
core.getObjects(
UnsafeMutableRawPointer(result.firstElementAddress)
.assumingMemoryBound(to: AnyObject.self),
range: _SwiftNSRange(location: bounds.lowerBound, length: boundsCount))
return _SliceBuffer(_buffer: result, shiftedToStartIndex: bounds.lowerBound)
}
/// Returns a pointer to the first element in the given non-empty `subRange`
@@ -56,7 +103,6 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
/// is sometimes conservative and may return `nil` even when
/// contiguous storage exists, e.g., if array doesn't have a smart
/// implementation of countByEnumerating.
@inlinable
internal func contiguousStorage(
_ subRange: Range<Int>
) -> UnsafeMutablePointer<AnyObject>?
@@ -69,7 +115,7 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
// acceptable conservative behavior, but could potentially be
// optimized for other cases.
let contiguousCount = withUnsafeMutablePointer(to: &enumerationState) {
self.buffer.countByEnumerating(with: $0, objects: nil, count: 0)
core.countByEnumerating(with: $0, objects: nil, count: 0)
}
return contiguousCount >= subRange.upperBound
@@ -79,12 +125,25 @@ internal struct _CocoaArrayWrapper : RandomAccessCollection {
: nil
}
@usableFromInline @_transparent
internal init(_ buffer: _NSArrayCore) {
self.buffer = buffer
}
@usableFromInline
internal var buffer: _NSArrayCore
__consuming internal func _copyContents(
subRange bounds: Range<Int>,
initializing target: UnsafeMutablePointer<AnyObject>
) -> UnsafeMutablePointer<AnyObject> {
let nsSubRange = SwiftShims._SwiftNSRange(
location: bounds.lowerBound,
length: bounds.upperBound - bounds.lowerBound)
// Copies the references out of the NSArray without retaining them
core.getObjects(target, range: nsSubRange)
// Make another pass to retain the copied objects
var result = target
for _ in bounds {
result.initialize(to: result.pointee)
result += 1
}
return result
}
}
#endif

View File

@@ -431,7 +431,7 @@ internal struct _ContiguousArrayBuffer<Element> : _ArrayBufferProtocol {
///
/// - Complexity: O(1).
@inlinable
internal __consuming func _asCocoaArray() -> _NSArrayCore {
internal __consuming func _asCocoaArray() -> AnyObject {
if count == 0 {
return _emptyArrayStorage
}

View File

@@ -58,8 +58,7 @@ public protocol _NSCopying : _ShadowProtocol {
/// Covers a set of operations everyone needs to implement in order to
/// be a useful `NSArray` subclass.
@unsafe_no_objc_tagged_pointer @objc
public protocol _NSArrayCore :
_NSCopying, _NSFastEnumeration {
internal protocol _NSArrayCore: _NSCopying, _NSFastEnumeration {
@objc(objectAtIndex:)
func objectAt(_ index: Int) -> AnyObject
@@ -185,8 +184,4 @@ internal protocol _NSNumber {
var objCType: UnsafePointer<Int8> { get }
}
#else
public protocol _NSArrayCore {}
#endif

View File

@@ -64,7 +64,7 @@ bb0(%0 : $TrivialDestructor):
store %0 to %10 : $*TrivialDestructor
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
strong_retain %0 : $TrivialDestructor
strong_release %15 : $Builtin.BridgeObject
// CHECK-NEXT: tuple ()
@@ -91,7 +91,7 @@ bb0(%0 : $TrivialDestructor):
%7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*TrivialDestructor
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
strong_retain %0 : $TrivialDestructor
strong_release %15 : $Builtin.BridgeObject
@@ -121,7 +121,7 @@ bb0(%0 : $TrivialDestructor):
%6 = tuple_extract %4 : $(Array<TrivialDestructor>, Builtin.RawPointer), 1
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
cond_br undef, bb1, bb2
bb1:
@@ -159,7 +159,7 @@ bb1:
%5 = tuple_extract %4 : $(Array<TrivialDestructor>, Builtin.RawPointer), 0
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
strong_release %15 : $Builtin.BridgeObject
%18 = tuple ()
return %18 : $()
@@ -190,7 +190,7 @@ bb0(%0 : $TrivialDestructor):
%12 = tuple_extract %4 : $(Array<TrivialDestructor>, Builtin.RawPointer), 0
%13 = struct_extract %12 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
strong_release %15 : $Builtin.BridgeObject
return %22 : $TrivialDestructor
@@ -217,7 +217,7 @@ bb0(%0 : $TrivialDestructor, %1 : $TrivialDestructor):
%7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*TrivialDestructor
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
cond_br undef, bb1, bb2
bb1:
@@ -260,7 +260,7 @@ bb1:
%7 = pointer_to_address %6 : $Builtin.RawPointer to [strict] $*TrivialDestructor
%13 = struct_extract %5 : $Array<TrivialDestructor>, #Array._buffer
%14 = struct_extract %13 : $_ArrayBuffer<TrivialDestructor>, #_ArrayBuffer._storage
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%15 = struct_extract %14 : $_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
strong_retain %0 : $TrivialDestructor
store %0 to %7 : $*TrivialDestructor
strong_release %15 : $Builtin.BridgeObject

View File

@@ -55,7 +55,7 @@ bb0:
%1 = struct_element_addr %0 : $*ReversedCollection<Array<Int>>, #ReversedCollection._base
%2 = struct_element_addr %1 : $*Array<Int>, #Array._buffer
%3 = struct_element_addr %2 : $*_ArrayBuffer<Int>, #_ArrayBuffer._storage
%4 = struct_element_addr %3 : $*_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%4 = struct_element_addr %3 : $*_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
%5 = load %4 : $*Builtin.BridgeObject
%6 = unchecked_ref_cast %5 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%7 = ref_element_addr %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity
@@ -140,7 +140,7 @@ bb0:
%1 = struct_element_addr %0 : $*ReversedCollection<Array<Int>>, #ReversedCollection._base
%2 = struct_element_addr %1 : $*Array<Int>, #Array._buffer
%3 = struct_element_addr %2 : $*_ArrayBuffer<Int>, #_ArrayBuffer._storage
%4 = struct_element_addr %3 : $*_BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore>, #_BridgeStorage.rawValue
%4 = struct_element_addr %3 : $*_BridgeStorage<__ContiguousArrayStorageBase, AnyObject>, #_BridgeStorage.rawValue
%5 = load %4 : $*Builtin.BridgeObject
%6 = unchecked_ref_cast %5 : $Builtin.BridgeObject to $__ContiguousArrayStorageBase
%7 = ref_element_addr %6 : $__ContiguousArrayStorageBase, #__ContiguousArrayStorageBase.countAndCapacity

View File

@@ -305,3 +305,25 @@ Var Set._Variant.object has declared type change from _BridgeStorage<_RawSetStor
Var _CocoaSet.object has declared type change from _NSSet to AnyObject
Protocol _NSNumber has been removed
Class _ContiguousArrayStorage has removed conformance to _NSArrayCore
Class __ContiguousArrayStorageBase has removed conformance to _NSArrayCore
Class __EmptyArrayStorage has removed conformance to _NSArrayCore
Class __SwiftDeferredNSArray has removed conformance to _NSArrayCore
Class __SwiftNativeNSArrayWithContiguousStorage has removed conformance to _NSArrayCore
Constructor Array.init(_immutableCocoaArray:) has parameter 0 type change from _NSArrayCore to AnyObject
Constructor _ArrayBuffer.init(nsArray:) has parameter 0 type change from _NSArrayCore to AnyObject
Constructor _ArrayBuffer.init(storage:) has parameter 0 type change from _BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore> to _BridgeStorage<__ContiguousArrayStorageBase, AnyObject>
Constructor _CocoaArrayWrapper.init(_:) has parameter 0 type change from _NSArrayCore to AnyObject
Func _ArrayBuffer._asCocoaArray() has return type change from _NSArrayCore to AnyObject
Func _CocoaArrayWrapper.contiguousStorage(_:) has been removed
Func _ContiguousArrayBuffer._asCocoaArray() has return type change from _NSArrayCore to AnyObject
Func _bridgeCocoaArray(_:) has parameter 0 type change from _NSArrayCore to AnyObject
Protocol _NSArrayCore has been removed
Struct _CocoaArrayWrapper has type witness type for BidirectionalCollection.SubSequence changing from Slice<_CocoaArrayWrapper> to _SliceBuffer<AnyObject>
Struct _CocoaArrayWrapper has type witness type for Collection.SubSequence changing from Slice<_CocoaArrayWrapper> to _SliceBuffer<AnyObject>
Struct _CocoaArrayWrapper has type witness type for RandomAccessCollection.SubSequence changing from Slice<_CocoaArrayWrapper> to _SliceBuffer<AnyObject>
Struct _CocoaArrayWrapper has type witness type for Sequence.SubSequence changing from Slice<_CocoaArrayWrapper> to _SliceBuffer<AnyObject>
Var _ArrayBuffer._nonNative has declared type change from _NSArrayCore to _CocoaArrayWrapper
Var _ArrayBuffer._storage has declared type change from _BridgeStorage<__ContiguousArrayStorageBase, _NSArrayCore> to _BridgeStorage<__ContiguousArrayStorageBase, AnyObject>
Var _CocoaArrayWrapper.buffer has declared type change from _NSArrayCore to AnyObject