Skip to content

[stdlib] ABI audit for _BridgeStorage #20159

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Oct 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions stdlib/public/core/ArrayBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ internal struct _ArrayBuffer<Element> : _ArrayBufferProtocol {
return _ArrayBuffer<U>(storage: _storage)
}

/// The spare bits that are set when a native array needs deferred
/// element type checking.
@inlinable
internal var deferredTypeCheckMask: Int { return 1 }

/// Returns an `_ArrayBuffer<U>` containing the same elements,
/// deferring checking each element's `U`-ness until it is accessed.
///
Expand All @@ -71,8 +66,7 @@ internal struct _ArrayBuffer<Element> : _ArrayBufferProtocol {
// _sanityCheck(U.self is Element.Type)

return _ArrayBuffer<U>(
storage: _ArrayBridgeStorage(
native: _native._storage, bits: deferredTypeCheckMask))
storage: _ArrayBridgeStorage(native: _native._storage, isFlagged: true))
}

@inlinable
Expand Down Expand Up @@ -109,7 +103,7 @@ extension _ArrayBuffer {
@inlinable
internal mutating func isUniquelyReferenced() -> Bool {
if !_isClassOrObjCExistential(Element.self) {
return _storage.isUniquelyReferenced_native_noSpareBits()
return _storage.isUniquelyReferencedUnflaggedNative()
}

// This is a performance optimization. This code used to be:
Expand Down Expand Up @@ -532,7 +526,7 @@ extension _ArrayBuffer {
if !_isClassOrObjCExistential(Element.self) {
return true
} else {
return _storage.isNativeWithClearedSpareBits(deferredTypeCheckMask)
return _storage.isUnflaggedNative
}
}

Expand All @@ -543,15 +537,15 @@ extension _ArrayBuffer {
internal var _native: NativeBuffer {
return NativeBuffer(
_isClassOrObjCExistential(Element.self)
? _storage.nativeInstance : _storage.nativeInstance_noSpareBits)
? _storage.nativeInstance : _storage.unflaggedNativeInstance)
}

/// Fast access to the native representation.
///
/// - Precondition: `_isNativeTypeChecked`.
@inlinable
internal var _nativeTypeChecked: NativeBuffer {
return NativeBuffer(_storage.nativeInstance_noSpareBits)
return NativeBuffer(_storage.unflaggedNativeInstance)
}

@inlinable
Expand Down
141 changes: 60 additions & 81 deletions stdlib/public/core/BridgeStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,45 @@
import SwiftShims

@_fixed_layout
public // @testable
struct _BridgeStorage<
NativeClass: AnyObject, ObjCClass: AnyObject
@usableFromInline
internal struct _BridgeStorage<
NativeClass: AnyObject,
ObjCClass: AnyObject
> {
public // @testable
typealias Native = NativeClass

public // @testable
typealias ObjC = ObjCClass

@inlinable // FIXME(sil-serialize-all)
@usableFromInline
internal typealias Native = NativeClass

@usableFromInline
internal typealias ObjC = ObjCClass

// rawValue is passed inout to _isUnique. Although its value
// is unchanged, it must appear mutable to the optimizer.
@usableFromInline
internal var rawValue: Builtin.BridgeObject

@inlinable
@inline(__always)
public // @testable
init(native: Native, bits: Int) {
internal init(native: Native, isFlagged flag: Bool) {
// Note: Some platforms provide more than one spare bit, but the minimum is
// a single bit.

_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))

// More bits are available on some platforms, but it's not portable
_sanityCheck(0...1 ~= bits,
"BridgeStorage can't store bits outside the range 0...1")

rawValue = _makeNativeBridgeObject(
native, UInt(bits) << _objectPointerLowSpareBitShift)
native,
flag ? (1 as UInt) << _objectPointerLowSpareBitShift : 0)
}
@inlinable // FIXME(sil-serialize-all)

@inlinable
@inline(__always)
public // @testable
init(objC: ObjC) {
internal init(objC: ObjC) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = _makeObjCBridgeObject(objC)
}
@inlinable // FIXME(sil-serialize-all)

@inlinable
@inline(__always)
public // @testable
init(native: Native) {
internal init(native: Native) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = Builtin.reinterpretCast(native)
}
Expand All @@ -69,97 +72,73 @@ struct _BridgeStorage<
}
#endif

@inlinable // FIXME(sil-serialize-all)
public // @testable
var spareBits: Int {
@inline(__always) get {
_sanityCheck(isNative)
return Int(
_nonPointerBits(rawValue) >> _objectPointerLowSpareBitShift)
}
}

