Skip to content

Commit 66b9238

Browse files
committed
trim: fix corrupt dispatch tables
Fix #59507
1 parent 5c93bf2 commit 66b9238

File tree

2 files changed

+56
-58
lines changed

2 files changed

+56
-58
lines changed

src/gf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ static int8_t jl_cachearg_offset(void)
124124
/// ----- Insertion logic for special entries ----- ///
125125

126126

127-
static uint_t speccache_hash(size_t idx, jl_value_t *data)
127+
uint_t speccache_hash(size_t idx, jl_value_t *data)
128128
{
129129
jl_method_instance_t *ml = (jl_method_instance_t*)jl_svecref(data, idx); // This must always happen inside the lock
130130
jl_value_t *sig = ml->specTypes;

src/staticdata.c

Lines changed: 55 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -2646,49 +2646,64 @@ static void jl_prune_binding_backedges(jl_array_t *backedges)
26462646
jl_array_del_end(backedges, n - ins);
26472647
}
26482648

2649-
26502649
uint_t bindingkey_hash(size_t idx, jl_value_t *data);
2650+
uint_t speccache_hash(size_t idx, jl_value_t *data);
26512651

2652-
static void jl_prune_module_bindings(jl_module_t * m) JL_GC_DISABLED
2652+
static void jl_prune_idset(_Atomic(jl_svec_t*) *pkeys, _Atomic(jl_genericmemory_t*) *pkeyset, uint_t (*key_hash)(size_t, jl_value_t*), jl_value_t *parent) JL_GC_DISABLED
26532653
{
2654-
jl_svec_t *bindings = jl_atomic_load_relaxed(&m->bindings);
2655-
size_t l = jl_svec_len(bindings), i;
2656-
arraylist_t bindings_list;
2657-
arraylist_new(&bindings_list, 0);
2654+
jl_svec_t *keys = jl_atomic_load_relaxed(pkeys);
2655+
size_t l = jl_svec_len(keys), i;
26582656
if (l == 0)
26592657
return;
2658+
arraylist_t keys_list;
2659+
arraylist_new(&keys_list, 0);
26602660
for (i = 0; i < l; i++) {
2661-
jl_value_t *ti = jl_svecref(bindings, i);
2662-
if (ti == jl_nothing)
2661+
jl_value_t *k = jl_svecref(keys, i);
2662+
if (k == jl_nothing)
26632663
continue;
2664-
jl_binding_t *ref = ((jl_binding_t*)ti);
2665-
if (ptrhash_get(&serialization_order, ref) != HT_NOTFOUND)
2666-
arraylist_push(&bindings_list, ref);
2667-
}
2668-
jl_genericmemory_t *bindingkeyset = jl_atomic_load_relaxed(&m->bindingkeyset);
2669-
_Atomic(jl_genericmemory_t*)bindingkeyset2;
2670-
jl_atomic_store_relaxed(&bindingkeyset2, (jl_genericmemory_t*)jl_an_empty_memory_any);
2671-
jl_svec_t *bindings2 = jl_alloc_svec_uninit(bindings_list.len);
2672-
for (i = 0; i < bindings_list.len; i++) {
2673-
jl_binding_t *ref = (jl_binding_t*)bindings_list.items[i];
2674-
jl_svecset(bindings2, i, ref);
2675-
jl_smallintset_insert(&bindingkeyset2, (jl_value_t*)m, bindingkey_hash, i, (jl_value_t*)bindings2);
2676-
}
2677-
void *idx = ptrhash_get(&serialization_order, bindings);
2664+
if (ptrhash_get(&serialization_order, k) != HT_NOTFOUND)
2665+
arraylist_push(&keys_list, k);
2666+
}
2667+
jl_genericmemory_t *keyset = jl_atomic_load_relaxed(pkeyset);
2668+
_Atomic(jl_genericmemory_t*)keyset2;
2669+
jl_atomic_store_relaxed(&keyset2, (jl_genericmemory_t*)jl_an_empty_memory_any);
2670+
jl_svec_t *keys2 = jl_alloc_svec_uninit(keys_list.len);
2671+
for (i = 0; i < keys_list.len; i++) {
2672+
jl_binding_t *ref = (jl_binding_t*)keys_list.items[i];
2673+
jl_svecset(keys2, i, ref);
2674+
jl_smallintset_insert(&keyset2, parent, key_hash, i, (jl_value_t*)keys2);
2675+
}
2676+
void *idx = ptrhash_get(&serialization_order, keys);
26782677
assert(idx != HT_NOTFOUND && idx != (void*)(uintptr_t)-1);
2679-
assert(serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] == bindings);
2680-
ptrhash_put(&serialization_order, bindings2, idx);
2681-
serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] = bindings2;
2678+
assert(serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] == keys);
2679+
ptrhash_put(&serialization_order, keys2, idx);
2680+
serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] = keys2;
26822681

