From 113b7c9b8355ae887076db20f67db3893a8e3572 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Thu, 25 Apr 2024 23:53:06 -0400 Subject: [PATCH 1/2] rename Memory wrapper from view to unsafe_vector --- base/exports.jl | 1 + base/genericmemory.jl | 8 ++++---- base/iobuffer.jl | 8 ++++---- base/strings/string.jl | 2 +- doc/src/base/arrays.md | 1 + test/arrayops.jl | 38 +++++++++++++++++++------------------- 6 files changed, 30 insertions(+), 28 deletions(-) diff --git a/base/exports.jl b/base/exports.jl index fc2ee86a8d0d4..bba6cbf13f535 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -986,6 +986,7 @@ export pointer, pointer_from_objref, unsafe_wrap, + unsafe_vector, unsafe_string, reenable_sigint, unsafe_copyto!, diff --git a/base/genericmemory.jl b/base/genericmemory.jl index c1dc215a68d33..4ff5e663d62d9 100644 --- a/base/genericmemory.jl +++ b/base/genericmemory.jl @@ -299,17 +299,17 @@ end end """ - view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) + unsafe_vector(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo, Colon}) Create a vector `v::Vector{T}` backed by the specified indices of `m`. It is only safe to resize `v` if `m` is subseqently not used. """ - function view(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) where {M, T} - isempty(inds) && return T[] # needed to allow view(Memory{T}(undef, 0), 2:1) + function unsafe_vector(m::GenericMemory{M, T}, inds::Union{UnitRange, OneTo}) where {M, T} + isempty(inds) && return T[] # needed to allow unsafe_vector(Memory{T}(undef, 0), 2:1) @boundscheck checkbounds(m, inds) ref = MemoryRef(m, first(inds)) # @inbounds would be safe here but does not help performance. dims = (Int(length(inds)),) $(Expr(:new, :(Array{T, 1}), :ref, :dims)) end end -view(m::GenericMemory, inds::Colon) = view(m, eachindex(m)) +unsafe_vector(m::GenericMemory, inds::Colon) = unsafe_vector(m, eachindex(m)) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index f9585b0599919..f31878d8c1509 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -42,7 +42,7 @@ end # allocate Vector{UInt8}s for IOBuffer storage that can efficiently become Strings StringMemory(n::Integer) = unsafe_wrap(Memory{UInt8}, _string_n(n)) -StringVector(n::Integer) = view(StringMemory(n), 1:n)::Vector{UInt8} +StringVector(n::Integer) = unsafe_vector(StringMemory(n), 1:n)::Vector{UInt8} # IOBuffers behave like Files. They are typically readable and writable. They are seekable. (They can be appendable). @@ -466,7 +466,7 @@ function take!(io::IOBuffer) if nbytes == 0 || io.reinit data = StringVector(0) elseif io.writable - data = view(io.data, io.offset+1:nbytes+io.offset) + data = unsafe_vector(io.data, io.offset+1:nbytes+io.offset) else data = copyto!(StringVector(nbytes), 1, io.data, io.offset + 1, nbytes) end @@ -475,7 +475,7 @@ function take!(io::IOBuffer) if nbytes == 0 data = StringVector(0) elseif io.writable - data = view(io.data, io.ptr:io.ptr+nbytes-1) + data = unsafe_vector(io.data, io.ptr:io.ptr+nbytes-1) else data = read!(io, data) end @@ -501,7 +501,7 @@ state. This should only be used internally for performance-critical It might save an allocation compared to `take!` (if the compiler elides the Array allocation), as well as omits some checks. """ -_unsafe_take!(io::IOBuffer) = view(io.data, io.offset+1:io.size) +_unsafe_take!(io::IOBuffer) = unsafe_vector(io.data, io.offset+1:io.size) function write(to::IO, from::GenericIOBuffer) written::Int = bytesavailable(from) diff --git a/base/strings/string.jl b/base/strings/string.jl index d091baeb6c663..f463937b7ace0 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -119,7 +119,7 @@ String(s::AbstractString) = print_to_string(s) unsafe_wrap(::Type{Memory{UInt8}}, s::String) = ccall(:jl_string_to_genericmemory, Ref{Memory{UInt8}}, (Any,), s) function unsafe_wrap(::Type{Vector{UInt8}}, s::String) mem = unsafe_wrap(Memory{UInt8}, s) - view(mem, eachindex(mem)) + unsafe_vector(mem, :) end Vector{UInt8}(s::CodeUnits{UInt8,String}) = copyto!(Vector{UInt8}(undef, length(s)), s) diff --git a/doc/src/base/arrays.md b/doc/src/base/arrays.md index 20e8e81614b9e..0c86e2ef38c77 100644 --- a/doc/src/base/arrays.md +++ b/doc/src/base/arrays.md @@ -139,6 +139,7 @@ Base.reshape Base.dropdims Base.vec Base.SubArray +Base.unsafe_vector ``` ## Concatenation and permutation diff --git a/test/arrayops.jl b/test/arrayops.jl index b64d08264e2d1..213157db9e824 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3214,38 +3214,38 @@ end end end -@testset "Wrapping Memory into Arrays with view and reshape" begin +@testset "Wrapping Memory into Arrays with unsafe_vector and reshape" begin mem::Memory{Int} = Memory{Int}(undef, 10) .= 11:20 @test_throws DimensionMismatch reshape(mem, 10, 10) @test_throws DimensionMismatch reshape(mem, 5) - @test_throws BoundsError view(mem, 1:10, 1:10) - @test_throws BoundsError view(mem, 1:11) - @test_throws BoundsError view(mem, 3:11) - @test_throws BoundsError view(mem, 0:4) - - @test @inferred(view(mem, 1:5))::Vector{Int} == 11:15 - @test @inferred(view(mem, 1:2))::Vector{Int} == 11:12 - @test @inferred(view(mem, 1:10))::Vector{Int} == 11:20 - @test @inferred(view(mem, 3:8))::Vector{Int} == 13:18 - @test @inferred(view(mem, 20:19))::Vector{Int} == [] - @test @inferred(view(mem, -5:-7))::Vector{Int} == [] - @test @inferred(view(mem, :))::Vector{Int} == mem + @test_throws BoundsError unsafe_vector(mem, 1:10, 1:10) + @test_throws BoundsError unsafe_vector(mem, 1:11) + @test_throws BoundsError unsafe_vector(mem, 3:11) + @test_throws BoundsError unsafe_vector(mem, 0:4) + + @test @inferred(unsafe_vector(mem, 1:5))::Vector{Int} == 11:15 + @test @inferred(unsafe_vector(mem, 1:2))::Vector{Int} == 11:12 + @test @inferred(unsafe_vector(mem, 1:10))::Vector{Int} == 11:20 + @test @inferred(unsafe_vector(mem, 3:8))::Vector{Int} == 13:18 + @test @inferred(unsafe_vector(mem, 20:19))::Vector{Int} == [] + @test @inferred(unsafe_vector(mem, -5:-7))::Vector{Int} == [] + @test @inferred(unsafe_vector(mem, :))::Vector{Int} == mem @test @inferred(reshape(mem, 5, 2))::Matrix{Int} == reshape(11:20, 5, 2) # 53990 - @test @inferred(view(mem, unsigned(1):10))::Vector{Int} == 11:20 + @test @inferred(unsafe_vector(mem, unsigned(1):10))::Vector{Int} == 11:20 empty_mem = Memory{Module}(undef, 0) - @test_throws BoundsError view(empty_mem, 0:1) - @test_throws BoundsError view(empty_mem, 1:2) + @test_throws BoundsError unsafe_vector(empty_mem, 0:1) + @test_throws BoundsError unsafe_vector(empty_mem, 1:2) @test_throws DimensionMismatch reshape(empty_mem, 1) @test_throws DimensionMismatch reshape(empty_mem, 1, 2, 3) @test_throws ArgumentError reshape(empty_mem, 2^16, 2^16, 2^16, 2^16) - @test @inferred(view(empty_mem, 1:0))::Vector{Module} == [] - @test @inferred(view(empty_mem, 10:3))::Vector{Module} == [] - @test @inferred(view(empty_mem, :))::Vector{Module} == empty_mem + @test @inferred(unsafe_vector(empty_mem, 1:0))::Vector{Module} == [] + @test @inferred(unsafe_vector(empty_mem, 10:3))::Vector{Module} == [] + @test @inferred(unsafe_vector(empty_mem, :))::Vector{Module} == empty_mem @test isempty(@inferred(reshape(empty_mem, 0, 7, 1))::Array{Module, 3}) offset_inds = OffsetArrays.IdOffsetRange(values=3:6, indices=53:56) From 0e4f6c068f4e4d29246a35b2b251e4e29aa8f615 Mon Sep 17 00:00:00 2001 From: nhz2 Date: Fri, 26 Apr 2024 13:11:45 -0400 Subject: [PATCH 2/2] fix test --- test/arrayops.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/arrayops.jl b/test/arrayops.jl index 213157db9e824..5bb3ebb254e2d 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -3219,7 +3219,7 @@ end @test_throws DimensionMismatch reshape(mem, 10, 10) @test_throws DimensionMismatch reshape(mem, 5) - @test_throws BoundsError unsafe_vector(mem, 1:10, 1:10) + @test_throws BoundsError view(mem, 1:10, 1:10) @test_throws BoundsError unsafe_vector(mem, 1:11) @test_throws BoundsError unsafe_vector(mem, 3:11) @test_throws BoundsError unsafe_vector(mem, 0:4)