Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
27 changes: 27 additions & 0 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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