@@ -296,7 +296,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, jl_sym_t *sname, jl_fptr_args_t fptr)
296296 m -> isva = 1 ;
297297 m -> nargs = 2 ;
298298 jl_atomic_store_relaxed (& m -> primary_world , 1 );
299- jl_atomic_store_relaxed (& m -> dispatch_status , METHOD_ISMINMAX_INVOKE_LATEST | METHOD_ISMINMAX_CALL_LATEST );
299+ jl_atomic_store_relaxed (& m -> dispatch_status , METHOD_SIG_LATEST_ONLY | METHOD_SIG_LATEST_ONLY );
300300 m -> sig = (jl_value_t * )jl_anytuple_type ;
301301 m -> slot_syms = jl_an_empty_string ;
302302 m -> nospecialize = 0 ;
@@ -1908,7 +1908,7 @@ static int is_replacing(char ambig, jl_value_t *type, jl_method_t *m, jl_method_
19081908 // since m2 was also a previous match over isect,
19091909 // see if m was previously dominant over all m2
19101910 // or if this was already ambiguous before
1911- if (ambig ! = morespec_is && !jl_type_morespecific (m -> sig , m2 -> sig )) {
1911+ if (ambig = = morespec_is && !jl_type_morespecific (m -> sig , m2 -> sig )) {
19121912 // m and m2 were previously ambiguous over the full intersection of mi with type, and will still be ambiguous with addition of type
19131913 return 0 ;
19141914 }
@@ -2334,13 +2334,17 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
23342334 // then check what entries we replaced
23352335 oldvalue = get_intersect_matches (jl_atomic_load_relaxed (& mt -> defs ), newentry , & replaced , jl_cachearg_offset (mt ), max_world );
23362336 int invalidated = 0 ;
2337+ int only = 1 ; // compute if this will be currently the only result that would returned from `ml_matches` given `sig`
23372338 if (replaced ) {
23382339 oldvalue = (jl_value_t * )replaced ;
2340+ jl_method_t * m = replaced -> func .method ;
2341+ int m_dispatch = jl_atomic_load_relaxed (& m -> dispatch_status );
23392342 invalidated = 1 ;
2340- method_overwrite (newentry , replaced -> func . method );
2343+ method_overwrite (newentry , m );
23412344 // this is an optimized version of below, given we know the type-intersection is exact
2342- jl_method_table_invalidate (mt , replaced -> func .method , max_world );
2343- jl_atomic_store_relaxed (& replaced -> func .method -> dispatch_status , 0 );
2345+ jl_method_table_invalidate (mt , m , max_world );
2346+ jl_atomic_store_relaxed (& m -> dispatch_status , 0 );
2347+ only = m_dispatch & METHOD_SIG_LATEST_ONLY ;
23442348 }
23452349 else {
23462350 jl_method_t * const * d ;
@@ -2412,8 +2416,10 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
24122416 memset (morespec , morespec_unknown , n );
24132417 for (j = 0 ; j < n ; j ++ ) {
24142418 jl_method_t * m = d [j ];
2415- if (morespec [j ] == (char )morespec_is )
2419+ if (morespec [j ] == (char )morespec_is ) {
2420+ only = 0 ;
24162421 continue ;
2422+ }
24172423 loctag = jl_atomic_load_relaxed (& m -> specializations ); // use loctag for a gcroot
24182424 _Atomic(jl_method_instance_t * ) * data ;
24192425 size_t l ;
@@ -2443,7 +2449,7 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
24432449 // not actually shadowing--the existing method is still better
24442450 break ;
24452451 if (ambig == morespec_unknown )
2446- ambig = jl_type_morespecific (type , m -> sig ) ? morespec_is : morespec_isnot ;
2452+ ambig = jl_type_morespecific (type , m -> sig ) ? morespec_isnot : morespec_is ;
24472453 // replacing a method--see if this really was the selected method previously
24482454 // over the intersection (not ambiguous) and the new method will be selected now (morespec_is)
24492455 int replaced_dispatch = is_replacing (ambig , type , m , d , n , isect , isect2 , morespec );
@@ -2460,6 +2466,20 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
24602466 invalidated |= invalidatedmi ;
24612467 }
24622468 }
2469+ // now compute and store updates to METHOD_SIG_LATEST_ONLY
2470+ int m_dispatch = jl_atomic_load_relaxed (& m -> dispatch_status );
2471+ if (m_dispatch & METHOD_SIG_LATEST_ONLY ) {
2472+ if (morespec [j ] == (char )morespec_unknown )
2473+ morespec [j ] = (char )(jl_type_morespecific (m -> sig , type ) ? morespec_is : morespec_isnot );
2474+ if (morespec [j ] == (char )morespec_isnot )
2475+ jl_atomic_store_relaxed (& m -> dispatch_status , ~METHOD_SIG_LATEST_ONLY & m_dispatch );
2476+ }
2477+ if (only ) {
2478+ if (morespec [j ] == (char )morespec_is || ambig == morespec_is ||
2479+ (morespec [j ] == (char )morespec_unknown && ambig == morespec_unknown && !jl_type_morespecific (type , m -> sig ))) {
2480+ only = 0 ;
2481+ }
2482+ }
24632483 }
24642484 if (jl_array_nrows (oldmi )) {
24652485 // search mt->cache and leafcache and drop anything that might overlap with the new method
@@ -2484,15 +2504,14 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
24842504 }
24852505 }
24862506 }
2487- // TODO: computed and store updates to METHOD_ISMINMAX_CALL_LATEST here
24882507 }
24892508 if (invalidated && _jl_debug_method_invalidation ) {
24902509 jl_array_ptr_1d_push (_jl_debug_method_invalidation , (jl_value_t * )method );
24912510 loctag = jl_cstr_to_string ("jl_method_table_insert" );
24922511 jl_array_ptr_1d_push (_jl_debug_method_invalidation , loctag );
24932512 }
24942513 jl_atomic_store_relaxed (& newentry -> max_world , ~(size_t )0 );
2495- jl_atomic_store_relaxed (& method -> dispatch_status , METHOD_ISMINMAX_INVOKE_LATEST ) ; // TODO: this should be sequenced after the world counter store
2514+ jl_atomic_store_relaxed (& method -> dispatch_status , METHOD_SIG_LATEST_WHICH | ( only ? METHOD_SIG_LATEST_ONLY : 0 )) ; // TODO: this should be sequenced fully after the world counter store
24962515 JL_UNLOCK (& mt -> writelock );
24972516 JL_GC_POP ();
24982517}
0 commit comments