How come this is non-allocating?

Since eltype(v) is abstract (and not a small union), the underlying data is stored as an array of pointers to tuples. And since tuples are immutable, when you assign them all to (1,1,1) the compiler is allowed to store the same pointer for every element:

julia> v = [ isodd(i) ? (0,0) : (0,0,0) for i in 1:5 ];

julia> mutate_vec!(v)

julia> p = unsafe_wrap(Array, Ptr{Ptr{Int}}(pointer(v)), length(v))
5-element Array{Ptr{Int64},1}:
 Ptr{Int64} @0x000000011655e470
 Ptr{Int64} @0x000000011655e470
 Ptr{Int64} @0x000000011655e470
 Ptr{Int64} @0x000000011655e470
 Ptr{Int64} @0x000000011655e470

julia> unsafe_wrap(Array, p[1], 3)
3-element Array{Int64,1}:
 1
 1
 1

Furthermore, the compiler may not need to allocate the (1,1,1) tuple on the heap — since it is constant and immutable, it might just get stored in a data segment of the compiled object code.

10 Likes