> On Jul 31, 2017, at 4:37 PM, Gor Gyolchanyan <[email protected]> 
> wrote:
> 
>> 
>> On Jul 31, 2017, at 11:23 PM, John McCall <[email protected] 
>> <mailto:[email protected]>> wrote:
>> 
>>> 
>>> On Jul 31, 2017, at 4:00 PM, Gor Gyolchanyan <[email protected] 
>>> <mailto:[email protected]>> wrote:
>>> 
>>> 
>>>> On Jul 31, 2017, at 10:09 PM, John McCall <[email protected] 
>>>> <mailto:[email protected]>> wrote:
>>>> 
>>>>> On Jul 31, 2017, at 3:15 AM, Gor Gyolchanyan 
>>>>> <[email protected] <mailto:[email protected]>> 
>>>>> wrote:
>>>>>> On Jul 31, 2017, at 7:10 AM, John McCall via swift-evolution 
>>>>>> <[email protected] <mailto:[email protected]>> wrote:
>>>>>> 
>>>>>>> On Jul 30, 2017, at 11:43 PM, Daryle Walker <[email protected] 
>>>>>>> <mailto:[email protected]>> 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.
>>> 
>>> I see your point. Dynamically-sized in-place allocation is something that 
>>> completely escaped me when I was thinking of fixed-size arrays. I can say 
>>> with confidence that a large portion of private-class-copy-on-write value 
>>> types would greatly benefit from this and would finally be able to become 
>>> true value types.
>> 
>> To be clear, it's not obvious that using an inline array is always a good 
>> move for performance!  But it would be a tool available for use when people 
>> felt it was important.
> 
> That's why I'm trying to push for compile-time execution system. All these 
> problems (among many others) could be designed out of existence and the 
> compiler would be incredibly simple in the light of all the different 
> specific features that the community is asking for. But I do feel your urge 
> to avoid inventing a bulldozer factory just for digging a hole in a sandbox. 
> It doesn't have to be relied upon by the type checker or generic resolution 
> mechanism. It would be purely auxiliary. But that would single-handedly move 
> a large chunk of the compiler into stdlib and a huge portion of various 
> little incidental proposals would fade away because they can now easily be 
> implemented in Swift for specific purposes.
> 
>>>>> As far as I know, the pinnacle of uses for fixed-size arrays is having a 
>>>>> compile-time pre-allocated space of the necessary size (either literally 
>>>>> at compile-time if that's a static variable, or added to the pre-computed 
>>>>> offset of the stack pointer in case of a local variable).
>>>> 
>>>> The difference between having to use dynamic offsets + alloca() and static 
>>>> offsets + a normal stack slot is noticeable but not nearly as extreme as 
>>>> you're imagining.  And again, in most common cases we would absolutely be 
>>>> able to fold a bound statically and fall into the optimal path you're 
>>>> talking about.  The critical guarantee, that the array does not get 
>>>> heap-allocated, is still absolutely intact.
>>> 
>>> Yet again, Swift (specifically - you in this case) is teaching me to trust 
>>> the compiler to optimize, which is still an alien feeling to me even after 
>>> all these years of heavy Swift usage. Damn you, C++ for corrupting my brain 
>>> πŸ˜€.
>> 
>> Well.  Trust but verify. πŸ™‚
> 
> The only good way I can think of doing that is hand-crafting a lightning-fast 
> implementation LLVM IR, then doing the same in Swift, decompiling the bitcode 
> and then doing a diff. It's going to be super tedious and painful, but it 
> seems to be the only way to prove that Swift can (hopefully, some day...) 
> replace C++ in sheer performance potential.
> 
>>> In the specific case of having dynamic-sized in-place-allocated value types 
>>> this will absolutely work. But this raises a chicken-and-the-egg problem: 
>>> which is built in what: in-place allocated dynamic-sized value types, or 
>>> specifically fixed-size arrays? On one hand I'm tempted to think that value 
>>> types should be able to dynamically decide (inside the initializer) the 
>>> exact size of the allocated memory (no less than the static size) that they 
>>> occupy (no matter if on the heap, on the stack or anywhere else), after 
>>> which they'd be able to access the "leftover" memory by a pointer and do 
>>> whatever they want with it. This approach seems more logical, since this is 
>>> essentially how fixed-size arrays would be implemented under the hood. But 
>>> on the other hand, this does make use of unsafe pointers (and no part of 
>>> Swift currently relies on unsafe pointers to function), so abstracting it 
>>> away behind a magical fixed-size array seems safer (with a hope that a 
>>> fixed-size array of UInt8 would be optimized down to exactly the first 
>>> case).
>> 
>> Representationally, I think we would have a builtin fixed-sized array type 
>> that.  But "fixed-size" means "the size is an inherent part of the type", 
>> not "we actually know that size statically".  Swift would just be able to 
>> use more optimal code-generation patterns for types whose bounds it was 
>> actually able to compute statically.
> 
> Well, yeah, knowing its size statically is not a requirement, but having a 
> guarantee of in-place allocation is. As long as non-escaped local fixed-size 
> arrays live on the stack, I'm happy. πŸ™‚

I was neutral on this, but after waking up I realized a problem. I want to use 
the LLVM type primitives to implement fixed-size arrays. Doing a run-time 
determination of layout and implementing it with alloca forfeits that (AFAIK). 
Unless the Swift run-time library comes with LLVM (which I doubt). Which means 
we do need compile-time constants after all.

β€” 
Daryle Walker
Mac, Internet, and Video Game Junkie
darylew AT mac DOT com 

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to