@inlinable // FIXME(sil-serialize-all)
@inlinable
@inline(__always)
public // @testable
mutating func isUniquelyReferencedNative() -> Bool {
internal mutating func isUniquelyReferencedNative() -> Bool {
return _isUnique(&rawValue)
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
var isNative: Bool {
@inlinable
internal var isNative: Bool {
@inline(__always) get {
let result = Builtin.classifyBridgeObject(rawValue)
return !Bool(Builtin.or_Int1(result.isObjCObject,
result.isObjCTaggedPointer))
}
}

@inlinable // FIXME(sil-serialize-all)
@inline(__always)
public // @testable
func isNativeWithClearedSpareBits(_ bits: Int) -> Bool {
return (_bitPattern(rawValue) &
(_bridgeObjectTaggedPointerBits | _objCTaggedPointerBits |
_objectPointerIsObjCBit |
(UInt(bits)) << _objectPointerLowSpareBitShift)) == 0

@inlinable
static var flagMask: UInt {
@inline(__always) get {
return (1 as UInt) << _objectPointerLowSpareBitShift
}
}

@inlinable
internal var isUnflaggedNative: Bool {
@inline(__always) get {
return (_bitPattern(rawValue) &
(_bridgeObjectTaggedPointerBits | _objCTaggedPointerBits |
_objectPointerIsObjCBit | _BridgeStorage.flagMask)) == 0
}
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
var isObjC: Bool {
@inlinable
internal var isObjC: Bool {
@inline(__always) get {
return !isNative
}
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
var nativeInstance: Native {

@inlinable
internal var nativeInstance: Native {
@inline(__always) get {
_sanityCheck(isNative)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
var nativeInstance_noSpareBits: Native {

@inlinable
internal var unflaggedNativeInstance: Native {
@inline(__always) get {
_sanityCheck(isNative)
_sanityCheck(_nonPointerBits(rawValue) == 0)
return Builtin.reinterpretCast(rawValue)
}
}
@inlinable // FIXME(sil-serialize-all)

@inlinable
@inline(__always)
public // @testable
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool {
internal mutating func isUniquelyReferencedUnflaggedNative() -> Bool {
_sanityCheck(isNative)
return _isUnique_native(&rawValue)
}

@inlinable // FIXME(sil-serialize-all)
public // @testable
var objCInstance: ObjC {
@inlinable
internal var objCInstance: ObjC {
@inline(__always) get {
_sanityCheck(isObjC)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}

//===--- private --------------------------------------------------------===//
@inlinable // FIXME(sil-serialize-all)
internal var _isTagged: Bool {
@inline(__always) get {
return Bool(Builtin.classifyBridgeObject(rawValue).isObjCTaggedPointer)
}
}

// rawValue is passed inout to _isUnique. Although its value
// is unchanged, it must appear mutable to the optimizer.
@usableFromInline
internal var rawValue: Builtin.BridgeObject
}
9 changes: 4 additions & 5 deletions stdlib/public/core/DictionaryVariant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,27 @@ extension Dictionary._Variant {

@inlinable
internal mutating func isUniquelyReferenced() -> Bool {
return object.isUniquelyReferenced_native_noSpareBits()
return object.isUniquelyReferencedUnflaggedNative()
}

#if _runtime(_ObjC)
@usableFromInline @_transparent
internal var isNative: Bool {
if guaranteedNative { return true }
return object.isNativeWithClearedSpareBits(0)
return object.isUnflaggedNative
}
#endif

@usableFromInline @_transparent
internal var asNative: _NativeDictionary<Key, Value> {
get {
return _NativeDictionary<Key, Value>(object.nativeInstance_noSpareBits)
return _NativeDictionary<Key, Value>(object.unflaggedNativeInstance)
}
set {
self = .init(native: newValue)
}
_modify {
var native = _NativeDictionary<Key, Value>(
object.nativeInstance_noSpareBits)
var native = _NativeDictionary<Key, Value>(object.unflaggedNativeInstance)
self = .init(dummy: ())
yield &native
object = .init(native: native._storage)
Expand Down
8 changes: 4 additions & 4 deletions stdlib/public/core/SetVariant.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,27 @@ extension Set._Variant {

@inlinable
internal mutating func isUniquelyReferenced() -> Bool {
return object.isUniquelyReferenced_native_noSpareBits()
return object.isUniquelyReferencedUnflaggedNative()
}

#if _runtime(_ObjC)
@usableFromInline @_transparent
internal var isNative: Bool {
if guaranteedNative { return true }
return object.isNativeWithClearedSpareBits(0)
return object.isUnflaggedNative
}
#endif

@usableFromInline @_transparent
internal var asNative: _NativeSet<Element> {
get {
return _NativeSet(object.nativeInstance_noSpareBits)
return _NativeSet(object.unflaggedNativeInstance)
}
set {
self = .init(native: newValue)
}
_modify {
var native = _NativeSet<Element>(object.nativeInstance_noSpareBits)
var native = _NativeSet<Element>(object.unflaggedNativeInstance)
self = .init(dummy: ())
yield &native
object = .init(native: native._storage)
Expand Down
7 changes: 7 additions & 0 deletions test/api-digester/Outputs/stability-stdlib-abi.swift.expected
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ Constructor AnyHashable.init(_box:) has been removed
Constructor AnyHashable.init(_usingDefaultRepresentationOf:) has been removed
Constructor ManagedBufferPointer.init(_:_:_:) has been removed
Constructor Zip2Sequence.init(_sequence1:_sequence2:) has been removed
Constructor _BridgeStorage.init(native:bits:) has been removed
Constructor _BridgeableMetatype.init(value:) has been removed
Func AnyHashable._downCastConditional(into:) has been removed
Func _BridgeStorage.isNativeWithClearedSpareBits(_:) has been removed
Func _BridgeStorage.isUniquelyReferenced_native_noSpareBits() has been removed
Func _CocoaDictionary.Index.copy() has been removed
Func _ContiguousArrayStorage._getNonVerbatimBridgedHeapBuffer() has been removed
Func _ContiguousArrayStorage._withVerbatimBridgedUnsafeBufferImpl(_:) has been removed
Expand All @@ -28,6 +31,10 @@ Var ManagedBufferPointer.baseAddress has been removed
Var ManagedBufferPointer.storage has been removed
Var ManagedBufferPointer.value has been removed
Var Optional._nilSentinel has been removed
Var _ArrayBuffer.deferredTypeCheckMask has been removed
Var _BridgeStorage._isTagged has been removed
Var _BridgeStorage.nativeInstance_noSpareBits has been removed
Var _BridgeStorage.spareBits has been removed
Var _BridgeableMetatype.value has been removed
Var _CocoaDictionary.Index._object has been removed
Var _CocoaSet.Index._object has been removed
Expand Down
Loading