diff --git a/base/array.jl b/base/array.jl index 480da74619c07..b345d27b9369e 100644 --- a/base/array.jl +++ b/base/array.jl @@ -211,49 +211,17 @@ julia> Base.isbitsunion(Union{Float64, String}) false ``` """ -isbitsunion(u::Union) = allocatedinline(u) -isbitsunion(x) = false +isbitsunion(u::Type) = u isa Union && allocatedinline(u) -function _unsetindex!(A::Array{T}, i::Int) where {T} +function _unsetindex!(A::Array, i::Int) @inline @boundscheck checkbounds(A, i) - t = @_gc_preserve_begin A - p = Ptr{Ptr{Cvoid}}(pointer(A, i)) - if !allocatedinline(T) - Intrinsics.atomic_pointerset(p, C_NULL, :monotonic) - elseif T isa DataType - if !datatype_pointerfree(T) - for j = 1:Core.sizeof(Ptr{Cvoid}):Core.sizeof(T) - Intrinsics.atomic_pointerset(p + j - 1, C_NULL, :monotonic) - end - end - end - @_gc_preserve_end t + @inbounds _unsetindex!(MemoryRef(A.ref, i)) return A end # TODO: deprecate this (aligned_sizeof and/or elsize and/or sizeof(Some{T}) are more correct) -""" - Base.bitsunionsize(U::Union) -> Int - -For a `Union` of [`isbitstype`](@ref) types, return the size of the largest type; assumes `Base.isbitsunion(U) == true`. - -# Examples -```jldoctest -julia> Base.bitsunionsize(Union{Float64, UInt8}) -8 - -julia> Base.bitsunionsize(Union{Float64, UInt8, Int128}) -16 -``` -""" -function bitsunionsize(u::Union) - isinline, sz, _ = uniontype_layout(u) - @assert isinline - return sz -end - elsize(::Type{A}) where {T,A<:Array{T}} = aligned_sizeof(T) function elsize(::Type{Ptr{T}}) where T # this only must return something valid for values which satisfy is_valid_intrinsic_elptr(T), @@ -1144,12 +1112,12 @@ function _growat!(a::Vector, i::Integer, delta::Integer) unsafe_copyto!(newref, ref, i) a.ref = newref for j in i:i+delta-1 - _unsetindex!(a, j) + @inbounds _unsetindex!(a, j) end elseif !prefer_start && memlen >= newmemlen unsafe_copyto!(mem, offset+delta+i, mem, offset+i, len-i+1) for j in i:i+delta-1 - _unsetindex!(a, j) + @inbounds _unsetindex!(a, j) end else # since we will allocate the array in the middle of the memory we need at least 2*delta extra space @@ -1170,7 +1138,7 @@ function _deletebeg!(a::Vector, delta::Integer) len = length(a) 0 <= delta <= len || throw(ArgumentError("_deleteat! requires delta in 0:length(a)")) for i in 1:delta - _unsetindex!(a, i) + @inbounds _unsetindex!(a, i) end newlen = len - delta if newlen != 0 # if newlen==0 we could accidentally index past the memory @@ -1185,7 +1153,7 @@ function _deleteend!(a::Vector, delta::Integer) 0 <= delta <= len || throw(ArgumentError("_deleteat! requires delta in 0:length(a)")) newlen = len - delta for i in newlen+1:len - _unsetindex!(a, i) + @inbounds _unsetindex!(a, i) end a.size = (newlen,) return @@ -1782,17 +1750,19 @@ struct Nowhere; end push!(::Nowhere, _) = nothing _growend!(::Nowhere, _) = nothing -@inline function _push_deleted!(dltd, a::Vector, ind) - if @inbounds isassigned(a, ind) - push!(dltd, @inbounds a[ind]) +function _push_deleted!(dltd, a::Vector, ind) + @_propagate_inbounds_meta + if isassigned(a, ind) + push!(dltd, a[ind]) else _growend!(dltd, 1) end end -@inline function _copy_item!(a::Vector, p, q) - if @inbounds isassigned(a, q) - @inbounds a[p] = a[q] +function _copy_item!(a::Vector, p, q) + @_propagate_inbounds_meta + if isassigned(a, q) + a[p] = a[q] else _unsetindex!(a, p) end @@ -1804,7 +1774,7 @@ function _deleteat!(a::Vector, inds, dltd=Nowhere()) y === nothing && return a (p, s) = y checkbounds(a, p) - _push_deleted!(dltd, a, p) + @inbounds _push_deleted!(dltd, a, p) q = p+1 while true y = iterate(inds, s) @@ -1818,14 +1788,14 @@ function _deleteat!(a::Vector, inds, dltd=Nowhere()) end end while q < i - _copy_item!(a, p, q) + @inbounds _copy_item!(a, p, q) p += 1; q += 1 end - _push_deleted!(dltd, a, i) + @inbounds _push_deleted!(dltd, a, i) q = i+1 end while q <= n - _copy_item!(a, p, q) + @inbounds _copy_item!(a, p, q) p += 1; q += 1 end _deleteend!(a, n-p+1) @@ -1838,7 +1808,7 @@ function deleteat!(a::Vector, inds::AbstractVector{Bool}) length(inds) == n || throw(BoundsError(a, inds)) p = 1 for (q, i) in enumerate(inds) - _copy_item!(a, p, q) + @inbounds _copy_item!(a, p, q) p += !i end _deleteend!(a, n-p+1) diff --git a/base/compiler/tfuncs.jl b/base/compiler/tfuncs.jl index 9bbe3f7241083..da13ba8e5b75d 100644 --- a/base/compiler/tfuncs.jl +++ b/base/compiler/tfuncs.jl @@ -1295,7 +1295,7 @@ end # - is_undefref_fieldtype(Int) === false # - is_undefref_fieldtype(Union{Int32,Int64}) === false function is_undefref_fieldtype(@nospecialize ftyp) - return !has_free_typevars(ftyp) && !allocatedinline(ftyp) + return isbitstype(ftyp) || isbitsunion(ftyp) end @nospecs function setfield!_tfunc(𝕃::AbstractLattice, o, f, v, order) @@ -2070,7 +2070,7 @@ function array_type_undefable(@nospecialize(arytype)) else elmtype = memoryref_elemtype(arytype::DataType) # TODO: use arraytype layout instead to derive this - return !(isbitstype(elmtype) || isbitsunion(elmtype)) + return !is_undefref_fieldtype(elmtype) end end diff --git a/base/genericmemory.jl b/base/genericmemory.jl index c0302e33bde85..a8ce0d81feb01 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -26,19 +26,27 @@ size(a::GenericMemory, d::Int) = size(a::GenericMemory, d::Integer) = size(a, convert(d, Int)) size(a::GenericMemory) = (length(a),) -pointer(mem::GenericMemory, i::Int) = unsafe_convert(Ptr{Cvoid}, MemoryRef(mem, i)) -function _unsetindex!(A::Memory{T}, i::Int) where {T} +pointer(mem::GenericMemory, i::Int) = (@_propagate_inbounds_meta; unsafe_convert(Ptr{Cvoid}, MemoryRef(mem, i))) # boundschecked, even for i==1 +pointer(mem::MemoryRef) = unsafe_convert(Ptr{Cvoid}, mem) # no bounds check, even for empty array + +_unsetindex!(A::Memory, i::Int) = (@_propagate_inbounds_meta; _unsetindex!(MemoryRef(A, i)); A) +function _unsetindex!(A::MemoryRef{:not_atomic,T}) where T @_terminates_locally_meta + @_propagate_inbounds_meta @inline - @boundscheck checkbounds(A, i) - t = @_gc_preserve_begin A - p = Ptr{Ptr{Cvoid}}(pointer(A, i)) - # TODO(jwn): access datatype_layout from A instead - if !allocatedinline(T) + @boundscheck MemoryRef(A, 1) + mem = A.mem + MemT = typeof(mem) + arrayelem = datatype_arrayelem(MemT) + elsz = datatype_layoutsize(MemT) + isboxed = 1; isunion = 2 + t = @_gc_preserve_begin mem + p = Ptr{Ptr{Cvoid}}(@inbounds pointer(A)) + if arrayelem == isboxed Intrinsics.atomic_pointerset(p, C_NULL, :monotonic) - elseif T isa DataType - if !datatype_pointerfree(T) - for j = 1:Core.sizeof(Ptr{Cvoid}):Core.sizeof(T) + elseif arrayelem != isunion + if !datatype_pointerfree(T::DataType) + for j = 1:Core.sizeof(Ptr{Cvoid}):elsz Intrinsics.atomic_pointerset(p + j - 1, C_NULL, :monotonic) end end diff --git a/test/core.jl b/test/core.jl index bfbd0d6c15898..0307479d5c376 100644 --- a/test/core.jl +++ b/test/core.jl @@ -6015,10 +6015,10 @@ const unboxedunions = [Union{Int8, Nothing}, @test Base.isbitsunion(unboxedunions[2]) @test Base.isbitsunion(unboxedunions[3]) -@test Base.bitsunionsize(unboxedunions[1]) == 1 -@test Base.bitsunionsize(unboxedunions[2]) == 2 -@test Base.bitsunionsize(unboxedunions[3]) == 16 -@test Base.bitsunionsize(unboxedunions[4]) == 8 +@test Base.aligned_sizeof(unboxedunions[1]) == 1 +@test Base.aligned_sizeof(unboxedunions[2]) == 2 +@test Base.aligned_sizeof(unboxedunions[3]) == 16 +@test Base.aligned_sizeof(unboxedunions[4]) == 8 @test sizeof(unboxedunions[1]) == 1 @test sizeof(unboxedunions[2]) == 2