/
BridgeStorage.swift
151 lines (132 loc) · 4.42 KB
/
BridgeStorage.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//===--- BridgeStorage.swift - Discriminated storage for bridged types ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Types that are bridged to Objective-C need to manage an object
// that may be either some native class or the @objc Cocoa
// equivalent. _BridgeStorage discriminates between these two
// possibilities and stores a few extra bits when the stored type is
// native. It is assumed that the @objc class instance may in fact
// be a tagged pointer, and thus no extra bits may be available.
//
//===----------------------------------------------------------------------===//
import SwiftShims
public // @testable
struct _BridgeStorage<
NativeClass: AnyObject, ObjCClass: AnyObject
> {
public // @testable
typealias Native = NativeClass
public // @testable
typealias ObjC = ObjCClass
@inline(__always)
public // @testable
init(native: Native, bits: Int) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
// More bits are available on some platforms, but it's not portable
_sanityCheck(0..<3 ~= bits,
"BridgeStorage can't store bits outside the range 0..<3")
rawValue = _makeNativeBridgeObject(
native, UInt(bits) << _objectPointerLowSpareBitShift)
}
@inline(__always)
public // @testable
init(objC: ObjC) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = _makeObjCBridgeObject(objC)
}
@inline(__always)
public // @testable
init(native: Native) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = Builtin.reinterpretCast(native)
}
public // @testable
var spareBits: Int {
@inline(__always) get {
_sanityCheck(isNative)
return Int(
_nonPointerBits(rawValue) >> _objectPointerLowSpareBitShift)
}
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedNative() -> Bool {
return _swift_isUniquelyReferencedNonObjC_nonNull_bridgeObject(
_bitPattern(rawValue)
)
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedOrPinnedNative() -> Bool {
return _swift_isUniquelyReferencedOrPinnedNonObjC_nonNull_bridgeObject(
_bitPattern(rawValue)
)
}
public // @testable
var isNative: Bool {
@inline(__always) get {
return !_isTagged && _nonPointerBits(rawValue) != _objectPointerSpareBits
}
}
public // @testable
var isObjC: Bool {
@inline(__always) get {
return _isTagged || _nonPointerBits(rawValue) == _objectPointerSpareBits
}
}
public // @testable
var nativeInstance: Native {
@inline(__always) get {
_sanityCheck(isNative)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}
public // @testable
var nativeInstance_noSpareBits: Native {
@inline(__always) get {
_sanityCheck(isNative)
_sanityCheck(_nonPointerBits(rawValue) == 0)
return Builtin.reinterpretCast(rawValue)
}
}
@inline(__always)
public // @testable
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool {
_sanityCheck(isNative)
_sanityCheck(_nonPointerBits(rawValue) == 0)
let p: UnsafePointer<HeapObject> = Builtin.reinterpretCast(rawValue)
return _swift_isUniquelyReferenced_nonNull_native(p)
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedOrPinned_native_noSpareBits() -> Bool {
_sanityCheck(isNative)
_sanityCheck(_nonPointerBits(rawValue) == 0)
let p: UnsafePointer<HeapObject> = Builtin.reinterpretCast(rawValue)
return _swift_isUniquelyReferencedOrPinned_nonNull_native(p)
}
public // @testable
var objCInstance: ObjC {
@inline(__always) get {
_sanityCheck(isObjC)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}
//===--- private --------------------------------------------------------===//
internal var _isTagged: Bool {
@inline(__always) get {
return _isObjCTaggedPointer(
Builtin.castReferenceFromBridgeObject(rawValue))
}
}
internal let rawValue: Builtin.BridgeObject
}