Skip to content

Commit ac69e97

Browse files
committed
fix #46778, precompile() for abstract but compileable signatures
1 parent ecf9e56 commit ac69e97

File tree

2 files changed

+81
-26
lines changed

2 files changed

+81
-26
lines changed

src/gf.c

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,39 @@ JL_DLLEXPORT jl_value_t *jl_normalize_to_compilable_sig(jl_methtable_t *mt, jl_t
22552255
return is_compileable ? (jl_value_t*)tt : jl_nothing;
22562256
}
22572257

2258+
// return a MethodInstance for a compileable method_match
2259+
jl_method_instance_t *jl_method_match_to_mi(jl_method_match_t *match, size_t world, size_t min_valid, size_t max_valid, int mt_cache)
2260+
{
2261+
jl_method_t *m = match->method;
2262+
jl_svec_t *env = match->sparams;
2263+
jl_tupletype_t *ti = match->spec_types;
2264+
jl_method_instance_t *mi = NULL;
2265+
if (jl_is_datatype(ti)) {
2266+
jl_methtable_t *mt = jl_method_get_table(m);
2267+
if ((jl_value_t*)mt != jl_nothing) {
2268+
// get the specialization without caching it
2269+
if (mt_cache && ((jl_datatype_t*)ti)->isdispatchtuple) {
2270+
// Since we also use this presence in the cache
2271+
// to trigger compilation when producing `.ji` files,
2272+
// inject it there now if we think it will be
2273+
// used via dispatch later (e.g. because it was hinted via a call to `precompile`)
2274+
JL_LOCK(&mt->writelock);
2275+
mi = cache_method(mt, &mt->cache, (jl_value_t*)mt, ti, m, world, min_valid, max_valid, env);
2276+
JL_UNLOCK(&mt->writelock);
2277+
}
2278+
else {
2279+
jl_value_t *tt = jl_normalize_to_compilable_sig(mt, ti, env, m);
2280+
JL_GC_PUSH1(&tt);
2281+
if (tt != jl_nothing) {
2282+
mi = jl_specializations_get_linfo(m, (jl_value_t*)tt, env);
2283+
}
2284+
JL_GC_POP();
2285+
}
2286+
}
2287+
}
2288+
return mi;
2289+
}
2290+
22582291
// compile-time method lookup
22592292
jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache)
22602293
{
@@ -2274,36 +2307,52 @@ jl_method_instance_t *jl_get_specialization1(jl_tupletype_t *types JL_PROPAGATES
22742307
*max_valid = max_valid2;
22752308
if (matches == jl_false || jl_array_len(matches) != 1 || ambig)
22762309
return NULL;
2277-
jl_value_t *tt = NULL;
2278-
JL_GC_PUSH2(&matches, &tt);
2310+
JL_GC_PUSH1(&matches);
22792311
jl_method_match_t *match = (jl_method_match_t*)jl_array_ptr_ref(matches, 0);
2280-
jl_method_t *m = match->method;
2281-
jl_svec_t *env = match->sparams;
2282-
jl_tupletype_t *ti = match->spec_types;
2283-
jl_method_instance_t *nf = NULL;
2284-
if (jl_is_datatype(ti)) {
2285-
jl_methtable_t *mt = jl_method_get_table(m);
2286-
if ((jl_value_t*)mt != jl_nothing) {
2287-
// get the specialization without caching it
2288-
if (mt_cache && ((jl_datatype_t*)ti)->isdispatchtuple) {
2289-
// Since we also use this presence in the cache
2290-
// to trigger compilation when producing `.ji` files,
2291-
// inject it there now if we think it will be
2292-
// used via dispatch later (e.g. because it was hinted via a call to `precompile`)
2293-
JL_LOCK(&mt->writelock);
2294-
nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, ti, m, world, min_valid2, max_valid2, env);
2295-
JL_UNLOCK(&mt->writelock);
2296-
}
2297-
else {
2298-
tt = jl_normalize_to_compilable_sig(mt, ti, env, m);
2299-
if (tt != jl_nothing) {
2300-
nf = jl_specializations_get_linfo(m, (jl_value_t*)tt, env);
2301-
}
2312+
jl_method_instance_t *mi = jl_method_match_to_mi(match, world, min_valid2, max_valid2, mt_cache);
2313+
JL_GC_POP();
2314+
return mi;
2315+
}
2316+
2317+
// Get a MethodInstance for a precompile() call. This uses a special kind of lookup that
2318+
// tries to find a method for which the requested signature is compileable.
2319+
jl_method_instance_t *jl_get_compile_hint_specialization(jl_tupletype_t *types JL_PROPAGATES_ROOT, size_t world, size_t *min_valid, size_t *max_valid, int mt_cache)
2320+
{
2321+
if (jl_has_free_typevars((jl_value_t*)types))
2322+
return NULL; // don't poison the cache due to a malformed query
2323+
if (!jl_has_concrete_subtype((jl_value_t*)types))
2324+
return NULL;
2325+
2326+
size_t min_valid2 = 1;
2327+
size_t max_valid2 = ~(size_t)0;
2328+
int ambig = 0;
2329+
jl_value_t *matches = jl_matching_methods(types, jl_nothing, -1, 1, world, &min_valid2, &max_valid2, &ambig);
2330+
if (*min_valid < min_valid2)
2331+
*min_valid = min_valid2;
2332+
if (*max_valid > max_valid2)
2333+
*max_valid = max_valid2;
2334+
size_t i, n = jl_array_len(matches);
2335+
if (n == 0)
2336+
return NULL;
2337+
JL_GC_PUSH1(&matches);
2338+
jl_method_match_t *match = NULL;
2339+
if (n == 1) {
2340+
match = (jl_method_match_t*)jl_array_ptr_ref(matches, 0);
2341+
}
2342+
else {
2343+
for (i = 0; i < n; i++) {
2344+
jl_method_match_t *match1 = (jl_method_match_t*)jl_array_ptr_ref(matches, i);
2345+
if (jl_isa_compileable_sig(match1->spec_types, match1->method)) {
2346+
match = match1;
2347+
break;
23022348
}
23032349
}
23042350
}
2351+
jl_method_instance_t *mi = NULL;
2352+
if (match != NULL)
2353+
mi = jl_method_match_to_mi(match, world, min_valid2, max_valid2, mt_cache);
23052354
JL_GC_POP();
2306-
return nf;
2355+
return mi;
23072356
}
23082357

23092358
static void _generate_from_hint(jl_method_instance_t *mi, size_t world)
@@ -2370,7 +2419,7 @@ JL_DLLEXPORT int jl_compile_hint(jl_tupletype_t *types)
23702419
size_t world = jl_atomic_load_acquire(&jl_world_counter);
23712420
size_t min_valid = 0;
23722421
size_t max_valid = ~(size_t)0;
2373-
jl_method_instance_t *mi = jl_get_specialization1(types, world, &min_valid, &max_valid, 1);
2422+
jl_method_instance_t *mi = jl_get_compile_hint_specialization(types, world, &min_valid, &max_valid, 1);
23742423
if (mi == NULL)
23752424
return 0;
23762425
JL_GC_PROMISE_ROOTED(mi);

test/precompile.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,3 +1556,9 @@ end
15561556

15571557
empty!(Base.DEPOT_PATH)
15581558
append!(Base.DEPOT_PATH, original_depot_path)
1559+
1560+
@testset "issue 46778" begin
1561+
f46778(::Any, ::Type{Int}) = 1
1562+
f46778(::Any, ::DataType) = 2
1563+
@test precompile(Tuple{typeof(f46778), Int, DataType})
1564+
end

0 commit comments

Comments
 (0)