diff --git a/base/array.jl b/base/array.jl index 051c678bf1a351..09a673b4a3d065 100644 --- a/base/array.jl +++ b/base/array.jl @@ -171,6 +171,8 @@ that N is inbounds on either array. Incorrect usage may corrupt or segfault your the same manner as C. """ function unsafe_copy!(dest::Array{T}, doffs, src::Array{T}, soffs, n) where T + t1 = @_gc_preserve_begin dest + t2 = @_gc_preserve_begin src if isbits(T) unsafe_copy!(pointer(dest, doffs), pointer(src, soffs), n) elseif isbitsunion(T) @@ -185,6 +187,8 @@ function unsafe_copy!(dest::Array{T}, doffs, src::Array{T}, soffs, n) where T ccall(:jl_array_ptr_copy, Void, (Any, Ptr{Void}, Any, Ptr{Void}, Int), dest, pointer(dest, doffs), src, pointer(src, soffs), n) end + @_gc_preserve_end t2 + @_gc_preserve_end t1 return dest end @@ -1570,6 +1574,7 @@ function vcat(arrays::Vector{T}...) where T else elsz = Core.sizeof(Ptr{Void}) end + t = @_gc_preserve_begin arr for a in arrays na = length(a) nba = na * elsz @@ -1589,6 +1594,7 @@ function vcat(arrays::Vector{T}...) where T end ptr += nba end + @_gc_preserve_end t return arr end diff --git a/base/datafmt.jl b/base/datafmt.jl index 6ceecd14acf404..a4a715b49bf44b 100644 --- a/base/datafmt.jl +++ b/base/datafmt.jl @@ -130,7 +130,7 @@ function readdlm_auto(input::AbstractString, dlm::Char, T::Type, eol::Char, auto # TODO: It would be nicer to use String(a) without making a copy, # but because the mmap'ed array is not NUL-terminated this causes # jl_try_substrtod to segfault below. - return readdlm_string(unsafe_string(pointer(a),length(a)), dlm, T, eol, auto, optsd) + return readdlm_string(Base.@gc_preserve(a, unsafe_string(pointer(a),length(a))), dlm, T, eol, auto, optsd) else return readdlm_string(read(input, String), dlm, T, eol, auto, optsd) end @@ -220,7 +220,7 @@ function DLMStore(::Type{T}, dims::NTuple{2,Integer}, end _chrinstr(sbuff::String, chr::UInt8, startpos::Int, endpos::Int) = - (endpos >= startpos) && (C_NULL != ccall(:memchr, Ptr{UInt8}, + Base.@gc_preserve sbuff (endpos >= startpos) && (C_NULL != ccall(:memchr, Ptr{UInt8}, (Ptr{UInt8}, Int32, Csize_t), pointer(sbuff)+startpos-1, chr, endpos-startpos+1)) function store_cell(dlmstore::DLMStore{T}, row::Int, col::Int, diff --git a/base/deepcopy.jl b/base/deepcopy.jl index e4c0947d809359..7ee72dc6926ceb 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -46,7 +46,7 @@ function deepcopy_internal(x::String, stackdict::ObjectIdDict) if haskey(stackdict, x) return stackdict[x] end - y = unsafe_string(pointer(x), sizeof(x)) + y = @gc_preserve x unsafe_string(pointer(x), sizeof(x)) stackdict[x] = y return y end diff --git a/base/env.jl b/base/env.jl index fb2d306e11f62c..73e1ff87bf0a3a 100644 --- a/base/env.jl +++ b/base/env.jl @@ -99,7 +99,7 @@ if Sys.iswindows() blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) buf = Vector{UInt16}(len) - unsafe_copy!(pointer(buf), pos, len) + @gc_preserve buf unsafe_copy!(pointer(buf), pos, len) env = transcode(String, buf) m = match(r"^(=?[^=]+)=(.*)$"s, env) if m === nothing diff --git a/base/essentials.jl b/base/essentials.jl index 04d49dcef2e15e..f1e02cd817ce81 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -18,6 +18,14 @@ macro _noinline_meta() Expr(:meta, :noinline) end +macro _gc_preserve_begin(arg1) + Expr(:gc_preserve_begin, esc(arg1)) +end + +macro _gc_preserve_end(token) + Expr(:gc_preserve_end, esc(token)) +end + """ @nospecialize @@ -513,16 +521,23 @@ end # SimpleVector function getindex(v::SimpleVector, i::Int) - if !(1 <= i <= length(v)) + @boundscheck if !(1 <= i <= length(v)) throw(BoundsError(v,i)) end + t = @_gc_preserve_begin v x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) x == C_NULL && throw(UndefRefError()) - return unsafe_pointer_to_objref(x) + o = unsafe_pointer_to_objref(x) + @_gc_preserve_end t + return o end -# TODO: add gc use intrinsic call instead of noinline -length(v::SimpleVector) = (@_noinline_meta; unsafe_load(convert(Ptr{Int},data_pointer_from_objref(v)))) +function length(v::SimpleVector) + t = @_gc_preserve_begin v + l = unsafe_load(convert(Ptr{Int},data_pointer_from_objref(v))) + @_gc_preserve_end t + return l +end endof(v::SimpleVector) = length(v) start(v::SimpleVector) = 1 next(v::SimpleVector,i) = (v[i],i+1) @@ -573,7 +588,9 @@ function isassigned end function isassigned(v::SimpleVector, i::Int) @boundscheck 1 <= i <= length(v) || return false + t = @_gc_preserve_begin v x = unsafe_load(convert(Ptr{Ptr{Void}},data_pointer_from_objref(v)) + i*sizeof(Ptr)) + @_gc_preserve_end t return x != C_NULL end diff --git a/base/gmp.jl b/base/gmp.jl index 79f3792dba115a..33eaa6e704c9a2 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -252,7 +252,7 @@ function tryparse_internal(::Type{BigInt}, s::AbstractString, startpos::Int, end if Base.containsnul(bstr) err = -1 # embedded NUL char (not handled correctly by GMP) else - err = MPZ.set_str!(z, pointer(bstr)+(i-start(bstr)), base) + err = Base.@gc_preserve bstr MPZ.set_str!(z, pointer(bstr)+(i-start(bstr)), base) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) @@ -612,7 +612,7 @@ function base(b::Integer, n::BigInt, pad::Integer=1) nd1 = ndigits(n, b) nd = max(nd1, pad) sv = Base.StringVector(nd + isneg(n)) - MPZ.get_str!(pointer(sv) + nd - nd1, b, n) + Base.@gc_preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, b, n) @inbounds for i = (1:nd-nd1) .+ isneg(n) sv[i] = '0' % UInt8 end diff --git a/base/io.jl b/base/io.jl index 63e32dc6e77ecd..a4e3e9e84beac6 100644 --- a/base/io.jl +++ b/base/io.jl @@ -365,9 +365,9 @@ function write(s::IO, A::AbstractArray) return nb end -@noinline function write(s::IO, a::Array) # mark noinline to ensure the array is gc-rooted somewhere (by the caller) +function write(s::IO, a::Array) if isbits(eltype(a)) - return unsafe_write(s, pointer(a), sizeof(a)) + return @gc_preserve a unsafe_write(s, pointer(a), sizeof(a)) else depwarn("Calling `write` on non-isbits arrays is deprecated. Use a loop or `serialize` instead.", :write) nb = 0 @@ -384,7 +384,7 @@ function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N} end elsz = sizeof(T) colsz = size(a,1) * elsz - if stride(a,1) != 1 + @gc_preserve a if stride(a,1) != 1 for idxs in CartesianRange(size(a)) unsafe_write(s, pointer(a, idxs.I), elsz) end @@ -444,14 +444,14 @@ end read(s::IO, ::Type{Bool}) = (read(s, UInt8) != 0) read(s::IO, ::Type{Ptr{T}}) where {T} = convert(Ptr{T}, read(s, UInt)) -@noinline function read!(s::IO, a::Array{UInt8}) # mark noinline to ensure the array is gc-rooted somewhere (by the caller) - unsafe_read(s, pointer(a), sizeof(a)) +function read!(s::IO, a::Array{UInt8}) + @gc_preserve a unsafe_read(s, pointer(a), sizeof(a)) return a end -@noinline function read!(s::IO, a::Array{T}) where T # mark noinline to ensure the array is gc-rooted somewhere (by the caller) +function read!(s::IO, a::Array{T}) where T if isbits(T) - unsafe_read(s, pointer(a), sizeof(a)) + @gc_preserve a unsafe_read(s, pointer(a), sizeof(a)) else for i in eachindex(a) a[i] = read(s, T) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 9da496d729a16f..19824915c07af5 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -99,7 +99,7 @@ function unsafe_read(from::GenericIOBuffer, p::Ptr{UInt8}, nb::UInt) from.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) avail = nb_available(from) adv = min(avail, nb) - unsafe_copy!(p, pointer(from.data, from.ptr), adv) + @gc_preserve from unsafe_copy!(p, pointer(from.data, from.ptr), adv) from.ptr += adv if nb > avail throw(EOFError()) @@ -114,7 +114,7 @@ function read_sub(from::GenericIOBuffer, a::AbstractArray{T}, offs, nel) where T end if isbits(T) && isa(a,Array) nb = UInt(nel * sizeof(T)) - unsafe_read(from, pointer(a, offs), nb) + @gc_preserve a unsafe_read(from, pointer(a, offs), nb) else for i = offs:offs+nel-1 a[i] = read(to, T) @@ -334,7 +334,7 @@ function write_sub(to::GenericIOBuffer, a::AbstractArray{UInt8}, offs, nel) if offs+nel-1 > length(a) || offs < 1 || nel < 0 throw(BoundsError()) end - unsafe_write(to, pointer(a, offs), UInt(nel)) + @gc_preserve a unsafe_write(to, pointer(a, offs), UInt(nel)) end @inline function write(to::GenericIOBuffer, a::UInt8) @@ -367,7 +367,7 @@ read(io::GenericIOBuffer, nb::Integer) = read!(io,StringVector(min(nb, nb_availa function search(buf::IOBuffer, delim::UInt8) p = pointer(buf.data, buf.ptr) - q = ccall(:memchr,Ptr{UInt8},(Ptr{UInt8},Int32,Csize_t),p,delim,nb_available(buf)) + q = @gc_preserve buf ccall(:memchr,Ptr{UInt8},(Ptr{UInt8},Int32,Csize_t),p,delim,nb_available(buf)) nb::Int = (q == C_NULL ? 0 : q-p+1) return nb end @@ -413,7 +413,7 @@ function crc32c(io::IOBuffer, nb::Integer, crc::UInt32=0x00000000) io.readable || throw(ArgumentError("read failed, IOBuffer is not readable")) n = min(nb, nb_available(io)) n == 0 && return crc - crc = unsafe_crc32c(pointer(io.data, io.ptr), n, crc) + crc = @gc_preserve io unsafe_crc32c(pointer(io.data, io.ptr), n, crc) io.ptr += n return crc end diff --git a/base/iostream.jl b/base/iostream.jl index 7ae9f112f50f64..33452f487fba32 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -264,7 +264,7 @@ end function readbytes_all!(s::IOStream, b::Array{UInt8}, nb) olb = lb = length(b) nr = 0 - while nr < nb + @gc_preserve b while nr < nb if lb < nr+1 lb = max(65536, (nr+1) * 2) resize!(b, lb) @@ -284,8 +284,8 @@ function readbytes_some!(s::IOStream, b::Array{UInt8}, nb) if nb > lb resize!(b, nb) end - nr = Int(ccall(:ios_read, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), - s.ios, pointer(b), nb)) + nr = @gc_preserve b Int(ccall(:ios_read, Csize_t, (Ptr{Void}, Ptr{Void}, Csize_t), + s.ios, pointer(b), nb)) if lb > olb && lb > nr resize!(b, nr) end diff --git a/base/libc.jl b/base/libc.jl index 34301239516caa..55f23400887c4c 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -249,7 +249,7 @@ function gethostname() ccall(:gethostname, Int32, (Ptr{UInt8}, UInt), hn, length(hn)) end systemerror("gethostname", err != 0) - return unsafe_string(pointer(hn)) + return Base.@gc_preserve hn unsafe_string(pointer(hn)) end ## system error handling ## @@ -305,7 +305,7 @@ if Sys.iswindows() p = lpMsgBuf[] len == 0 && return "" buf = Vector{UInt16}(len) - unsafe_copy!(pointer(buf), p, len) + Base.@gc_preserve buf unsafe_copy!(pointer(buf), p, len) ccall(:LocalFree, stdcall, Ptr{Void}, (Ptr{Void},), p) return transcode(String, buf) end diff --git a/base/linalg/blas.jl b/base/linalg/blas.jl index 6cf36f09b04e18..740bcd965ac9fd 100644 --- a/base/linalg/blas.jl +++ b/base/linalg/blas.jl @@ -313,21 +313,21 @@ function dot(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T}, if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - dot(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + Base.@gc_preserve DX DY dot(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end function dotc(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - dotc(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + Base.@gc_preserve DX DY dotc(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end function dotu(DX::Union{DenseArray{T},StridedVector{T}}, DY::Union{DenseArray{T},StridedVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - dotu(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + Base.@gc_preserve DX DY dotu(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end ## nrm2 @@ -364,7 +364,7 @@ for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), end end end -nrm2(x::Union{StridedVector,Array}) = nrm2(length(x), pointer(x), stride1(x)) +nrm2(x::Union{StridedVector,Array}) = Base.@gc_preserve x nrm2(length(x), pointer(x), stride1(x)) ## asum @@ -397,7 +397,7 @@ for (fname, elty, ret_type) in ((:dasum_,:Float64,:Float64), end end end -asum(x::Union{StridedVector,Array}) = asum(length(x), pointer(x), stride1(x)) +asum(x::Union{StridedVector,Array}) = Base.@gc_preserve x asum(length(x), pointer(x), stride1(x)) ## axpy @@ -445,7 +445,7 @@ function axpy!(alpha::Number, x::Union{DenseArray{T},StridedVector{T}}, y::Union if length(x) != length(y) throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) end - axpy!(length(x), convert(T,alpha), pointer(x), stride(x, 1), pointer(y), stride(y, 1)) + Base.@gc_preserve x y axpy!(length(x), convert(T,alpha), pointer(x), stride(x, 1), pointer(y), stride(y, 1)) y end @@ -460,7 +460,7 @@ function axpy!(alpha::Number, x::Array{T}, rx::Union{UnitRange{Ti},AbstractRange if minimum(ry) < 1 || maximum(ry) > length(y) throw(ArgumentError("range out of bounds for y, of length $(length(y))")) end - axpy!(length(rx), convert(T, alpha), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) + Base.@gc_preserve x y axpy!(length(rx), convert(T, alpha), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) y end @@ -509,7 +509,7 @@ function axpby!(alpha::Number, x::Union{DenseArray{T},StridedVector{T}}, beta::N if length(x) != length(y) throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) end - axpby!(length(x), convert(T,alpha), pointer(x), stride(x, 1), convert(T,beta), pointer(y), stride(y, 1)) + Base.@gc_preserve x y axpby!(length(x), convert(T,alpha), pointer(x), stride(x, 1), convert(T,beta), pointer(y), stride(y, 1)) y end @@ -526,7 +526,7 @@ for (fname, elty) in ((:idamax_,:Float64), end end end -iamax(dx::Union{StridedVector,Array}) = iamax(length(dx), pointer(dx), stride1(dx)) +iamax(dx::Union{StridedVector,Array}) = Base.@gc_preserve dx iamax(length(dx), pointer(dx), stride1(dx)) # Level 2 ## mv @@ -1526,7 +1526,10 @@ function copy!(dest::Array{T}, rdest::Union{UnitRange{Ti},AbstractRange{Ti}}, if length(rdest) != length(rsrc) throw(DimensionMismatch("ranges must be of the same length")) end - BLAS.blascopy!(length(rsrc), pointer(src)+(first(rsrc)-1)*sizeof(T), step(rsrc), - pointer(dest)+(first(rdest)-1)*sizeof(T), step(rdest)) + Base.@gc_preserve src dest BLAS.blascopy!(length(rsrc), + pointer(src) + (first(rsrc) - 1) * sizeof(T), + step(rsrc), + pointer(dest) + (first(rdest) - 1) * sizeof(T), + step(rdest)) dest end diff --git a/base/linalg/dense.jl b/base/linalg/dense.jl index a7945f2a6df27d..71d7abff447ebe 100644 --- a/base/linalg/dense.jl +++ b/base/linalg/dense.jl @@ -30,7 +30,7 @@ scale!(s::T, X::Array{T}) where {T<:BlasFloat} = scale!(X, s) scale!(X::Array{T}, s::Number) where {T<:BlasFloat} = scale!(X, convert(T, s)) function scale!(X::Array{T}, s::Real) where T<:BlasComplex R = typeof(real(zero(T))) - BLAS.scal!(2*length(X), convert(R,s), convert(Ptr{R},pointer(X)), 1) + Base.@gc_preserve X BLAS.scal!(2*length(X), convert(R,s), convert(Ptr{R},pointer(X)), 1) X end @@ -119,7 +119,7 @@ function norm(x::StridedVector{T}, rx::Union{UnitRange{TI},AbstractRange{TI}}) w if minimum(rx) < 1 || maximum(rx) > length(x) throw(BoundsError(x, rx)) end - BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) + Base.@gc_preserve x BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) end vecnorm1(x::Union{Array{T},StridedVector{T}}) where {T<:BlasReal} = diff --git a/base/linalg/matmul.jl b/base/linalg/matmul.jl index fe1b9b10194aba..0ca518a58fb41d 100644 --- a/base/linalg/matmul.jl +++ b/base/linalg/matmul.jl @@ -51,7 +51,7 @@ function dot(x::Vector{T}, rx::Union{UnitRange{TI},AbstractRange{TI}}, y::Vector if minimum(ry) < 1 || maximum(ry) > length(y) throw(BoundsError(y, ry)) end - BLAS.dot(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) + Base.@gc_preserve x y BLAS.dot(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end function dot(x::Vector{T}, rx::Union{UnitRange{TI},AbstractRange{TI}}, y::Vector{T}, ry::Union{UnitRange{TI},AbstractRange{TI}}) where {T<:BlasComplex,TI<:Integer} @@ -64,7 +64,7 @@ function dot(x::Vector{T}, rx::Union{UnitRange{TI},AbstractRange{TI}}, y::Vector if minimum(ry) < 1 || maximum(ry) > length(y) throw(BoundsError(y, ry)) end - BLAS.dotc(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) + Base.@gc_preserve x y BLAS.dotc(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx), pointer(y)+(first(ry)-1)*sizeof(T), step(ry)) end At_mul_B(x::StridedVector{T}, y::StridedVector{T}) where {T<:BlasComplex} = BLAS.dotu(x, y) @@ -503,6 +503,7 @@ function _generic_matmatmul!(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat @inbounds begin if tile_size > 0 sz = (tile_size, tile_size) + # FIXME: This code is completely invalid!!! Atile = unsafe_wrap(Array, convert(Ptr{T}, pointer(Abuf)), sz) Btile = unsafe_wrap(Array, convert(Ptr{S}, pointer(Bbuf)), sz) @@ -524,6 +525,7 @@ function _generic_matmatmul!(C::AbstractVecOrMat{R}, tA, tB, A::AbstractVecOrMat end end else + # FIXME: This code is completely invalid!!! Ctile = unsafe_wrap(Array, convert(Ptr{R}, pointer(Cbuf)), sz) for jb = 1:tile_size:nB jlim = min(jb+tile_size-1,nB) diff --git a/base/loading.jl b/base/loading.jl index 5b1f748a5c0504..62bd713382be0c 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -53,7 +53,7 @@ elseif Sys.isapple() (Cstring, Ptr{Void}, Ptr{Void}, Csize_t, Culong), path, attr_list, buf, sizeof(buf), FSOPT_NOFOLLOW) systemerror(:getattrlist, ret ≠ 0) - filename_length = unsafe_load( + filename_length = @gc_preserve buf unsafe_load( convert(Ptr{UInt32}, pointer(buf) + 8)) if (filename_length + header_size) > length(buf) resize!(buf, filename_length + header_size) diff --git a/base/mmap.jl b/base/mmap.jl index c8d111e0373305..0811bc1d3beddf 100644 --- a/base/mmap.jl +++ b/base/mmap.jl @@ -290,7 +290,7 @@ Forces synchronization between the in-memory version of a memory-mapped `Array` function sync!(m::Array{T}, flags::Integer=MS_SYNC) where T offset = rem(UInt(pointer(m)), PAGESIZE) ptr = pointer(m) - offset - @static if Sys.isunix() + Base.@gc_preserve m @static if Sys.isunix() systemerror("msync", ccall(:msync, Cint, (Ptr{Void}, Csize_t, Cint), ptr, length(m) * sizeof(T), flags) != 0) else diff --git a/base/parse.jl b/base/parse.jl index 7cca49a22c43aa..1aa21de45bd598 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -171,10 +171,12 @@ function tryparse_internal(::Type{Bool}, sbuff::Union{String,SubString}, len = endpos - startpos + 1 p = pointer(sbuff) + startpos - 1 - (len == 4) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), - p, "true", 4)) && (return Nullable(true)) - (len == 5) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), - p, "false", 5)) && (return Nullable(false)) + @gc_preserve sbuff begin + (len == 4) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), + p, "true", 4)) && (return Nullable(true)) + (len == 5) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), + p, "false", 5)) && (return Nullable(false)) + end if raise substr = SubString(sbuff, orig_start, orig_end) # show input string in the error to avoid confusion diff --git a/base/pcre.jl b/base/pcre.jl index 97b7fae7000d76..361a325c80c45e 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -123,7 +123,7 @@ function err_message(errno) buffer = Vector{UInt8}(256) ccall((:pcre2_get_error_message_8, PCRE_LIB), Void, (Int32, Ptr{UInt8}, Csize_t), errno, buffer, sizeof(buffer)) - unsafe_string(pointer(buffer)) + Base.@gc_preserve buffer unsafe_string(pointer(buffer)) end function exec(re,subject,offset,options,match_data) diff --git a/base/random/RNGs.jl b/base/random/RNGs.jl index ae5c4d32d9ce50..6d2c8c19ee1e8e 100644 --- a/base/random/RNGs.jl +++ b/base/random/RNGs.jl @@ -137,7 +137,7 @@ hash(r::MersenneTwister, h::UInt) = foldr(hash, h, (r.seed, r.state, r.vals, r.i @inline mt_pop!(r::MersenneTwister) = @inbounds return r.vals[r.idx+=1] function gen_rand(r::MersenneTwister) - dsfmt_fill_array_close1_open2!(r.state, pointer(r.vals), length(r.vals)) + Base.@gc_preserve r dsfmt_fill_array_close1_open2!(r.state, pointer(r.vals), length(r.vals)) mt_setfull!(r) end @@ -303,7 +303,7 @@ function rand!(r::MersenneTwister, A::Array{Float64}, n::Int=length(A), else pA = pointer(A) align = Csize_t(pA) % 16 - if align > 0 + Base.@gc_preserve A if align > 0 pA2 = pA + 16 - align fill_array!(r.state, pA2, n2, I) # generate the data in-place, but shifted unsafe_copy!(pA, pA2, n2) # move the data to the beginning of the array @@ -328,8 +328,9 @@ function rand!(r::MersenneTwister, A::Union{Array{Float16},Array{Float32}}, T = eltype(A) n = length(A) n128 = n * sizeof(T) ÷ 16 - rand!(r, unsafe_wrap(Array, convert(Ptr{Float64}, pointer(A)), 2*n128), - 2*n128, Close1Open2()) + Base.@gc_preserve A rand!(r, unsafe_wrap(Array, convert(Ptr{Float64}, pointer(A)), 2*n128), + 2*n128, Close1Open2()) + # FIXME: This code is completely invalid!!! A128 = unsafe_wrap(Array, convert(Ptr{UInt128}, pointer(A)), n128) @inbounds for i in 1:n128 u = A128[i] @@ -370,6 +371,7 @@ function rand!(r::MersenneTwister, A::Array{UInt128}, n::Int=length(A)) if n > length(A) throw(BoundsError(A,n)) end + # FIXME: This code is completely invalid!!! Af = unsafe_wrap(Array, convert(Ptr{Float64}, pointer(A)), 2n) i = n while true @@ -399,6 +401,7 @@ function rand!(r::MersenneTwister, A::Base.BitIntegerArray) n = length(A) T = eltype(A) n128 = n * sizeof(T) ÷ 16 + # FIXME: This code is completely invalid!!! rand!(r, unsafe_wrap(Array, convert(Ptr{UInt128}, pointer(A)), n128)) for i = 16*n128÷sizeof(T)+1:n @inbounds A[i] = rand(r, T) diff --git a/base/random/generation.jl b/base/random/generation.jl index 45b2329d301768..a148c1d4229d72 100644 --- a/base/random/generation.jl +++ b/base/random/generation.jl @@ -58,7 +58,7 @@ function _rand(rng::AbstractRNG, gen::BigFloatRandGenerator) limbs[end] |= Limb_high_bit end z.sign = 1 - unsafe_copy!(z.d, pointer(limbs), gen.nlimbs) + Base.@gc_preserve limbs unsafe_copy!(z.d, pointer(limbs), gen.nlimbs) (z, randbool) end @@ -382,7 +382,7 @@ rand(s::Union{Associative,AbstractSet}, dims::Dims) = rand(GLOBAL_RNG, s, dims) ## random characters from a string -isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(unsafe_load(pointer(s), i)) +isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(Base.@gc_preserve s unsafe_load(pointer(s), i)) isvalid_unsafe(s::AbstractString, i) = isvalid(s, i) _endof(s::String) = sizeof(s) _endof(s::AbstractString) = endof(s) diff --git a/base/strings/string.jl b/base/strings/string.jl index ce2298653a0ffb..244642378e6f83 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -76,7 +76,8 @@ codeunit(s::AbstractString, i::Integer) @gc_preserve s unsafe_load(pointer(s, i)) end -write(io::IO, s::String) = unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))) +write(io::IO, s::String) = + @gc_preserve s unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))) ## comparison ## diff --git a/src/cgutils.cpp b/src/cgutils.cpp index 4987ea22e6daf1..81c34acd36d534 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -2108,6 +2108,9 @@ static Value *boxed(jl_codectx_t &ctx, const jl_cgval_t &vinfo) return UndefValue::get(T_prjlvalue); if (vinfo.constant) return maybe_decay_untracked(literal_pointer_val(ctx, vinfo.constant)); + // This can happen in early bootstrap for `gc_preserve_begin` return value. + if (jt == jl_void_type) + return maybe_decay_untracked(literal_pointer_val(ctx, jl_nothing)); if (vinfo.isboxed) { assert(vinfo.V == vinfo.Vboxed); return vinfo.V;