Skip to content

Commit c4e298c

Browse files
KristofferCKristofferC
authored andcommitted
Binding invalidation data race fixes (#58924)
(cherry picked from commit c3282ce)
1 parent 9a7388c commit c4e298c

File tree

3 files changed

+45
-17
lines changed

3 files changed

+45
-17
lines changed

base/invalidation.jl

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -122,23 +122,23 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core
122122
invalidated_any |= invalidate_method_for_globalref!(gr, method, invalidated_bpart, new_max_world)
123123
end
124124
end
125-
if isdefined(b, :backedges)
126-
for edge in b.backedges
127-
if isa(edge, CodeInstance)
128-
ccall(:jl_invalidate_code_instance, Cvoid, (Any, UInt), edge, new_max_world)
129-
invalidated_any = true
130-
elseif isa(edge, Core.Binding)
131-
isdefined(edge, :partitions) || continue
132-
latest_bpart = edge.partitions
133-
latest_bpart.max_world == typemax(UInt) || continue
134-
is_some_imported(binding_kind(latest_bpart)) || continue
135-
if is_some_binding_imported(binding_kind(latest_bpart))
136-
partition_restriction(latest_bpart) === b || continue
137-
end
138-
push!(queued_bindings, (edge, latest_bpart, latest_bpart))
139-
else
140-
invalidated_any |= invalidate_method_for_globalref!(gr, edge::Method, invalidated_bpart, new_max_world)
125+
nbackedges = ccall(:jl_binding_backedges_length, Csize_t, (Any,), b)
126+
for i = 1:nbackedges
127+
edge = ccall(:jl_binding_backedges_getindex, Any, (Any, Csize_t), b, i)
128+
if isa(edge, CodeInstance)
129+
ccall(:jl_invalidate_code_instance, Cvoid, (Any, UInt), edge, new_max_world)
130+
invalidated_any = true
131+
elseif isa(edge, Core.Binding)
132+
isdefined(edge, :partitions) || continue
133+
latest_bpart = edge.partitions
134+
latest_bpart.max_world == typemax(UInt) || continue
135+
is_some_imported(binding_kind(latest_bpart)) || continue
136+
if is_some_binding_imported(binding_kind(latest_bpart))
137+
partition_restriction(latest_bpart) === b || continue
141138
end
139+
push!(queued_bindings, (edge, latest_bpart, latest_bpart))
140+
else
141+
invalidated_any |= invalidate_method_for_globalref!(gr, edge::Method, invalidated_bpart, new_max_world)
142142
end
143143
end
144144
end
@@ -149,7 +149,7 @@ function invalidate_code_for_globalref!(b::Core.Binding, invalidated_bpart::Core
149149
usings_backedges = ccall(:jl_get_module_usings_backedges, Any, (Any,), gr.mod)
150150
if usings_backedges !== nothing
151151
for user::Module in usings_backedges::Vector{Any}
152-
user_binding = ccall(:jl_get_module_binding_or_nothing, Any, (Any, Any), user, gr.name)
152+
user_binding = ccall(:jl_get_module_binding_or_nothing, Any, (Any, Any), user, gr.name)::Union{Core.Binding, Nothing}
153153
user_binding === nothing && continue
154154
isdefined(user_binding, :partitions) || continue
155155
latest_bpart = user_binding.partitions

src/module.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,25 @@ JL_DLLEXPORT jl_value_t *jl_get_binding_leaf_partitions_value_if_const(jl_bindin
470470
return NULL;
471471
}
472472

473+
JL_DLLEXPORT size_t jl_binding_backedges_length(jl_binding_t *b)
474+
{
475+
JL_LOCK(&b->globalref->mod->lock);
476+
size_t len = 0;
477+
if (b->backedges)
478+
len = jl_array_len(b->backedges);
479+
JL_UNLOCK(&b->globalref->mod->lock);
480+
return len;
481+
}
482+
483+
JL_DLLEXPORT jl_value_t *jl_binding_backedges_getindex(jl_binding_t *b, size_t i)
484+
{
485+
JL_LOCK(&b->globalref->mod->lock);
486+
assert(b->backedges);
487+
jl_value_t *ret = jl_array_ptr_ref(b->backedges, i-1);
488+
JL_UNLOCK(&b->globalref->mod->lock);
489+
return ret;
490+
}
491+
473492
static jl_module_t *jl_new_module__(jl_sym_t *name, jl_module_t *parent)
474493
{
475494
jl_task_t *ct = jl_current_task;
@@ -527,7 +546,9 @@ jl_module_t *jl_new_module_(jl_sym_t *name, jl_module_t *parent, uint8_t default
527546
{
528547
jl_module_t *m = jl_new_module__(name, parent);
529548
JL_GC_PUSH1(&m);
549+
JL_LOCK(&world_counter_lock);
530550
jl_add_default_names(m, default_using_core, self_name);
551+
JL_UNLOCK(&world_counter_lock);
531552
JL_GC_POP();
532553
return m;
533554
}
@@ -1617,16 +1638,19 @@ void jl_invalidate_binding_refs(jl_globalref_t *ref, jl_binding_partition_t *inv
16171638

16181639
JL_DLLEXPORT void jl_add_binding_backedge(jl_binding_t *b, jl_value_t *edge)
16191640
{
1641+
JL_LOCK(&b->globalref->mod->lock);
16201642
if (!b->backedges) {
16211643
b->backedges = jl_alloc_vec_any(0);
16221644
jl_gc_wb(b, b->backedges);
16231645
} else if (jl_array_len(b->backedges) > 0 &&
16241646
jl_array_ptr_ref(b->backedges, jl_array_len(b->backedges)-1) == edge) {
16251647
// Optimization: Deduplicate repeated insertion of the same edge (e.g. during
16261648
// definition of a method that contains many references to the same global)
1649+
JL_UNLOCK(&b->globalref->mod->lock);
16271650
return;
16281651
}
16291652
jl_array_ptr_1d_push(b->backedges, edge);
1653+
JL_UNLOCK(&b->globalref->mod->lock);
16301654
}
16311655

16321656
// Called for all GlobalRefs found in lowered code. Adds backedges for cross-module

src/staticdata.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,15 +3745,19 @@ static int jl_validate_binding_partition(jl_binding_t *b, jl_binding_partition_t
37453745
// We need to go through and re-validate any bindings in the same image that
37463746
// may have imported us.
37473747
if (b->backedges) {
3748+
JL_LOCK(&b->globalref->mod->lock);
37483749
for (size_t i = 0; i < jl_array_len(b->backedges); i++) {
37493750
jl_value_t *edge = jl_array_ptr_ref(b->backedges, i);
37503751
if (!jl_is_binding(edge))
37513752
continue;
37523753
jl_binding_t *bedge = (jl_binding_t*)edge;
37533754
if (!jl_atomic_load_relaxed(&bedge->partitions))
37543755
continue;
3756+
JL_UNLOCK(&b->globalref->mod->lock);
37553757
jl_validate_binding_partition(bedge, jl_atomic_load_relaxed(&bedge->partitions), mod_idx, 0, 0);
3758+
JL_LOCK(&b->globalref->mod->lock);
37563759
}
3760+
JL_UNLOCK(&b->globalref->mod->lock);
37573761
}
37583762
if (bpart->kind & PARTITION_FLAG_EXPORTED) {
37593763
jl_module_t *mod = b->globalref->mod;

0 commit comments

Comments
 (0)