Skip to content

Commit 123b067

Browse files
author
Itai Ferber
committed
Refine inlinability of LargeSlice and RangeReference
1 parent 03dd2a3 commit 123b067

File tree

1 file changed

+53
-39
lines changed

1 file changed

+53
-39
lines changed

stdlib/public/Darwin/Foundation/Data.swift

Lines changed: 53 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,70 +1029,78 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
10291029
}
10301030
}
10311031

1032+
// A reference wrapper around a Range<Int> for when the range of a data buffer is too large to whole in a single word.
1033+
// Inlinability strategy: everything should be inlinable as trivial.
10321034
@usableFromInline
10331035
@_fixed_layout
10341036
internal final class RangeReference {
1035-
@usableFromInline
1036-
var range: Range<Int>
1037+
@usableFromInline var range: Range<Int>
10371038

1038-
@inlinable
1039-
var lowerBound: Int { return range.lowerBound }
1039+
@inlinable @inline(__always) // This is @inlinable as trivially forwarding.
1040+
var lowerBound: Int {
1041+
return range.lowerBound
1042+
}
10401043

1041-
@inlinable
1042-
var upperBound: Int { return range.upperBound }
1044+
@inlinable @inline(__always) // This is @inlinable as trivially forwarding.
1045+
var upperBound: Int {
1046+
return range.upperBound
1047+
}
10431048

1044-
@inlinable
1045-
var count: Int { return range.upperBound - range.lowerBound }
1049+
@inlinable @inline(__always) // This is @inlinable as trivially computable.
1050+
var count: Int {
1051+
return range.upperBound - range.lowerBound
1052+
}
10461053

1047-
@inlinable
1054+
@inlinable @inline(__always) // This is @inlinable as a trivial initializer.
10481055
init(_ range: Range<Int>) {
10491056
self.range = range
10501057
}
10511058
}
10521059

