From 46b5d7557c8ac23508ab251fb3ae6dec1d199cd8 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Wed, 17 Jan 2018 12:13:32 -0800 Subject: [PATCH 1/2] Deprecate gc and gc_enable in favor of GC.gc and GC.enable We document that these functions should not generally be used, and yet they're exported from Base. This moves the two functions into their own submodule, Base.GC, and deprecates the exported functions. --- NEWS.md | 3 ++ base/deprecated.jl | 3 ++ base/exports.jl | 3 +- base/gcutils.jl | 22 +++++++--- doc/src/base/base.md | 4 +- doc/src/manual/faq.md | 2 +- stdlib/FileWatching/test/runtests.jl | 10 ++--- stdlib/Mmap/test/runtests.jl | 62 ++++++++++++++-------------- stdlib/SharedArrays/test/runtests.jl | 8 ++-- stdlib/SparseArrays/test/sparse.jl | 6 +-- stdlib/SuiteSparse/test/cholmod.jl | 2 +- test/ccall.jl | 2 +- test/channels.jl | 6 +-- test/codegen.jl | 4 +- test/core.jl | 62 ++++++++++++++-------------- test/misc.jl | 16 +++---- test/netload/memtest.jl | 4 +- test/perf/kernel/perf.jl | 2 +- test/perf/perfutil.jl | 2 +- test/perf/sort/perf.jl | 4 +- test/threads.jl | 2 +- 21 files changed, 122 insertions(+), 107 deletions(-) diff --git a/NEWS.md b/NEWS.md index 7e064afc111a1..6b474e0f53a06 100644 --- a/NEWS.md +++ b/NEWS.md @@ -966,6 +966,8 @@ 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]). + Command-line option changes --------------------------- @@ -1217,3 +1219,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/deprecated.jl b/base/deprecated.jl index b72db1016c290..b7e3181b6d61d 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1573,6 +1573,9 @@ end @deprecate object_id objectid +@deprecate gc GC.gc +@deprecate gc_enable GC.enable + # issue #9053 if Sys.iswindows() function Filesystem.tempname(uunique::UInt32) 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..525a350a4b81b 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -38,18 +38,28 @@ 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 + +end # module GC 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/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/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/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..f01fbb00c52aa 100644 --- a/test/codegen.jl +++ b/test/codegen.jl @@ -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) From bdc9094afc426423b6ab78abfbf54116b5272c29 Mon Sep 17 00:00:00 2001 From: Alex Arslan Date: Thu, 18 Jan 2018 17:37:10 -0800 Subject: [PATCH 2/2] Deprecate Base.@gc_preserve in favor of GC.@preserve --- NEWS.md | 2 ++ base/compiler/optimize.jl | 2 +- base/deepcopy.jl | 2 +- base/deprecated.jl | 1 + base/env.jl | 2 +- base/gcutils.jl | 23 +++++++++++++++++++++ base/gmp.jl | 4 ++-- base/io.jl | 10 ++++----- base/iobuffer.jl | 10 ++++----- base/iostream.jl | 4 ++-- base/libc.jl | 4 ++-- base/libgit2/blame.jl | 2 +- base/libgit2/commit.jl | 6 +++--- base/libgit2/index.jl | 2 +- base/libgit2/libgit2.jl | 2 +- base/libgit2/merge.jl | 2 +- base/libgit2/oid.jl | 2 +- base/libgit2/rebase.jl | 4 ++-- base/libgit2/reference.jl | 8 +++---- base/libgit2/status.jl | 2 +- base/libgit2/tag.jl | 4 ++-- base/libgit2/tree.jl | 2 +- base/loading.jl | 2 +- base/parse.jl | 2 +- base/pcre.jl | 2 +- base/pointer.jl | 21 ------------------- base/reinterpretarray.jl | 4 ++-- base/show.jl | 2 +- base/strings/string.jl | 4 ++-- stdlib/DelimitedFiles/src/DelimitedFiles.jl | 4 ++-- stdlib/LinearAlgebra/src/blas.jl | 20 +++++++++--------- stdlib/LinearAlgebra/src/dense.jl | 4 ++-- stdlib/LinearAlgebra/src/matmul.jl | 4 ++-- stdlib/Mmap/src/Mmap.jl | 2 +- stdlib/Random/src/RNGs.jl | 12 +++++------ stdlib/Random/src/Random.jl | 2 +- stdlib/Random/src/generation.jl | 6 +++--- test/codegen.jl | 2 +- 38 files changed, 99 insertions(+), 94 deletions(-) diff --git a/NEWS.md b/NEWS.md index 6b474e0f53a06..195e2cdf70bfe 100644 --- a/NEWS.md +++ b/NEWS.md @@ -968,6 +968,8 @@ Deprecated or removed * `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 --------------------------- 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 b7e3181b6d61d..018d1de5a2927 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -1575,6 +1575,7 @@ end @deprecate gc GC.gc @deprecate gc_enable GC.enable +@eval @deprecate $(Symbol("@gc_preserve")) GC.$(Symbol("@preserve")) false # issue #9053 if Sys.iswindows() 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/gcutils.jl b/base/gcutils.jl index 525a350a4b81b..2c58152b541bb 100644 --- a/base/gcutils.jl +++ b/base/gcutils.jl @@ -62,4 +62,27 @@ Control whether garbage collection is enabled using a boolean argument (`true` f """ 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/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/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/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/test/codegen.jl b/test/codegen.jl index f01fbb00c52aa..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