diff --git a/NEWS.md b/NEWS.md index 7e064afc111a1..195e2cdf70bfe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -966,6 +966,10 @@ Deprecated or removed * `ObjectIdDict` has been deprecated in favor of `IdDict{Any,Any}` ([#25210]). + * `gc` and `gc_enable` have been deprecated in favor of `GC.gc` and `GC.enable` ([#25616]). + + * `Base.@gc_preserve` has been deprecated in favor of `GC.@preserve` ([#25616]). + Command-line option changes --------------------------- @@ -1217,3 +1221,4 @@ Command-line option changes [#25424]: https://github.com/JuliaLang/julia/issues/25424 [#25532]: https://github.com/JuliaLang/julia/issues/25532 [#25545]: https://github.com/JuliaLang/julia/issues/25545 +[#25616]: https://github.com/JuliaLang/julia/issues/25616 diff --git a/base/compiler/optimize.jl b/base/compiler/optimize.jl index 336d91484bfa6..aab09ccfd03ea 100644 --- a/base/compiler/optimize.jl +++ b/base/compiler/optimize.jl @@ -3091,7 +3091,7 @@ function split_struct_alloc!(ctx::AllocOptContext, info, key) # Requires all conditions for `getfield`. # Additionally require all defs to be mutable. # - # * preserved objects (`@gc_preserve` and `ccall` roots) + # * preserved objects (`GC.@preserve` and `ccall` roots) # # No `setfield!` should be called for mutable defs on the NULL sites. # This is because it's currently unclear how conditional undefined root slots diff --git a/base/deepcopy.jl b/base/deepcopy.jl index 2b60833e562f0..01c0d3bbd61e5 100644 --- a/base/deepcopy.jl +++ b/base/deepcopy.jl @@ -46,7 +46,7 @@ function deepcopy_internal(x::String, stackdict::IdDict) if haskey(stackdict, x) return stackdict[x] end - y = @gc_preserve x 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/deprecated.jl b/base/deprecated.jl index b72db1016c290..018d1de5a2927 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1573,6 +1573,10 @@ end @deprecate object_id objectid +@deprecate gc GC.gc +@deprecate gc_enable GC.enable +@eval @deprecate $(Symbol("@gc_preserve")) GC.$(Symbol("@preserve")) false + # issue #9053 if Sys.iswindows() function Filesystem.tempname(uunique::UInt32) diff --git a/base/env.jl b/base/env.jl index a886264e69d93..f79979b7b49cb 100644 --- a/base/env.jl +++ b/base/env.jl @@ -97,7 +97,7 @@ if Sys.iswindows() blk = block[2] len = ccall(:wcslen, UInt, (Ptr{UInt16},), pos) buf = Vector{UInt16}(uninitialized, len) - @gc_preserve buf unsafe_copyto!(pointer(buf), pos, len) + GC.@preserve buf unsafe_copyto!(pointer(buf), pos, len) env = transcode(String, buf) m = match(r"^(=?[^=]+)=(.*)$"s, env) if m === nothing diff --git a/base/exports.jl b/base/exports.jl index 667f81cd3d018..ff2264b31c01e 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -806,10 +806,9 @@ export include_dependency, # RTS internals + GC, finalizer, finalize, - gc, - gc_enable, precompile, # misc diff --git a/base/gcutils.jl b/base/gcutils.jl index cacce1119c1d9..2c58152b541bb 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -38,18 +38,51 @@ Immediately run finalizers registered for object `x`. finalize(@nospecialize(o)) = ccall(:jl_finalize_th, Cvoid, (Ptr{Cvoid}, Any,), Core.getptls(), o) +module GC + """ - gc() + GC.gc() + +Perform garbage collection. -Perform garbage collection. This should not generally be used. +!!! warning + Excessive use will likely lead to poor performance. """ gc(full::Bool=true) = ccall(:jl_gc_collect, Cvoid, (Int32,), full) """ - gc_enable(on::Bool) + GC.enable(on::Bool) Control whether garbage collection is enabled using a boolean argument (`true` for enabled, -`false` for disabled). Return previous GC state. Disabling garbage collection should be -used only with extreme caution, as it can cause memory use to grow without bound. +`false` for disabled). Return previous GC state. + +!!! warning + Disabling garbage collection should be used only with caution, as it can cause memory + use to grow without bound. """ -gc_enable(on::Bool) = ccall(:jl_gc_enable, Int32, (Int32,), on) != 0 +enable(on::Bool) = ccall(:jl_gc_enable, Int32, (Int32,), on) != 0 + +""" + GC.@preserve x1 x2 ... xn expr + +Temporarily protect the given objects from being garbage collected, even if they would +otherwise be unreferenced. + +The last argument is the expression during which the object(s) will be preserved. +The previous arguments are the objects to preserve. +""" +macro preserve(args...) + syms = args[1:end-1] + for x in syms + isa(x, Symbol) || error("Preserved variable must be a symbol") + end + s, r = gensym(), gensym() + esc(quote + $s = $(Expr(:gc_preserve_begin, syms...)) + $r = $(args[end]) + $(Expr(:gc_preserve_end, s)) + $r + end) +end + +end # module GC diff --git a/base/gmp.jl b/base/gmp.jl index 625663539f56f..aefe62110d65f 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -253,7 +253,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 = Base.@gc_preserve bstr MPZ.set_str!(z, pointer(bstr)+(i-start(bstr)), base) + err = GC.@preserve bstr MPZ.set_str!(z, pointer(bstr)+(i-start(bstr)), base) end if err != 0 raise && throw(ArgumentError("invalid BigInt: $(repr(bstr))")) @@ -613,7 +613,7 @@ function base(b::Integer, n::BigInt, pad::Integer=1) nd1 = ndigits(n, b) nd = max(nd1, pad) sv = Base.StringVector(nd + isneg(n)) - Base.@gc_preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, b, n) + 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 7d2ceaf89b01a..7d061cb53812e 100644 --- a/base/io.jl +++ b/base/io.jl @@ -404,7 +404,7 @@ readlines(s=STDIN; chomp::Bool=true) = collect(eachline(s, chomp=chomp)) ## byte-order mark, ntoh & hton ## let a = UInt32[0x01020304] - endian_bom = @gc_preserve a unsafe_load(convert(Ptr{UInt8}, pointer(a))) + endian_bom = GC.@preserve a unsafe_load(convert(Ptr{UInt8}, pointer(a))) global ntoh, hton, ltoh, htol if endian_bom == 0x01 ntoh(x) = x @@ -517,7 +517,7 @@ end function write(s::IO, a::Array) if isbits(eltype(a)) - return @gc_preserve a 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 @@ -534,7 +534,7 @@ function write(s::IO, a::SubArray{T,N,<:Array}) where {T,N} end elsz = sizeof(T) colsz = size(a,1) * elsz - @gc_preserve a if stride(a,1) != 1 + GC.@preserve a if stride(a,1) != 1 for idxs in CartesianIndices(size(a)) unsafe_write(s, pointer(a, idxs.I), elsz) end @@ -585,13 +585,13 @@ read(s::IO, ::Type{Bool}) = (read(s, UInt8) != 0) read(s::IO, ::Type{Ptr{T}}) where {T} = convert(Ptr{T}, read(s, UInt)) function read!(s::IO, a::Array{UInt8}) - @gc_preserve a unsafe_read(s, pointer(a), sizeof(a)) + GC.@preserve a unsafe_read(s, pointer(a), sizeof(a)) return a end function read!(s::IO, a::Array{T}) where T if isbits(T) - @gc_preserve a 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 fea9cabea2a7f..67bc9ae4365b3 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -149,7 +149,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) - @gc_preserve from unsafe_copyto!(p, pointer(from.data, from.ptr), adv) + GC.@preserve from unsafe_copyto!(p, pointer(from.data, from.ptr), adv) from.ptr += adv if nb > avail throw(EOFError()) @@ -164,7 +164,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)) - @gc_preserve a 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) @@ -395,7 +395,7 @@ function write_sub(to::GenericIOBuffer, a::AbstractArray{UInt8}, offs, nel) if offs+nel-1 > length(a) || offs < 1 || nel < 0 throw(BoundsError()) end - @gc_preserve a 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) @@ -428,7 +428,7 @@ read(io::GenericIOBuffer, nb::Integer) = read!(io,StringVector(min(nb, nb_availa function findfirst(delim::EqualTo{UInt8}, buf::IOBuffer) p = pointer(buf.data, buf.ptr) - q = @gc_preserve buf ccall(:memchr,Ptr{UInt8},(Ptr{UInt8},Int32,Csize_t),p,delim.x,nb_available(buf)) + q = GC.@preserve buf ccall(:memchr,Ptr{UInt8},(Ptr{UInt8},Int32,Csize_t),p,delim.x,nb_available(buf)) q == C_NULL && return nothing return Int(q-p+1) end @@ -474,7 +474,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 = @gc_preserve io 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 902e55a6277b8..fd9bdce6bdd79 100644 --- a/base/iostream.jl +++ b/base/iostream.jl @@ -373,7 +373,7 @@ end function readbytes_all!(s::IOStream, b::Array{UInt8}, nb) olb = lb = length(b) nr = 0 - @gc_preserve b while nr < nb + GC.@preserve b while nr < nb if lb < nr+1 lb = max(65536, (nr+1) * 2) resize!(b, lb) @@ -393,7 +393,7 @@ function readbytes_some!(s::IOStream, b::Array{UInt8}, nb) if nb > lb resize!(b, nb) end - nr = @gc_preserve b Int(ccall(:ios_read, Csize_t, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), + nr = GC.@preserve b Int(ccall(:ios_read, Csize_t, (Ptr{Cvoid}, Ptr{Cvoid}, Csize_t), s.ios, pointer(b), nb)) if lb > olb && lb > nr resize!(b, nr) diff --git a/base/libc.jl b/base/libc.jl index fe9fdfb180787..e203c820cd85b 100644 --- a/base/libc.jl +++ b/base/libc.jl @@ -251,7 +251,7 @@ function gethostname() ccall(:gethostname, Int32, (Ptr{UInt8}, UInt), hn, length(hn)) end systemerror("gethostname", err != 0) - return Base.@gc_preserve hn unsafe_string(pointer(hn)) + return GC.@preserve hn unsafe_string(pointer(hn)) end ## system error handling ## @@ -307,7 +307,7 @@ if Sys.iswindows() p = lpMsgBuf[] len == 0 && return "" buf = Vector{UInt16}(uninitialized, len) - Base.@gc_preserve buf unsafe_copyto!(pointer(buf), p, len) + GC.@preserve buf unsafe_copyto!(pointer(buf), p, len) ccall(:LocalFree, stdcall, Ptr{Cvoid}, (Ptr{Cvoid},), p) return transcode(String, buf) end diff --git a/base/libgit2/blame.jl b/base/libgit2/blame.jl index b7106b92c583c..53e3b31326784 100644 --- a/base/libgit2/blame.jl +++ b/base/libgit2/blame.jl @@ -32,7 +32,7 @@ function Base.getindex(blame::GitBlame, i::Integer) if !(1 <= i <= counthunks(blame)) throw(BoundsError(blame, (i,))) end - Base.@gc_preserve blame begin + GC.@preserve blame begin hunk_ptr = ccall((:git_blame_get_hunk_byindex, :libgit2), Ptr{BlameHunk}, (Ptr{Cvoid}, Csize_t), blame.ptr, i-1) diff --git a/base/libgit2/commit.jl b/base/libgit2/commit.jl index 2df3dfdb2237e..39ec4c2518c03 100644 --- a/base/libgit2/commit.jl +++ b/base/libgit2/commit.jl @@ -9,7 +9,7 @@ leading newlines removed). If `raw` is `true`, the message is not stripped of any such newlines. """ function message(c::GitCommit, raw::Bool=false) - Base.@gc_preserve c begin + GC.@preserve c begin local msg_ptr::Cstring msg_ptr = raw ? ccall((:git_commit_message_raw, :libgit2), Cstring, (Ptr{Cvoid},), c.ptr) : ccall((:git_commit_message, :libgit2), Cstring, (Ptr{Cvoid},), c.ptr) @@ -28,7 +28,7 @@ Return the `Signature` of the author of the commit `c`. The author is the person who made changes to the relevant file(s). See also [`committer`](@ref). """ function author(c::GitCommit) - Base.@gc_preserve c begin + GC.@preserve c begin ptr = ccall((:git_commit_author, :libgit2), Ptr{SignatureStruct}, (Ptr{Cvoid},), c.ptr) @assert ptr != C_NULL sig = Signature(ptr) @@ -45,7 +45,7 @@ need not be the same as the `author`, for example, if the `author` emailed a pat a `committer` who committed it. """ function committer(c::GitCommit) - Base.@gc_preserve c begin + GC.@preserve c begin ptr = ccall((:git_commit_committer, :libgit2), Ptr{SignatureStruct}, (Ptr{Cvoid},), c.ptr) sig = Signature(ptr) end diff --git a/base/libgit2/index.jl b/base/libgit2/index.jl index be4baf7580c04..9dabe302514cf 100644 --- a/base/libgit2/index.jl +++ b/base/libgit2/index.jl @@ -168,7 +168,7 @@ function Base.count(idx::GitIndex) end function Base.getindex(idx::GitIndex, i::Integer) - Base.@gc_preserve idx begin + GC.@preserve idx begin ie_ptr = ccall((:git_index_get_byindex, :libgit2), Ptr{IndexEntry}, (Ptr{Cvoid}, Csize_t), idx.ptr, i-1) diff --git a/base/libgit2/libgit2.jl b/base/libgit2/libgit2.jl index 5727097a856f1..d76a8dfb340de 100644 --- a/base/libgit2/libgit2.jl +++ b/base/libgit2/libgit2.jl @@ -525,7 +525,7 @@ function clone(repo_url::AbstractString, repo_path::AbstractString; payload::Union{CredentialPayload, AbstractCredential, CachedCredentials, Nothing}=CredentialPayload()) # setup clone options lbranch = Base.cconvert(Cstring, branch) - @Base.gc_preserve lbranch begin + GC.@preserve lbranch begin p = reset!(deprecate_nullable_creds(:clone, "repo_url, repo_path", payload)) fetch_opts = FetchOptions(callbacks = RemoteCallbacks(credentials=credentials_cb(), payload=p)) clone_opts = CloneOptions( diff --git a/base/libgit2/merge.jl b/base/libgit2/merge.jl index ac62c058ac1c1..2f130be7a382c 100644 --- a/base/libgit2/merge.jl +++ b/base/libgit2/merge.jl @@ -44,7 +44,7 @@ function GitAnnotated(repo::GitRepo, comittish::AbstractString) end function GitHash(ann::GitAnnotated) - Base.@gc_preserve ann begin + GC.@preserve ann begin oid = unsafe_load(ccall((:git_annotated_commit_id, :libgit2), Ptr{GitHash}, (Ptr{Cvoid},), ann.ptr)) end return oid diff --git a/base/libgit2/oid.jl b/base/libgit2/oid.jl index 2500fe600b419..daf1ad603011d 100644 --- a/base/libgit2/oid.jl +++ b/base/libgit2/oid.jl @@ -106,7 +106,7 @@ Get the identifier (`GitHash`) of the object referred to by the direct reference function GitHash(ref::GitReference) isempty(ref) && return GitHash() reftype(ref) != Consts.REF_OID && return GitHash() - Base.@gc_preserve ref begin + GC.@preserve ref begin oid_ptr = ccall((:git_reference_target, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), ref.ptr) oid_ptr == C_NULL && return GitHash() oid = GitHash(oid_ptr) diff --git a/base/libgit2/rebase.jl b/base/libgit2/rebase.jl index b59c827af75e7..facc0d79951cf 100644 --- a/base/libgit2/rebase.jl +++ b/base/libgit2/rebase.jl @@ -32,7 +32,7 @@ function Base.getindex(rb::GitRebase, i::Integer) if !(1 <= i <= count(rb)) throw(BoundsError(rb, (i,))) end - Base.@gc_preserve rb begin + GC.@preserve rb begin rb_op_ptr = ccall((:git_rebase_operation_byindex, :libgit2), Ptr{RebaseOperation}, (Ptr{Cvoid}, Csize_t), rb.ptr, i-1) @@ -43,7 +43,7 @@ end function Base.next(rb::GitRebase) rb_op_ptr_ptr = Ref{Ptr{RebaseOperation}}(C_NULL) - Base.@gc_preserve rb begin + GC.@preserve rb begin try @check ccall((:git_rebase_next, :libgit2), Cint, (Ptr{Ptr{RebaseOperation}}, Ptr{Cvoid}), diff --git a/base/libgit2/reference.jl b/base/libgit2/reference.jl index b9297d0aa5dba..68f8ada3cde85 100644 --- a/base/libgit2/reference.jl +++ b/base/libgit2/reference.jl @@ -62,7 +62,7 @@ julia> LibGit2.shortname(branch_ref) """ function shortname(ref::GitReference) isempty(ref) && return "" - Base.@gc_preserve ref begin + GC.@preserve ref begin name_ptr = ccall((:git_reference_shorthand, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) name_ptr == C_NULL && return "" name = unsafe_string(name_ptr) @@ -92,7 +92,7 @@ reference, return an empty string. function fullname(ref::GitReference) isempty(ref) && return "" reftype(ref) == Consts.REF_OID && return "" - Base.@gc_preserve ref begin + GC.@preserve ref begin rname = ccall((:git_reference_symbolic_target, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) rname == C_NULL && return "" name = unsafe_string(rname) @@ -107,7 +107,7 @@ Return the full name of `ref`. """ function name(ref::GitReference) isempty(ref) && return "" - Base.@gc_preserve ref begin + GC.@preserve ref begin name_ptr = ccall((:git_reference_name, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) name_ptr == C_NULL && return "" name = unsafe_string(name_ptr) @@ -118,7 +118,7 @@ end function branch(ref::GitReference) isempty(ref) && return "" str_ptr_ptr = Ref{Cstring}() - Base.@gc_preserve ref begin + GC.@preserve ref begin @check ccall((:git_branch_name, :libgit2), Cint, (Ptr{Cstring}, Ptr{Cvoid},), str_ptr_ptr, ref.ptr) str = unsafe_string(str_ptr_ptr[]) diff --git a/base/libgit2/status.jl b/base/libgit2/status.jl index 52fb8128bf8a0..b05a8ac4a8c65 100644 --- a/base/libgit2/status.jl +++ b/base/libgit2/status.jl @@ -24,7 +24,7 @@ end function Base.getindex(status::GitStatus, i::Integer) 1 <= i <= length(status) || throw(BoundsError()) - Base.@gc_preserve status begin + GC.@preserve status begin entry_ptr = ccall((:git_status_byindex, :libgit2), Ptr{StatusEntry}, (Ptr{Cvoid}, Csize_t), diff --git a/base/libgit2/tag.jl b/base/libgit2/tag.jl index 53bcf713f0ebc..6f917435271bc 100644 --- a/base/libgit2/tag.jl +++ b/base/libgit2/tag.jl @@ -57,7 +57,7 @@ end The name of `tag` (e.g. `"v0.5"`). """ function name(tag::GitTag) - Base.@gc_preserve tag begin + GC.@preserve tag begin str_ptr = ccall((:git_tag_name, :libgit2), Cstring, (Ptr{Cvoid},), tag.ptr) str_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) str = unsafe_string(str_ptr) @@ -72,7 +72,7 @@ end The `GitHash` of the target object of `tag`. """ function target(tag::GitTag) - Base.@gc_preserve tag begin + GC.@preserve tag begin oid_ptr = ccall((:git_tag_target_id, :libgit2), Ptr{GitHash}, (Ptr{Cvoid},), tag.ptr) oid_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) str = unsafe_load(oid_ptr) diff --git a/base/libgit2/tree.jl b/base/libgit2/tree.jl index faf22e6b35eba..c871ae6d5c6d3 100644 --- a/base/libgit2/tree.jl +++ b/base/libgit2/tree.jl @@ -66,7 +66,7 @@ end Return the [`GitHash`](@ref) of the object to which `te` refers. """ function entryid(te::GitTreeEntry) - Base.@gc_preserve te begin + GC.@preserve te begin oid_ptr = ccall((:git_tree_entry_id, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), te.ptr) oid = GitHash(oid_ptr) end diff --git a/base/loading.jl b/base/loading.jl index 3ab7acbe50972..994e723ea838e 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -53,7 +53,7 @@ elseif Sys.isapple() (Cstring, Ptr{Cvoid}, Ptr{Cvoid}, Csize_t, Culong), path, attr_list, buf, sizeof(buf), FSOPT_NOFOLLOW) systemerror(:getattrlist, ret ≠ 0) - filename_length = @gc_preserve buf 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/parse.jl b/base/parse.jl index 58856ce0b4645..cf461142dba61 100644 --- a/base/parse.jl +++ b/base/parse.jl @@ -176,7 +176,7 @@ function tryparse_internal(::Type{Bool}, sbuff::Union{String,SubString{String}}, len = endpos - startpos + 1 p = pointer(sbuff) + startpos - 1 - @gc_preserve sbuff begin + GC.@preserve sbuff begin (len == 4) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), p, "true", 4)) && (return true) (len == 5) && (0 == ccall(:memcmp, Int32, (Ptr{UInt8}, Ptr{UInt8}, UInt), diff --git a/base/pcre.jl b/base/pcre.jl index d144e9a6a5b1c..d45252b3d5c5e 100644 --- a/base/pcre.jl +++ b/base/pcre.jl @@ -123,7 +123,7 @@ function err_message(errno) buffer = Vector{UInt8}(uninitialized, 256) ccall((:pcre2_get_error_message_8, PCRE_LIB), Cvoid, (Int32, Ptr{UInt8}, Csize_t), errno, buffer, sizeof(buffer)) - Base.@gc_preserve buffer unsafe_string(pointer(buffer)) + GC.@preserve buffer unsafe_string(pointer(buffer)) end function exec(re,subject,offset,options,match_data) diff --git a/base/pointer.jl b/base/pointer.jl index 63ffd8b4be3d8..2ed621c569d94 100644 --- a/base/pointer.jl +++ b/base/pointer.jl @@ -154,24 +154,3 @@ isless(x::Ptr, y::Ptr) = isless(UInt(x), UInt(y)) +(x::Ptr, y::Integer) = oftype(x, Intrinsics.add_ptr(UInt(x), (y % UInt) % UInt)) -(x::Ptr, y::Integer) = oftype(x, Intrinsics.sub_ptr(UInt(x), (y % UInt) % UInt)) +(x::Integer, y::Ptr) = y + x - -""" -Temporarily protects an object from being garbage collected, even -if it would otherwise be unreferenced. - -The last argument is the expression to preserve objects during. -The previous arguments are the objects to preserve. -""" -macro gc_preserve(args...) - syms = args[1:end-1] - for x in syms - isa(x, Symbol) || error("Preserved variable must be a symbol") - end - s, r = gensym(), gensym() - esc(quote - $s = $(Expr(:gc_preserve_begin, syms...)) - $r = $(args[end]) - $(Expr(:gc_preserve_end, s)) - $r - end) -end diff --git a/base/reinterpretarray.jl b/base/reinterpretarray.jl index ab186612b2673..4a1291d5f128d 100644 --- a/base/reinterpretarray.jl +++ b/base/reinterpretarray.jl @@ -55,7 +55,7 @@ unsafe_convert(::Type{Ptr{T}}, a::ReinterpretArray{T,N,S} where N) where {T,S} = ind_start, sidx = divrem((inds[1]-1)*sizeof(T), sizeof(S)) t = Ref{T}() s = Ref{S}() - @gc_preserve t s begin + GC.@preserve t s begin tptr = Ptr{UInt8}(unsafe_convert(Ref{T}, t)) sptr = Ptr{UInt8}(unsafe_convert(Ref{S}, s)) i = 1 @@ -90,7 +90,7 @@ end ind_start, sidx = divrem((inds[1]-1)*sizeof(T), sizeof(S)) t = Ref{T}(v) s = Ref{S}() - @gc_preserve t s begin + GC.@preserve t s begin tptr = Ptr{UInt8}(unsafe_convert(Ref{T}, t)) sptr = Ptr{UInt8}(unsafe_convert(Ref{S}, s)) nbytes_copied = 0 diff --git a/base/show.jl b/base/show.jl index 77f92a1a91c5b..283ab54f481e3 100644 --- a/base/show.jl +++ b/base/show.jl @@ -182,7 +182,7 @@ function show_default(io::IO, @nospecialize(x)) else print(io, "0x") r = Ref(x) - @gc_preserve r begin + GC.@preserve r begin p = unsafe_convert(Ptr{Cvoid}, r) for i in (nb - 1):-1:0 print(io, hex(unsafe_load(convert(Ptr{UInt8}, p + i)), 2)) diff --git a/base/strings/string.jl b/base/strings/string.jl index 498558f3a65c5..1910efe4154f4 100644 --- a/base/strings/string.jl +++ b/base/strings/string.jl @@ -78,11 +78,11 @@ codeunit(s::String) = UInt8 @inline function codeunit(s::String, i::Integer) @boundscheck checkbounds(s, i) - @gc_preserve s unsafe_load(pointer(s, i)) + GC.@preserve s unsafe_load(pointer(s, i)) end write(io::IO, s::String) = - @gc_preserve s unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))) + GC.@preserve s unsafe_write(io, pointer(s), reinterpret(UInt, sizeof(s))) ## comparison ## diff --git a/doc/src/base/base.md b/doc/src/base/base.md index e4fa75f137069..e04d69e7836b5 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -326,8 +326,8 @@ Base.@functionloc ## Internals ```@docs -Base.gc -Base.gc_enable +Base.GC.gc +Base.GC.enable Meta.lower Meta.@lower Meta.parse(::AbstractString, ::Int) diff --git a/doc/src/manual/faq.md b/doc/src/manual/faq.md index 6a24562d18e13..d367791dad20f 100644 --- a/doc/src/manual/faq.md +++ b/doc/src/manual/faq.md @@ -10,7 +10,7 @@ session (technically, in module `Main`), it is always present. If memory usage is your concern, you can always replace objects with ones that consume less memory. For example, if `A` is a gigabyte-sized array that you no longer need, you can free the memory with `A = nothing`. The memory will be released the next time the garbage collector runs; you can force -this to happen with [`gc()`](@ref). Moreover, an attempt to use `A` will likely result in an error, because most methods are not defined on type `Nothing`. +this to happen with [`gc()`](@ref Base.GC.gc). Moreover, an attempt to use `A` will likely result in an error, because most methods are not defined on type `Nothing`. ### How can I modify the declaration of a type in my session? diff --git a/stdlib/DelimitedFiles/src/DelimitedFiles.jl b/stdlib/DelimitedFiles/src/DelimitedFiles.jl index c8cf5c873f8fe..2d48600f467ec 100644 --- a/stdlib/DelimitedFiles/src/DelimitedFiles.jl +++ b/stdlib/DelimitedFiles/src/DelimitedFiles.jl @@ -247,7 +247,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(Base.@gc_preserve(a, unsafe_string(pointer(a),length(a))), dlm, T, eol, auto, optsd) + return readdlm_string(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 @@ -337,7 +337,7 @@ function DLMStore(::Type{T}, dims::NTuple{2,Integer}, end _chrinstr(sbuff::String, chr::UInt8, startpos::Int, endpos::Int) = - Base.@gc_preserve sbuff (endpos >= startpos) && (C_NULL != ccall(:memchr, Ptr{UInt8}, + 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/stdlib/FileWatching/test/runtests.jl b/stdlib/FileWatching/test/runtests.jl index ce90324aa0652..8aef7119e2c71 100644 --- a/stdlib/FileWatching/test/runtests.jl +++ b/stdlib/FileWatching/test/runtests.jl @@ -144,7 +144,7 @@ end end let a = Ref(0) make_unrooted_timer(a) - gc() + GC.gc() @test a[] == 1 end @@ -161,8 +161,8 @@ function test_12992() close(pfw) pfw = PollingFileWatcher(@__FILE__, 0.01) close(pfw) - gc() - gc() + GC.gc() + GC.gc() end # Make sure multiple close is fine @@ -176,8 +176,8 @@ function test2_12992() pfw = PollingFileWatcher(@__FILE__, 0.01) close(pfw) close(pfw) - gc() - gc() + GC.gc() + GC.gc() end test_12992() diff --git a/stdlib/LinearAlgebra/src/blas.jl b/stdlib/LinearAlgebra/src/blas.jl index 6b551b245402f..fcdc219857683 100644 --- a/stdlib/LinearAlgebra/src/blas.jl +++ b/stdlib/LinearAlgebra/src/blas.jl @@ -324,21 +324,21 @@ function dot(DX::Union{DenseArray{T},AbstractVector{T}}, DY::Union{DenseArray{T} if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - Base.@gc_preserve DX DY dot(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + GC.@preserve DX DY dot(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end function dotc(DX::Union{DenseArray{T},AbstractVector{T}}, DY::Union{DenseArray{T},AbstractVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - Base.@gc_preserve DX DY dotc(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + GC.@preserve DX DY dotc(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end function dotu(DX::Union{DenseArray{T},AbstractVector{T}}, DY::Union{DenseArray{T},AbstractVector{T}}) where T<:BlasComplex n = length(DX) if n != length(DY) throw(DimensionMismatch("dot product arguments have lengths $(length(DX)) and $(length(DY))")) end - Base.@gc_preserve DX DY dotu(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) + GC.@preserve DX DY dotu(n, pointer(DX), stride(DX, 1), pointer(DY), stride(DY, 1)) end ## nrm2 @@ -372,7 +372,7 @@ for (fname, elty, ret_type) in ((:dnrm2_,:Float64,:Float64), end end end -nrm2(x::Union{AbstractVector,DenseArray}) = Base.@gc_preserve x nrm2(length(x), pointer(x), stride1(x)) +nrm2(x::Union{AbstractVector,DenseArray}) = GC.@preserve x nrm2(length(x), pointer(x), stride1(x)) ## asum @@ -405,7 +405,7 @@ for (fname, elty, ret_type) in ((:dasum_,:Float64,:Float64), end end end -asum(x::Union{AbstractVector,DenseArray}) = Base.@gc_preserve x asum(length(x), pointer(x), stride1(x)) +asum(x::Union{AbstractVector,DenseArray}) = GC.@preserve x asum(length(x), pointer(x), stride1(x)) ## axpy @@ -453,7 +453,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 - Base.@gc_preserve x y axpy!(length(x), convert(T,alpha), pointer(x), stride(x, 1), pointer(y), stride(y, 1)) + GC.@preserve x y axpy!(length(x), convert(T,alpha), pointer(x), stride(x, 1), pointer(y), stride(y, 1)) y end @@ -468,7 +468,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 - 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)) + 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 @@ -517,7 +517,7 @@ function axpby!(alpha::Number, x::Union{DenseArray{T},AbstractVector{T}}, beta:: if length(x) != length(y) throw(DimensionMismatch("x has length $(length(x)), but y has length $(length(y))")) end - Base.@gc_preserve x y axpby!(length(x), convert(T,alpha), pointer(x), stride(x, 1), convert(T,beta), pointer(y), stride(y, 1)) + 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 @@ -534,7 +534,7 @@ for (fname, elty) in ((:idamax_,:Float64), end end end -iamax(dx::Union{AbstractVector,DenseArray}) = Base.@gc_preserve dx iamax(length(dx), pointer(dx), stride1(dx)) +iamax(dx::Union{AbstractVector,DenseArray}) = GC.@preserve dx iamax(length(dx), pointer(dx), stride1(dx)) # Level 2 ## mv @@ -1565,7 +1565,7 @@ function copyto!(dest::Array{T}, rdest::Union{UnitRange{Ti},AbstractRange{Ti}}, if length(rdest) != length(rsrc) throw(DimensionMismatch("ranges must be of the same length")) end - Base.@gc_preserve src dest BLAS.blascopy!(length(rsrc), + GC.@preserve src dest BLAS.blascopy!(length(rsrc), pointer(src) + (first(rsrc) - 1) * sizeof(T), step(rsrc), pointer(dest) + (first(rdest) - 1) * sizeof(T), diff --git a/stdlib/LinearAlgebra/src/dense.jl b/stdlib/LinearAlgebra/src/dense.jl index e683008349049..8748dd308a3e5 100644 --- a/stdlib/LinearAlgebra/src/dense.jl +++ b/stdlib/LinearAlgebra/src/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))) - Base.@gc_preserve X BLAS.scal!(2*length(X), convert(R,s), convert(Ptr{R},pointer(X)), 1) + GC.@preserve X BLAS.scal!(2*length(X), convert(R,s), convert(Ptr{R},pointer(X)), 1) X end @@ -132,7 +132,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 - Base.@gc_preserve x BLAS.nrm2(length(rx), pointer(x)+(first(rx)-1)*sizeof(T), step(rx)) + 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/stdlib/LinearAlgebra/src/matmul.jl b/stdlib/LinearAlgebra/src/matmul.jl index 3f3bf8143db3b..c0c4daea077f0 100644 --- a/stdlib/LinearAlgebra/src/matmul.jl +++ b/stdlib/LinearAlgebra/src/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 - 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)) + 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 - 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)) + 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 *(transx::Transpose{<:Any,<:StridedVector{T}}, y::StridedVector{T}) where {T<:BlasComplex} = diff --git a/stdlib/Mmap/src/Mmap.jl b/stdlib/Mmap/src/Mmap.jl index 1b3576e3aebdb..d30b47463dd50 100644 --- a/stdlib/Mmap/src/Mmap.jl +++ b/stdlib/Mmap/src/Mmap.jl @@ -337,7 +337,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 - Base.@gc_preserve m @static if Sys.isunix() + GC.@preserve m @static if Sys.isunix() systemerror("msync", ccall(:msync, Cint, (Ptr{Cvoid}, Csize_t, Cint), ptr, length(m) * sizeof(T), flags) != 0) else diff --git a/stdlib/Mmap/test/runtests.jl b/stdlib/Mmap/test/runtests.jl index 7ca20e7aa42b3..0face3bf6fd55 100644 --- a/stdlib/Mmap/test/runtests.jl +++ b/stdlib/Mmap/test/runtests.jl @@ -6,20 +6,20 @@ file = tempname() write(file, "Hello World\n") t = b"Hello World" @test Mmap.mmap(file, Array{UInt8,3}, (11,1,1)) == reshape(t,(11,1,1)) -gc(); gc() +GC.gc(); GC.gc() @test Mmap.mmap(file, Array{UInt8,3}, (1,11,1)) == reshape(t,(1,11,1)) -gc(); gc() +GC.gc(); GC.gc() @test Mmap.mmap(file, Array{UInt8,3}, (1,1,11)) == reshape(t,(1,1,11)) -gc(); gc() +GC.gc(); GC.gc() @test Mmap.mmap(file, Array{UInt8,3}, (11,0,1)) == Array{UInt8}(uninitialized, (0,0,0)) @test Mmap.mmap(file, Vector{UInt8}, (11,)) == t -gc(); gc() +GC.gc(); GC.gc() @test Mmap.mmap(file, Array{UInt8,2}, (1,11)) == t' -gc(); gc() +GC.gc(); GC.gc() @test Mmap.mmap(file, Array{UInt8,2}, (0,12)) == Array{UInt8}(uninitialized, (0,0)) m = Mmap.mmap(file, Array{UInt8,3}, (1,2,1)) @test m == reshape(b"He",(1,2,1)) -finalize(m); m=nothing; gc() +finalize(m); m=nothing; GC.gc() # constructors @test length(@inferred Mmap.mmap(file)) == 12 @@ -45,7 +45,7 @@ s = open(file) @test length(@inferred Mmap.mmap(s, Vector{Int8}, 12, 0; shared=false)) == 12 close(s) @test_throws ErrorException Mmap.mmap(file, Vector{Ref}) # must be bit-type -gc(); gc() +GC.gc(); GC.gc() s = open(f->f,file,"w") @test Mmap.mmap(file) == Vector{UInt8}() # requested len=0 on empty file @@ -54,7 +54,7 @@ s = open(file, "r+") m = Mmap.mmap(s,Vector{UInt8},12) m[:] = b"Hello World\n" Mmap.sync!(m) -close(s); finalize(m); m=nothing; gc() +close(s); finalize(m); m=nothing; GC.gc() @test open(x->read(x, String),file) == "Hello World\n" s = open(file, "r") @@ -71,39 +71,39 @@ close(s) for i = 0x01:0x0c @test length(Mmap.mmap(file, Vector{UInt8}, i)) == Int(i) end -gc(); gc() +GC.gc(); GC.gc() sz = filesize(file) s = open(file, "r+") m = Mmap.mmap(s, Vector{UInt8}, sz+1) @test length(m) == sz+1 # test growing @test m[end] == 0x00 -close(s); finalize(m); m=nothing; gc() +close(s); finalize(m); m=nothing; GC.gc() sz = filesize(file) s = open(file, "r+") m = Mmap.mmap(s, Vector{UInt8}, 1, sz) @test length(m) == 1 @test m[1] == 0x00 -close(s); finalize(m); m=nothing; gc() +close(s); finalize(m); m=nothing; GC.gc() sz = filesize(file) # test where offset is actually > than size of file; file is grown with zeroed bytes s = open(file, "r+") m = Mmap.mmap(s, Vector{UInt8}, 1, sz+1) @test length(m) == 1 @test m[1] == 0x00 -close(s); finalize(m); m=nothing; gc() +close(s); finalize(m); m=nothing; GC.gc() s = open(file, "r") m = Mmap.mmap(s) @test_throws ReadOnlyMemoryError m[5] = UInt8('x') # tries to setindex! on read-only array -finalize(m); m=nothing; gc() +finalize(m); m=nothing; GC.gc() write(file, "Hello World\n") s = open(file, "r") m = Mmap.mmap(s) close(s) -finalize(m); m=nothing; gc() +finalize(m); m=nothing; GC.gc() m = Mmap.mmap(file) s = open(file, "r+") c = Mmap.mmap(s) @@ -114,7 +114,7 @@ close(s) @test m[1] == UInt8('J') @test d[1] == UInt8('J') finalize(m); finalize(c); finalize(d) -m=nothing; c=nothing; d=nothing; gc() +m=nothing; c=nothing; d=nothing; GC.gc() write(file, "Hello World\n") @@ -122,10 +122,10 @@ s = open(file, "r") @test isreadonly(s) == true c = Mmap.mmap(s, Vector{UInt8}, (11,)) @test c == b"Hello World" -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() c = Mmap.mmap(s, Vector{UInt8}, (UInt16(11),)) @test c == b"Hello World" -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() @test_throws ArgumentError Mmap.mmap(s, Vector{UInt8}, (Int16(-11),)) @test_throws ArgumentError Mmap.mmap(s, Vector{UInt8}, (typemax(UInt),)) close(s) @@ -139,22 +139,22 @@ s = open(file, "r") str = readline(s) close(s) @test startswith(str, "Hellx World") -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() c = Mmap.mmap(file) @test c == b"Hellx World\n" -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() c = Mmap.mmap(file, Vector{UInt8}, 3) @test c == b"Hel" -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() s = open(file, "r") c = Mmap.mmap(s, Vector{UInt8}, 6) @test c == b"Hellx " close(s) -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() c = Mmap.mmap(file, Vector{UInt8}, 5, 6) @test c == b"World" -finalize(c); c=nothing; gc() +finalize(c); c=nothing; GC.gc() s = open(file, "w") write(s, "Hello World\n") @@ -167,7 +167,7 @@ for i = 1:12 @test m[i] == tdata[i] end @test_throws BoundsError m[13] -finalize(m); m=nothing; gc() +finalize(m); m=nothing; GC.gc() m = Mmap.mmap(file,Vector{UInt8},6) @test m[1] == b"H"[1] @@ -177,13 +177,13 @@ m = Mmap.mmap(file,Vector{UInt8},6) @test m[5] == b"o"[1] @test m[6] == b" "[1] @test_throws BoundsError m[7] -finalize(m); m=nothing; gc() +finalize(m); m=nothing; GC.gc() m = Mmap.mmap(file,Vector{UInt8},2,6) @test m[1] == b"W"[1] @test m[2] == b"o"[1] @test_throws BoundsError m[3] -finalize(m); m = nothing; gc() +finalize(m); m = nothing; GC.gc() s = open(file, "w") write(s, [0xffffffffffffffff, @@ -214,7 +214,7 @@ b = Mmap.mmap(s, BitArray, (17,19)) close(s) finalize(b); finalize(b0) b = nothing; b0 = nothing -gc() +GC.gc() open(file,"w") do f write(f,UInt64(1)) @@ -225,7 +225,7 @@ s = open(file, "r+") m = Mmap.mmap(s, BitArray, (72,)) @test Base._check_bitarray_consistency(m) @test length(m) == 72 -close(s); finalize(m); m = nothing; gc() +close(s); finalize(m); m = nothing; GC.gc() rm(file) # Mmap.mmap with an offset @@ -249,7 +249,7 @@ A4 = Mmap.mmap(s, Matrix{Int}, (m,150), convert(Int64, (2+150*m)*sizeof(Int))) close(s) finalize(A2); finalize(A3); finalize(A4) A2 = A3 = A4 = nothing -gc() +GC.gc() rm(fname) # Mmap.Anonymous @@ -289,7 +289,7 @@ n = similar(m, (2,2)) n = similar(m, 12) @test length(n) == 12 @test size(n) == (12,) -finalize(m); m = nothing; gc() +finalize(m); m = nothing; GC.gc() # test #14885 file = tempname() @@ -297,9 +297,9 @@ touch(file) open(file, "r+") do s A = Mmap.mmap(s, Vector{UInt8}, (10,), 0) Mmap.sync!(A) - finalize(A); A = nothing; gc() + finalize(A); A = nothing; GC.gc() A = Mmap.mmap(s, Vector{UInt8}, (10,), 1) Mmap.sync!(A) - finalize(A); A = nothing; gc() + finalize(A); A = nothing; GC.gc() end rm(file) diff --git a/stdlib/Random/src/RNGs.jl b/stdlib/Random/src/RNGs.jl index 669b4a43f6ce9..f8729d65032c1 100644 --- a/stdlib/Random/src/RNGs.jl +++ b/stdlib/Random/src/RNGs.jl @@ -173,7 +173,7 @@ mt_setempty!(r::MersenneTwister) = r.idxF = MT_CACHE_F mt_pop!(r::MersenneTwister) = @inbounds return r.vals[r.idxF+=1] function gen_rand(r::MersenneTwister) - @gc_preserve r dsfmt_fill_array_close1_open2!(r.state, pointer(r.vals), length(r.vals)) + GC.@preserve r dsfmt_fill_array_close1_open2!(r.state, pointer(r.vals), length(r.vals)) mt_setfull!(r) end @@ -382,12 +382,12 @@ function _rand_max383!(r::MersenneTwister, A::UnsafeView{Float64}, I::FloatInter mt_avail(r) == 0 && gen_rand(r) # from now on, at most one call to gen_rand(r) will be necessary m = min(n, mt_avail(r)) - @gc_preserve r unsafe_copyto!(A.ptr, pointer(r.vals, r.idxF+1), m) + GC.@preserve r unsafe_copyto!(A.ptr, pointer(r.vals, r.idxF+1), m) if m == n r.idxF += m else # m < n gen_rand(r) - @gc_preserve r unsafe_copyto!(A.ptr+m*sizeof(Float64), pointer(r.vals), n-m) + GC.@preserve r unsafe_copyto!(A.ptr+m*sizeof(Float64), pointer(r.vals), n-m) r.idxF = n-m end if I isa CloseOpen01 @@ -437,7 +437,7 @@ end function _rand!(r::MersenneTwister, A::Array{T}, n64::Int, I::FloatInterval_64) where T # n64 is the length in terms of `Float64` of the target @assert sizeof(Float64)*n64 <= sizeof(T)*length(A) && isbits(T) - @gc_preserve A rand!(r, UnsafeView{Float64}(pointer(A), n64), SamplerTrivial(I)) + GC.@preserve A rand!(r, UnsafeView{Float64}(pointer(A), n64), SamplerTrivial(I)) A end @@ -457,7 +457,7 @@ for T in (Float16, Float32) n = length(A) n128 = n * sizeof($T) ÷ 16 _rand!(r, A, 2*n128, CloseOpen12()) - @gc_preserve A begin + GC.@preserve A begin A128 = UnsafeView{UInt128}(pointer(A), n128) for i in 1:n128 u = A128[i] @@ -520,7 +520,7 @@ end for T in BitInteger_types @eval rand!(r::MersenneTwister, A::Array{$T}, sp::SamplerType{$T}) = - (@gc_preserve A rand!(r, UnsafeView(pointer(A), length(A)), sp); A) + (GC.@preserve A rand!(r, UnsafeView(pointer(A), length(A)), sp); A) T == UInt128 && continue diff --git a/stdlib/Random/src/Random.jl b/stdlib/Random/src/Random.jl index 24c9fa185abbb..ed79352fd4199 100644 --- a/stdlib/Random/src/Random.jl +++ b/stdlib/Random/src/Random.jl @@ -10,7 +10,7 @@ using .DSFMT using Base.GMP.MPZ using Base.GMP: Limb -using Base: BitInteger, BitInteger_types, BitUnsigned, @gc_preserve +using Base: BitInteger, BitInteger_types, BitUnsigned import Base: copymutable, copy, copy!, ==, hash, serialize, deserialize, convert import Base: rand, randn diff --git a/stdlib/Random/src/generation.jl b/stdlib/Random/src/generation.jl index 0d36a6a7c9f5b..427157f106ef3 100644 --- a/stdlib/Random/src/generation.jl +++ b/stdlib/Random/src/generation.jl @@ -66,7 +66,7 @@ function _rand(rng::AbstractRNG, sp::SamplerBigFloat) limbs[end] |= Limb_high_bit end z.sign = 1 - Base.@gc_preserve limbs unsafe_copyto!(z.d, pointer(limbs), sp.nlimbs) + GC.@preserve limbs unsafe_copyto!(z.d, pointer(limbs), sp.nlimbs) (z, randbool) end @@ -319,7 +319,7 @@ end function rand(rng::AbstractRNG, sp::SamplerBigInt) x = MPZ.realloc2(sp.nlimbsmax*8*sizeof(Limb)) - @gc_preserve x begin + GC.@preserve x begin limbs = UnsafeView(x.d, sp.nlimbs) while true rand!(rng, limbs) @@ -418,7 +418,7 @@ Sampler(rng::AbstractRNG, str::AbstractString, n::Val{Inf}) = Sampler(rng, colle Sampler(rng::AbstractRNG, str::AbstractString, ::Val{1}) = SamplerSimple(str, Sampler(rng, 1:_endof(str), Val(Inf))) -isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(Base.@gc_preserve s unsafe_load(pointer(s), i)) +isvalid_unsafe(s::String, i) = !Base.is_valid_continuation(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/stdlib/SharedArrays/test/runtests.jl b/stdlib/SharedArrays/test/runtests.jl index 6dcea0aaa3b73..a4bfa65d4944e 100644 --- a/stdlib/SharedArrays/test/runtests.jl +++ b/stdlib/SharedArrays/test/runtests.jl @@ -145,9 +145,9 @@ finalize(S) # call gc 3 times to avoid unlink: operation not permitted (EPERM) on Windows S = nothing -@everywhere gc() -@everywhere gc() -@everywhere gc() +@everywhere GC.gc() +@everywhere GC.gc() +@everywhere GC.gc() rm(fn); rm(fn2); rm(fn3) ### Utility functions @@ -288,7 +288,7 @@ let id = a1.id aorig = nothing a1 = remotecall_fetch(fill!, id_other, a1, 1.0) - gc(); gc() + GC.gc(); GC.gc() a1 = remotecall_fetch(fill!, id_other, a1, 1.0) @test haskey(SharedArrays.sa_refs, id) finalize(a1) diff --git a/stdlib/SparseArrays/test/sparse.jl b/stdlib/SparseArrays/test/sparse.jl index 99441c1165799..909a47b070249 100644 --- a/stdlib/SparseArrays/test/sparse.jl +++ b/stdlib/SparseArrays/test/sparse.jl @@ -1214,7 +1214,7 @@ end times = Float64[0,0,0] best = [typemax(Float64), 0] for searchtype in [0, 1, 2] - gc() + GC.gc() tres = @timed test_getindex_algs(S, I, J, searchtype) res[searchtype+1] = tres[1] times[searchtype+1] = tres[2] @@ -1270,9 +1270,9 @@ end for I in IA Isorted = sort(I) for S in SA - gc() + GC.gc() ru = @timed S[I, J] - gc() + GC.gc() rs = @timed S[Isorted, Jsorted] if debug @printf(" %7d | %7d | %7d | %4.2e | %4.2e | %4.2e | %4.2e |\n", round(Int,nnz(S)/S.n), length(I), length(J), rs[2], ru[2], rs[3], ru[3]) diff --git a/stdlib/SuiteSparse/test/cholmod.jl b/stdlib/SuiteSparse/test/cholmod.jl index 1efa24ecfba51..0275adb3e082d 100644 --- a/stdlib/SuiteSparse/test/cholmod.jl +++ b/stdlib/SuiteSparse/test/cholmod.jl @@ -625,7 +625,7 @@ end A = Float64[10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10] @test sparse(cholfact(sparse(A))) ≈ A end -gc() +GC.gc() @testset "Issue 11747 - Wrong show method defined for FactorComponent" begin v = cholfact(sparse(Float64[ 10 1 1 1; 1 10 0 0; 1 0 10 0; 1 0 0 10])).L diff --git a/test/ccall.jl b/test/ccall.jl index 4250591b2ac4f..178030de8cecb 100644 --- a/test/ccall.jl +++ b/test/ccall.jl @@ -1295,7 +1295,7 @@ struct Bits22734 <: Abstract22734 y::Float64 end function cb22734(ptr::Ptr{Cvoid}) - gc() + GC.gc() obj = unsafe_pointer_to_objref(ptr)::Bits22734 obj.x + obj.y end diff --git a/test/channels.jl b/test/channels.jl index 10301bd3e804a..97d87c5b9b99e 100644 --- a/test/channels.jl +++ b/test/channels.jl @@ -232,14 +232,14 @@ end # test for yield/wait/event failures @noinline garbage_finalizer(f) = finalizer(f, "gar" * "bage") let t, run = Ref(0) - gc_enable(false) + GC.enable(false) # test for finalizers trying to yield leading to failed attempts to context switch garbage_finalizer((x) -> (run[] += 1; sleep(1))) garbage_finalizer((x) -> (run[] += 1; yield())) garbage_finalizer((x) -> (run[] += 1; yieldto(@task () -> ()))) t = @task begin - gc_enable(true) - gc() + GC.enable(true) + GC.gc() end oldstderr = STDERR local newstderr, errstream diff --git a/test/codegen.jl b/test/codegen.jl index 0f5909b32d665..e263931fc52ae 100644 --- a/test/codegen.jl +++ b/test/codegen.jl @@ -197,7 +197,7 @@ end function load_dummy_ref(x::Int) r = Ref{Int}(x) - Base.@gc_preserve r begin + GC.@preserve r begin unsafe_load(Ptr{Int}(pointer_from_objref(r))) end end @@ -234,13 +234,13 @@ let was_gced = false a = Ref(1) use(x); use(a); use(y) c = Ref(3) - gc() + GC.gc() assert_not_gced() use(x) use(c) end foo22770() - gc() + GC.gc() @test was_gced end diff --git a/test/core.jl b/test/core.jl index b6040eb90ea4e..b6793fc53d1f4 100644 --- a/test/core.jl +++ b/test/core.jl @@ -3,10 +3,10 @@ # test core language features using Random +using SparseArrays const Bottom = Union{} -using SparseArrays # For curmod_* include("testenv.jl") @@ -905,7 +905,7 @@ let A = [1] finalize(A) @test x == 1 A = 0 - gc(); gc() + GC.gc(); GC.gc() @test x == 1 end @@ -1475,7 +1475,7 @@ end function foo4075(f::Foo4075, s::Symbol) x = getfield(f,s) - gc() + GC.gc() x end @@ -2473,10 +2473,10 @@ mutable struct Obj; x; end wref = [] mk_wr(ref, wref) test_wr(ref, wref) - gc() + GC.gc() test_wr(ref, wref) pop!(ref) - gc() + GC.gc() @test wref[1].value === nothing end test_wr() @@ -2553,7 +2553,7 @@ try val::Bar{T} end end -gc() +GC.gc() redirect_stdout(OLD_STDOUT) close(file) rm(fname) @@ -3097,7 +3097,7 @@ struct Array_512_Uint8 d511::UInt8 d512::UInt8 end -gc() +GC.gc() # issue #10867 @test collect(enumerate((Tuple,Int))) == [(1,Tuple), (2,Int)] @@ -3653,11 +3653,11 @@ let # obj should be marked for promotion after the second gc and be promoted # after the third GC # GC_CLEAN; age = 0 - gc(false) + GC.gc(false) # GC_CLEAN; age = 1 - gc(false) + GC.gc(false) # GC_QUEUED; age = 1 - gc(false) + GC.gc(false) # GC_MARKED; age = 1 finalize(obj) @test finalized == 1 @@ -3666,14 +3666,14 @@ end # check if finalizers for the old gen can be triggered manually # PR #14181 let - # The following three `gc(false)` clears the `finalizer_list`. It is + # The following three `GC.gc(false)` clears the `finalizer_list`. It is # not strictly necessary to make the test pass but should make the failure # more repeatable if something breaks. - gc(false) + GC.gc(false) # At least: GC_CLEAN; age = 1 - gc(false) + GC.gc(false) # At least: GC_QUEUED; age = 1 - gc(false) + GC.gc(false) # all objects in `finalizer_list` are now moved to `finalizer_list_marked` obj1 = Ref(1) @@ -3719,9 +3719,9 @@ let i = 9.0 end # Make sure the old f() method is GC'd if it was not rooted properly -gc() -gc() -gc() +GC.gc() +GC.gc() +GC.gc() # Run again. g() @@ -3982,9 +3982,9 @@ let ary = Vector{Any}(uninitialized, 10) ary = Vector{Any}(uninitialized, n) # Try to free the previous buffer that was filled with random content # and to increase the chance of getting a non-zero'd buffer next time - gc() - gc() - gc() + GC.gc() + GC.gc() + GC.gc() ccall(:jl_array_grow_beg, Cvoid, (Any, Csize_t), ary, 4) ccall(:jl_array_del_beg, Cvoid, (Any, Csize_t), ary, 4) ccall(:jl_array_grow_end, Cvoid, (Any, Csize_t), ary, n) @@ -4027,16 +4027,16 @@ end end # disable GC to make sure no collection/promotion happens # when we are constructing the objects -let gc_enabled13995 = gc_enable(false) +let gc_enabled13995 = GC.enable(false) finalized13995 = [false, false, false, false] create_dead_object13995(finalized13995) - gc_enable(true) + GC.enable(true) # obj is unreachable and young, a single young gc should collect it # and trigger all the finalizers. - gc(false) - gc_enable(false) + GC.gc(false) + GC.enable(false) @test finalized13995 == [true, true, true, true] - gc_enable(gc_enabled13995) + GC.enable(gc_enabled13995) end # issue #15283 @@ -4831,7 +4831,7 @@ end # issue #17255, take `deferred_alloc` into account # when calculating total allocation size. @noinline function f17255(n) - gc_enable(false) + GC.enable(false) b0 = Base.gc_bytes() local a for i in 1:n @@ -4845,7 +4845,7 @@ end return true, a end @test f17255(10000)[1] -gc_enable(true) +GC.enable(true) # issue #18710 bad_tvars() where {T} = 1 @@ -5023,7 +5023,7 @@ if Sys.WORD_SIZE == 64 try # Do no touch the string to avoid triggering OOM slot[] = Base._string_n(2^32) - gc(false) + GC.gc(false) catch ex # This can happen if there's a virtual address size limit @test isa(ex, OutOfMemoryError) @@ -5032,13 +5032,13 @@ if Sys.WORD_SIZE == 64 return end @noinline function tester20360() - gc() - # Makes sure the string is rooted during the `gc(false)` + GC.gc() + # Makes sure the string is rooted during the `GC.gc(false)` # but is not before the last gc in this function. slot = Ref{Any}() test_large_string20360(slot) slot[] = nothing - gc() + GC.gc() return end @test_nowarn tester20360() diff --git a/test/misc.jl b/test/misc.jl index eafcbd35003a7..8e4173c8090b3 100644 --- a/test/misc.jl +++ b/test/misc.jl @@ -83,12 +83,12 @@ let # test the process title functions, issue #9957 @test Sys.get_process_title() == oldtitle end -# test gc_enable/disable -@test gc_enable(true) -@test gc_enable(false) -@test gc_enable(false) == false -@test gc_enable(true) == false -@test gc_enable(true) +# test GC.enable/disable +@test GC.enable(true) +@test GC.enable(false) +@test GC.enable(false) == false +@test GC.enable(true) == false +@test GC.enable(true) # test methodswith # `methodswith` relies on exported symbols @@ -146,7 +146,7 @@ let c = Ref(0), t2 = @schedule (wait(); c[] += 99) @test c[] == 0 f6597(c) - gc() # this should run the finalizer for t + GC.gc() # this should run the finalizer for t @test c[] == 1 yield() @test c[] == 1 @@ -646,4 +646,4 @@ end module A export missing varinfo(A) -end \ No newline at end of file +end diff --git a/test/netload/memtest.jl b/test/netload/memtest.jl index 78a203b314202..dade493720c13 100644 --- a/test/netload/memtest.jl +++ b/test/netload/memtest.jl @@ -48,14 +48,14 @@ function mtest_create_strings() for i in 1:10^8 string("$i") end - gc() + GC.gc() end function mtest_remotecall_fetch() for i in 1:10^5 remotecall_fetch(myid, 1) end - gc() + GC.gc() end run_mtest("create_strings", () -> mtest_create_strings()) diff --git a/test/perf/kernel/perf.jl b/test/perf/kernel/perf.jl index 4ccb0e2d590bd..cc519ac37db33 100644 --- a/test/perf/kernel/perf.jl +++ b/test/perf/kernel/perf.jl @@ -21,7 +21,7 @@ function listn1n2(n1::Int,n2::Int) end @timeit listn1n2(1,10^6) "cons" "List concatenation" -gc() +GC.gc() # issue #1211 include("ziggurat.jl") diff --git a/test/perf/perfutil.jl b/test/perf/perfutil.jl index 7c923aa3612a0..b13d372d0d3ef 100644 --- a/test/perf/perfutil.jl +++ b/test/perf/perfutil.jl @@ -65,7 +65,7 @@ macro output_timings(t,name,desc,group) elseif print_output @printf "julia,%s,%f,%f,%f,%f\n" $name minimum($t) maximum($t) mean($t) std($t) end - gc() + GC.gc() end end diff --git a/test/perf/sort/perf.jl b/test/perf/sort/perf.jl index 0ec5373ecc429..9e589ef889fb0 100644 --- a/test/perf/sort/perf.jl +++ b/test/perf/sort/perf.jl @@ -20,7 +20,7 @@ if codespeed for s in sorts if s == InsertionSort && size != 2^6; continue; end data = Vector{T}(uninitialized, size) - gc() + GC.gc() ## Random name = "$(typename)_$(size)_$(string(s)[1:end-5])_random" @@ -45,7 +45,7 @@ else if s == InsertionSort && logsize >=14 continue end #Too slow println(s, s==RadixSort, s, typename, typename==AbstractString, logsize) data = Vector{T}(uninitialized, size) - gc() + GC.gc() ## Random name = "$(typename)_$(logsize)_$(string(s)[1:end-5])_random" diff --git a/test/threads.jl b/test/threads.jl index 12b3cffd0454e..f28bc40c991fe 100644 --- a/test/threads.jl +++ b/test/threads.jl @@ -124,7 +124,7 @@ function threaded_gc_locked(::Type{LockT}) where LockT @threads for i = 1:20 @test lock(critical) === nothing @test islocked(critical) - gc(false) + GC.gc(false) @test unlock(critical) === nothing end @test !islocked(critical)