diff --git a/Compiler/src/tfuncs.jl b/Compiler/src/tfuncs.jl index 906bc9521adf9..e51d43e5b2fe1 100644 --- a/Compiler/src/tfuncs.jl +++ b/Compiler/src/tfuncs.jl @@ -2017,9 +2017,12 @@ function tuple_tfunc(𝕃::AbstractLattice, argtypes::Vector{Any}) return anyinfo ? PartialStruct(𝕃, typ, argtypes) : typ end -@nospecs function memorynew_tfunc(𝕃::AbstractLattice, memtype, m) - hasintersect(widenconst(m), Int) || return Bottom - return tmeet(𝕃, instanceof_tfunc(memtype, true)[1], GenericMemory) +@nospecs function memorynew_tfunc(𝕃::AbstractLattice, memtype, memlen) + hasintersect(widenconst(memlen), Int) || return Bottom + memt = tmeet(𝕃, instanceof_tfunc(memtype, true)[1], GenericMemory) + memt == Union{} && return memt + # PartialStruct so that loads of Const `length` get inferred + return PartialStruct(𝕃, memt, Any[memlen, Ptr{Nothing}]) end add_tfunc(Core.memorynew, 2, 2, memorynew_tfunc, 10) @@ -3125,16 +3128,7 @@ add_tfunc(Core.get_binding_type, 2, 2, @nospecs((𝕃::AbstractLattice, args...) const FOREIGNCALL_ARG_START = 6 -function foreigncall_effects(@specialize(abstract_eval), e::Expr) - args = e.args - name = args[1] - isa(name, QuoteNode) && (name = name.value) - if name === :jl_alloc_genericmemory - nothrow = new_genericmemory_nothrow(abstract_eval, args) - return Effects(EFFECTS_TOTAL; consistent=CONSISTENT_IF_NOTRETURNED, nothrow) - elseif name === :jl_genericmemory_copy_slice - return Effects(EFFECTS_TOTAL; consistent=CONSISTENT_IF_NOTRETURNED, nothrow=false) - end +function foreigncall_effects(@nospecialize(abstract_eval), e::Expr) # `:foreigncall` can potentially perform all sorts of operations, including calling # overlay methods, but the `:foreigncall` itself is not dispatched, and there is no # concern that the method calls that potentially occur within the `:foreigncall` will diff --git a/base/array.jl b/base/array.jl index 4c3dde73d52ba..aafcfc182124b 100644 --- a/base/array.jl +++ b/base/array.jl @@ -346,12 +346,13 @@ See also [`copy!`](@ref Base.copy!), [`copyto!`](@ref), [`deepcopy`](@ref). """ copy -@eval function copy(a::Array{T}) where {T} - # `jl_genericmemory_copy_slice` only throws when the size exceeds the max allocation - # size, but since we're copying an existing array, we're guaranteed that this will not happen. +@eval function copy(a::Array) + # `copy` only throws when the size exceeds the max allocation size, + # but since we're copying an existing array, we're guaranteed that this will not happen. @_nothrow_meta ref = a.ref - newmem = ccall(:jl_genericmemory_copy_slice, Ref{Memory{T}}, (Any, Ptr{Cvoid}, Int), ref.mem, ref.ptr_or_offset, length(a)) + newmem = typeof(ref.mem)(undef, length(a)) + @inbounds unsafe_copyto!(memoryref(newmem), ref, length(a)) return $(Expr(:new, :(typeof(a)), :(memoryref(newmem)), :(a.size))) end diff --git a/base/genericmemory.jl b/base/genericmemory.jl index 9d4614135050b..2a33336c0aad6 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -144,6 +144,7 @@ function unsafe_copyto!(dest::Memory{T}, doffs, src::Memory{T}, soffs, n) where{ return dest end +#fallback method when types don't match function unsafe_copyto!(dest::Memory, doffs, src::Memory, soffs, n) @_terminates_locally_meta n == 0 && return dest @@ -171,7 +172,13 @@ function unsafe_copyto!(dest::Memory, doffs, src::Memory, soffs, n) return dest end -copy(a::T) where {T<:Memory} = ccall(:jl_genericmemory_copy, Ref{T}, (Any,), a) +function copy(a::T) where {T<:Memory} + # `copy` only throws when the size exceeds the max allocation size, + # but since we're copying an existing array, we're guaranteed that this will not happen. + @_nothrow_meta + newmem = T(undef, length(a)) + @inbounds unsafe_copyto!(newmem, 1, a, 1, length(a)) +end copyto!(dest::Memory, src::Memory) = copyto!(dest, 1, src, 1, length(src)) function copyto!(dest::Memory, doffs::Integer, src::Memory, soffs::Integer, n::Integer)