Skip to content

Commit d0a725b

Browse files
vtjnashKeno
andcommitted
dump: ordering error in .ji deserialization
Fixes: #38312 Co-authored-by: Keno Fischer <keno@juliacomputing.com>
1 parent 5be3e27 commit d0a725b

File tree

2 files changed

+94
-24
lines changed

2 files changed

+94
-24
lines changed

src/dump.c

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static int type_in_worklist(jl_datatype_t *dt) JL_NOTSAFEPOINT
142142
int i, l = jl_svec_len(dt->parameters);
143143
for (i = 0; i < l; i++) {
144144
jl_value_t *p = jl_unwrap_unionall(jl_tparam(dt, i));
145-
// XXX: what about Union and TypeVar??
145+
// TODO: what about Union and TypeVar??
146146
if (type_in_worklist((jl_datatype_t*)(jl_is_datatype(p) ? p : jl_typeof(p))))
147147
return 1;
148148
}
@@ -2252,7 +2252,52 @@ STATIC_INLINE jl_value_t *verify_type(jl_value_t *v) JL_NOTSAFEPOINT
22522252
}
22532253
#endif
22542254

2255-
static jl_datatype_t *jl_recache_type(jl_datatype_t *dt) JL_GC_DISABLED
2255+
2256+
static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED;
2257+
2258+
static jl_value_t *recache_type(jl_value_t *p) JL_GC_DISABLED
2259+
{
2260+
if (jl_is_datatype(p)) {
2261+
jl_datatype_t *pdt = (jl_datatype_t*)p;
2262+
if (ptrhash_get(&uniquing_table, p) != HT_NOTFOUND) {
2263+
p = (jl_value_t*)recache_datatype(pdt);
2264+
}
2265+
else {
2266+
jl_svec_t *tt = pdt->parameters;
2267+
// ensure all type parameters are recached
2268+
size_t i, l = jl_svec_len(tt);
2269+
for (i = 0; i < l; i++)
2270+
jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
2271+
ptrhash_put(&uniquing_table, p, p); // ensures this algorithm isn't too exponential
2272+
}
2273+
}
2274+
else if (jl_is_typevar(p)) {
2275+
jl_tvar_t *ptv = (jl_tvar_t*)p;
2276+
ptv->lb = recache_type(ptv->lb);
2277+
ptv->ub = recache_type(ptv->ub);
2278+
}
2279+
else if (jl_is_uniontype(p)) {
2280+
jl_uniontype_t *pu = (jl_uniontype_t*)p;
2281+
pu->a = recache_type(pu->a);
2282+
pu->b = recache_type(pu->b);
2283+
}
2284+
else if (jl_is_unionall(p)) {
2285+
jl_unionall_t *pa = (jl_unionall_t*)p;
2286+
pa->var = (jl_tvar_t*)recache_type((jl_value_t*)pa->var);
2287+
pa->body = recache_type(pa->body);
2288+
}
2289+
else {
2290+
jl_datatype_t *pt = (jl_datatype_t*)jl_typeof(p);
2291+
jl_datatype_t *cachep = recache_datatype(pt);
2292+
if (cachep->instance)
2293+
p = cachep->instance;
2294+
else if (pt != cachep)
2295+
jl_set_typeof(p, cachep);
2296+
}
2297+
return p;
2298+
}
2299+
2300+
static jl_datatype_t *recache_datatype(jl_datatype_t *dt) JL_GC_DISABLED
22562301
{
22572302
jl_datatype_t *t; // the type after unique'ing
22582303
assert(verify_type((jl_value_t*)dt));
@@ -2265,27 +2310,8 @@ static jl_datatype_t *jl_recache_type(jl_datatype_t *dt) JL_GC_DISABLED
22652310
jl_svec_t *tt = dt->parameters;
22662311
// recache all type parameters
22672312
size_t i, l = jl_svec_len(tt);
2268-
for (i = 0; i < l; i++) {
2269-
jl_datatype_t *p = (jl_datatype_t*)jl_svecref(tt, i);
2270-
if (jl_is_datatype(p)) {
2271-
jl_datatype_t *cachep = jl_recache_type(p);
2272-
if (p != cachep)
2273-
jl_svecset(tt, i, cachep);
2274-
}
2275-
// XXX: else if (jl_is_typevar(p))
2276-
// XXX: else if (jl_is_uniontype(p))
2277-
// XXX: else if (jl_is_unionall(p))
2278-
else {
2279-
p = (jl_datatype_t*)jl_typeof(p);
2280-
jl_datatype_t *cachep = jl_recache_type(p);
2281-
if (p != cachep) {
2282-
if (cachep->instance)
2283-
jl_svecset(tt, i, cachep->instance);
2284-
else
2285-
jl_set_typeof(jl_svecref(tt, i), cachep);
2286-
}
2287-
}
2288-
}
2313+
for (i = 0; i < l; i++)
2314+
jl_svecset(tt, i, recache_type(jl_svecref(tt, i)));
22892315

22902316
// then recache the type itself
22912317
if (jl_svec_len(tt) == 0) { // jl_cache_type doesn't work if length(parameters) == 0
@@ -2323,7 +2349,7 @@ static void jl_recache_types(void) JL_GC_DISABLED
23232349
dt = (jl_datatype_t*)jl_typeof(o);
23242350
v = o;
23252351
}
2326-
jl_datatype_t *t = jl_recache_type(dt);
2352+
jl_datatype_t *t = recache_datatype(dt);
23272353
if ((jl_value_t*)dt == o && t != dt) {
23282354
assert(!type_in_worklist(dt));
23292355
if (loc)

test/precompile.jl

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,28 @@ FooBase_module = :FooBase4b3a94a1a081a8cb
1212
end
1313
using .ConflictingBindings
1414

15+
function precompile_test_harness(@nospecialize(f), testset::String)
16+
@testset "$testset" begin
17+
precompile_test_harness(f)
18+
end
19+
end
20+
function precompile_test_harness(@nospecialize(f), separate::Bool=true)
21+
load_path = mktempdir()
22+
load_cache_path = separate ? mktempdir() : load_path
23+
try
24+
pushfirst!(LOAD_PATH, load_path)
25+
pushfirst!(DEPOT_PATH, load_cache_path)
26+
f(load_path)
27+
finally
28+
rm(load_path, recursive=true, force=true)
29+
separate && rm(load_cache_path, recursive=true, force=true)
30+
filter!(()(load_path), LOAD_PATH)
31+
separate && filter!(()(load_cache_path), DEPOT_PATH)
32+
end
33+
nothing
34+
end
35+
36+
1537
(f -> f())() do # wrap in function scope, so we can test world errors
1638
dir = mktempdir()
1739
dir2 = mktempdir()
@@ -904,4 +926,26 @@ let
904926
end
905927
end
906928

929+
# Issue #38312
930+
let
931+
TheType = """Array{Ref{Val{1}}, 1}"""
932+
write(joinpath(load_path, "Foo38312.jl"),
933+
"""
934+
module Foo38312
935+
const TheType = $TheType
936+
end
937+
""")
938+
write(joinpath(load_path, "Bar38312.jl"),
939+
"""
940+
module Bar38312
941+
const TheType = $TheType
942+
end
943+
""")
944+
Base.compilecache(Base.PkgId("Foo38312"))
945+
Base.compilecache(Base.PkgId("Bar38312"))
946+
@test pointer_from_objref((@eval (using Foo38312; Foo38312)).TheType) ===
947+
pointer_from_objref(eval(Meta.parse(TheType))) ===
948+
pointer_from_objref((@eval (using Bar38312; Bar38312)).TheType)
949+
end
950+
907951
end # !withenv

0 commit comments

Comments
 (0)