Skip to content

Migrate parts of the stdlib to UnsafeRawPointer. #3792

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 27, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion stdlib/private/SwiftPrivate/SwiftPrivate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public func withArrayOfCStrings<R>(

return argsBuffer.withUnsafeMutableBufferPointer {
(argsBuffer) in
let ptr = UnsafeMutablePointer<CChar>(argsBuffer.baseAddress!)
let ptr = UnsafeMutableRawPointer(argsBuffer.baseAddress!).bindMemory(
to: CChar.self, capacity: argsBuffer.count)
var cStrings: [UnsafeMutablePointer<CChar>?] = argsOffsets.map { ptr + $0 }
cStrings[cStrings.count - 1] = nil
return body(cStrings)
Expand Down
3 changes: 2 additions & 1 deletion stdlib/public/SDK/GLKit/GLKit.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ vectorElementNames = [
@inline(__always)
public func _indexHomogeneousValue<TTT, T>(_ aggregate: UnsafePointer<TTT>,
_ index: Int) -> T {
return UnsafePointer<T>(aggregate)[index]
return UnsafeRawPointer(aggregate).load(
fromByteOffset: index * strideof(T.self), as: T.self)
}

%{
Expand Down
2 changes: 1 addition & 1 deletion stdlib/public/core/Character.swift
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ public struct Character :
}
else {
if let native = s._core.nativeBuffer,
native.start == UnsafeMutablePointer(s._core._baseAddress!) {
native.start == s._core._baseAddress! {
_representation = .large(native._storage)
return
}
Expand Down
16 changes: 11 additions & 5 deletions stdlib/public/core/HashedCollections.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -265,11 +265,11 @@ internal func _stdlib_NSObject_isEqual(_ lhs: AnyObject, _ rhs: AnyObject) -> Bo
/// Like `UnsafeMutablePointer<Unmanaged<AnyObject>>`, or `id
/// __unsafe_unretained *` in Objective-C ARC.
internal struct _UnmanagedAnyObjectArray {
/// Underlying pointer, Unmanaged to escape reference counting.
internal var value: UnsafeMutablePointer<Unmanaged<AnyObject>>
/// Underlying pointer.
internal var value: UnsafeMutableRawPointer

internal init(_ up: UnsafeMutablePointer<AnyObject>) {
self.value = UnsafeMutablePointer(up)
self.value = UnsafeMutableRawPointer(up)
}

internal init?(_ up: UnsafeMutablePointer<AnyObject>?) {
Expand All @@ -279,10 +279,16 @@ internal struct _UnmanagedAnyObjectArray {

internal subscript(i: Int) -> AnyObject {
get {
return value[i].takeUnretainedValue()
let unmanaged = value.load(
fromByteOffset: i * strideof(AnyObject.self),
as: Unmanaged<AnyObject>.self)
return unmanaged.takeUnretainedValue()
}
nonmutating set(newValue) {
value[i] = Unmanaged.passUnretained(newValue)
let unmanaged = Unmanaged.passUnretained(newValue)
value.storeBytes(of: unmanaged,
toByteOffset: i * strideof(AnyObject.self),
as: Unmanaged<AnyObject>.self)
}
}
}
Expand Down
28 changes: 15 additions & 13 deletions stdlib/public/core/Runtime.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ import SwiftShims
// Atomics
//===----------------------------------------------------------------------===//

public typealias _PointerToPointer = UnsafeMutablePointer<UnsafeRawPointer?>

@_transparent
public // @testable
func _stdlib_atomicCompareExchangeStrongPtrImpl(
object target: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
expected: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
desired: UnsafeMutableRawPointer?) -> Bool {
func _stdlib_atomicCompareExchangeStrongPtr(
object target: _PointerToPointer,
expected: _PointerToPointer,
desired: UnsafeRawPointer?) -> Bool {

// We use Builtin.Word here because Builtin.RawPointer can't be nil.
let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_Word(
target._rawValue,
UInt(bitPattern: expected.pointee)._builtinWordValue,
UInt(bitPattern: desired)._builtinWordValue)
expected.pointee = UnsafeMutableRawPointer(bitPattern: Int(oldValue))
expected.pointee = UnsafeRawPointer(bitPattern: Int(oldValue))
return Bool(won)
}

Expand Down Expand Up @@ -70,23 +72,23 @@ func _stdlib_atomicCompareExchangeStrongPtr<T>(
object target: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
expected: UnsafeMutablePointer<UnsafeMutablePointer<T>${optional}>,
desired: UnsafeMutablePointer<T>${optional}) -> Bool {
return _stdlib_atomicCompareExchangeStrongPtrImpl(
object: UnsafeMutablePointer(target),
expected: UnsafeMutablePointer(expected),
desired: UnsafeMutablePointer(desired))
return _stdlib_atomicCompareExchangeStrongPtr(
object: unsafeBitCast(target, to: _PointerToPointer.self),
expected: unsafeBitCast(expected, to: _PointerToPointer.self),
desired: unsafeBitCast(desired, to: Optional<UnsafeRawPointer>.self))
}
% end
% end # optional

@_transparent
@discardableResult
public // @testable
func _stdlib_atomicInitializeARCRef(
object target: UnsafeMutablePointer<AnyObject?>,
desired: AnyObject) -> Bool {
var expected: UnsafeMutableRawPointer? = nil
var expected: UnsafeRawPointer? = nil
let desiredPtr = Unmanaged.passRetained(desired).toOpaque()
let wonRace = _stdlib_atomicCompareExchangeStrongPtrImpl(
object: UnsafeMutablePointer(target),
let wonRace = _stdlib_atomicCompareExchangeStrongPtr(
object: unsafeBitCast(target, to: _PointerToPointer.self),
expected: &expected,
desired: desiredPtr)
if !wonRace {
Expand Down
40 changes: 24 additions & 16 deletions stdlib/public/core/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ extension String : _ExpressibleByBuiltinUTF16StringLiteral {
) {
self = String(
_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: UnsafeMutableRawPointer(start),
count: Int(utf16CodeUnitCount),
elementShift: 1,
hasCocoaBuffer: false,
Expand All @@ -418,7 +418,7 @@ extension String : _ExpressibleByBuiltinStringLiteral {
if Bool(isASCII) {
self = String(
_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: UnsafeMutableRawPointer(start),
count: Int(utf8CodeUnitCount),
elementShift: 0,
hasCocoaBuffer: false,
Expand Down Expand Up @@ -699,13 +699,15 @@ extension String : Hashable {
}
#else
if self._core.isASCII {
return _swift_stdlib_unicode_hash_ascii(
UnsafeMutablePointer<Int8>(_core.startASCII),
Int32(_core.count))
return _core.startASCII.withMemoryRebound(
to: CChar.self, capacity: _core.count) {
_swift_stdlib_unicode_hash_ascii($0, Int32(_core.count))
}
} else {
return _swift_stdlib_unicode_hash(
UnsafeMutablePointer<UInt16>(_core.startUTF16),
Int32(_core.count))
return _core.startUTF16.withMemoryRebound(
to: UInt16.self, capacity: _core.count) {
_swift_stdlib_unicode_hash($0, Int32(_core.count))
}
}
#endif
}
Expand Down Expand Up @@ -821,7 +823,8 @@ internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)

// Try to write it out to the same length.
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
let z = _swift_stdlib_unicode_strToLower(
dest, Int32(str._core.count),
str._core.startUTF16, Int32(str._core.count))
Expand All @@ -831,7 +834,8 @@ internal func _nativeUnicodeLowercaseString(_ str: String) -> String {
if correctSize != str._core.count {
buffer = _StringBuffer(
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
_swift_stdlib_unicode_strToLower(
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
}
Expand All @@ -844,7 +848,8 @@ internal func _nativeUnicodeUppercaseString(_ str: String) -> String {
capacity: str._core.count, initialSize: str._core.count, elementWidth: 2)

// Try to write it out to the same length.
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
let z = _swift_stdlib_unicode_strToUpper(
dest, Int32(str._core.count),
str._core.startUTF16, Int32(str._core.count))
Expand All @@ -854,7 +859,8 @@ internal func _nativeUnicodeUppercaseString(_ str: String) -> String {
if correctSize != str._core.count {
buffer = _StringBuffer(
capacity: correctSize, initialSize: correctSize, elementWidth: 2)
let dest = UnsafeMutablePointer<UTF16.CodeUnit>(buffer.start)
let dest = buffer.start.bindMemory(
to: UTF16.CodeUnit.self, capacity: str._core.count)
_swift_stdlib_unicode_strToUpper(
dest, Int32(correctSize), str._core.startUTF16, Int32(str._core.count))
}
Expand Down Expand Up @@ -904,7 +910,7 @@ extension String {
let source = self._core.startASCII
let buffer = _StringBuffer(
capacity: count, initialSize: count, elementWidth: 1)
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
let dest = buffer.start
for i in 0..<count {
// For each character in the string, we lookup if it should be shifted
// in our ascii table, then we return 0x20 if it should, 0x0 if not.
Expand All @@ -923,7 +929,8 @@ extension String {
// Since we are left with either 0x0 or 0x20, we can safely truncate to
// a UInt8 and add to our ASCII value (this will not overflow numbers in
// the ASCII range).
dest[i] = value &+ UInt8(truncatingBitPattern: add)
dest.storeBytes(of: value &+ UInt8(truncatingBitPattern: add),
toByteOffset: i, as: UInt8.self)
}
return String(_storage: buffer)
}
Expand Down Expand Up @@ -953,15 +960,16 @@ extension String {
let source = self._core.startASCII
let buffer = _StringBuffer(
capacity: count, initialSize: count, elementWidth: 1)
let dest = UnsafeMutablePointer<UInt8>(buffer.start)
let dest = buffer.start
for i in 0..<count {
// See the comment above in lowercaseString.
let value = source[i]
let isLower =
_asciiLowerCaseTable >>
UInt64(((value &- 1) & 0b0111_1111) >> 1)
let add = (isLower & 0x1) << 5
dest[i] = value &- UInt8(truncatingBitPattern: add)
dest.storeBytes(of: value &- UInt8(truncatingBitPattern: add),
toByteOffset: i, as: UInt8.self)
}
return String(_storage: buffer)
}
Expand Down
10 changes: 5 additions & 5 deletions stdlib/public/core/StringBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func _cocoaStringToSwiftString_NonASCII(
let start = _stdlib_binary_CFStringGetCharactersPtr(cfImmutableValue)

return String(_StringCore(
baseAddress: OpaquePointer(start),
baseAddress: start,
count: length,
elementShift: 1,
hasCocoaBuffer: true,
Expand All @@ -81,7 +81,7 @@ internal func _cocoaStringToContiguous(

_swift_stdlib_CFStringGetCharacters(
source, _swift_shims_CFRange(location: startIndex, length: count),
UnsafeMutablePointer<_swift_shims_UniChar>(buffer.start))
buffer.start.assumingMemoryBound(to: _swift_shims_UniChar.self))

return buffer
}
Expand Down Expand Up @@ -163,13 +163,13 @@ extension String {

// start will hold the base pointer of contiguous storage, if it
// is found.
var start: OpaquePointer?
var start: UnsafeMutableRawPointer?
let isUTF16 = (nulTerminatedASCII == nil)
if isUTF16 {
let utf16Buf = _swift_stdlib_CFStringGetCharactersPtr(cfImmutableValue)
start = OpaquePointer(utf16Buf)
start = UnsafeMutableRawPointer(mutating: utf16Buf)
} else {
start = OpaquePointer(nulTerminatedASCII)
start = UnsafeMutableRawPointer(mutating: nulTerminatedASCII)
}

self._core = _StringCore(
Expand Down
42 changes: 27 additions & 15 deletions stdlib/public/core/StringBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct _StringBufferIVars {
}

internal init(
_usedEnd: UnsafeMutablePointer<_RawByte>,
_usedEnd: UnsafeMutableRawPointer,
byteCapacity: Int,
elementWidth: Int
) {
Expand All @@ -31,7 +31,7 @@ struct _StringBufferIVars {

// This stored property should be stored at offset zero. We perform atomic
// operations on it using _HeapBuffer's pointer.
var usedEnd: UnsafeMutablePointer<_RawByte>?
var usedEnd: UnsafeMutableRawPointer?

var capacityAndElementShift: Int
var byteCapacity: Int {
Expand Down Expand Up @@ -78,6 +78,14 @@ public struct _StringBuffer {
_StringBufferIVars(_elementWidth: elementWidth),
(capacity + capacityBump + divRound) >> divRound
)
// This conditional branch should fold away during code gen.
if elementShift == 0 {
start.bindMemory(to: UTF8.CodeUnit.self, capacity: initialSize)
}
else {
start.bindMemory(to: UTF16.CodeUnit.self, capacity: initialSize)
}

self.usedEnd = start + (initialSize << elementShift)
_storage.value.capacityAndElementShift
= ((_storage._capacity() - capacityBump) << 1) + elementShift
Expand Down Expand Up @@ -107,7 +115,7 @@ public struct _StringBuffer {
elementWidth: isAscii ? 1 : 2)

if isAscii {
var p = UnsafeMutablePointer<UTF8.CodeUnit>(result.start)
var p = result.start.assumingMemoryBound(to: UTF8.CodeUnit.self)
let sink: (UTF32.CodeUnit) -> Void = {
p.pointee = UTF8.CodeUnit($0)
p += 1
Expand Down Expand Up @@ -137,12 +145,12 @@ public struct _StringBuffer {

/// A pointer to the start of this buffer's data area.
public // @testable
var start: UnsafeMutablePointer<_RawByte> {
return UnsafeMutablePointer(_storage.baseAddress)
var start: UnsafeMutableRawPointer {
return UnsafeMutableRawPointer(_storage.baseAddress)
}

/// A past-the-end pointer for this buffer's stored data.
var usedEnd: UnsafeMutablePointer<_RawByte> {
var usedEnd: UnsafeMutableRawPointer {
get {
return _storage.value.usedEnd!
}
Expand All @@ -156,7 +164,7 @@ public struct _StringBuffer {
}

/// A past-the-end pointer for this buffer's available storage.
var capacityEnd: UnsafeMutablePointer<_RawByte> {
var capacityEnd: UnsafeMutableRawPointer {
return start + _storage.value.byteCapacity
}

Expand All @@ -181,11 +189,11 @@ public struct _StringBuffer {
// two separate phases. Operations with one-phase growth should use
// "grow()," below.
func hasCapacity(
_ cap: Int, forSubRange r: Range<UnsafePointer<_RawByte>>
_ cap: Int, forSubRange r: Range<UnsafeRawPointer>
) -> Bool {
// The substring to be grown could be pointing in the middle of this
// _StringBuffer.
let offset = (r.lowerBound - UnsafePointer(start)) >> elementShift
let offset = (r.lowerBound - UnsafeRawPointer(start)) >> elementShift
return cap + offset <= capacity
}

Expand All @@ -202,13 +210,14 @@ public struct _StringBuffer {
@inline(__always)
@discardableResult
mutating func grow(
oldBounds bounds: Range<UnsafePointer<_RawByte>>, newUsedCount: Int
oldBounds bounds: Range<UnsafeRawPointer>, newUsedCount: Int
) -> Bool {
var newUsedCount = newUsedCount
// The substring to be grown could be pointing in the middle of this
// _StringBuffer. Adjust the size so that it covers the imaginary
// substring from the start of the buffer to `oldUsedEnd`.
newUsedCount += (bounds.lowerBound - UnsafePointer(start)) >> elementShift
newUsedCount
+= (bounds.lowerBound - UnsafeRawPointer(start)) >> elementShift

if _slowPath(newUsedCount > capacity) {
return false
Expand All @@ -230,11 +239,14 @@ public struct _StringBuffer {
// usedEnd = newUsedEnd
// return true
// }
let usedEndPhysicalPtr =
UnsafeMutablePointer<UnsafeMutablePointer<_RawByte>>(_storage._value)
var expected = UnsafeMutablePointer<_RawByte>(bounds.upperBound)

// &StringBufferIVars.usedEnd
let usedEndPhysicalPtr = _PointerToPointer(_storage._value)
// Create a temp var to hold the exchanged `expected` value.
var expected : UnsafeRawPointer? = bounds.upperBound
if _stdlib_atomicCompareExchangeStrongPtr(
object: usedEndPhysicalPtr, expected: &expected, desired: newUsedEnd) {
object: usedEndPhysicalPtr, expected: &expected,
desired: UnsafeRawPointer(newUsedEnd)) {
return true
}

Expand Down
Loading