Skip to content

Commit fb129c5

Browse files
vtjnashKristofferC
authored andcommitted
extend Method.dispatch_status optimization to ml_matches_visitor also (#58335)
This extends the use of the optimization in #58291 to also apply to some uses of ml_matches also. (cherry picked from commit d1ec7d5)
1 parent 98e1487 commit fb129c5

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

src/gf.c

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,6 @@ static int get_intersect_visitor(jl_typemap_entry_t *oldentry, struct typemap_in
16911691
assert(jl_atomic_load_relaxed(&oldentry->min_world) <= jl_atomic_load_relaxed(&closure->newentry->min_world) && "old method cannot be newer than new method");
16921692
assert(jl_atomic_load_relaxed(&oldentry->max_world) != jl_atomic_load_relaxed(&closure->newentry->min_world) && "method cannot be added at the same time as method deleted");
16931693
// don't need to consider other similar methods if this oldentry will always fully intersect with them and dominates all of them
1694-
typemap_slurp_search(oldentry, &closure->match);
16951694
jl_method_t *oldmethod = oldentry->func.method;
16961695
if (closure->match.issubty // e.g. jl_subtype(closure->newentry.sig, oldentry->sig)
16971696
&& jl_subtype(oldmethod->sig, (jl_value_t*)closure->newentry->sig)) { // e.g. jl_type_equal(closure->newentry->sig, oldentry->sig)
@@ -1700,7 +1699,18 @@ static int get_intersect_visitor(jl_typemap_entry_t *oldentry, struct typemap_in
17001699
}
17011700
if (closure->shadowed == NULL)
17021701
closure->shadowed = (jl_value_t*)jl_alloc_vec_any(0);
1702+
if (closure->match.issubty) { // this should be rarely true (in fact, get_intersect_visitor should be rarely true), but might as well skip the rest of the scan fast anyways since we can
1703+
int only = jl_atomic_load_relaxed(&oldmethod->dispatch_status) & METHOD_SIG_LATEST_ONLY;
1704+
if (only) {
1705+
size_t len = jl_array_nrows(closure->shadowed);
1706+
if (len > 0)
1707+
jl_array_del_end((jl_array_t*)closure->shadowed, len);
1708+
jl_array_ptr_1d_push((jl_array_t*)closure->shadowed, (jl_value_t*)oldmethod);
1709+
return 0;
1710+
}
1711+
}
17031712
jl_array_ptr_1d_push((jl_array_t*)closure->shadowed, (jl_value_t*)oldmethod);
1713+
typemap_slurp_search(oldentry, &closure->match);
17041714
return 1;
17051715
}
17061716

@@ -3936,37 +3946,36 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio
39363946
if (closure->match.max_valid > max_world)
39373947
closure->match.max_valid = max_world;
39383948
jl_method_t *meth = ml->func.method;
3939-
if (closure->lim >= 0 && jl_is_dispatch_tupletype(meth->sig)) {
3940-
int replaced = 0;
3941-
// check if this is replaced, in which case we need to avoid double-counting it against the limit
3942-
// (although it will figure out later which one to keep and return)
3943-
size_t len = jl_array_nrows(closure->t);
3944-
for (int i = 0; i < len; i++) {
3945-
if (jl_types_equal(((jl_method_match_t*)jl_array_ptr_ref(closure->t, i))->method->sig, meth->sig)) {
3946-
replaced = 1;
3947-
break;
3948-
}
3949-
}
3950-
if (!replaced) {
3951-
if (closure->lim == 0)
3952-
return 0;
3953-
closure->lim--;
3949+
int only = jl_atomic_load_relaxed(&meth->dispatch_status) & METHOD_SIG_LATEST_ONLY;
3950+
if (closure->lim >= 0 && only) {
3951+
if (closure->lim == 0) {
3952+
closure->t = jl_an_empty_vec_any;
3953+
return 0;
39543954
}
3955+
closure->lim--;
39553956
}
3956-
// don't need to consider other similar methods if this ml will always fully intersect with them and dominates all of them
3957-
if (!closure->include_ambiguous || closure->lim != -1)
3958-
typemap_slurp_search(ml, &closure->match);
39593957
closure->matc = make_method_match((jl_tupletype_t*)closure->match.ti,
39603958
closure->match.env, meth,
39613959
closure->match.issubty ? FULLY_COVERS : NOT_FULLY_COVERS);
39623960
size_t len = jl_array_nrows(closure->t);
3961+
if (closure->match.issubty && only) {
3962+
if (len == 0)
3963+
closure->t = (jl_value_t*)jl_alloc_vec_any(1);
3964+
else if (len > 1)
3965+
jl_array_del_end((jl_array_t*)closure->t, len - 1);
3966+
jl_array_ptr_set(closure->t, 0, (jl_value_t*)closure->matc);
3967+
return 0;
3968+
}
39633969
if (len == 0) {
39643970
closure->t = (jl_value_t*)jl_alloc_vec_any(1);
39653971
jl_array_ptr_set(closure->t, 0, (jl_value_t*)closure->matc);
39663972
}
39673973
else {
39683974
jl_array_ptr_1d_push((jl_array_t*)closure->t, (jl_value_t*)closure->matc);
39693975
}
3976+
// don't need to consider other similar methods if this ml will always fully intersect with them and dominates all of them
3977+
if (!closure->include_ambiguous || closure->lim != -1)
3978+
typemap_slurp_search(ml, &closure->match);
39703979
return 1;
39713980
}
39723981

@@ -4347,19 +4356,19 @@ static jl_value_t *ml_matches(jl_methtable_t *mt,
43474356
return env.t;
43484357
}
43494358
}
4350-
if (!ml_mtable_visitor(mt, &env.match)) {
4359+
if (!ml_mtable_visitor(mt, &env.match) && env.t == jl_an_empty_vec_any) {
43514360
JL_GC_POP();
4352-
// if we return early, set only the min/max valid collected from matching
4361+
// if we return early without returning methods, set only the min/max valid collected from matching
43534362
*min_valid = env.match.min_valid;
43544363
*max_valid = env.match.max_valid;
43554364
return jl_nothing;
43564365
}
43574366
}
43584367
else {
43594368
// else: scan everything
4360-
if (!jl_foreach_reachable_mtable(ml_mtable_visitor, &env.match)) {
4369+
if (!jl_foreach_reachable_mtable(ml_mtable_visitor, &env.match) && env.t == jl_an_empty_vec_any) {
43614370
JL_GC_POP();
4362-
// if we return early, set only the min/max valid collected from matching
4371+
// if we return early without returning methods, set only the min/max valid collected from matching
43634372
*min_valid = env.match.min_valid;
43644373
*max_valid = env.match.max_valid;
43654374
return jl_nothing;

0 commit comments

Comments
 (0)