Skip to content

Commit c3282ce

Browse files
authored
Binding invalidation data race fixes (#58924)
2 parents 5741911 + 7a1590f commit c3282ce

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
}
@@ -1620,16 +1641,19 @@ void jl_invalidate_binding_refs(jl_globalref_t *ref, jl_binding_partition_t *inv
16201641

16211642
JL_DLLEXPORT void jl_add_binding_backedge(jl_binding_t *b, jl_value_t *edge)
16221643
{
1644+
JL_LOCK(&b->globalref->mod->lock);
16231645
if (!b->backedges) {
16241646
b->backedges = jl_alloc_vec_any(0);
16251647
jl_gc_wb(b, b->backedges);
16261648
} else if (jl_array_len(b->backedges) > 0 &&
16271649
jl_array_ptr_ref(b->backedges, jl_array_len(b->backedges)-1) == edge) {
16281650
// Optimization: Deduplicate repeated insertion of the same edge (e.g. during
16291651
// definition of a method that contains many references to the same global)
1652+
JL_UNLOCK(&b->globalref->mod->lock);
16301653
return;
16311654
}
16321655
jl_array_ptr_1d_push(b->backedges, edge);
1656+
JL_UNLOCK(&b->globalref->mod->lock);
16331657
}
16341658

16351659
// 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
@@ -3751,15 +3751,19 @@ static int jl_validate_binding_partition(jl_binding_t *b, jl_binding_partition_t
37513751
// We need to go through and re-validate any bindings in the same image that
37523752
// may have imported us.
37533753
if (b->backedges) {
3754+
JL_LOCK(&b->globalref->mod->lock);
37543755
for (size_t i = 0; i < jl_array_len(b->backedges); i++) {
37553756
jl_value_t *edge = jl_array_ptr_ref(b->backedges, i);
37563757
if (!jl_is_binding(edge))
37573758
continue;
37583759
jl_binding_t *bedge = (jl_binding_t*)edge;
37593760
if (!jl_atomic_load_relaxed(&bedge->partitions))
37603761
continue;
3762+
JL_UNLOCK(&b->globalref->mod->lock);
37613763
jl_validate_binding_partition(bedge, jl_atomic_load_relaxed(&bedge->partitions), mod_idx, 0, 0);
3764+
JL_LOCK(&b->globalref->mod->lock);
37623765
}
3766+
JL_UNLOCK(&b->globalref->mod->lock);
37633767
}
37643768
if (bpart->kind & PARTITION_FLAG_EXPORTED) {
37653769
jl_module_t *mod = b->globalref->mod;

0 commit comments

Comments
 (0)