Skip to content

Commit

Permalink
dump: ordering error in .ji deserialization
Browse files Browse the repository at this point in the history
Fixes: #38312
Co-authored-by: Keno Fischer <[email protected]>
  • Loading branch information
vtjnash and Keno committed Nov 20, 2020
1 parent 5be3e27 commit d0a725b
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 24 deletions.
74 changes: 50 additions & 24 deletions src/dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT
int i, l = jl_svec_len(dt->parameters);
for (i = 0; i < l; i++) {
jl_value_t *p = jl_unwrap_unionall(jl_tparam(dt, i));
// XXX: what about Union and TypeVar??
// TODO: what about Union and TypeVar??
if (type_in_worklist((jl_datatype_t*)(jl_is_datatype(p) ? p : jl_typeof(p))))
return 1;
}
Expand Down Expand Up @@ -2252,7 +2252,52 @@ STATIC_INLINE jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
}
#endif

static jl_datatype_t *jl_recache_type(jl_datatype_t *dt) JL_GC_DISABLED

static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED;

static jl_value_t *recache_type(jl_value_t *p) JL_GC_DISABLED
{
if (jl_is_datatype(p)) {
jl_datatype_t *pdt = (jl_datatype_t*)p;
if (ptrhash_get(&uniquing_table, p) != HT_NOTFOUND) {
p = (jl_value_t*)recache_datatype(pdt);
}
else {
jl_svec_t *tt = pdt->parameters;
// ensure all type parameters are recached
size_t i, l = jl_svec_len(tt);
for (i = 0; i < l; i++)
jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
ptrhash_put(&uniquing_table, p, p); // ensures this algorithm isn't too exponential
}
}
else if (jl_is_typevar(p)) {
jl_tvar_t *ptv = (jl_tvar_t*)p;
ptv->lb = recache_type(ptv->lb);
ptv->ub = recache_type(ptv->ub);
}
else if (jl_is_uniontype(p)) {
jl_uniontype_t *pu = (jl_uniontype_t*)p;
pu->a = recache_type(pu->a);
pu->b = recache_type(pu->b);
}
else if (jl_is_unionall(p)) {
jl_unionall_t *pa = (jl_unionall_t*)p;
pa->var = (jl_tvar_t*)recache_type((jl_value_t*)pa->var);
pa->body = recache_type(pa->body);
}
else {
jl_datatype_t *pt = (jl_datatype_t*)jl_typeof(p);
jl_datatype_t *cachep = recache_datatype(pt);
if (cachep->instance)
p = cachep->instance;
else if (pt != cachep)
jl_set_typeof(p, cachep);
}
return p;
}

static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED
{
jl_datatype_t *t; // the type after unique'ing
assert(verify_type((jl_value_t*)dt));
Expand All @@ -2265,27 +2310,8 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt) JL_GC_DISABLED
jl_svec_t *tt = dt->parameters;
// recache all type parameters
size_t i, l = jl_svec_len(tt);
for (i = 0; i < l; i++) {
jl_datatype_t *p = (jl_datatype_t*)jl_svecref(tt, i);
if (jl_is_datatype(p)) {
jl_datatype_t *cachep = jl_recache_type(p);
if (p != cachep)
jl_svecset(tt, i, cachep);
}
// XXX: else if (jl_is_typevar(p))
// XXX: else if (jl_is_uniontype(p))
// XXX: else if (jl_is_unionall(p))
else {
p = (jl_datatype_t*)jl_typeof(p);
jl_datatype_t *cachep = jl_recache_type(p);
if (p != cachep) {
if (cachep->instance)
jl_svecset(tt, i, cachep->instance);
else
jl_set_typeof(jl_svecref(tt, i), cachep);
}
}
}
for (i = 0; i < l; i++)
jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));

// then recache the type itself
if (jl_svec_len(tt) == 0) { // jl_cache_type doesn't work if length(parameters) == 0
Expand Down Expand Up @@ -2323,7 +2349,7 @@ static void jl_recache_types(void) JL_GC_DISABLED
dt = (jl_datatype_t*)jl_typeof(o);
v = o;
}
jl_datatype_t *t = jl_recache_type(dt);
jl_datatype_t *t = recache_datatype(dt);
if ((jl_value_t*)dt == o && t != dt) {
assert(!type_in_worklist(dt));
if (loc)
Expand Down
44 changes: 44 additions & 0 deletions test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@ FooBase_module = :FooBase4b3a94a1a081a8cb
end
using .ConflictingBindings

function precompile_test_harness(@nospecialize(f), testset::String)
@testset "$testset" begin
precompile_test_harness(f)
end
end
function precompile_test_harness(@nospecialize(f), separate::Bool=true)
load_path = mktempdir()
load_cache_path = separate ? mktempdir() : load_path
try
pushfirst!(LOAD_PATH, load_path)
pushfirst!(DEPOT_PATH, load_cache_path)
f(load_path)
finally
rm(load_path, recursive=true, force=true)
separate && rm(load_cache_path, recursive=true, force=true)
filter!(()(load_path), LOAD_PATH)
separate && filter!(()(load_cache_path), DEPOT_PATH)
end
nothing
end


(f -> f())() do # wrap in function scope, so we can test world errors
dir = mktempdir()
dir2 = mktempdir()
Expand Down Expand Up @@ -904,4 +926,26 @@ let
end
end

# Issue #38312
let
TheType = """Array{Ref{Val{1}}, 1}"""
write(joinpath(load_path, "Foo38312.jl"),
"""
module Foo38312
const TheType = $TheType
end
""")
write(joinpath(load_path, "Bar38312.jl"),
"""
module Bar38312
const TheType = $TheType
end
""")
Base.compilecache(Base.PkgId("Foo38312"))
Base.compilecache(Base.PkgId("Bar38312"))
@test pointer_from_objref((@eval (using Foo38312; Foo38312)).TheType) ===
pointer_from_objref(eval(Meta.parse(TheType))) ===
pointer_from_objref((@eval (using Bar38312; Bar38312)).TheType)
end

end # !withenv

0 comments on commit d0a725b

Please sign in to comment.