Skip to content

Commit

Permalink
Merge pull request #47741 from JuliaLang/jn/backports-release-1.8-47685
Browse files Browse the repository at this point in the history
[release 1.8] backport of precompile: serialize the full edges graph (#46920)
  • Loading branch information
KristofferC authored and KristofferC committed Dec 14, 2022
1 parent fd92d74 commit 5a1d35e
Show file tree
Hide file tree
Showing 7 changed files with 720 additions and 415 deletions.
1,048 changes: 657 additions & 391 deletions src/dump.c

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ JL_DLLEXPORT jl_code_instance_t* jl_new_codeinst(
int32_t const_flags, size_t min_world, size_t max_world,
uint32_t ipo_effects, uint32_t effects, jl_value_t *argescapes,
uint8_t relocatability);
JL_DLLEXPORT void jl_mi_cache_insert(jl_method_instance_t *mi JL_ROOTING_ARGUMENT,
jl_code_instance_t *ci JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);

jl_datatype_t *jl_mk_builtin_func(jl_datatype_t *dt, const char *name, jl_fptr_args_t fptr) JL_GC_DISABLED
{
Expand Down Expand Up @@ -436,7 +434,10 @@ JL_DLLEXPORT void jl_mi_cache_insert(jl_method_instance_t *mi JL_ROOTING_ARGUMEN
JL_GC_PUSH1(&ci);
if (jl_is_method(mi->def.method))
JL_LOCK(&mi->def.method->writelock);
ci->next = mi->cache;
jl_code_instance_t *oldci = mi->cache;
ci->next = oldci;
if (oldci)
jl_gc_wb(ci, oldci);
jl_atomic_store_release(&mi->cache, ci);
jl_gc_wb(mi, ci);
if (jl_is_method(mi->def.method))
Expand Down Expand Up @@ -1423,6 +1424,7 @@ static void invalidate_method_instance(void (*f)(jl_code_instance_t*), jl_method
jl_array_ptr_1d_push(_jl_debug_method_invalidation, boxeddepth);
JL_GC_POP();
}
//jl_static_show(JL_STDERR, (jl_value_t*)replaced);
if (!jl_is_method(replaced->def.method))
return; // shouldn't happen, but better to be safe
JL_LOCK(&replaced->def.method->writelock);
Expand Down Expand Up @@ -1450,10 +1452,11 @@ static void invalidate_method_instance(void (*f)(jl_code_instance_t*), jl_method
}

// invalidate cached methods that overlap this definition
void invalidate_backedges(void (*f)(jl_code_instance_t*), jl_method_instance_t *replaced_mi, size_t max_world, const char *why)
static void invalidate_backedges(void (*f)(jl_code_instance_t*), jl_method_instance_t *replaced_mi, size_t max_world, const char *why)
{
JL_LOCK(&replaced_mi->def.method->writelock);
jl_array_t *backedges = replaced_mi->backedges;
//jl_static_show(JL_STDERR, (jl_value_t*)replaced_mi);
if (backedges) {
// invalidate callers (if any)
replaced_mi->backedges = NULL;
Expand Down
1 change: 0 additions & 1 deletion src/jl_exported_funcs.inc
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@
XX(jl_environ) \
XX(jl_eof_error) \
XX(jl_eqtable_get) \
XX(jl_eqtable_nextind) \
XX(jl_eqtable_pop) \
XX(jl_eqtable_put) \
XX(jl_errno) \
Expand Down
8 changes: 5 additions & 3 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -1635,9 +1635,10 @@ STATIC_INLINE jl_function_t *jl_get_function(jl_module_t *m, const char *name)
}

// eq hash tables
JL_DLLEXPORT jl_array_t *jl_eqtable_put(jl_array_t *h, jl_value_t *key, jl_value_t *val, int *inserted);
JL_DLLEXPORT jl_value_t *jl_eqtable_get(jl_array_t *h, jl_value_t *key, jl_value_t *deflt) JL_NOTSAFEPOINT;
jl_value_t *jl_eqtable_getkey(jl_array_t *h, jl_value_t *key, jl_value_t *deflt) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_array_t *jl_eqtable_put(jl_array_t *h JL_ROOTING_ARGUMENT, jl_value_t *key, jl_value_t *val JL_ROOTED_ARGUMENT, int *inserted);
JL_DLLEXPORT jl_value_t *jl_eqtable_get(jl_array_t *h JL_PROPAGATES_ROOT, jl_value_t *key, jl_value_t *deflt) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_value_t *jl_eqtable_pop(jl_array_t *h, jl_value_t *key, jl_value_t *deflt, int *found);
jl_value_t *jl_eqtable_getkey(jl_array_t *h JL_PROPAGATES_ROOT, jl_value_t *key, jl_value_t *deflt) JL_NOTSAFEPOINT;

// system information
JL_DLLEXPORT int jl_errno(void) JL_NOTSAFEPOINT;
Expand Down Expand Up @@ -1814,6 +1815,7 @@ JL_DLLEXPORT jl_value_t *jl_compress_argnames(jl_array_t *syms);
JL_DLLEXPORT jl_array_t *jl_uncompress_argnames(jl_value_t *syms);
JL_DLLEXPORT jl_value_t *jl_uncompress_argname_n(jl_value_t *syms, size_t i);


JL_DLLEXPORT int jl_is_operator(char *sym);
JL_DLLEXPORT int jl_is_unary_operator(char *sym);
JL_DLLEXPORT int jl_is_unary_and_binary_operator(char *sym);
Expand Down
8 changes: 6 additions & 2 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,6 @@ extern tracer_cb jl_newmeth_tracer;
void jl_call_tracer(tracer_cb callback, jl_value_t *tracee);
void print_func_loc(JL_STREAM *s, jl_method_t *m);
extern jl_array_t *_jl_debug_method_invalidation JL_GLOBALLY_ROOTED;
void invalidate_backedges(void (*f)(jl_code_instance_t*), jl_method_instance_t *replaced_mi, size_t max_world, const char *why);

extern JL_DLLEXPORT size_t jl_page_size;
extern jl_function_t *jl_typeinf_func;
Expand Down Expand Up @@ -642,15 +641,18 @@ jl_method_instance_t *jl_method_lookup(jl_value_t **args, size_t nargs, size_t w

jl_value_t *jl_gf_invoke_by_method(jl_method_t *method, jl_value_t *gf, jl_value_t **args, size_t nargs);
jl_value_t *jl_gf_invoke(jl_value_t *types, jl_value_t *f, jl_value_t **args, size_t nargs);
JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup_worlds(jl_value_t *types, jl_value_t *mt, size_t world, size_t *min_world, size_t *max_world);
JL_DLLEXPORT jl_value_t *jl_matching_methods(jl_tupletype_t *types, jl_value_t *mt, int lim, int include_ambiguous,
size_t world, size_t *min_valid, size_t *max_valid, int *ambig);
JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup_worlds(jl_value_t *types, jl_value_t *mt, size_t world, size_t *min_world, size_t *max_world);


JL_DLLEXPORT jl_datatype_t *jl_first_argument_datatype(jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_value_t *jl_argument_datatype(jl_value_t *argt JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_methtable_t *jl_method_table_for(
jl_value_t *argtypes JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
JL_DLLEXPORT jl_methtable_t *jl_method_get_table(
jl_method_t *method) JL_NOTSAFEPOINT;
jl_method_t *method JL_PROPAGATES_ROOT) JL_NOTSAFEPOINT;
jl_methtable_t *jl_argument_method_table(jl_value_t *argt JL_PROPAGATES_ROOT);

JL_DLLEXPORT int jl_pointer_egal(jl_value_t *t);
Expand Down Expand Up @@ -874,6 +876,8 @@ JL_DLLEXPORT jl_method_instance_t *jl_specializations_get_linfo(
jl_method_instance_t *jl_specializations_get_or_insert(jl_method_instance_t *mi_ins);
JL_DLLEXPORT void jl_method_instance_add_backedge(jl_method_instance_t *callee, jl_method_instance_t *caller);
JL_DLLEXPORT void jl_method_table_add_backedge(jl_methtable_t *mt, jl_value_t *typ, jl_value_t *caller);
JL_DLLEXPORT void jl_mi_cache_insert(jl_method_instance_t *mi JL_ROOTING_ARGUMENT,
jl_code_instance_t *ci JL_ROOTED_ARGUMENT JL_MAYBE_UNROOTED);

uint32_t jl_module_next_counter(jl_module_t *m) JL_NOTSAFEPOINT;
jl_tupletype_t *arg_type_tuple(jl_value_t *arg1, jl_value_t **args, size_t nargs);
Expand Down
1 change: 0 additions & 1 deletion src/typemap.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ static jl_typemap_t *mtcache_hash_lookup(jl_array_t *cache JL_PROPAGATES_ROOT, j
if (cache == (jl_array_t*)jl_an_empty_vec_any)
return (jl_typemap_t*)jl_nothing;
jl_typemap_t *ml = (jl_typemap_t*)jl_eqtable_get(cache, ty, jl_nothing);
JL_GC_PROMISE_ROOTED(ml); // clang-sa doesn't trust our JL_PROPAGATES_ROOT claim
return ml;
}

Expand Down
58 changes: 45 additions & 13 deletions test/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -630,16 +630,11 @@ precompile_test_harness("code caching") do dir
msize = which(size, (Vector{<:Any},))
hasspec = false
for i = 1:length(msize.specializations)
if isassigned(msize.specializations, i)
mi = msize.specializations[i]
if isa(mi, Core.MethodInstance)
tt = Base.unwrap_unionall(mi.specTypes)
if tt.parameters[2] == Vector{Cacheb8321416e8a3e2f1.X}
if isdefined(mi, :cache) && isa(mi.cache, Core.CodeInstance) && mi.cache.max_world == typemax(UInt) && mi.cache.inferred !== nothing
hasspec = true
break
end
end
mi = msize.specializations[i]
if isa(mi, Core.MethodInstance) && mi.specTypes == Tuple{typeof(size),Vector{Cacheb8321416e8a3e2f1.X}}
if isdefined(mi, :cache) && isa(mi.cache, Core.CodeInstance) && mi.cache.max_world == typemax(UInt) && mi.cache.inferred !== nothing
hasspec = true
break
end
end
end
Expand All @@ -659,7 +654,7 @@ precompile_test_harness("code caching") do dir
# Check that internal methods and their roots are accounted appropriately
minternal = which(M.getelsize, (Vector,))
mi = minternal.specializations[1]
@test Base.unwrap_unionall(mi.specTypes).parameters[2] == Vector{Int32}
@test mi.specTypes == Tuple{typeof(M.getelsize),Vector{Int32}}
ci = mi.cache
@test ci.relocatability == 1
@test ci.inferred !== nothing
Expand Down Expand Up @@ -775,7 +770,7 @@ precompile_test_harness("code caching") do dir
end
end

# Invalidations (this test is adapted from from SnoopCompile)
# Invalidations (this test is adapted from SnoopCompile)
function hasvalid(mi, world)
isdefined(mi, :cache) || return false
ci = mi.cache
Expand Down Expand Up @@ -805,6 +800,10 @@ precompile_test_harness("code caching") do dir
build_stale(37)
stale('c')
## Reporting tests (unrelated to the above)
nbits(::Int8) = 8
nbits(::Int16) = 16
end
"""
)
Expand All @@ -823,6 +822,11 @@ precompile_test_harness("code caching") do dir
# force precompilation
useA()
## Reporting tests
call_nbits(x::Integer) = $StaleA.nbits(x)
map_nbits() = map(call_nbits, Integer[Int8(1), Int16(1)])
map_nbits()
end
"""
)
Expand All @@ -844,9 +848,12 @@ precompile_test_harness("code caching") do dir
Base.compilecache(Base.PkgId(string(pkg)))
end
@eval using $StaleA
MA = getfield(@__MODULE__, StaleA)
Base.eval(MA, :(nbits(::UInt8) = 8))
@eval using $StaleC
invalidations = ccall(:jl_debug_method_invalidation, Any, (Cint,), 1)
@eval using $StaleB
MA = getfield(@__MODULE__, StaleA)
ccall(:jl_debug_method_invalidation, Any, (Cint,), 0)
MB = getfield(@__MODULE__, StaleB)
MC = getfield(@__MODULE__, StaleC)
world = Base.get_world_counter()
Expand All @@ -871,6 +878,31 @@ precompile_test_harness("code caching") do dir
m = only(methods(MC.call_buildstale))
mi = m.specializations[1]
@test hasvalid(mi, world) # was compiled with the new method

# Reporting test
@test all(i -> isassigned(invalidations, i), eachindex(invalidations))
m = only(methods(MB.call_nbits))
for mi in m.specializations
mi === nothing && continue
hv = hasvalid(mi, world)
@test mi.specTypes.parameters[end] === Integer ? !hv : hv
end

idxs = findall(==("verify_methods"), invalidations)
idxsbits = filter(idxs) do i
mi = invalidations[i-1]
mi.def == m
end
idx = only(idxsbits)
tagbad = invalidations[idx+1]
@test isa(tagbad, Int32)
j = findfirst(==(tagbad), invalidations)
@test invalidations[j-1] == "insert_backedges_callee"
@test isa(invalidations[j-2], Type)
@test isa(invalidations[j+1], Vector{Any}) # [nbits(::UInt8)]

m = only(methods(MB.map_nbits))
@test !hasvalid(m.specializations[1], world+1) # insert_backedges invalidations also trigger their backedges
end

# test --compiled-modules=no command line option
Expand Down

0 comments on commit 5a1d35e

Please sign in to comment.