diff --git a/src/compiler.jl b/src/compiler.jl index 9416ebea92..2438945b3a 100644 --- a/src/compiler.jl +++ b/src/compiler.jl @@ -1970,19 +1970,31 @@ end return y end - flds = Vector{Any}(undef, nf) - for i in 1:nf - if isdefined(prevs, i) + + y = if all(p -> isdefined(p, nf), prevs) + # fast path when all fields are set + splatnew(RT, ntuple(Val(nf)) do i + Base.@_inline_meta xis = ntuple(j -> getfield(prevs[j], i), N) T = Core.Typeof(first(xis)) - yi = recursive_map(T, f, seen, xis, basetype) - flds[i] = yi - else - nf = i - 1 # rest of tail must be undefined values - break + recursive_map(T, f, seen, xis, basetype) + end) + else + flds = Vector{Any}(undef, nf) + nset = nf + for i in 1:nf + if all(p -> isdefined(p, i), prevs) + xis = ntuple(j -> getfield(prevs[j], i), N) + T = Core.Typeof(first(xis)) + yi = recursive_map(T, f, seen, xis, basetype) + flds[i] = yi + else + nset = i - 1 # rest of tail must be undefined values + break + end end + ccall(:jl_new_structv, Any, (Any, Ptr{Any}, UInt32), RT, flds, nset) end - y = ccall(:jl_new_structv, Any, (Any, Ptr{Any}, UInt32), RT, flds, nf) seen[prevs] = y return y end