Skip to content

Commit 9a3edfd

Browse files
committed
Switch to an Unowned View of Bitstream Record Data
Now that we no longer have any entrypoints that can escape this data, switch to a non-owning view of bitstream data. This saves a significant amount of copying overhead when deserializing many/large bitstream files and allows callers to decide for themselves what format they wish to reinterpret the data as.
1 parent 7ad699c commit 9a3edfd

File tree

2 files changed

+18
-12
lines changed

2 files changed

+18
-12
lines changed

Sources/TSCUtility/Bitstream.swift

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,28 @@ public struct Bitcode {
1818
public let blockInfo: [UInt64: BlockInfo]
1919
}
2020

21+
/// A non-owning view of a bitcode element.
2122
public enum BitcodeElement {
2223
public struct Block {
2324
public var id: UInt64
2425
public var elements: [BitcodeElement]
2526
}
2627

28+
/// A record element.
29+
///
30+
/// - Warning: A `Record` element's fields and payload only live as long as
31+
/// the `visit` function that provides them is called. To persist
32+
/// a record, always make a copy of it.
2733
public struct Record {
2834
public enum Payload {
2935
case none
3036
case array([UInt64])
3137
case char6String(String)
32-
case blob(Data)
38+
case blob(ArraySlice<UInt8>)
3339
}
3440

3541
public var id: UInt64
36-
public var fields: [UInt64]
42+
public var fields: UnsafeBufferPointer<UInt64>
3743
public var payload: Payload
3844
}
3945

Sources/TSCUtility/SerializedDiagnostics.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ extension SerializedDiagnostics {
9898
case .blob(let diagnosticBlob) = record.payload
9999
else { throw Error.malformedRecord }
100100

101-
text = String(data: diagnosticBlob, encoding: .utf8)
101+
text = String(decoding: diagnosticBlob, as: UTF8.self)
102102
level = Level(rawValue: record.fields[0])
103103
location = SourceLocation(fields: record.fields[1...4],
104104
filenameMap: filenameMap)
@@ -116,38 +116,38 @@ extension SerializedDiagnostics {
116116
}
117117
case .flag:
118118
guard record.fields.count == 2,
119-
case .blob(let flagBlob) = record.payload,
120-
let flagText = String(data: flagBlob, encoding: .utf8)
119+
case .blob(let flagBlob) = record.payload
121120
else { throw Error.malformedRecord }
122121

122+
let flagText = String(decoding: flagBlob, as: UTF8.self)
123123
let diagnosticID = record.fields[0]
124124
flagMap[diagnosticID] = flagText
125125

126126
case .category:
127127
guard record.fields.count == 2,
128-
case .blob(let categoryBlob) = record.payload,
129-
let categoryText = String(data: categoryBlob, encoding: .utf8)
128+
case .blob(let categoryBlob) = record.payload
130129
else { throw Error.malformedRecord }
131130

131+
let categoryText = String(decoding: categoryBlob, as: UTF8.self)
132132
let categoryID = record.fields[0]
133133
categoryMap[categoryID] = categoryText
134134

135135
case .filename:
136136
guard record.fields.count == 4,
137-
case .blob(let filenameBlob) = record.payload,
138-
let filenameText = String(data: filenameBlob, encoding: .utf8)
137+
case .blob(let filenameBlob) = record.payload
139138
else { throw Error.malformedRecord }
140139

140+
let filenameText = String(decoding: filenameBlob, as: UTF8.self)
141141
let filenameID = record.fields[0]
142142
// record.fields[1] and record.fields[2] are no longer used.
143143
filenameMap[filenameID] = filenameText
144144

145145
case .fixit:
146146
guard record.fields.count == 9,
147-
case .blob(let fixItBlob) = record.payload,
148-
let fixItText = String(data: fixItBlob, encoding: .utf8)
147+
case .blob(let fixItBlob) = record.payload
149148
else { throw Error.malformedRecord }
150149

150+
let fixItText = String(decoding: fixItBlob, as: UTF8.self)
151151
if let start = SourceLocation(fields: record.fields[0...3],
152152
filenameMap: filenameMap),
153153
let end = SourceLocation(fields: record.fields[4...7],
@@ -184,7 +184,7 @@ extension SerializedDiagnostics {
184184
/// Clang includes this, it is set to 0 by Swift.
185185
public var offset: UInt64
186186

187-
fileprivate init?(fields: ArraySlice<UInt64>,
187+
fileprivate init?(fields: Slice<UnsafeBufferPointer<UInt64>>,
188188
filenameMap: [UInt64: String]) {
189189
guard let filename = filenameMap[fields[fields.startIndex]] else { return nil }
190190
self.filename = filename

0 commit comments

Comments
 (0)