> On 3. Aug 2017, at 00:21, John McCall <rjmcc...@apple.com> wrote:
> 
> 
>> On Aug 2, 2017, at 6:10 PM, John McCall via swift-evolution 
>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> On Aug 2, 2017, at 5:56 PM, Karl Wagner <razie...@gmail.com 
>>> <mailto:razie...@gmail.com>> wrote:
>>>> On 31. Jul 2017, at 21:09, John McCall via swift-evolution 
>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>> 
>>>>> On Jul 31, 2017, at 3:15 AM, Gor Gyolchanyan 
>>>>> <gor.f.gyolchan...@icloud.com <mailto:gor.f.gyolchan...@icloud.com>> 
>>>>> wrote:
>>>>>> On Jul 31, 2017, at 7:10 AM, John McCall via swift-evolution 
>>>>>> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
>>>>>> 
>>>>>>> On Jul 30, 2017, at 11:43 PM, Daryle Walker <dary...@mac.com 
>>>>>>> <mailto:dary...@mac.com>> wrote:
>>>>>>> The parameters for a fixed-size array type determine the type's 
>>>>>>> size/stride, so how could the bounds not be needed during compile-time? 
>>>>>>> The compiler can't layout objects otherwise. 
>>>>>> 
>>>>>> Swift is not C; it is perfectly capable of laying out objects at run 
>>>>>> time.  It already has to do that for generic types and types with 
>>>>>> resilient members.  That does, of course, have performance consequences, 
>>>>>> and those performance consequences might be unacceptable to you; but the 
>>>>>> fact that we can handle it means that we don't ultimately require a 
>>>>>> semantic concept of a constant expression, except inasmuch as we want to 
>>>>>> allow users to explicitly request guarantees about static layout.
>>>>> 
>>>>> Doesn't this defeat the purpose of generic value parameters? We might as 
>>>>> well use a regular parameter if there's no compile-time evaluation 
>>>>> involved. In that case, fixed-sized arrays will be useless, because 
>>>>> they'll be normal arrays with resizing disabled.
>>>> 
>>>> You're making huge leaps here.  The primary purpose of a fixed-size array 
>>>> feature is to allow the array to be allocated "inline" in its context 
>>>> instead of "out-of-line" using heap-allocated copy-on-write buffers.  
>>>> There is no reason that that representation would not be supportable just 
>>>> because the array's bound is not statically known; the only thing that 
>>>> matters is whether the bound is consistent for all instances of the 
>>>> container.
>>>> 
>>>> That is, it would not be okay to have a type like:
>>>>  struct Widget {
>>>>    let length: Int
>>>>    var array: [length x Int]
>>>>  }
>>>> because the value of the bound cannot be computed independently of a 
>>>> specific value.
>>>> 
>>>> But it is absolutely okay to have a type like:
>>>>  struct Widget {
>>>>    var array: [(isRunningOnIOS15() ? 20 : 10) x Int]
>>>>  }
>>>> It just means that the bound would get computed at runtime and, 
>>>> presumably, cached.  The fact that this type's size isn't known statically 
>>>> does mean that the compiler has to be more pessimistic, but its values 
>>>> would still get allocated inline into their containers and even on the 
>>>> stack, using pretty much the same techniques as C99 VLAs.
>>> 
>>> Do we really want to make that guarantee about heap/stack allocation? C99’s 
>>> VLAs are not very loop-friendly:
>>> 
>>> echo "int main() { 
>>>         for(int i = 0; i<1000000; i++) {
>>>           int myArray[i * 1000]; myArray[0] = 32;
>>>         }
>>>         return 0;
>>>       }" | clang -x c - && ./a.out
>>> 
>>> Segmentation Fault: 11
>>> 
>>> C compilers also do not inline code with VLAs by default. If you force it, 
>>> you expose yourself to possible stack overflows:
>>> 
>>> echo "static inline void doSomething(int i) {
>>>         int myArray[i * 1000]; myArray[0] = 32;
>>>       }
>>>       int main() {
>>>         for(int i = 0; i<1000000; i++) {
>>>           doSomething(i);
>>>         }
>>>       return 0;
>>>       }" | clang -x c - && ./a.out
>>> 
>>> Segmentation Fault: 11
>>> 
>>> I wouldn’t like us to import these kinds of issues in to Swift
>> 
>> We probably would not make an absolute guarantee of stack allocation, no.
> 
> Although I will note that the problem in your example has nothing to do with 
> it being a loop and everything to do with it asking for an almost 4GB array. 
> :)
> 
> John.


Yeah, apologies - it was a bit of a poorly-written example.

The root cause, of course, is that the VLAs require new stack allocations each 
time, and the stack is only deallocated as one lump when the frame ends. A 
fixed-size object could be allocated once and re-used. Inlining prevents new 
stack frames being created and hence defers deallocation of those objects until 
the outer function ends, pushing up the high-water mark of the stack.

The problem also happens with an outer loop of only 10_000, so only 38MB. 
Still, enough to blow it up.

- Karl
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to