Sorry, not sure how I missed that 😑.

> On Aug 4, 2017, at 3:16 PM, Félix Cloutier <felixclout...@icloud.com> wrote:
> 
> 
>> Le 4 août 2017 à 11:39, Robert Bennett <rltbenn...@icloud.com> a écrit :
>> 
>>> That's not a concern with the `let` case that Robert brought up, since you 
>>> can't mutate a `let` array at all.
>>> 
>>> The big thing is that unconstrained escape analysis is uncomputable. Since 
>>> Swift array storage is COW, any function that receives the array as a 
>>> parameter is allowed to take a reference on its storage. If the storage 
>>> lives on the stack and that reference outlives the stack frame, you've got 
>>> a problem. It's the same problem that motivated @escaping for closures.
>>> 
>>> You could allow storage to be on the stack by forcing user to make a 
>>> pessimistic copy, which is possibly not an improvement.
>> 
>> 
>> Good point. If this is only problematic when multiple threads are accessing 
>> an array, then it could still be worthwhile if all accesses are (provably) 
>> on the thread that created the array.
> 
> To be clear, it's a problem independently of multi-threading. `func foo() -> 
> [Int] { return [1, 2, 3] }` is the most basic representation of it: you can't 
> store the array in the stack frame if you return it. (To be fair, that one 
> would be caught by escape analysis of any quality.) `func foo() { bar([1, 2, 
> 3, 4]) }` is another example: if you don't know what `bar` does with the 
> array, you can't store it on the stack because it might pass it to an object 
> that lives on the heap and outlives `foo`, for instance. @escaping solves 
> that problem for closures by specifically annotating parameters when the 
> assigned closure could still be referenced after the called function returns.
> 
>> And pessimistic copying might still be worth it for arrays below a certain 
>> size — for instance, copying an Array<Int> of length 1 (and recall that the 
>> array in question is a constant so its size is known at compile time) would 
>> definitely be worth not having that array in heap memory.
> 
> You only need pessimistic copies when that copy escapes, and since it 
> escapes, it needs to live on the heap by definition. Right now an array of 
> size 1 passed to 4 objects on the heap has one single backing representation. 
> With pessimistic copies, you'd get 4 times that buffer of size 1, which is 
> definitely not an improvement.
> 
>> Going back to the literal notion of FSAs — fixed size arrays not necessarily 
>> on the stack — I think that simply copying Array’s implementation sans 
>> RangeReplaceableCollection conformance is not a bad way to go. Any 
>> optimizations used for `let` Arrays could probably be applied to this type 
>> of FSA.
> 
> We're actually splitting this in multiple directions. John talks of 
> variable-sized arrays necessarily on the stack. :)
> 
> I see two useful characteristics to fixed-size arrays, which, 
> uncoincidentally, are what it takes to use them for C interop:
> 
> Their storage is inlined into their container (whether it be the stack or an 
> object)
> Their length is part of their type (and not directly included with the data 
> itself)
> 
> This is also enough to implement fixed-size arrays not necessarily on the 
> stack, mind you.
> 
> Félix
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to