Skip to content

Commit 6e5e87b

Browse files
authored
Root globals in toplevel exprs (#54433)
This fixes #54422, the code here assumes that top level exprs are always rooted, but I don't see that referenced anywhere else, or guaranteed, so conservatively always root objects that show up in code.
1 parent c601b11 commit 6e5e87b

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

src/codegen.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6473,8 +6473,9 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaidx_
64736473
jl_value_t *val = expr;
64746474
if (jl_is_quotenode(expr))
64756475
val = jl_fieldref_noalloc(expr, 0);
6476-
if (jl_is_method(ctx.linfo->def.method)) // toplevel exprs are already rooted
6477-
val = jl_ensure_rooted(ctx, val);
6476+
// Toplevel exprs are rooted but because codegen assumes this is constant, it removes the write barriers for this code.
6477+
// This means we have to globally root the value here. (The other option would be to change how we optimize toplevel code)
6478+
val = jl_ensure_rooted(ctx, val);
64786479
return mark_julia_const(ctx, val);
64796480
}
64806481

test/gc.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,17 @@ end
7272
@testset "Base.GC docstrings" begin
7373
@test isempty(Docs.undocumented_names(GC))
7474
end
75+
76+
#testset doesn't work here because this needs to run in top level
77+
#Check that we ensure objects in toplevel exprs are rooted
78+
global dims54422 = [] # allocate the Binding
79+
GC.gc(); GC.gc(); # force the binding to be old
80+
GC.enable(false); # prevent new objects from being old
81+
@eval begin
82+
Base.Experimental.@force_compile # use the compiler
83+
dims54422 = $([])
84+
nothing
85+
end
86+
GC.enable(true); GC.gc(false) # incremental collection
87+
@test typeof(dims54422) == Vector{Any}
88+
@test isempty(dims54422)

0 commit comments

Comments
 (0)