> 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

Reply via email to