diff --git a/stdlib/public/core/ArrayBufferProtocol.swift b/stdlib/public/core/ArrayBufferProtocol.swift index cf6512badb16b..db464227a0160 100644 --- a/stdlib/public/core/ArrayBufferProtocol.swift +++ b/stdlib/public/core/ArrayBufferProtocol.swift @@ -24,6 +24,8 @@ internal protocol _ArrayBufferProtocol /// Adopt the entire buffer, presenting it at the provided `startIndex`. init(_buffer: _ContiguousArrayBuffer, shiftedToStartIndex: Int) + init(copying buffer: Self) + /// Copy the elements in `bounds` from this buffer into uninitialized /// memory starting at `target`. Return a pointer "past the end" of the /// just-initialized memory. @@ -124,7 +126,7 @@ internal protocol _ArrayBufferProtocol var endIndex: Int { get } } -extension _ArrayBufferProtocol { +extension _ArrayBufferProtocol where Indices == CountableRange{ @_inlineable @_versioned @@ -132,6 +134,19 @@ extension _ArrayBufferProtocol { return firstElementAddress } + // Make sure the compiler does not inline _copyBuffer to reduce code size. + @_inlineable + @inline(never) + @_versioned + internal init(copying buffer: Self) { + let newBuffer = _ContiguousArrayBuffer( + _uninitializedCount: buffer.count, minimumCapacity: buffer.count) + buffer._copyContents( + subRange: Range(buffer.indices), + initializing: newBuffer.firstElementAddress) + self = Self( _buffer: newBuffer, shiftedToStartIndex: buffer.startIndex) + } + @_inlineable @_versioned internal mutating func replaceSubrange( diff --git a/stdlib/public/core/Arrays.swift.gyb b/stdlib/public/core/Arrays.swift.gyb index 1c06f5513a244..8502f7a0bd0ac 100644 --- a/stdlib/public/core/Arrays.swift.gyb +++ b/stdlib/public/core/Arrays.swift.gyb @@ -835,27 +835,12 @@ extension ${Self} { return Builtin.unsafeCastToNativeObject(_buffer.owner) } - // FIXME(ABI)#12 : move to an initializer on _Buffer. - // Make sure the compiler does not inline _copyBuffer to reduce code size. - @inline(never) - @_inlineable - @_versioned - static internal func _copyBuffer(_ buffer: inout _Buffer) { - let newBuffer = _ContiguousArrayBuffer( - _uninitializedCount: buffer.count, minimumCapacity: buffer.count) - buffer._copyContents( - subRange: buffer.indices, - initializing: newBuffer.firstElementAddress) - buffer = _Buffer( - _buffer: newBuffer, shiftedToStartIndex: buffer.startIndex) - } - @_inlineable @_versioned @_semantics("array.make_mutable") internal mutating func _makeMutableAndUnique() { if _slowPath(!_buffer.isMutableAndUniquelyReferenced()) { - ${Self}._copyBuffer(&_buffer) + _buffer = _Buffer(copying: _buffer) } } @@ -864,7 +849,7 @@ extension ${Self} { @_semantics("array.make_mutable") internal mutating func _makeMutableAndUniqueOrPinned() { if _slowPath(!_buffer.isMutableAndUniquelyReferencedOrPinned()) { - ${Self}._copyBuffer(&_buffer) + _buffer = _Buffer(copying: _buffer) } } @@ -1543,8 +1528,8 @@ extension ${Self} : RangeReplaceableCollection, ArrayProtocol { @_inlineable public mutating func popLast() -> Element? { let newCount = _getCount() - 1 - guard newCount >= 0 else { return nil } - _makeUniqueAndReserveCapacityIfNotUnique() + guard !isEmpty else { return nil } + return _customRemoveLast().unsafelyUnwrapped let pointer = (_buffer.firstElementAddress + newCount) let element = pointer.move() _buffer.count = newCount diff --git a/test/SILOptimizer/swap_refcnt.swift b/test/SILOptimizer/swap_refcnt.swift deleted file mode 100644 index 8153ca0c9e9ab..0000000000000 --- a/test/SILOptimizer/swap_refcnt.swift +++ /dev/null @@ -1,12 +0,0 @@ -// RUN: %target-swift-frontend -O -emit-sil %s | %target-sil-opt -assume-parsing-unqualified-ownership-sil -simplify-unreachable-containing-blocks | %FileCheck %s - -// Make sure we can swap two values in an array without retaining anything along non-fatalerror paths. - -// CHECK-LABEL: sil @$S11swap_refcnt0A7ByIndex1A1x1yySays4Int8VGz_S2itF : $@convention(thin) (@inout Array, Int, Int) -> () { -// CHECK-NOT: strong_retain -// CHECK-NOT: strong_release -// CHECK: } // end sil function '$S11swap_refcnt0A7ByIndex1A1x1yySays4Int8VGz_S2itF' -public func swapByIndex(A: inout [Int8], x : Int, y : Int) { - swap(&A[x],&A[y]) -} -