//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 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 // //===----------------------------------------------------------------------===// /// The memory layout of a type, describing its size, stride, and alignment. /// /// You can use `MemoryLayout` as a source of information about a type when /// allocating or binding memory using raw pointers. The following example /// declares a `Point` type with `x` and `y` coordinates and a Boolean /// `isFilled` property. /// /// struct Point { /// let x: Double /// let y: Double /// let isFilled: Bool /// } /// /// The size, stride, and alignment of the `Point` type are accessible as /// static properties of `MemoryLayout`. /// /// // MemoryLayout.size == 17 /// // MemoryLayout.stride == 24 /// // MemoryLayout.alignment == 8 /// /// Always use a multiple of a type's `stride` instead of its `size` when /// allocating memory or accounting for the distance between instances in /// memory. This example allocates uninitialized raw memory with space /// for four instances of `Point`. /// /// let count = 4 /// let pointPointer = UnsafeMutableRawPointer.allocate( /// byteCount: count * MemoryLayout.stride, /// alignment: MemoryLayout.alignment) @frozen // namespace public enum MemoryLayout { /// The contiguous memory footprint of `T`, in bytes. /// /// A type's size does not include any dynamically allocated or out of line /// storage. In particular, `MemoryLayout.size`, when `T` is a class /// type, is the same regardless of how many stored properties `T` has. /// /// When allocating memory for multiple instances of `T` using an unsafe /// pointer, use a multiple of the type's stride instead of its size. @_transparent public static var size: Int { return Int(Builtin.sizeof(T.self)) } /// The number of bytes from the start of one instance of `T` to the start of /// the next when stored in contiguous memory or in an `Array`. /// /// This is the same as the number of bytes moved when an `UnsafePointer` /// instance is incremented. `T` may have a lower minimal alignment that /// trades runtime performance for space efficiency. This value is always /// positive. @_transparent public static var stride: Int { return Int(Builtin.strideof(T.self)) } /// The default memory alignment of `T`, in bytes. /// /// Use the `alignment` property for a type when allocating memory using an /// unsafe pointer. This value is always positive. @_transparent public static var alignment: Int { return Int(Builtin.alignof(T.self)) } } extension MemoryLayout { /// Returns the contiguous memory footprint of the given instance. /// /// The result does not include any dynamically allocated or out of line /// storage. In particular, pointers and class instances all have the same /// contiguous memory footprint, regardless of the size of the referenced /// data. /// /// When you have a type instead of an instance, use the /// `MemoryLayout.size` static property instead. /// /// let x: Int = 100 /// /// // Finding the size of a value's type /// let s = MemoryLayout.size(ofValue: x) /// // s == 8 /// /// // Finding the size of a type directly /// let t = MemoryLayout.size /// // t == 8 /// /// - Parameter value: A value representative of the type to describe. /// - Returns: The size, in bytes, of the given value's type. @_transparent public static func size(ofValue value: T) -> Int { return MemoryLayout.size } /// Returns the number of bytes from the start of one instance of `T` to the /// start of the next when stored in contiguous memory or in an `Array`. /// /// This is the same as the number of bytes moved when an `UnsafePointer` /// instance is incremented. `T` may have a lower minimal alignment that /// trades runtime performance for space efficiency. The result is always /// positive. /// /// When you have a type instead of an instance, use the /// `MemoryLayout.stride` static property instead. /// /// let x: Int = 100 /// /// // Finding the stride of a value's type /// let s = MemoryLayout.stride(ofValue: x) /// // s == 8 /// /// // Finding the stride of a type directly /// let t = MemoryLayout.stride /// // t == 8 /// /// - Parameter value: A value representative of the type to describe. /// - Returns: The stride, in bytes, of the given value's type. @_transparent public static func stride(ofValue value: T) -> Int { return MemoryLayout.stride } /// Returns the default memory alignment of `T`. /// /// Use a type's alignment when allocating memory using an unsafe pointer. /// /// When you have a type instead of an instance, use the /// `MemoryLayout.stride` static property instead. /// /// let x: Int = 100 /// /// // Finding the alignment of a value's type /// let s = MemoryLayout.alignment(ofValue: x) /// // s == 8 /// /// // Finding the alignment of a type directly /// let t = MemoryLayout.alignment /// // t == 8 /// /// - Parameter value: A value representative of the type to describe. /// - Returns: The default memory alignment, in bytes, of the given value's /// type. This value is always positive. @_transparent public static func alignment(ofValue value: T) -> Int { return MemoryLayout.alignment } /// Returns the offset of an inline stored property within a type's in-memory /// representation. /// /// You can use this method to find the distance in bytes that can be added /// to a pointer of type `T` to get a pointer to the property referenced by /// `key`. The offset is available only if the given key refers to inline, /// directly addressable storage within the in-memory representation of `T`. /// /// If the return value of this method is non-`nil`, then accessing the value /// by key path or by an offset pointer are equivalent. For example, for a /// variable `root` of type `T`, a key path `key` of type /// `WritableKeyPath`, and a `value` of type `U`: /// /// // Mutation through the key path /// root[keyPath: key] = value /// /// // Mutation through the offset pointer /// withUnsafeMutableBytes(of: &root) { bytes in /// let offset = MemoryLayout.offset(of: key)! /// let rawPointerToValue = bytes.baseAddress! + offset /// let pointerToValue = rawPointerToValue.assumingMemoryBound(to: U.self) /// pointerToValue.pointee = value /// } /// /// A property has inline, directly addressable storage when it is a stored /// property for which no additional work is required to extract or set the /// value. Properties are not directly accessible if they trigger any /// `didSet` or `willSet` accessors, perform any representation changes such /// as bridging or closure reabstraction, or mask the value out of /// overlapping storage as for packed bitfields. In addition, because class /// instance properties are always stored out-of-line, their positions are /// not accessible using `offset(of:)`. /// /// For example, in the `ProductCategory` type defined here, only /// `\.updateCounter`, `\.identifier`, and `\.identifier.name` refer to /// properties with inline, directly addressable storage: /// /// struct ProductCategory { /// struct Identifier { /// var name: String // addressable /// } /// /// var identifier: Identifier // addressable /// var updateCounter: Int // addressable /// var products: [Product] { // not addressable: didSet handler /// didSet { updateCounter += 1 } /// } /// var productCount: Int { // not addressable: computed property /// return products.count /// } /// } /// /// When using `offset(of:)` with a type imported from a library, don't /// assume that future versions of the library will have the same behavior. /// If a property is converted from a stored property to a computed /// property, the result of `offset(of:)` changes to `nil`. That kind of /// conversion is nonbreaking in other contexts, but would trigger a runtime /// error if the result of `offset(of:)` is force-unwrapped. /// /// - Parameter key: A key path referring to storage that can be accessed /// through a value of type `T`. /// - Returns: The offset in bytes from a pointer to a value of type `T` to a /// pointer to the storage referenced by `key`, or `nil` if no such offset /// is available for the storage referenced by `key`. If the value is /// `nil`, it can be because `key` is computed, has observers, requires /// reabstraction, or overlaps storage with other properties. @_transparent public static func offset(of key: PartialKeyPath) -> Int? { return key._storedInlineOffset } } // Not-yet-public alignment conveniences extension MemoryLayout { internal static var _alignmentMask: Int { return alignment - 1 } internal static func _roundingUpToAlignment(_ value: Int) -> Int { return (value + _alignmentMask) & ~_alignmentMask } internal static func _roundingDownToAlignment(_ value: Int) -> Int { return value & ~_alignmentMask } internal static func _roundingUpToAlignment(_ value: UInt) -> UInt { return (value + UInt(bitPattern: _alignmentMask)) & ~UInt(bitPattern: _alignmentMask) } internal static func _roundingDownToAlignment(_ value: UInt) -> UInt { return value & ~UInt(bitPattern: _alignmentMask) } internal static func _roundingUpToAlignment(_ value: UnsafeRawPointer) -> UnsafeRawPointer { return UnsafeRawPointer(bitPattern: _roundingUpToAlignment(UInt(bitPattern: value))).unsafelyUnwrapped } internal static func _roundingDownToAlignment(_ value: UnsafeRawPointer) -> UnsafeRawPointer { return UnsafeRawPointer(bitPattern: _roundingDownToAlignment(UInt(bitPattern: value))).unsafelyUnwrapped } internal static func _roundingUpToAlignment(_ value: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { return UnsafeMutableRawPointer(bitPattern: _roundingUpToAlignment(UInt(bitPattern: value))).unsafelyUnwrapped } internal static func _roundingDownToAlignment(_ value: UnsafeMutableRawPointer) -> UnsafeMutableRawPointer { return UnsafeMutableRawPointer(bitPattern: _roundingDownToAlignment(UInt(bitPattern: value))).unsafelyUnwrapped } internal static func _roundingUpBaseToAlignment(_ value: UnsafeRawBufferPointer) -> UnsafeRawBufferPointer { let baseAddressBits = Int(bitPattern: value.baseAddress) var misalignment = baseAddressBits & _alignmentMask if misalignment != 0 { misalignment = _alignmentMask & -misalignment return UnsafeRawBufferPointer( start: UnsafeRawPointer(bitPattern: baseAddressBits + misalignment), count: value.count - misalignment) } return value } internal static func _roundingUpBaseToAlignment(_ value: UnsafeMutableRawBufferPointer) -> UnsafeMutableRawBufferPointer { let baseAddressBits = Int(bitPattern: value.baseAddress) var misalignment = baseAddressBits & _alignmentMask if misalignment != 0 { misalignment = _alignmentMask & -misalignment return UnsafeMutableRawBufferPointer( start: UnsafeMutableRawPointer(bitPattern: baseAddressBits + misalignment), count: value.count - misalignment) } return value } }