Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ Neither `convert` nor `cconvert` should take a Julia object and turn it into a `
"""
function cconvert end

cconvert(T::Type, x) = x isa T ? x : convert(T, x) # do the conversion eagerly in most cases
cconvert(::Type{T}, x) where {T} = x isa T ? x : convert(T, x) # do the conversion eagerly in most cases
cconvert(::Type{Union{}}, x...) = convert(Union{}, x...)
cconvert(::Type{<:Ptr}, x) = x # but defer the conversion to Ptr to unsafe_convert
unsafe_convert(::Type{T}, x::T) where {T} = x # unsafe_convert (like convert) defaults to assuming the convert occurred
Expand Down
19 changes: 15 additions & 4 deletions base/staticdata.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ end

function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n::Int, world::UInt)
# verify that these edges intersect with the same methods as before
mi = nothing
if n == 1
# first, fast-path a check if the expected method simply dominates its sig anyways
# so the result of ml_matches is already simply known
Expand All @@ -289,11 +290,18 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
meth = t
else
if t isa CodeInstance
t = get_ci_mi(t)
mi = get_ci_mi(t)::MethodInstance
else
t = t::MethodInstance
mi = t::MethodInstance
end
meth = mi.def::Method
if !iszero(mi.dispatch_status & METHOD_SIG_LATEST_ONLY)
minworld = meth.primary_world
@assert minworld ≤ world
maxworld = typemax(UInt)
result = Any[] # result is unused
return minworld, maxworld, result
end
meth = t.def::Method
end
if !iszero(meth.dispatch_status & METHOD_SIG_LATEST_ONLY)
minworld = meth.primary_world
Expand Down Expand Up @@ -327,7 +335,7 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
meth = t
else
if t isa CodeInstance
t = get_ci_mi(t)
t = get_ci_mi(t)::MethodInstance
else
t = t::MethodInstance
end
Expand All @@ -354,6 +362,9 @@ function verify_call(@nospecialize(sig), expecteds::Core.SimpleVector, i::Int, n
resize!(result, ins)
end
end
if maxworld[] == typemax(UInt) && mi isa MethodInstance
ccall(:jl_promote_mi_to_current, Cvoid, (Any, UInt, UInt), mi, minworld[], world)
end
return minworld[], maxworld[], result
end

Expand Down
4 changes: 4 additions & 0 deletions doc/src/devdocs/locks.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ may result in pernicious and hard-to-find deadlocks. BE VERY CAREFUL!
>
> * Libdl.LazyLibrary lock

The following is a level 7 lock, which can only be acquired when not holding any other locks:

> * world_counter_lock


The following is the root lock, meaning no other lock shall be held when trying to acquire it:

Expand Down
163 changes: 130 additions & 33 deletions src/gf.c

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3575,7 +3575,7 @@ void jl_init_types(void) JL_GC_DISABLED
jl_module_type,
jl_symbol_type,
jl_int32_type,
jl_int32_type,
jl_uint8_type,
jl_ulong_type,
jl_type_type,
jl_any_type, // union(jl_simplevector_type, jl_method_instance_type),
Expand Down Expand Up @@ -3613,27 +3613,29 @@ void jl_init_types(void) JL_GC_DISABLED
jl_method_instance_type =
jl_new_datatype(jl_symbol("MethodInstance"), core,
jl_any_type, jl_emptysvec,
jl_perm_symsvec(7,
jl_perm_symsvec(8,
"def",
"specTypes",
"sparam_vals",
"backedges",
"cache",
"cache_with_orig",
"flags"),
jl_svec(7,
"flags",
"dispatch_status"),
jl_svec(8,
jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type),
jl_any_type,
jl_simplevector_type,
jl_array_any_type,
jl_any_type/*jl_code_instance_type*/,
jl_bool_type,
jl_bool_type),
jl_bool_type,
jl_uint8_type),
jl_emptysvec,
0, 1, 3);
// These fields should be constant, but Serialization wants to mutate them in initialization
//const static uint32_t method_instance_constfields[1] = { 0b0000111 }; // fields 1, 2, 3
const static uint32_t method_instance_atomicfields[1] = { 0b1010000 }; // fields 5, 7
const static uint32_t method_instance_atomicfields[1] = { 0b11010000 }; // fields 5, 7, 8
//Fields 4 and 5 must be protected by method->write_lock, and thus all operations on jl_method_instance_t are threadsafe.
//jl_method_instance_type->name->constfields = method_instance_constfields;
jl_method_instance_type->name->atomicfields = method_instance_atomicfields;
Expand Down
3 changes: 2 additions & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ typedef struct _jl_method_t {
struct _jl_module_t *module;
jl_sym_t *file;
int32_t line;
_Atomic(int32_t) dispatch_status; // bits defined in staticdata.jl
_Atomic(uint8_t) dispatch_status; // bits defined in staticdata.jl
_Atomic(size_t) primary_world;

// method's type signature. redundant with TypeMapEntry->specTypes
Expand Down Expand Up @@ -408,6 +408,7 @@ struct _jl_method_instance_t {
// bit 2: The ->backedges field is currently being walked higher up the stack - entries may be deleted, but not moved
// bit 3: The ->backedges field was modified and should be compacted when clearing bit 2
_Atomic(uint8_t) flags;
_Atomic(uint8_t) dispatch_status; // bits defined in staticdata.jl
};
#define JL_MI_FLAGS_MASK_PRECOMPILED 0x01
#define JL_MI_FLAGS_MASK_DISPATCHED 0x02
Expand Down
1 change: 1 addition & 0 deletions src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void)
jl_atomic_store_relaxed(&mi->cache, NULL);
mi->cache_with_orig = 0;
jl_atomic_store_relaxed(&mi->flags, 0);
jl_atomic_store_relaxed(&mi->dispatch_status, 0);
return mi;
}

Expand Down
46 changes: 3 additions & 43 deletions src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -1853,6 +1853,9 @@ static void jl_write_values(jl_serializer_state *s) JL_GC_DISABLED
assert(f == s->s);
jl_method_instance_t *newmi = (jl_method_instance_t*)&f->buf[reloc_offset];
jl_atomic_store_relaxed(&newmi->flags, 0);
if (s->incremental) {
jl_atomic_store_relaxed(&newmi->dispatch_status, 0);
}
}
else if (jl_is_code_instance(v)) {
assert(f == s->s);
Expand Down Expand Up @@ -4547,49 +4550,6 @@ JL_DLLEXPORT jl_value_t *jl_restore_package_image_from_file(const char *fname, j
return mod;
}

JL_DLLEXPORT void _jl_promote_ci_to_current(jl_code_instance_t *ci, size_t validated_world) JL_NOTSAFEPOINT
{
if (jl_atomic_load_relaxed(&ci->max_world) != validated_world)
return;
jl_atomic_store_relaxed(&ci->max_world, ~(size_t)0);
jl_svec_t *edges = jl_atomic_load_relaxed(&ci->edges);
for (size_t i = 0; i < jl_svec_len(edges); i++) {
jl_value_t *edge = jl_svecref(edges, i);
if (!jl_is_code_instance(edge))
continue;
_jl_promote_ci_to_current((jl_code_instance_t *)edge, validated_world);
}
}

JL_DLLEXPORT void jl_promote_ci_to_current(jl_code_instance_t *ci, size_t validated_world)
{
size_t current_world = jl_atomic_load_relaxed(&jl_world_counter);
// No need to acquire the lock if we've been invalidated anyway
if (current_world > validated_world)
return;
JL_LOCK(&world_counter_lock);
current_world = jl_atomic_load_relaxed(&jl_world_counter);
if (current_world == validated_world) {
_jl_promote_ci_to_current(ci, validated_world);
}
JL_UNLOCK(&world_counter_lock);
}

JL_DLLEXPORT void jl_promote_cis_to_current(jl_code_instance_t **cis, size_t n, size_t validated_world)
{
size_t current_world = jl_atomic_load_relaxed(&jl_world_counter);
// No need to acquire the lock if we've been invalidated anyway
if (current_world > validated_world)
return;
JL_LOCK(&world_counter_lock);
current_world = jl_atomic_load_relaxed(&jl_world_counter);
if (current_world == validated_world) {
for (size_t i = 0; i < n; i++) {
_jl_promote_ci_to_current(cis[i], validated_world);
}
}
JL_UNLOCK(&world_counter_lock);
}

#ifdef __cplusplus
}
Expand Down
2 changes: 1 addition & 1 deletion test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ for (T, c) in (
(Core.CodeInfo, []),
(Core.CodeInstance, [:next, :min_world, :max_world, :inferred, :edges, :debuginfo, :ipo_purity_bits, :invoke, :specptr, :specsigflags, :precompile, :time_compile]),
(Core.Method, [:primary_world, :did_scan_source, :dispatch_status]),
(Core.MethodInstance, [:cache, :flags]),
(Core.MethodInstance, [:cache, :flags, :dispatch_status]),
(Core.MethodTable, [:defs]),
(Core.MethodCache, [:leafcache, :cache, :var""]),
(Core.TypeMapEntry, [:next, :min_world, :max_world]),
Expand Down