diff --git a/base/array.jl b/base/array.jl index cde8e292d881d..a572ee5c305e7 100644 --- a/base/array.jl +++ b/base/array.jl @@ -1053,9 +1053,19 @@ function push!(a::Array{T,1}, item) where T return a end -function push!(a::Array{Any,1}, @nospecialize item) +# specialize and optimize the single argument case +function push!(a::Vector{Any}, @nospecialize x) _growend!(a, 1) - arrayset(true, a, item, length(a)) + arrayset(true, a, x, length(a)) + return a +end +function push!(a::Vector{Any}, @nospecialize x...) + na = length(a) + nx = length(x) + _growend!(a, nx) + for i = 1:nx + arrayset(true, a, x[i], na+i) + end return a end @@ -1385,6 +1395,22 @@ function pushfirst!(a::Array{T,1}, item) where T return a end +# specialize and optimize the single argument case +function pushfirst!(a::Vector{Any}, @nospecialize x) + _growbeg!(a, 1) + a[1] = x + return a +end +function pushfirst!(a::Vector{Any}, @nospecialize x...) + na = length(a) + nx = length(x) + _growbeg!(a, nx) + for i = 1:nx + a[i] = x[i] + end + return a +end + """ popfirst!(collection) -> item diff --git a/test/compiler/inline.jl b/test/compiler/inline.jl index 3dac08370c123..5a9cb1733be77 100644 --- a/test/compiler/inline.jl +++ b/test/compiler/inline.jl @@ -1375,3 +1375,30 @@ let src = code_typed1() do @test count(isnew, src.code) == 1 @test count(isinvoke(:noinline_finalizer), src.code) == 1 end + +# optimize `[push!|pushfirst!](::Vector{Any}, x...)` +@testset "optimize `$f(::Vector{Any}, x...)`" for f = Any[push!, pushfirst!] + @eval begin + let src = code_typed1((Vector{Any}, Any)) do xs, x + $f(xs, x) + end + @test count(iscall((src, $f)), src.code) == 0 + @test count(src.code) do @nospecialize x + isa(x, Core.GotoNode) || + isa(x, Core.GotoIfNot) || + iscall((src, getfield))(x) + end == 0 # no loop should be involved for the common single arg case + end + let src = code_typed1((Vector{Any}, Any, Any)) do xs, x, y + $f(xs, x, y) + end + @test count(iscall((src, $f)), src.code) == 0 + end + let xs = Any[] + $f(xs, :x, "y", 'z') + @test xs[1] === :x + @test xs[2] == "y" + @test xs[3] === 'z' + end + end +end