Skip to content

Commit 26d515b

Browse files
committed
[Heap] bubbleUp: remove @_effects attribute
This reintroduces retain/release operations for the empty array until swiftlang/swift#38898 lands. Mitigate the performance costs of this by refactoring code to reduce the size of the inlined bubbleUpMin/Max invocations.
1 parent c4282ca commit 26d515b

File tree

1 file changed

+6
-52
lines changed

1 file changed

+6
-52
lines changed

Sources/PriorityQueueModule/Heap+UnsafeHandle.swift

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -91,66 +91,20 @@ extension Heap._UnsafeHandle {
9191
}
9292

9393
extension Heap._UnsafeHandle {
94-
// Note: the releasenone annotation here tells the compiler that this function
95-
// will not release any strong references, so it doesn't need to worry about
96-
// retaining things. This is true in the sense that `bubbleUp` just reorders
97-
// storage contents, but it does call `Element.<`, which we cannot really
98-
// promise anything about -- it may release things!
99-
//
100-
// FWIW, I think `Element`'s Comparable implementation can only cause the
101-
// heap's storage to be released if it included an exclusivity violation --
102-
// `bubbleUp` is only ever called from mutating heap members, after all.
103-
// So if there is an issue, I think it would be triggered by the `Comparable`
104-
// implementation releasing something inside `Element`, and/or by the
105-
// `releasenone` annotation here having an effect in client code that called
106-
// into `Heap`.
107-
@_effects(releasenone)
10894
@inlinable
10995
internal func bubbleUp(_ node: _Node) {
110-
if node.isRoot {
111-
// We're can't go any further
112-
return
113-
}
114-
let parent = node.parent()
96+
guard !node.isRoot else { return }
11597

116-
if node.isMinLevel {
117-
if self[node] > self[parent] {
118-
swapAt(node, parent)
119-
bubbleUpMax(parent)
120-
} else {
121-
bubbleUpMin(node)
122-
}
123-
} else {
124-
if self[node] < self[parent] {
125-
swapAt(node, parent)
126-
bubbleUpMin(parent)
127-
} else {
128-
bubbleUpMax(node)
129-
}
130-
}
131-
}
98+
let parent = node.parent()
13299

133-
@_effects(releasenone)
134-
@inline(__always)
135-
@inlinable
136-
internal func bubbleUpMin(_ node: _Node) {
137100
var node = node
138-
139-
while let grandparent = node.grandParent(),
140-
self[node] < self[grandparent] {
141-
swapAt(node, grandparent)
142-
node = grandparent
101+
if node.isMinLevel == (self[node] > self[parent]) {
102+
swapAt(node, parent)
103+
node = parent
143104
}
144-
}
145-
146-
@_effects(releasenone)
147-
@inline(__always)
148-
@inlinable
149-
internal func bubbleUpMax(_ node: _Node) {
150-
var node = node
151105

152106
while let grandparent = node.grandParent(),
153-
self[node] > self[grandparent] {
107+
node.isMinLevel == (self[node] < self[grandparent]) {
154108
swapAt(node, grandparent)
155109
node = grandparent
156110
}

0 commit comments

Comments
 (0)