Skip to content

Commit bff9120

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

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
@@ -149,46 +149,33 @@ extension _ArrayBufferProtocol {
149149
elementsOf newValues: __owned C
150150
) where C: Collection, C.Element == Element {
151151
_internalInvariant(startIndex == 0, "_SliceBuffer should override this function.")
152-
let oldCount = self.count
153-
let eraseCount = subrange.count
154-
155-
let growth = newCount - eraseCount
156-
// This check will prevent storing a 0 count to the empty array singleton.
157-
if growth != 0 {
158-
self.count = oldCount + growth
159-
}
160152

161153
let elements = self.firstElementAddress
162154

163155
// erase all the elements we're replacing to create a hole
164156
let holeStart = elements + subrange.lowerBound
165-
let holeEnd = holeStart + newCount
166-
167-
// directly forwards to Builtin.destroyArray
168-
// TODO: should we branch here or does the compiler branch implicitly?
157+
let eraseCount = subrange.count
169158
holeStart.deinitialize(count: eraseCount)
170159

171-
// resize the hole to make it the correct size
172-
// safe to always call, moveInitialize to the same location is a no-op
173-
let tailStart = elements + subrange.upperBound
174-
let tailCount = oldCount - subrange.upperBound
175-
holeEnd.moveInitialize(from: tailStart, count: tailCount)
160+
let growth = newCount - eraseCount
176161

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

0 commit comments

Comments
 (0)