Skip to content

Commit 71f1af4

Browse files
authored
Merge pull request #608 from rintaro/bump-ptr-allocator-perf
2 parents 1b53f6a + db3c85e commit 71f1af4

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

Sources/SwiftSyntax/BumpPtrAllocator.swift

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,27 +20,27 @@ public class BumpPtrAllocator {
2020
static private var SLAB_ALIGNMENT: Int = 8
2121

2222
private var slabs: [Slab]
23-
/// Points to the next unused address in `slabs.last`.
24-
private var currentPtr: UnsafeMutableRawPointer?
25-
/// Points to the end address of `slabs.last`. If `slabs` is not empty, this
26-
/// is equivalent to `slabs.last!.baseAddress! + slabs.last!.count`
27-
private var endPtr: UnsafeMutableRawPointer?
23+
/// Pair of pointers in the current slab.
24+
/// - pointer: Points to the next unused address in `slabs.last`.
25+
/// - end: Points to the end address of `slabs.last`. This is equivalent to
26+
/// `slabs.last!.baseAddress! + slabs.last!.count`
27+
/// 'nil' if `slabs` is empty.
28+
private var current: (pointer: UnsafeMutableRawPointer,
29+
end: UnsafeMutableRawPointer)?
2830
private var customSizeSlabs: [Slab]
2931
private var _totalBytesAllocated: Int
3032

3133
public init() {
3234
slabs = []
33-
currentPtr = nil
34-
endPtr = nil
35+
current = nil
3536
customSizeSlabs = []
3637
_totalBytesAllocated = 0
3738
}
3839

3940
deinit {
4041
/// Deallocate all memory.
4142
_totalBytesAllocated = 0
42-
currentPtr = nil
43-
endPtr = nil
43+
current = nil
4444
while let slab = slabs.popLast() {
4545
slab.deallocate()
4646
}
@@ -59,9 +59,28 @@ public class BumpPtrAllocator {
5959
let newSlabSize = Self.slabSize(at: slabs.count)
6060
let newSlab = Slab.allocate(
6161
byteCount: newSlabSize, alignment: Self.SLAB_ALIGNMENT)
62+
let pointer = newSlab.baseAddress!
63+
current = (pointer, pointer.advanced(by: newSlabSize))
6264
slabs.append(newSlab)
63-
currentPtr = newSlab.baseAddress!
64-
endPtr = currentPtr!.advanced(by: newSlabSize)
65+
}
66+
67+
/// Allocate 'byteCount' of memory from the current slab if available.
68+
private func allocateFromCurrentSlab(
69+
_ byteCount: Int,
70+
_ alignment: Int
71+
) -> UnsafeMutableRawBufferPointer? {
72+
guard let current = self.current else {
73+
return nil
74+
}
75+
76+
let aligned = current.pointer.alignedUp(toMultipleOf: alignment)
77+
guard byteCount <= aligned.distance(to: current.end) else {
78+
return nil
79+
}
80+
81+
// Bump the pointer, and return the allocated buffer.
82+
self.current = (aligned + byteCount, current.end)
83+
return .init(start: aligned, count: byteCount)
6584
}
6685

6786
/// Allocate 'byteCount' of memory.
@@ -70,7 +89,7 @@ public class BumpPtrAllocator {
7089
/// Clients should never call `deallocate()` on the returned buffer.
7190
public func allocate(byteCount: Int, alignment: Int) -> UnsafeMutableRawBufferPointer {
7291

73-
precondition(alignment <= Self.SLAB_ALIGNMENT)
92+
assert(alignment <= Self.SLAB_ALIGNMENT)
7493
guard byteCount > 0 else {
7594
return .init(start: nil, count: 0)
7695
}
@@ -79,12 +98,8 @@ public class BumpPtrAllocator {
7998
_totalBytesAllocated += byteCount
8099

81100
// Check if the current slab has enough space.
82-
if !slabs.isEmpty {
83-
let aligned = currentPtr!.alignedUp(toMultipleOf: alignment)
84-
if aligned + byteCount <= endPtr! {
85-
currentPtr = aligned + byteCount
86-
return .init(start: aligned, count: byteCount)
87-
}
101+
if let allocated = allocateFromCurrentSlab(byteCount, alignment) {
102+
return allocated
88103
}
89104

90105
// If the size is too big, allocate a dedicated slab for it.
@@ -97,10 +112,10 @@ public class BumpPtrAllocator {
97112

98113
// Otherwise, start a new slab and try again.
99114
startNewSlab()
100-
let aligned = currentPtr!.alignedUp(toMultipleOf: alignment)
101-
assert(aligned + byteCount <= endPtr!, "Unable to allocate memory!")
102-
currentPtr = aligned + byteCount
103-
return .init(start: aligned, count: byteCount)
115+
if let allocated = allocateFromCurrentSlab(byteCount, alignment) {
116+
return allocated
117+
}
118+
fatalError("Unable to allocate memory!")
104119
}
105120

106121
/// Allocate a chunk of bound memory of `MemoryLayout<T>.stride * count'.

0 commit comments

Comments
 (0)