From 05a2e5f290c3ea40e34e9e61ab879e18e85cf7c3 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Thu, 28 Aug 2025 05:16:41 +0000 Subject: [PATCH 1/3] Pin array before taking pointers in abstractarray tests --- test/abstractarray.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index bff6e28f8b19b..5a11108ffc9fc 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1260,6 +1260,8 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S @testset "Simple 3d strided views and permutes" for sz in ((5, 3, 2), (7, 11, 13)) A = collect(reshape(1:prod(sz), sz)) + # The following test takes pointers from A, we need to ensure A is not moved by GC. + Base.increment_pin_count!(A) S = Strider(vec(A), strides(A), sz) @test pointer(A) == pointer(S) for i in 1:prod(sz) @@ -1318,10 +1320,13 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S # constant propagation in the PermutedDimsArray constructor X = @inferred (A -> PermutedDimsArray(A, (2,3,1)))(A) @test @inferred((X -> PermutedDimsArray(X, (3,1,2)))(X)) == A + Base.decrement_pin_count!(A) end @testset "simple 2d strided views, permutes, transposes" for sz in ((5, 3), (7, 11)) A = collect(reshape(1:prod(sz), sz)) + # The following test takes pointers from A, we need to ensure A is not moved by GC. + Base.increment_pin_count!(A) S = Strider(vec(A), strides(A), sz) @test pointer(A) == pointer(S) for i in 1:prod(sz) @@ -1387,6 +1392,7 @@ end @test Vp[i] == Avp[i] == Svp[i] == Avt[i] == Ava[i] == Svt[i] == Sva[i] end end + Base.decrement_pin_count!(A) end @testset "first/last n elements of $(typeof(itr))" for itr in (collect(1:9), @@ -1915,6 +1921,7 @@ module IRUtils end function check_pointer_strides(A::AbstractArray) + Base.increment_pin_count!(A) # Make sure stride(A, i) is equivalent with strides(A)[i] (if 1 <= i <= ndims(A)) dims = ntuple(identity, ndims(A)) map(i -> stride(A, i), dims) == @inferred(strides(A)) || return false @@ -1924,6 +1931,7 @@ function check_pointer_strides(A::AbstractArray) for i in eachindex(IndexLinear(), A) A[i] === Base.unsafe_load(pointer(A, i)) || return false end + Base.decrement_pin_count!(A) return true end From ab00bad235234f2fdce3f50383b811e56a1e95b5 Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Tue, 9 Sep 2025 05:04:56 +0000 Subject: [PATCH 2/3] Fix test in arrayops.jl --- test/arrayops.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/arrayops.jl b/test/arrayops.jl index 84b9c8e7b2f6a..bd60ac6577ddc 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -767,7 +767,10 @@ end @test_throws ArgumentError PermutedDimsArray(a, (1,1,1)) @test_throws ArgumentError PermutedDimsArray(s, (1,1,1)) cp = PermutedDimsArray(c, (3,2,1)) + # The following test takes pointers from c, we need to ensure c is not moved by GC. + Base.increment_pin_count!(c) @test pointer(cp) == pointer(c) + Base.decrement_pin_count!(c) @test_throws ArgumentError pointer(cp, 2) @test strides(cp) == (9,3,1) ap = PermutedDimsArray(Array(a), (2,1,3)) @@ -3045,14 +3048,19 @@ Base.:(==)(a::T11053, b::T11053) = a.a == b.a # check a == b for arrays of Union type (#22403) let TT = Union{UInt8, Int8} + # The following test takes pointers from a and b, we need to pin both a = TT[0x0, 0x1] + Base.increment_pin_count!(a) b = TT[0x0, 0x0] + Base.increment_pin_count!(b) pa = pointer(a) pb = pointer(b) resize!(a, 1) # sets a[2] = 0 resize!(b, 1) @assert pointer(a) == pa @assert pointer(b) == pb + Base.decrement_pin_count!(a) + Base.decrement_pin_count!(b) unsafe_store!(Ptr{UInt8}(pa), 0x1, 2) # reset a[2] to 1 @test length(a) == length(b) == 1 @test a[1] == b[1] == 0x0 From d04763554c4ad9aec75ca92017d44ee523f16c9f Mon Sep 17 00:00:00 2001 From: Yi Lin Date: Thu, 11 Sep 2025 05:54:08 +0000 Subject: [PATCH 3/3] Use tpin for array pinning. Add more tpins --- test/abstractarray.jl | 20 ++++++++++++++------ test/arrayops.jl | 12 ++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/test/abstractarray.jl b/test/abstractarray.jl index 5a11108ffc9fc..954204c140fea 100644 --- a/test/abstractarray.jl +++ b/test/abstractarray.jl @@ -1261,7 +1261,9 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S @testset "Simple 3d strided views and permutes" for sz in ((5, 3, 2), (7, 11, 13)) A = collect(reshape(1:prod(sz), sz)) # The following test takes pointers from A, we need to ensure A is not moved by GC. - Base.increment_pin_count!(A) + # Furthermore, as pointer() returns the buffer address, we need to ensure the underlying buffer. We use tpin. + # If we take address from any newly allocation array in this test, it needs to be tpinned. + Base.increment_tpin_count!(A) S = Strider(vec(A), strides(A), sz) @test pointer(A) == pointer(S) for i in 1:prod(sz) @@ -1274,6 +1276,7 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S (sz[1]:-1:1, sz[2]:-1:1, sz[3]:-1:1), (sz[1]-1:-3:1, sz[2]:-2:3, 1:sz[3]),) Ai = A[idxs...] + Base.increment_tpin_count!(Ai) Av = view(A, idxs...) Sv = view(S, idxs...) Ss = Strider{Int, 3}(vec(A), sum((first.(idxs).-1).*strides(A))+1, strides(Av), length.(idxs)) @@ -1284,6 +1287,7 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S end for perm in ((3, 2, 1), (2, 1, 3), (3, 1, 2)) P = permutedims(A, perm) + Base.increment_tpin_count!(P) Ap = Base.PermutedDimsArray(A, perm) Sp = Base.PermutedDimsArray(S, perm) Ps = Strider{Int, 3}(vec(A), 1, strides(A)[collect(perm)], sz[collect(perm)]) @@ -1305,7 +1309,9 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S @test Pi[i] == Pv[i] == Apv[i] == Spv[i] == Pvs[i] end Vp = permutedims(Av, perm) + Base.increment_tpin_count!(Vp) Ip = permutedims(Ai, perm) + Base.increment_tpin_count!(Ip) Avp = Base.PermutedDimsArray(Av, perm) Svp = Base.PermutedDimsArray(Sv, perm) @test pointer(Avp) == pointer(Svp) @@ -1320,13 +1326,14 @@ Base.cconvert(::Type{Ptr{T}}, S::Strider{T}) where {T} = memoryref(S.data.ref, S # constant propagation in the PermutedDimsArray constructor X = @inferred (A -> PermutedDimsArray(A, (2,3,1)))(A) @test @inferred((X -> PermutedDimsArray(X, (3,1,2)))(X)) == A - Base.decrement_pin_count!(A) end @testset "simple 2d strided views, permutes, transposes" for sz in ((5, 3), (7, 11)) A = collect(reshape(1:prod(sz), sz)) # The following test takes pointers from A, we need to ensure A is not moved by GC. - Base.increment_pin_count!(A) + # Furthermore, as pointer() returns the buffer address, we need to ensure the underlying buffer. We use tpin. + # If we take address from any newly allocation array in this test, it needs to be tpinned. + Base.increment_tpin_count!(A) S = Strider(vec(A), strides(A), sz) @test pointer(A) == pointer(S) for i in 1:prod(sz) @@ -1348,6 +1355,7 @@ end end perm = (2, 1) P = permutedims(A, perm) + Base.increment_tpin_count!(P) Ap = Base.PermutedDimsArray(A, perm) At = transpose(A) Aa = adjoint(A) @@ -1377,6 +1385,7 @@ end @test Pv[i] == Apv[i] == Spv[i] == Pvs[i] == Atv[i] == Ata[i] == Stv[i] == Sta[i] end Vp = permutedims(Av, perm) + Base.increment_tpin_count!(Vp) Avp = Base.PermutedDimsArray(Av, perm) Avt = transpose(Av) Ava = adjoint(Av) @@ -1392,7 +1401,6 @@ end @test Vp[i] == Avp[i] == Svp[i] == Avt[i] == Ava[i] == Svt[i] == Sva[i] end end - Base.decrement_pin_count!(A) end @testset "first/last n elements of $(typeof(itr))" for itr in (collect(1:9), @@ -1921,7 +1929,7 @@ module IRUtils end function check_pointer_strides(A::AbstractArray) - Base.increment_pin_count!(A) + Base.increment_tpin_count!(A) # Make sure stride(A, i) is equivalent with strides(A)[i] (if 1 <= i <= ndims(A)) dims = ntuple(identity, ndims(A)) map(i -> stride(A, i), dims) == @inferred(strides(A)) || return false @@ -1931,7 +1939,7 @@ function check_pointer_strides(A::AbstractArray) for i in eachindex(IndexLinear(), A) A[i] === Base.unsafe_load(pointer(A, i)) || return false end - Base.decrement_pin_count!(A) + Base.decrement_tpin_count!(A) return true end diff --git a/test/arrayops.jl b/test/arrayops.jl index bd60ac6577ddc..3617ec0186bbd 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -768,9 +768,9 @@ end @test_throws ArgumentError PermutedDimsArray(s, (1,1,1)) cp = PermutedDimsArray(c, (3,2,1)) # The following test takes pointers from c, we need to ensure c is not moved by GC. - Base.increment_pin_count!(c) + Base.increment_tpin_count!(c) @test pointer(cp) == pointer(c) - Base.decrement_pin_count!(c) + Base.decrement_tpin_count!(c) @test_throws ArgumentError pointer(cp, 2) @test strides(cp) == (9,3,1) ap = PermutedDimsArray(Array(a), (2,1,3)) @@ -3050,17 +3050,17 @@ Base.:(==)(a::T11053, b::T11053) = a.a == b.a let TT = Union{UInt8, Int8} # The following test takes pointers from a and b, we need to pin both a = TT[0x0, 0x1] - Base.increment_pin_count!(a) + Base.increment_tpin_count!(a) b = TT[0x0, 0x0] - Base.increment_pin_count!(b) + Base.increment_tpin_count!(b) pa = pointer(a) pb = pointer(b) resize!(a, 1) # sets a[2] = 0 resize!(b, 1) @assert pointer(a) == pa @assert pointer(b) == pb - Base.decrement_pin_count!(a) - Base.decrement_pin_count!(b) + Base.decrement_tpin_count!(a) + Base.decrement_tpin_count!(b) unsafe_store!(Ptr{UInt8}(pa), 0x1, 2) # reset a[2] to 1 @test length(a) == length(b) == 1 @test a[1] == b[1] == 0x0