Skip to content

Commit f0e17a6

Browse files
committed
WIP: avoid invalidations when the overlap is ambiguous
In these cases, the new method would not be called because the call would be an ambiguity error instead.
1 parent db90631 commit f0e17a6

File tree

1 file changed

+33
-6
lines changed

1 file changed

+33
-6
lines changed

src/gf.c

+33-6
Original file line numberDiff line numberDiff line change
@@ -1682,18 +1682,41 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho
16821682
JL_UNLOCK(&mt->writelock);
16831683
}
16841684

1685+
static int jl_is_call_ambiguous(jl_value_t *types, jl_method_t *m)
1686+
{
1687+
if (m->ambig == jl_nothing)
1688+
return 0;
1689+
for (size_t i = 0; i < jl_array_len(m->ambig); i++) {
1690+
jl_typemap_entry_t *mambig = (jl_typemap_entry_t*)jl_array_ptr_ref(m->ambig, i);
1691+
if (mambig->min_world <= jl_world_counter && jl_world_counter <= mambig->max_world)
1692+
if (jl_subtype((jl_value_t*)types, (jl_value_t*)mambig->sig))
1693+
return 1;
1694+
}
1695+
return 0;
1696+
}
1697+
1698+
static int jl_is_function_call_ambiguous(jl_value_t *types JL_PROPAGATES_ROOT, size_t world)
1699+
{
1700+
jl_methtable_t *mt = jl_first_argument_datatype(types)->name->mt;
1701+
struct jl_typemap_assoc search = {types, world, NULL, 0, ~(size_t)0};
1702+
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, &search, 0, 1);
1703+
if (!entry)
1704+
return 0;
1705+
return jl_is_call_ambiguous(types, entry->func.method);
1706+
}
1707+
16851708
JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method, jl_tupletype_t *simpletype)
16861709
{
16871710
JL_TIMING(ADD_METHOD);
16881711
assert(jl_is_method(method));
16891712
assert(jl_is_mtable(mt));
16901713
jl_value_t *type = method->sig;
1691-
jl_value_t *oldvalue = NULL;
1714+
jl_value_t *oldvalue = NULL, *isect = NULL;
16921715
if (method->primary_world == 1)
16931716
method->primary_world = ++jl_world_counter;
16941717
size_t max_world = method->primary_world - 1;
16951718
int invalidated = 0;
1696-
JL_GC_PUSH1(&oldvalue);
1719+
JL_GC_PUSH2(&oldvalue, &isect);
16971720
JL_LOCK(&mt->writelock);
16981721
// first delete the existing entry (we'll disable it later)
16991722
struct jl_typemap_assoc search = {(jl_value_t*)type, method->primary_world, NULL, 0, ~(size_t)0};
@@ -1718,7 +1741,8 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
17181741
size_t ins = 0;
17191742
for (i = 1; i < na; i += 2) {
17201743
jl_value_t *backedgetyp = backedges[i - 1];
1721-
if (!jl_has_empty_intersection(backedgetyp, (jl_value_t*)type)) {
1744+
isect = jl_type_intersection(backedgetyp, (jl_value_t*)type);
1745+
if (isect != jl_bottom_type && !jl_is_function_call_ambiguous(isect, max_world)) {
17221746
jl_method_instance_t *backedge = (jl_method_instance_t*)backedges[i];
17231747
invalidate_method_instance(backedge, max_world, 0);
17241748
invalidated = 1;
@@ -1766,9 +1790,12 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
17661790
size_t i, l = jl_svec_len(specializations);
17671791
for (i = 0; i < l; i++) {
17681792
jl_method_instance_t *mi = (jl_method_instance_t*)jl_svecref(specializations, i);
1769-
if (mi != NULL && !jl_has_empty_intersection(type, (jl_value_t*)mi->specTypes))
1770-
if (invalidate_backedges(mi, max_world))
1771-
invalidated = 1;
1793+
if (mi != NULL) {
1794+
isect = jl_type_intersection(type, (jl_value_t*)mi->specTypes);
1795+
if (isect != jl_bottom_type && !jl_is_function_call_ambiguous(isect, max_world))
1796+
if (invalidate_backedges(mi, max_world))
1797+
invalidated = 1;
1798+
}
17721799
}
17731800
}
17741801
}

0 commit comments

Comments
 (0)