diff --git a/base/atomics.jl b/base/atomics.jl index 1d93f48a1def4..241d7a134d8d1 100644 --- a/base/atomics.jl +++ b/base/atomics.jl @@ -334,7 +334,7 @@ inttype(::Type{Float32}) = Int32 inttype(::Type{Float64}) = Int64 -gc_alignment(::Type{T}) where {T} = ccall(:jl_alignment, Cint, (Csize_t,), sizeof(T)) +import ..Base.gc_alignment # All atomic operations have acquire and/or release semantics, depending on # whether the load or store values. Most of the time, this is what one wants diff --git a/base/reflection.jl b/base/reflection.jl index e79af20cc7f14..113d36ed714c7 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -337,6 +337,9 @@ function datatype_alignment(dt::DataType) return Int(alignment & 0x1FF) end +gc_alignment(sz::Integer) = Int(ccall(:jl_alignment, Cint, (Csize_t,), sz)) +gc_alignment(T::Type) = gc_alignment(Core.sizeof(T)) + """ Base.datatype_haspadding(dt::DataType) -> Bool diff --git a/base/summarysize.jl b/base/summarysize.jl index 3ae3ee135d531..714b60ed8dfea 100644 --- a/base/summarysize.jl +++ b/base/summarysize.jl @@ -74,14 +74,25 @@ end end if isa(obj, UnionAll) || isa(obj, Union) # black-list of items that don't have a Core.sizeof - return 2 * sizeof(Int) + sz = 2 * sizeof(Int) + else + sz = Core.sizeof(obj) end - return Core.sizeof(obj) + if sz == 0 + # 0-field mutable structs are not unique + return gc_alignment(0) + end + return sz end (::SummarySize)(obj::Symbol) = 0 (::SummarySize)(obj::SummarySize) = 0 -(::SummarySize)(obj::String) = Core.sizeof(Int) + Core.sizeof(obj) + +function (ss::SummarySize)(obj::String) + key = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), obj) + haskey(ss.seen, key) ? (return 0) : (ss.seen[key] = true) + return Core.sizeof(Int) + Core.sizeof(obj) +end function (ss::SummarySize)(obj::DataType) key = pointer_from_objref(obj) @@ -108,7 +119,12 @@ function (ss::SummarySize)(obj::Array) datakey = unsafe_convert(Ptr{Cvoid}, obj) if !haskey(ss.seen, datakey) ss.seen[datakey] = true - size += Core.sizeof(obj) + dsize = Core.sizeof(obj) + if isbitsunion(eltype(obj)) + # add 1 union selector byte for each element + dsize += length(obj) + end + size += dsize if !isbitstype(eltype(obj)) && !isempty(obj) push!(ss.frontier_x, obj) push!(ss.frontier_i, 1) diff --git a/test/misc.jl b/test/misc.jl index a011e72ee5166..930b80eebeb14 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -194,6 +194,15 @@ let A = zeros(1000), B = reshape(A, (1,1000)) @test summarysize(A) > sizeof(A) end +# issue #32881 +mutable struct S32881; end +let s = "abc" + @test summarysize([s,s]) < summarysize(["abc","xyz"]) +end +@test summarysize(Vector{Union{Nothing,Missing}}(undef, 16)) < summarysize(Vector{Union{Nothing,Missing}}(undef, 32)) +@test summarysize(Vector{Nothing}(undef, 16)) == summarysize(Vector{Nothing}(undef, 32)) +@test summarysize(S32881()) == sizeof(Int) + # issue #13021 let ex = try Main.x13021 = 0