Skip to content

Commit 8921865

Browse files
committed
[stdlib] use UnsafeMutableBufferPointer.initialize(fromContentsOf:) in Array.replaceSubrange
1 parent d3a4b6b commit 8921865

File tree

1 file changed

+19
-32
lines changed

1 file changed

+19
-32
lines changed

stdlib/public/core/ArrayBufferProtocol.swift

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -145,46 +145,33 @@ extension _ArrayBufferProtocol {
145145
elementsOf newValues: __owned C
146146
) where C: Collection, C.Element == Element {
147147
_internalInvariant(startIndex == 0, "_SliceBuffer should override this function.")
148-
let oldCount = self.count
149-
let eraseCount = subrange.count
150-
151-
let growth = newCount - eraseCount
152-
// This check will prevent storing a 0 count to the empty array singleton.
153-
if growth != 0 {
154-
self.count = oldCount + growth
155-
}
156148

157149
let elements = self.firstElementAddress
158150

159151
// erase all the elements we're replacing to create a hole
160152
let holeStart = elements + subrange.lowerBound
161-
let holeEnd = holeStart + newCount
162-
163-
// directly forwards to Builtin.destroyArray
164-
// TODO: should we branch here or does the compiler branch implicitly?
153+
let eraseCount = subrange.count
165154
holeStart.deinitialize(count: eraseCount)
166155

167-
// resize the hole to make it the correct size
168-
// safe to always call, moveInitialize to the same location is a no-op
169-
let tailStart = elements + subrange.upperBound
170-
let tailCount = oldCount - subrange.upperBound
171-
holeEnd.moveInitialize(from: tailStart, count: tailCount)
156+
let growth = newCount - eraseCount
172157

173-
// place the values into the hole we created
174-
if newCount > 0 {
175-
let done: Void? = newValues.withContiguousStorageIfAvailable {
176-
holeStart.initialize(from: $0.baseAddress!, count: newCount)
177-
}
178-
if done == nil {
179-
var place = holeStart
180-
var i = newValues.startIndex
181-
while place < holeEnd {
182-
place.initialize(to: newValues[i])
183-
place += 1
184-
newValues.formIndex(after: &i)
185-
}
186-
_expectEnd(of: newValues, is: i)
187-
}
158+
// This check will prevent storing a 0 count to the empty array singleton.
159+
if growth != 0 {
160+
let holeEnd = holeStart + newCount
161+
let tailStart = elements + subrange.upperBound
162+
let tailCount = self.count - subrange.upperBound
163+
holeEnd.moveInitialize(from: tailStart, count: tailCount)
164+
self.count += growth
188165
}
166+
167+
// place the values into the hole we created
168+
let buf = UnsafeMutableBufferPointer(start: holeStart, count: newCount)
169+
let res = buf.initialize(fromContentsOf: newValues)
170+
// memory safety: if we did not fill the buffer, we now have
171+
// uninitialized memory in the middle of our array
172+
precondition(
173+
res == buf.endIndex,
174+
"invalid Collection: count differed in successive traversals"
175+
)
189176
}
190177
}

0 commit comments

Comments
 (0)