Skip to content

Commit f91bb74

Browse files
authored
staticdata: fix unreferenced data assertion (#39246)
Need to sequence operations correctly here. We need to first finish marking referenced data before we start deleting unreferenced data. This otherwise can lead to an assertion failure in some situations. Refs #37650
1 parent 77865f2 commit f91bb74

File tree

1 file changed

+33
-16
lines changed

1 file changed

+33
-16
lines changed

src/staticdata.c

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,30 +1425,33 @@ static void jl_finalize_deserializer(jl_serializer_state *s) JL_GC_DISABLED
14251425

14261426

14271427

1428-
// --- helper functions ---
1429-
1430-
// remove cached types not referenced in the stream
1431-
static int keep_type_cache_entry(jl_value_t *ti)
1428+
static void jl_scan_type_cache_gv(jl_serializer_state *s, jl_svec_t *cache)
14321429
{
1433-
if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND || jl_get_llvm_gv(native_functions, ti) != 0)
1434-
return 1;
1435-
if (jl_is_datatype(ti)) {
1436-
jl_value_t *singleton = ((jl_datatype_t*)ti)->instance;
1437-
if (singleton && (ptrhash_get(&backref_table, singleton) != HT_NOTFOUND ||
1438-
jl_get_llvm_gv(native_functions, singleton) != 0))
1439-
return 1;
1440-
}
1441-
return 0;
1430+
size_t l = jl_svec_len(cache), i;
1431+
for (i = 0; i < l; i++) {
1432+
jl_value_t *ti = jl_svecref(cache, i);
1433+
if (ti == NULL || ti == jl_nothing)
1434+
continue;
1435+
if (jl_get_llvm_gv(native_functions, ti)) {
1436+
jl_serialize_value(s, ti);
1437+
}
1438+
else if (jl_is_datatype(ti)) {
1439+
jl_value_t *singleton = ((jl_datatype_t*)ti)->instance;
1440+
if (singleton && jl_get_llvm_gv(native_functions, singleton))
1441+
jl_serialize_value(s, ti);
1442+
}
1443+
}
14421444
}
14431445

1446+
// remove cached types not referenced in the stream
14441447
static void jl_prune_type_cache_hash(jl_svec_t *cache)
14451448
{
14461449
size_t l = jl_svec_len(cache), i;
14471450
for (i = 0; i < l; i++) {
14481451
jl_value_t *ti = jl_svecref(cache, i);
14491452
if (ti == NULL || ti == jl_nothing)
14501453
continue;
1451-
if (!keep_type_cache_entry(ti))
1454+
if (ptrhash_get(&backref_table, ti) == HT_NOTFOUND)
14521455
jl_svecset(cache, i, jl_nothing);
14531456
}
14541457
}
@@ -1460,7 +1463,7 @@ static void jl_prune_type_cache_linear(jl_svec_t *cache)
14601463
jl_value_t *ti = jl_svecref(cache, i);
14611464
if (ti == NULL)
14621465
break;
1463-
if (keep_type_cache_entry(ti))
1466+
if (ptrhash_get(&backref_table, ti) != HT_NOTFOUND)
14641467
jl_svecset(cache, ins++, ti);
14651468
}
14661469
if (i > ins) {
@@ -1526,14 +1529,28 @@ static void jl_save_system_image_to_stream(ios_t *f) JL_GC_DISABLED
15261529
jl_value_t *tag = *tags[i];
15271530
jl_serialize_value(&s, tag);
15281531
}
1529-
// prune unused entries from built-in type caches
1532+
// step 1.1: check for values only found in the generated code
1533+
arraylist_t typenames;
1534+
arraylist_new(&typenames, 0);
15301535
for (i = 0; i < backref_table.size; i += 2) {
15311536
jl_typename_t *tn = (jl_typename_t*)backref_table.table[i];
15321537
if (tn == HT_NOTFOUND || !jl_is_typename(tn))
15331538
continue;
1539+
arraylist_push(&typenames, tn);
1540+
}
1541+
for (i = 0; i < typenames.len; i++) {
1542+
jl_typename_t *tn = (jl_typename_t*)typenames.items[i];
1543+
jl_scan_type_cache_gv(&s, tn->cache);
1544+
jl_scan_type_cache_gv(&s, tn->linearcache);
1545+
}
1546+
// step 1.2: prune (garbage collect) some special weak references from
1547+
// built-in type caches
1548+
for (i = 0; i < typenames.len; i++) {
1549+
jl_typename_t *tn = (jl_typename_t*)typenames.items[i];
15341550
jl_prune_type_cache_hash(tn->cache);
15351551
jl_prune_type_cache_linear(tn->linearcache);
15361552
}
1553+
arraylist_free(&typenames);
15371554
}
15381555

15391556
{ // step 2: build all the sysimg sections

0 commit comments

Comments
 (0)