> On May 6, 2017, at 9:33 PM, Kelvin Ma via swift-users <swift-users@swift.org> 
> wrote:
> 
> If I have a “large” struct like
> 
> struct Vertex
> {
>     let x:Double, y:Double
>     var r:Int, g:Int, b:Int
>     let s:Double, t:Double
>     var selected:Bool
> }
> 
> and I want to pass it to a function without modifying it like
> 
> func taxicab_distance(_ v1:Vertex, _ v2:Vertex) -> Double
> {
>     return v2.x - v1.x + v2.y - v1.y
> }
> 
> Will the entire struct Vertex get copied and pushed onto the stack, or will 
> only the relevant members be passed to the function?
> 
> In other words, does the compiler know to optimize this call down to
> 
> func taxicab_distance(v2x:Double, v1x:Double, v2y:Double, v1y:Double) -> 
> Double
> {
>     return v2x - v1x + v2y - v1y
> }

When passed as an argument, a struct is recursively broken up into individual 
primitives, and each of those is passed in separate arguments. (The primitive 
types in question are mostly special "builtin" types which are wrapped by 
standard library types like `Int` and `Double`.) As far as I'm aware, there is 
no optimization that removes unused parts of the struct. That means this would 
be passed as something like:

func taxicab_distance(_ v1.x._value: Builtin.Float64, _ v1.y._value: 
Builtin.Float64, _ v1.r._value: Builtin.Int64, _ v1.g._value: Builtin.Int64, _ 
v1.b._value: Builtin.Int64, _ v1.s._value: Builtin.Float64, _ v1.t._value: 
Builtin.Float64, _ v1.selected._value: Builtin.Int1, _ v2.x._value: 
Builtin.Float64, _ v2.y._value: Builtin.Float64, _ v2.r._value: Builtin.Int64, 
_ v2.g._value: Builtin.Int64, _ v2.b._value: Builtin.Int64, _ v2.s._value: 
Builtin.Float64, _ v2.t._value: Builtin.Float64, _ v2.selected._value: 
Builtin.Int1) -> Builtin.Float64 { … }

Because of this, it may sometimes make sense to convert large structs into 
copy-on-write types by hand—basically, make a struct which wraps an inner class 
type, guarding all mutations with an `isUniquelyReferenced(_:)` check. (You're 
right that there's no implicit copy-on-write behavior in structs currently—when 
a struct has copy-on-write behavior, it has been manually implemented that way.)

Note that this may not always be the case: There's a built-in copy-on-write 
optimization which will soon come to instances which have been cast to a 
protocol type, and the "resilient" structs planned for a future version of 
Swift will probably be passed by reference in some way. But I believe that's 
the state of things in Swift 3.

-- 
Brent Royal-Gordon
Architechies

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

Reply via email to