> 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
