Skip to content

Commit

Permalink
some moer general cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
vtjnash committed Sep 25, 2023
1 parent fe3789c commit 80a67bc
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 66 deletions.
70 changes: 20 additions & 50 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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

Expand Down
28 changes: 18 additions & 10 deletions base/genericmemory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 80a67bc

Please sign in to comment.