2683-
idx = ptrhash_get(&serialization_order, bindingkeyset);
2682+
idx = ptrhash_get(&serialization_order, keyset);
26842683
assert(idx != HT_NOTFOUND && idx != (void*)(uintptr_t)-1);
2685-
assert(serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] == bindingkeyset);
2686-
ptrhash_put(&serialization_order, jl_atomic_load_relaxed(&bindingkeyset2), idx);
2687-
serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] = jl_atomic_load_relaxed(&bindingkeyset2);
2688-
jl_atomic_store_relaxed(&m->bindings, bindings2);
2689-
jl_atomic_store_relaxed(&m->bindingkeyset, jl_atomic_load_relaxed(&bindingkeyset2));
2690-
jl_gc_wb(m, bindings2);
2691-
jl_gc_wb(m, jl_atomic_load_relaxed(&bindingkeyset2));
2684+
assert(serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] == keyset);
2685+
ptrhash_put(&serialization_order, jl_atomic_load_relaxed(&keyset2), idx);
2686+
serialization_queue.items[(char*)idx - 1 - (char*)HT_NOTFOUND] = jl_atomic_load_relaxed(&keyset2);
2687+
jl_atomic_store_relaxed(pkeys, keys2);
2688+
jl_gc_wb(parent, keys2);
2689+
jl_atomic_store_relaxed(pkeyset, jl_atomic_load_relaxed(&keyset2));
2690+
jl_gc_wb(parent, jl_atomic_load_relaxed(&keyset2));
2691+
}
2692+
2693+
static void jl_prune_method_specializations(jl_method_t *m) JL_GC_DISABLED
2694+
{
2695+
jl_value_t *specializations_ = jl_atomic_load_relaxed(&m->specializations);
2696+
if (!jl_is_svec(specializations_)) {
2697+
if (ptrhash_get(&serialization_order, specializations_) == HT_NOTFOUND)
2698+
record_field_change((jl_value_t **)&m->specializations, (jl_value_t*)jl_emptysvec);
2699+
return;
2700+
}
2701+
jl_prune_idset((_Atomic(jl_svec_t*)*)&m->specializations, &m->speckeyset, speccache_hash, (jl_value_t*)m);
2702+
}
2703+
2704+
static void jl_prune_module_bindings(jl_module_t *m) JL_GC_DISABLED
2705+
{
2706+
jl_prune_idset(&m->bindings, &m->bindingkeyset, bindingkey_hash, (jl_value_t*)m);
26922707
}
26932708

26942709
static void strip_slotnames(jl_array_t *slotnames, int n)
@@ -3253,32 +3268,15 @@ static void jl_save_system_image_to_stream(ios_t *f, jl_array_t *mod_array,
32533268
// step 1.5: prune (garbage collect) some special weak references known caches
32543269
for (i = 0; i < serialization_queue.len; i++) {
32553270
jl_value_t *v = (jl_value_t*)serialization_queue.items[i];
3256-
if (jl_options.trim) {
3257-
if (jl_is_method(v)) {
3258-
jl_method_t *m = (jl_method_t*)v;
3259-
jl_value_t *specializations_ = jl_atomic_load_relaxed(&m->specializations);
3260-
if (!jl_is_svec(specializations_)) {
3261-
if (ptrhash_get(&serialization_order, specializations_) == HT_NOTFOUND)
3262-
record_field_change((jl_value_t **)&m->specializations, (jl_value_t*)jl_emptysvec);
3263-
continue;
3264-
}
3265-
3266-
jl_svec_t *specializations = (jl_svec_t *)specializations_;
3267-
size_t l = jl_svec_len(specializations), i;
3268-
for (i = 0; i < l; i++) {
3269-
jl_value_t *mi = jl_svecref(specializations, i);
3270-
if (mi == jl_nothing)
3271-
continue;
3272-
if (ptrhash_get(&serialization_order, mi) == HT_NOTFOUND)
3273-
jl_svecset(specializations, i, jl_nothing);
3274-
}
3275-
}
3276-
else if (jl_is_module(v)) {
3271+
if (jl_is_method(v)) {
3272+
if (jl_options.trim)
3273+
jl_prune_method_specializations((jl_method_t*)v);
3274+
}
3275+
else if (jl_is_module(v)) {
3276+
if (jl_options.trim)
32773277
jl_prune_module_bindings((jl_module_t*)v);
3278-
}
32793278
}
3280-
// Not else
3281-
if (jl_is_typename(v)) {
3279+
else if (jl_is_typename(v)) {
32823280
jl_typename_t *tn = (jl_typename_t*)v;
32833281
jl_atomic_store_relaxed(&tn->cache,
32843282
jl_prune_type_cache_hash(jl_atomic_load_relaxed(&tn->cache)));

0 commit comments

Comments
 (0)