1060+
// A buffer of bytes whose range is too large to fit in a signle word. Used alongside a RangeReference to make it fit into _Representation's two-word size.
1061+
// Inlinability strategy: everything here should be easily inlinable as large _DataStorage methods should not inline into here.
10531062
@usableFromInline
10541063
@_fixed_layout
10551064
internal struct LargeSlice {
10561065
// ***WARNING***
10571066
// These ivars are specifically laid out so that they cause the enum _Representation to be 16 bytes on 64 bit platforms. This means we _MUST_ have the class type thing last
1058-
@usableFromInline
1059-
var slice: RangeReference
1060-
@usableFromInline
1061-
var storage: _DataStorage
1067+
@usableFromInline var slice: RangeReference
1068+
@usableFromInline var storage: _DataStorage
10621069

1063-
@inlinable
1070+
@inlinable // This is @inlinable as a convenience initializer.
10641071
init(_ buffer: UnsafeRawBufferPointer) {
10651072
self.init(_DataStorage(bytes: buffer.baseAddress, length: buffer.count), count: buffer.count)
10661073
}
10671074

1068-
@inlinable
1075+
@inlinable // This is @inlinable as a convenience initializer.
10691076
init(capacity: Int) {
10701077
self.init(_DataStorage(capacity: capacity), count: 0)
10711078
}
10721079

1073-
@inlinable
1080+
@inlinable // This is @inlinable as a convenience initializer.
10741081
init(count: Int) {
10751082
self.init(_DataStorage(length: count), count: count)
10761083
}
10771084

1078-
@inlinable
1085+
@inlinable // This is @inlinable as a convenience initializer.
10791086
init(_ inline: InlineData) {
1080-
self.init(inline.withUnsafeBytes { return _DataStorage(bytes: $0.baseAddress, length: $0.count) }, count: inline.count)
1087+
let storage = inline.withUnsafeBytes { return _DataStorage(bytes: $0.baseAddress, length: $0.count) }
1088+
self.init(storage, count: inline.count)
10811089
}
10821090

1083-
@inlinable
1091+
@inlinable // This is @inlinable as a trivial initializer.
10841092
init(_ slice: InlineSlice) {
10851093
self.storage = slice.storage
10861094
self.slice = RangeReference(slice.range)
10871095
}
10881096

1089-
@inlinable
1097+
@inlinable // This is @inlinable as a trivial initializer.
10901098
init(_ storage: _DataStorage, count: Int) {
10911099
self.storage = storage
1092-
slice = RangeReference(0..<count)
1100+
self.slice = RangeReference(0..<count)
10931101
}
10941102

1095-
@inlinable
1103+
@inlinable // This is @inlinable as trivially computable (and inlining may help avoid retain-release traffic).
10961104
mutating func ensureUniqueReference() {
10971105
if !isKnownUniquelyReferenced(&storage) {
10981106
storage = storage.mutableCopy(range)
@@ -1102,25 +1110,29 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11021110
}
11031111
}
11041112

1105-
@inlinable
1106-
var startIndex: Int { return slice.range.lowerBound }
1113+
@inlinable // This is @inlinable as trivially forwarding.
1114+
var startIndex: Int {
1115+
return slice.range.lowerBound
1116+
}
11071117

1108-
@inlinable
1109-
var endIndex: Int { return slice.range.upperBound }
1118+
@inlinable // This is @inlinable as trivially forwarding.
1119+
var endIndex: Int {
1120+
return slice.range.upperBound
1121+
}
11101122

1111-
@inlinable
1123+
@inlinable // This is @inlinable as trivially forwarding.
11121124
var capacity: Int {
11131125
return storage.capacity
11141126
}
11151127

1116-
@inlinable
1128+
@inlinable // This is @inlinable as trivially computable.
11171129
mutating func reserveCapacity(_ minimumCapacity: Int) {
11181130
ensureUniqueReference()
11191131
// the current capacity can be zero (representing externally owned buffer), and count can be greater than the capacity
11201132
storage.ensureUniqueBufferReference(growingTo: Swift.max(minimumCapacity, count))
11211133
}
11221134

1123-
@inlinable
1135+
@inlinable // This is @inlinable as trivially computable.
11241136
var count: Int {
11251137
get {
11261138
return slice.count
@@ -1132,28 +1144,30 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11321144
}
11331145
}
11341146

1135-
@inlinable
1136-
var range: Range<Int> { return slice.range }
1147+
@inlinable // This is @inlinable as it is trivially forwarding.
1148+
var range: Range<Int> {
1149+
return slice.range
1150+
}
11371151

1138-
@inlinable
1152+
@inlinable // This is @inlinable as a generic, trivially forwarding function.
11391153
func withUnsafeBytes<Result>(_ apply: (UnsafeRawBufferPointer) throws -> Result) rethrows -> Result {
11401154
return try storage.withUnsafeBytes(in: range, apply: apply)
11411155
}
11421156

1143-
@inlinable
1157+
@inlinable // This is @inlinable as a generic, trivially forwarding function.
11441158
mutating func withUnsafeMutableBytes<Result>(_ apply: (UnsafeMutableRawBufferPointer) throws -> Result) rethrows -> Result {
11451159
ensureUniqueReference()
11461160
return try storage.withUnsafeMutableBytes(in: range, apply: apply)
11471161
}
11481162

1149-
@inlinable
1163+
@inlinable // This is @inlinable as reasonably small.
11501164
mutating func append(contentsOf buffer: UnsafeRawBufferPointer) {
11511165
ensureUniqueReference()
11521166
storage.replaceBytes(in: NSRange(location: range.upperBound, length: storage.length - (range.upperBound - storage._offset)), with: buffer.baseAddress, length: buffer.count)
11531167
slice.range = slice.range.lowerBound..<slice.range.upperBound + buffer.count
11541168
}
11551169

1156-
@inlinable
1170+
@inlinable // This is @inlinable as trivially computable.
11571171
subscript(index: Index) -> UInt8 {
11581172
get {
11591173
precondition(startIndex <= index, "index \(index) is out of bounds of \(startIndex)..<\(endIndex)")
@@ -1168,12 +1182,12 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11681182
}
11691183
}
11701184

1171-
@inlinable
1185+
@inlinable // This is @inlinable as trivially forwarding.
11721186
func bridgedReference() -> NSData {
11731187
return storage.bridgedReference(self.range)
11741188
}
11751189

1176-
@inlinable
1190+
@inlinable // This is @inlinable as reasonably small.
11771191
mutating func resetBytes(in range: Range<Int>) {
11781192
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
11791193
ensureUniqueReference()
@@ -1183,7 +1197,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11831197
}
11841198
}
11851199

1186-
@inlinable
1200+
@inlinable // This is @inlinable as reasonably small.
11871201
mutating func replaceSubrange(_ subrange: Range<Index>, with bytes: UnsafeRawPointer?, count cnt: Int) {
11881202
precondition(startIndex <= subrange.lowerBound, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
11891203
precondition(subrange.lowerBound <= endIndex, "index \(subrange.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
@@ -1198,7 +1212,7 @@ public struct Data : ReferenceConvertible, Equatable, Hashable, RandomAccessColl
11981212
slice.range = slice.range.lowerBound..<resultingUpper
11991213
}
12001214

1201-
@inlinable
1215+
@inlinable // This is @inlinable as reasonably small.
12021216
func copyBytes(to pointer: UnsafeMutableRawPointer, from range: Range<Int>) {
12031217
precondition(startIndex <= range.lowerBound, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")
12041218
precondition(range.lowerBound <= endIndex, "index \(range.lowerBound) is out of bounds of \(startIndex)..<\(endIndex)")

0 commit comments

Comments
 (0)