@@ -346,7 +346,8 @@ extension Array {
346346 @_semantics ( " array.make_mutable " )
347347 internal mutating func _makeMutableAndUnique( ) {
348348 if _slowPath ( !_buffer. isMutableAndUniquelyReferenced ( ) ) {
349- _buffer = _Buffer ( copying: _buffer)
349+ _createNewBuffer ( bufferIsUnique: false , minimumCapacity: count,
350+ growForAppend: false )
350351 }
351352 }
352353
@@ -1023,19 +1024,65 @@ extension Array: RangeReplaceableCollection {
10231024 @inlinable
10241025 @_semantics ( " array.mutate_unknown " )
10251026 public mutating func reserveCapacity( _ minimumCapacity: Int ) {
1026- if _buffer. requestUniqueMutableBackingBuffer (
1027- minimumCapacity: minimumCapacity) == nil {
1027+ _reserveCapacityImpl ( minimumCapacity: minimumCapacity,
1028+ growForAppend: false )
1029+ }
1030+
1031+ /// Reserves enough space to store `minimumCapacity` elements.
1032+ /// If a new buffer needs to be allocated and `growForAppend` is true,
1033+ /// the new capacity is calculated using `_growArrayCapacity`, but at least
1034+ /// kept at `minimumCapacity`.
1035+ @_alwaysEmitIntoClient
1036+ internal mutating func _reserveCapacityImpl(
1037+ minimumCapacity: Int , growForAppend: Bool
1038+ ) {
1039+ let isUnique = _buffer. isUniquelyReferenced ( )
1040+ if _slowPath ( !isUnique || _getCapacity ( ) < minimumCapacity) {
1041+ _createNewBuffer ( bufferIsUnique: isUnique,
1042+ minimumCapacity: Swift . max ( minimumCapacity, count) ,
1043+ growForAppend: growForAppend)
1044+ }
1045+ _internalInvariant ( capacity >= minimumCapacity)
1046+ _internalInvariant ( capacity == 0 || _buffer. isUniquelyReferenced ( ) )
1047+ }
10281048
1029- let newBuffer = _ContiguousArrayBuffer < Element > (
1030- _uninitializedCount: count, minimumCapacity: minimumCapacity)
1049+ /// Creates a new buffer, replacing the current buffer.
1050+ ///
1051+ /// If `bufferIsUnique` is true, the buffer is assumed to be uniquely
1052+ /// referenced by this array and the elements are moved - instead of copied -
1053+ /// to the new buffer.
1054+ /// The `minimumCapacity` is the lower bound for the new capacity.
1055+ /// If `growForAppend` is true, the new capacity is calculated using
1056+ /// `_growArrayCapacity`, but at least kept at `minimumCapacity`.
1057+ @_alwaysEmitIntoClient
1058+ @inline ( never)
1059+ internal mutating func _createNewBuffer(
1060+ bufferIsUnique: Bool , minimumCapacity: Int , growForAppend: Bool
1061+ ) {
1062+ let newCapacity = _growArrayCapacity ( oldCapacity: _getCapacity ( ) ,
1063+ minimumCapacity: minimumCapacity,
1064+ growForAppend: growForAppend)
1065+ let count = _getCount ( )
1066+ _internalInvariant ( newCapacity >= count)
1067+
1068+ let newBuffer = _ContiguousArrayBuffer < Element > (
1069+ _uninitializedCount: count, minimumCapacity: newCapacity)
10311070
1071+ if bufferIsUnique {
1072+ _internalInvariant ( _buffer. isUniquelyReferenced ( ) )
1073+
1074+ // As an optimization, if the original buffer is unique, we can just move
1075+ // the elements instead of copying.
1076+ let dest = newBuffer. firstElementAddress
1077+ dest. moveInitialize ( from: _buffer. firstElementAddress,
1078+ count: count)
1079+ _buffer. count = 0
1080+ } else {
10321081 _buffer. _copyContents (
1033- subRange: _buffer . indices ,
1082+ subRange: 0 ..< count ,
10341083 initializing: newBuffer. firstElementAddress)
1035- _buffer = _Buffer (
1036- _buffer: newBuffer, shiftedToStartIndex: _buffer. startIndex)
10371084 }
1038- _internalInvariant ( capacity >= minimumCapacity )
1085+ _buffer = _Buffer ( _buffer : newBuffer , shiftedToStartIndex : 0 )
10391086 }
10401087
10411088 /// Copy the contents of the current buffer to a new unique mutable buffer.
@@ -1054,7 +1101,9 @@ extension Array: RangeReplaceableCollection {
10541101 @_semantics ( " array.make_mutable " )
10551102 internal mutating func _makeUniqueAndReserveCapacityIfNotUnique( ) {
10561103 if _slowPath ( !_buffer. isMutableAndUniquelyReferenced ( ) ) {
1057- _copyToNewBuffer ( oldCount: _buffer. count)
1104+ _createNewBuffer ( bufferIsUnique: false ,
1105+ minimumCapacity: count + 1 ,
1106+ growForAppend: true )
10581107 }
10591108 }
10601109
@@ -1083,7 +1132,9 @@ extension Array: RangeReplaceableCollection {
10831132 _buffer. isMutableAndUniquelyReferenced ( ) )
10841133
10851134 if _slowPath ( oldCount + 1 > _buffer. capacity) {
1086- _copyToNewBuffer ( oldCount: oldCount)
1135+ _createNewBuffer ( bufferIsUnique: true ,
1136+ minimumCapacity: oldCount + 1 ,
1137+ growForAppend: true )
10871138 }
10881139 }
10891140
@@ -1124,6 +1175,8 @@ extension Array: RangeReplaceableCollection {
11241175 @inlinable
11251176 @_semantics ( " array.append_element " )
11261177 public mutating func append( _ newElement: __owned Element) {
1178+ // Separating uniqueness check and capacity check allows hoisting the
1179+ // uniqueness check out of a loop.
11271180 _makeUniqueAndReserveCapacityIfNotUnique ( )
11281181 let oldCount = _getCount ( )
11291182 _reserveCapacityAssumingUniqueBuffer ( oldCount: oldCount)
@@ -1160,7 +1213,7 @@ extension Array: RangeReplaceableCollection {
11601213 start: startNewElements,
11611214 count: self . capacity - oldCount)
11621215
1163- let ( remainder, writtenUpTo) = buf. initialize ( from: newElements)
1216+ var ( remainder, writtenUpTo) = buf. initialize ( from: newElements)
11641217
11651218 // trap on underflow from the sequence's underestimate:
11661219 let writtenCount = buf. distance ( from: buf. startIndex, to: writtenUpTo)
@@ -1176,30 +1229,39 @@ extension Array: RangeReplaceableCollection {
11761229 if writtenUpTo == buf. endIndex {
11771230 // there may be elements that didn't fit in the existing buffer,
11781231 // append them in slow sequence-only mode
1179- _buffer. _arrayAppendSequence ( IteratorSequence ( remainder) )
1232+ var newCount = _getCount ( )
1233+ var nextItem = remainder. next ( )
1234+ while nextItem != nil {
1235+ reserveCapacityForAppend ( newElementsCount: 1 )
1236+
1237+ let currentCapacity = _getCapacity ( )
1238+ let base = _buffer. firstElementAddress
1239+
1240+ // fill while there is another item and spare capacity
1241+ while let next = nextItem, newCount < currentCapacity {
1242+ ( base + newCount) . initialize ( to: next)
1243+ newCount += 1
1244+ nextItem = remainder. next ( )
1245+ }
1246+ _buffer. count = newCount
1247+ }
11801248 }
11811249 }
11821250
11831251 @inlinable
11841252 @_semantics ( " array.reserve_capacity_for_append " )
11851253 internal mutating func reserveCapacityForAppend( newElementsCount: Int ) {
1186- let oldCount = self . count
1187- let oldCapacity = self . capacity
1188- let newCount = oldCount + newElementsCount
1189-
11901254 // Ensure uniqueness, mutability, and sufficient storage. Note that
11911255 // for consistency, we need unique self even if newElements is empty.
1192- self . reserveCapacity (
1193- newCount > oldCapacity ?
1194- Swift . max ( newCount, _growArrayCapacity ( oldCapacity) )
1195- : newCount)
1256+ _reserveCapacityImpl ( minimumCapacity: self . count + newElementsCount,
1257+ growForAppend: true )
11961258 }
11971259
11981260 @inlinable
11991261 public mutating func _customRemoveLast( ) -> Element ? {
1262+ _makeMutableAndUnique ( )
12001263 let newCount = _getCount ( ) - 1
12011264 _precondition ( newCount >= 0 , " Can't removeLast from an empty Array " )
1202- _makeUniqueAndReserveCapacityIfNotUnique ( )
12031265 let pointer = ( _buffer. firstElementAddress + newCount)
12041266 let element = pointer. move ( )
12051267 _buffer. count = newCount
@@ -1224,10 +1286,11 @@ extension Array: RangeReplaceableCollection {
12241286 @inlinable
12251287 @discardableResult
12261288 public mutating func remove( at index: Int ) -> Element {
1227- _precondition ( index < endIndex, " Index out of range " )
1228- _precondition ( index >= startIndex, " Index out of range " )
1229- _makeUniqueAndReserveCapacityIfNotUnique ( )
1230- let newCount = _getCount ( ) - 1
1289+ _makeMutableAndUnique ( )
1290+ let currentCount = _getCount ( )
1291+ _precondition ( index < currentCount, " Index out of range " )
1292+ _precondition ( index >= 0 , " Index out of range " )
1293+ let newCount = currentCount - 1
12311294 let pointer = ( _buffer. firstElementAddress + index)
12321295 let result = pointer. move ( )
12331296 pointer. moveInitialize ( from: pointer + 1 , count: newCount - index)
@@ -1524,9 +1587,8 @@ extension Array {
15241587 public mutating func withUnsafeMutableBufferPointer< R> (
15251588 _ body: ( inout UnsafeMutableBufferPointer < Element > ) throws -> R
15261589 ) rethrows -> R {
1590+ _makeMutableAndUnique ( )
15271591 let count = self . count
1528- // Ensure unique storage
1529- _buffer. _outlinedMakeUniqueBuffer ( bufferCount: count)
15301592
15311593 // Ensure that body can't invalidate the storage or its bounds by
15321594 // moving self into a temporary working array.
@@ -1638,19 +1700,12 @@ extension Array {
16381700 _precondition ( subrange. upperBound <= _buffer. endIndex,
16391701 " Array replace: subrange extends past the end " )
16401702
1641- let oldCount = _buffer. count
16421703 let eraseCount = subrange. count
16431704 let insertCount = newElements. count
16441705 let growth = insertCount - eraseCount
16451706
1646- if _buffer. requestUniqueMutableBackingBuffer (
1647- minimumCapacity: oldCount + growth) != nil {
1648-
1649- _buffer. replaceSubrange (
1650- subrange, with: insertCount, elementsOf: newElements)
1651- } else {
1652- _buffer. _arrayOutOfPlaceReplace ( subrange, with: newElements, count: insertCount)
1653- }
1707+ reserveCapacityForAppend ( newElementsCount: growth)
1708+ _buffer. replaceSubrange ( subrange, with: insertCount, elementsOf: newElements)
16541709 }
16551710}
16561711
0 commit comments