> On Sep 6, 2017, at 2:28 PM, Andrew Trick <[email protected]> wrote: > > >> On Sep 6, 2017, at 1:12 PM, Joe Groff via swift-evolution >> <[email protected]> wrote: >> >>> >>> On Sep 6, 2017, at 1:06 PM, Taylor Swift <[email protected]> wrote: >>> >>> >>> >>> On Wed, Sep 6, 2017 at 12:41 PM, Joe Groff via swift-evolution >>> <[email protected]> wrote: >>>> Currently, memory is deallocated by an instance method on >>>> UnsafeMutablePointer, deallocate(count:). Like much of the Swift pointer >>>> API, performing this operation on a buffer pointer requires extracting >>>> baseAddress! and count. It is very common for the allocation code above to >>>> be immediately followed by: >>>> >>>> defer >>>> >>>> { >>>> buffer. >>>> baseAddress?.deallocate(capacity: buffer.count >>>> ) >>>> } >>>> >>>> This method is extremely problematic because nearly all users, on first >>>> seeing the signature of deallocate(capacity:), will naturally conclude >>>> from the capacity label that deallocate(capacity:) is equivalent to some >>>> kind of realloc()that can only shrink the buffer. However this is not the >>>> actual behavior — deallocate(capacity:) actually ignores the capacity >>>> argument and just calls free() on self. The current API is not only >>>> awkward and suboptimal, it is misleading. You can write perfectly legal >>>> Swift code that shouldn’t segfault, but still can, for example >>>> >>>> var ptr = UnsafeMutablePointer<UInt8>.allocate(capacity: 1000000 >>>> ) >>>> ptr. >>>> initialize(to: 13, count: 1000000 >>>> ) >>>> ptr. >>>> deallocate(capacity: 500000) // deallocate the second half of the memory >>>> block >>>> ptr[0] // segmentation fault >>>> where the first 500000 addresses should still be valid if the >>>> documentation is to be read literally. >>> >>> The fact that the Swift runtime currently uses malloc/free is an >>> implementation detail. Tracking deallocation size is a very useful >>> optimization for better allocator backends, and C++ underwent an ABI break >>> to make it so that sized delete can be supported. Maybe we can change the >>> name to `deallocate(allocatedCapacity:)` to make it clear that it isn't >>> resizing the memory, and/or make the capacity argument optional so that you >>> can pay for the overhead of the allocator deriving the size if it's >>> inconvenient for the calling code to carry the size around, but we >>> shouldn't remove the functionality altogether. >>> >>> -Joe >>> _______________________________________________ >>> swift-evolution mailing list >>> [email protected] >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>> >>> The idea is to get the house in order by removing all parameters from >>> deallocate(), since that’s what it really does right now. Then, in the >>> future, if Swift gets a more sophisticated allocator backend, a new method >>> like deallocate(capacity:) or reallocate(toCapacity:) could be added >>> without conflicting with the currently named deallocate(capacity:). >>> However, using the function signature to pretend that it does something it >>> can’t actually do right now is extremely dangerous. >> >> I don't think that's a good idea in this case, because it's not unlikely we >> would explore an optimized allocator soon after ABI stability, and >> retrofitting these interfaces in a future version of Swift would put a >> deployment target limit on when they can be used, and mean that a lot of >> user code would need to be retrofitted to carry allocated capacities where >> needed to see any benefit. >> >> -Joe > > The fact that we’re using malloc and free is already part of the ABI because > old libraries need to be able to deallocate memory allocated by newer > libraries.
The compiler doesn't ever generate calls directly to malloc and free, and the runtime entry points we do use already take size and alignment on both allocation and deallocation. > Within the standard library we could make use of some new deallocation fast > path in the future without worrying about backward deployment. > > Outside of the standard library, clients will get the benefits of whatever > allocator is available on their deployed platform because we now encourage > them to use UnsafeBufferPointer.deallocate(). We can change the > implementation inside UnsafeBufferPointer all we want, as long as it’s still > malloc-compatible. > > I’m sure we’ll want to provide a better allocation/deallocation API in the > future for systems programmers based on move-only types. That will already be > deployment-limited. > > Absolute worst case, we introduce a sized UnsafePointer.deallocate in the > future. Any new code outside the stdlib that wants the performance advantage > would either need to > - trivially wrap deallocation using UnsafeBufferPointer > - create a trivial UnsafePointer.deallocate thunk under an availability flag Since we already have sized deallocate, why would we take it away? If the name is misleading, we can change the name. -Joe _______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
