mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Add a use an unchecked subscript on UnsafeBufferPointer, which skips debugPrecondition checks (in case we're not inlined) as well as a force-unwrap check.
83 lines
2.9 KiB
Swift
83 lines
2.9 KiB
Swift
//===--- SmallBuffer.swift ------------------------------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// A specialized type which is a buffer of trivial values utilizing in-line
|
|
// storage
|
|
//
|
|
internal struct _SmallBuffer<T: FixedWidthInteger> {
|
|
// FIXME(rdar://45443666): The storage is currently set at 64 bytes, which
|
|
// actually hides a normalization bug in validation-test/stdlib/String.swift,
|
|
// where exceedingly long segments may compare only the first `n` code units
|
|
// worth of a given segment before moving on to the next segment. We'd also
|
|
// like to make this be 32-bytes, as commented out below. Adjusting the size
|
|
// here was simpler than XFAILing the test, but when fixed, restore size to 32
|
|
// bytes.
|
|
//
|
|
// private var _inlineStorage: (UInt64, UInt64, UInt64, UInt64) = (0,0,0,0)
|
|
//
|
|
private var _inlineStorage: (
|
|
UInt64, UInt64, UInt64, UInt64, UInt64, UInt64, UInt64, UInt64
|
|
) = (0,0,0,0,0,0,0,0)
|
|
|
|
internal init() {
|
|
_invariantCheck()
|
|
}
|
|
}
|
|
|
|
extension _SmallBuffer {
|
|
private var stride: Int { return MemoryLayout<T>.stride }
|
|
}
|
|
|
|
extension _SmallBuffer {
|
|
private var byteCapacity: Int {
|
|
return MemoryLayout.stride(ofValue: _inlineStorage)
|
|
}
|
|
internal var capacity: Int { return byteCapacity / stride }
|
|
|
|
internal subscript(i: Int) -> T {
|
|
get {
|
|
_internalInvariant(i >= 0 && i < capacity)
|
|
let capacity = self.capacity
|
|
return withUnsafeBytes(of: _inlineStorage) {
|
|
let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked
|
|
let bufPtr = UnsafeBufferPointer(
|
|
start: rawPtr.assumingMemoryBound(to: T.self), count: capacity)
|
|
return bufPtr[_unchecked: i]
|
|
}
|
|
}
|
|
set {
|
|
_internalInvariant(i >= 0 && i < capacity)
|
|
let capacity = self.capacity
|
|
withUnsafeMutableBytes(of: &_inlineStorage) {
|
|
let rawPtr = $0.baseAddress._unsafelyUnwrappedUnchecked
|
|
let bufPtr = UnsafeMutableBufferPointer(
|
|
start: rawPtr.assumingMemoryBound(to: T.self), count: capacity)
|
|
bufPtr[_unchecked: i] = newValue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
extension _SmallBuffer {
|
|
#if !INTERNAL_CHECKS_ENABLED
|
|
@inlinable @inline(__always) internal func _invariantCheck() {}
|
|
#else
|
|
@usableFromInline @inline(never) @_effects(releasenone)
|
|
internal mutating func _invariantCheck() {
|
|
_internalInvariant(MemoryLayout<_SmallBuffer<Int>>.stride == byteCapacity)
|
|
_internalInvariant(capacity * stride == byteCapacity)
|
|
_internalInvariant(_isPOD(T.self))
|
|
}
|
|
#endif // INTERNAL_CHECKS_ENABLED
|
|
}
|
|
|