Skip to content

Commit 1d78444

Browse files
committed
[Perf] Improve the performance of custom buffers
`Array.append(contentsOf:)` requires `Sequence._copyContents` to optimze it to `memcpy`.
1 parent 0386d87 commit 1d78444

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

Sources/SwiftSyntax/SyntaxArenaAllocatedBuffer.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
/// reference its contents, we know that the pointer's contents won't get
1818
/// deallocated while being accessed and thus we can add an unchecked `Sendable`
1919
/// conformance.
20-
@_spi(RawSyntax) public struct SyntaxArenaAllocatedPointer<Element: Sendable>: @unchecked Sendable {
20+
@_spi(RawSyntax)
21+
public struct SyntaxArenaAllocatedPointer<Element: Sendable>: @unchecked Sendable {
2122
private let pointer: UnsafePointer<Element>
2223

2324
/// Create a pointer from an `UnsafePointer` that was allocated inside a
@@ -61,22 +62,21 @@ public struct SyntaxArenaAllocatedBufferPointer<Element: Sendable>: RandomAccess
6162
/// - Important: The client needs to ensure sure that the buffer is indeed
6263
/// allocated by a ``SyntaxArena`` and that the ``SyntaxArena`` will outlive
6364
/// any users of this ``SyntaxArenaAllocatedBufferPointer``.
64-
@_spi(RawSyntax) public init(_ buffer: UnsafeBufferPointer<Element>) {
65+
public init(_ buffer: UnsafeBufferPointer<Element>) {
6566
self.buffer = buffer
6667
}
6768

68-
@_spi(RawSyntax)
6969
public subscript<RangeType: RangeExpression<Int>>(
7070
range: RangeType
7171
) -> SyntaxArenaAllocatedBufferPointer<Element> {
7272
return SyntaxArenaAllocatedBufferPointer(UnsafeBufferPointer(rebasing: self.buffer[range]))
7373
}
7474

75-
@_spi(RawSyntax) public subscript(_ index: Int) -> Element {
75+
public subscript(_ index: Int) -> Element {
7676
return self.buffer[index]
7777
}
7878

79-
@_spi(RawSyntax) public func makeIterator() -> UnsafeBufferPointer<Element>.Iterator {
79+
public func makeIterator() -> UnsafeBufferPointer<Element>.Iterator {
8080
return buffer.makeIterator()
8181
}
8282

@@ -111,4 +111,8 @@ public struct SyntaxArenaAllocatedBufferPointer<Element: Sendable>: RandomAccess
111111
public func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R? {
112112
try body(buffer)
113113
}
114+
115+
public func _copyContents(initializing ptr: UnsafeMutableBufferPointer<Element>) -> (Iterator, Int) {
116+
buffer._copyContents(initializing: ptr)
117+
}
114118
}

Sources/SwiftSyntax/SyntaxText.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@ import Musl
4747
/// replacement character (`\u{FFFD}`).
4848
@_spi(RawSyntax)
4949
public struct SyntaxText: Sendable {
50-
var buffer: SyntaxArenaAllocatedBufferPointer<UInt8>
50+
public typealias Buffer = SyntaxArenaAllocatedBufferPointer<UInt8>
51+
var buffer: Buffer
5152

5253
/// Construct a ``SyntaxText`` whose text is represented by the given `buffer`.
53-
public init(buffer: SyntaxArenaAllocatedBufferPointer<UInt8>) {
54+
public init(buffer: Buffer) {
5455
self.buffer = buffer
5556
}
5657

@@ -180,6 +181,18 @@ extension SyntaxText: RandomAccessCollection {
180181
public subscript(index: Index) -> Element {
181182
get { return buffer[index] }
182183
}
184+
185+
public func makeIterator() -> Buffer.Iterator {
186+
buffer.makeIterator()
187+
}
188+
189+
public func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<Element>) throws -> R) rethrows -> R? {
190+
try buffer.withContiguousStorageIfAvailable(body)
191+
}
192+
193+
public func _copyContents(initializing ptr: UnsafeMutableBufferPointer<Element>) -> (Iterator, Int) {
194+
buffer._copyContents(initializing: ptr)
195+
}
183196
}
184197

185198
extension SyntaxText: Hashable {

0 commit comments

Comments
 (0)