Skip to content

Commit 911b8cf

Browse files
authored
Backports release 1.11 (#53790)
Backported PRs: - [x] #53757 <!-- Add an IndexStyle example to the diagind docstring --> - [x] #53809 <!-- Add missing GC_POP() in emit_cfunction --> - [x] #53789 <!-- also check that UUID of project is non-null when treating it as a package --> - [x] #53805 <!-- precompilepkgs: simplify custom config printing if only one --> - [x] #53822 <!-- Bump libuv --> - [x] #53837 <!-- update MPFR to 4.2.1 --> - [x] #53862 <!-- precompilepkgs: fix error reporting --> - [x] #53774 <!-- Remove some duplicates from emitted compilation traces --> - [ ] #53696 <!-- add invokelatest to on_done callback in bracketed paste --> - [x] #53383 <!-- Add `_unsetindex!` methods for `SubArray`s and `CartesianIndex`es --> - [x] #53475 <!-- Fix boundscheck in unsetindex for SubArrays --> - [x] #53888 - [x] #53870 <!-- Revert change to checksum for llvm-julia --> - [x] #53906 <!-- Add `Base.isrelocatable(pkg)` --> - [x] #53833 <!-- Profile: make heap snapshots viewable in vscode viewer --> - [x] #53961 <!-- `LazyString` in `LinearAlgebra.checksquare` error message --> - [x] #53962 <!-- Use StringMemory instead of StringVector where possible --> - [x] #53825 <!-- profile: doc: update the `Allocs.@profile` doc string --> - [x] #53975 <!-- `LazyString` in `DimensionMismatch` error messages in broadcasting --> - [x] #53905 <!-- Avoid repeated precompilation when loading from non-relocatable cachefiles --> - [x] #53896 <!-- Make reshape and view on Memory produce Arrays and delete wrap --> - [x] #53991 <!-- Test and fix non-int-length bug in `view(::Memory, ::Union{UnitRange, Base.OneTo})` -->
2 parents 383eb07 + eb96c07 commit 911b8cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+575
-253
lines changed

NEWS.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ New library functions
8787
* `Sys.username()` can be used to return the current user's username ([#51897]).
8888
* `Sys.isreadable(), Sys.iswritable()` can be used to check if the current user has access permissions
8989
that permit reading and writing, respectively. ([#53320]).
90-
* `wrap(Array, m::Union{MemoryRef{T}, Memory{T}}, dims)` is the safe counterpart to `unsafe_wrap` ([#52049]).
9190
* `GC.logging_enabled()` can be used to test whether GC logging has been enabled via `GC.enable_logging` ([#51647]).
9291
* `IdSet` is now exported from Base and considered public ([#53262]).
9392
* `@time` now reports a count of any lock conflicts where a `ReentrantLock` had to wait, plus a new macro

base/abstractarray.jl

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1473,7 +1473,20 @@ function _setindex!(::IndexCartesian, A::AbstractArray, v, I::Vararg{Int,M}) whe
14731473
r
14741474
end
14751475

1476-
_unsetindex!(A::AbstractArray, i::Integer) = _unsetindex!(A, to_index(i))
1476+
function _unsetindex!(A::AbstractArray, i::Integer...)
1477+
@_propagate_inbounds_meta
1478+
_unsetindex!(A, map(to_index, i)...)
1479+
end
1480+
1481+
function _unsetindex!(A::AbstractArray{T}, i::Int...) where T
1482+
# this provides a fallback method which is a no-op if the element is already unassigned
1483+
# such that copying into an uninitialized object generally always will work,
1484+
# even if the specific custom array type has not implemented `_unsetindex!`
1485+
@inline
1486+
@boundscheck checkbounds(A, i...)
1487+
allocatedinline(T) || @inbounds(!isassigned(A, i...)) || throw(MethodError(_unsetindex!, (A, i...)))
1488+
return A
1489+
end
14771490

14781491
"""
14791492
parent(A)

base/array.jl

Lines changed: 6 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,12 @@ function _unsetindex!(A::Array, i::Int)
219219
@inbounds _unsetindex!(GenericMemoryRef(A.ref, i))
220220
return A
221221
end
222-
222+
function _unsetindex!(A::Array, i::Int...)
223+
@inline
224+
@boundscheck checkbounds(A, i...)
225+
@inbounds _unsetindex!(A, _to_linear_index(A, i...))
226+
return A
227+
end
223228

224229
# TODO: deprecate this (aligned_sizeof and/or elsize and/or sizeof(Some{T}) are more correct)
225230
elsize(::Type{A}) where {T,A<:Array{T}} = aligned_sizeof(T)
@@ -3062,54 +3067,3 @@ intersect(r::AbstractRange, v::AbstractVector) = intersect(v, r)
30623067
_getindex(v, i)
30633068
end
30643069
end
3065-
3066-
"""
3067-
wrap(Array, m::Union{Memory{T}, MemoryRef{T}}, dims)
3068-
3069-
Create an array of size `dims` using `m` as the underlying memory. This can be thought of as a safe version
3070-
of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointers.
3071-
"""
3072-
function wrap end
3073-
3074-
# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller
3075-
function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N}
3076-
mem = ref.mem
3077-
mem_len = length(mem) + 1 - memoryrefoffset(ref)
3078-
len = Core.checked_dims(dims...)
3079-
@boundscheck mem_len >= len || invalid_wrap_err(mem_len, dims, len)
3080-
if N != 1 && !(ref === GenericMemoryRef(mem) && len === mem_len)
3081-
mem = ccall(:jl_genericmemory_slice, Memory{T}, (Any, Ptr{Cvoid}, Int), mem, ref.ptr_or_offset, len)
3082-
ref = MemoryRef(mem)
3083-
end
3084-
return ref
3085-
end
3086-
3087-
@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch(
3088-
"Attempted to wrap a MemoryRef of length $len with an Array of size dims=$dims, which is invalid because prod(dims) = $proddims > $len, so that the array would have more elements than the underlying memory can store."))
3089-
3090-
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N}
3091-
dims = convert(Dims, dims)
3092-
ref = _wrap(m, dims)
3093-
$(Expr(:new, :(Array{T, N}), :ref, :dims))
3094-
end
3095-
3096-
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
3097-
dims = convert(Dims, dims)
3098-
ref = _wrap(MemoryRef(m), dims)
3099-
$(Expr(:new, :(Array{T, N}), :ref, :dims))
3100-
end
3101-
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
3102-
dims = (Int(l),)
3103-
ref = _wrap(m, dims)
3104-
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
3105-
end
3106-
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
3107-
dims = (Int(l),)
3108-
ref = _wrap(MemoryRef(m), (l,))
3109-
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
3110-
end
3111-
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T}
3112-
ref = MemoryRef(m)
3113-
dims = (length(m),)
3114-
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
3115-
end

base/broadcast.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,8 @@ function _bcs(shape::Tuple, newshape::Tuple)
517517
return (_bcs1(shape[1], newshape[1]), _bcs(tail(shape), tail(newshape))...)
518518
end
519519
# _bcs1 handles the logic for a single dimension
520-
_bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths $a and $b"))))
521-
_bcs1(a::Integer, b) = a == 1 ? b : (first(b) == 1 && last(b) == a ? b : throw(DimensionMismatch("arrays could not be broadcast to a common size; got a dimension with lengths $a and $(length(b))")))
520+
_bcs1(a::Integer, b::Integer) = a == 1 ? b : (b == 1 ? a : (a == b ? a : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size; got a dimension with lengths ", a, " and ", b)))))
521+
_bcs1(a::Integer, b) = a == 1 ? b : (first(b) == 1 && last(b) == a ? b : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size; got a dimension with lengths ", a, " and ", length(b)))))
522522
_bcs1(a, b::Integer) = _bcs1(b, a)
523523
_bcs1(a, b) = _bcsm(b, a) ? axistype(b, a) : _bcsm(a, b) ? axistype(a, b) : throw(DimensionMismatch(LazyString("arrays could not be broadcast to a common size: a has axes ", a, " and b has axes ", b)))
524524
# _bcsm tests whether the second index is consistent with the first
@@ -1057,7 +1057,7 @@ end
10571057

10581058

10591059
@noinline throwdm(axdest, axsrc) =
1060-
throw(DimensionMismatch("destination axes $axdest are not compatible with source axes $axsrc"))
1060+
throw(DimensionMismatch(LazyString("destination axes ", axdest, " are not compatible with source axes ", axsrc)))
10611061

10621062
function restart_copyto_nonleaf!(newdest, dest, bc, val, I, iter, state, count)
10631063
# Function barrier that makes the copying to newdest type stable

base/exports.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,6 @@ export
460460
vcat,
461461
vec,
462462
view,
463-
wrap,
464463
zeros,
465464

466465
# search, find, match and related functions

base/genericmemory.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,27 @@ function indcopy(sz::Dims, I::GenericMemory)
288288
src = eltype(I)[I[i][_findin(I[i], i < n ? (1:sz[i]) : (1:s))] for i = 1:n]
289289
dst, src
290290
end
291+
292+
# Wrapping a memory region in an Array
293+
@eval begin # @eval for the Array construction. Block for the docstring.
294+
function reshape(m::GenericMemory{M, T}, dims::Vararg{Int, N}) where {M, T, N}
295+
len = Core.checked_dims(dims...)
296+
length(m) == len || throw(DimensionMismatch("parent has $(length(m)) elements, which is incompatible with size $(dims)"))
297+
ref = MemoryRef(m)
298+
$(Expr(:new, :(Array{T, N}), :ref, :dims))
299+
end
300+
301+
"""
302+
view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo})
303+
304+
Create a vector `v::Vector{T}` backed by the specified indices of `m`. It is only safe to
305+
resize `v` if `m` is subseqently not used.
306+
"""
307+
function view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) where {M, T}
308+
isempty(inds) && return T[] # needed to allow view(Memory{T}(undef, 0), 2:1)
309+
@boundscheck checkbounds(m, inds)
310+
ref = MemoryRef(m, first(inds)) # @inbounds would be safe here but does not help performance.
311+
dims = (Int(length(inds)),)
312+
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
313+
end
314+
end

base/gmp.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1)
754754
iszero(n) && pad < 1 && return ""
755755
nd1 = ndigits(n, base=base)
756756
nd = max(nd1, pad)
757-
sv = Base.StringVector(nd + isneg(n))
757+
sv = Base.StringMemory(nd + isneg(n))
758758
GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, base, n)
759759
@inbounds for i = (1:nd-nd1) .+ isneg(n)
760760
sv[i] = '0' % UInt8

base/intfuncs.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, ba
742742
function bin(x::Unsigned, pad::Int, neg::Bool)
743743
m = top_set_bit(x)
744744
n = neg + max(pad, m)
745-
a = StringVector(n)
745+
a = StringMemory(n)
746746
# for i in 0x0:UInt(n-1) # automatic vectorization produces redundant codes
747747
# @inbounds a[n - i] = 0x30 + (((x >> i) % UInt8)::UInt8 & 0x1)
748748
# end
@@ -769,7 +769,7 @@ end
769769
function oct(x::Unsigned, pad::Int, neg::Bool)
770770
m = div(top_set_bit(x) + 2, 3)
771771
n = neg + max(pad, m)
772-
a = StringVector(n)
772+
a = StringMemory(n)
773773
i = n
774774
while i > neg
775775
@inbounds a[i] = 0x30 + ((x % UInt8)::UInt8 & 0x7)
@@ -844,7 +844,7 @@ end
844844

845845
function dec(x::Unsigned, pad::Int, neg::Bool)
846846
n = neg + ndigits(x, pad=pad)
847-
a = StringVector(n)
847+
a = StringMemory(n)
848848
append_c_digits_fast(n, x, a, 1)
849849
neg && (@inbounds a[1] = 0x2d) # UInt8('-')
850850
String(a)
@@ -853,7 +853,7 @@ end
853853
function hex(x::Unsigned, pad::Int, neg::Bool)
854854
m = 2 * sizeof(x) - (leading_zeros(x) >> 2)
855855
n = neg + max(pad, m)
856-
a = StringVector(n)
856+
a = StringMemory(n)
857857
i = n
858858
while i >= 2
859859
b = (x % UInt8)::UInt8
@@ -880,7 +880,7 @@ function _base(base::Integer, x::Integer, pad::Int, neg::Bool)
880880
b = (base % Int)::Int
881881
digits = abs(b) <= 36 ? base36digits : base62digits
882882
n = neg + ndigits(x, base=b, pad=pad)
883-
a = StringVector(n)
883+
a = StringMemory(n)
884884
i = n
885885
@inbounds while i > neg
886886
if b > 0
@@ -956,7 +956,7 @@ julia> bitstring(2.2)
956956
function bitstring(x::T) where {T}
957957
isprimitivetype(T) || throw(ArgumentError("$T not a primitive type"))
958958
sz = sizeof(T) * 8
959-
str = StringVector(sz)
959+
str = StringMemory(sz)
960960
i = sz
961961
@inbounds while i >= 4
962962
b = UInt32(sizeof(T) == 1 ? bitcast(UInt8, x) : trunc_int(UInt8, x))

base/iobuffer.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ end
4242

4343
# allocate Vector{UInt8}s for IOBuffer storage that can efficiently become Strings
4444
StringMemory(n::Integer) = unsafe_wrap(Memory{UInt8}, _string_n(n))
45-
StringVector(n::Integer) = wrap(Array, StringMemory(n))
45+
StringVector(n::Integer) = view(StringMemory(n), 1:n)::Vector{UInt8}
4646

4747
# IOBuffers behave like Files. They are typically readable and writable. They are seekable. (They can be appendable).
4848

@@ -456,7 +456,7 @@ function take!(io::IOBuffer)
456456
if nbytes == 0 || io.reinit
457457
data = StringVector(0)
458458
elseif io.writable
459-
data = wrap(Array, MemoryRef(io.data, io.offset + 1), nbytes)
459+
data = view(io.data, io.offset+1:nbytes+io.offset)
460460
else
461461
data = copyto!(StringVector(io.size), 1, io.data, io.offset + 1, nbytes)
462462
end
@@ -465,7 +465,7 @@ function take!(io::IOBuffer)
465465
if nbytes == 0
466466
data = StringVector(0)
467467
elseif io.writable
468-
data = wrap(Array, MemoryRef(io.data, io.ptr), nbytes)
468+
data = view(io.data, io.ptr:io.ptr+nbytes-1)
469469
else
470470
data = read!(io, data)
471471
end
@@ -491,11 +491,7 @@ state. This should only be used internally for performance-critical
491491
It might save an allocation compared to `take!` (if the compiler elides the
492492
Array allocation), as well as omits some checks.
493493
"""
494-
_unsafe_take!(io::IOBuffer) =
495-
wrap(Array, io.size == io.offset ?
496-
MemoryRef(Memory{UInt8}()) :
497-
MemoryRef(io.data, io.offset + 1),
498-
io.size - io.offset)
494+
_unsafe_take!(io::IOBuffer) = view(io.data, io.offset+1:io.size)
499495

500496
function write(to::IO, from::GenericIOBuffer)
501497
written::Int = bytesavailable(from)

0 commit comments

Comments
 (0)