@@ -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 -> deleted_world , ~( size_t ) 0 );
299+ jl_atomic_store_relaxed (& m -> dispatch_status , METHOD_ISMINMAX_INVOKE_LATEST | METHOD_ISMINMAX_CALL_LATEST );
300300 m -> sig = (jl_value_t * )jl_anytuple_type ;
301301 m -> slot_syms = jl_an_empty_string ;
302302 m -> nospecialize = 0 ;
@@ -307,7 +307,7 @@ void jl_mk_builtin_func(jl_datatype_t *dt, jl_sym_t *sname, jl_fptr_args_t fptr)
307307 JL_GC_PUSH2 (& m , & newentry );
308308
309309 newentry = jl_typemap_alloc (jl_anytuple_type , NULL , jl_emptysvec ,
310- (jl_value_t * )m , jl_atomic_load_relaxed ( & m -> primary_world ), jl_atomic_load_relaxed ( & m -> deleted_world ) );
310+ (jl_value_t * )m , 1 , ~( size_t ) 0 );
311311 jl_typemap_insert (& mt -> defs , (jl_value_t * )mt , newentry , jl_cachearg_offset (mt ));
312312
313313 jl_method_instance_t * mi = jl_get_specialized (m , (jl_value_t * )jl_anytuple_type , jl_emptysvec );
@@ -2242,17 +2242,22 @@ JL_DLLEXPORT void jl_method_table_disable(jl_methtable_t *mt, jl_method_t *metho
22422242 JL_LOCK (& world_counter_lock );
22432243 if (!jl_atomic_load_relaxed (& allow_new_worlds ))
22442244 jl_error ("Method changes have been disabled via a call to disable_new_worlds." );
2245- JL_LOCK (& mt -> writelock );
2246- // Narrow the world age on the method to make it uncallable
2247- size_t world = jl_atomic_load_relaxed (& jl_world_counter );
2248- assert (method == methodentry -> func .method );
2249- assert (jl_atomic_load_relaxed (& method -> deleted_world ) == ~(size_t )0 );
2250- jl_atomic_store_relaxed (& method -> deleted_world , world );
2251- jl_atomic_store_relaxed (& methodentry -> max_world , world );
2252- jl_method_table_invalidate (mt , method , world );
2253- jl_atomic_store_release (& jl_world_counter , world + 1 );
2254- JL_UNLOCK (& mt -> writelock );
2245+ int enabled = jl_atomic_load_relaxed (& methodentry -> max_world ) == ~(size_t )0 ;
2246+ if (enabled ) {
2247+ JL_LOCK (& mt -> writelock );
2248+ // Narrow the world age on the method to make it uncallable
2249+ size_t world = jl_atomic_load_relaxed (& jl_world_counter );
2250+ assert (method == methodentry -> func .method );
2251+ jl_atomic_store_relaxed (& method -> dispatch_status , 0 );
2252+ assert (jl_atomic_load_relaxed (& methodentry -> max_world ) == ~(size_t )0 );
2253+ jl_atomic_store_relaxed (& methodentry -> max_world , world );
2254+ jl_method_table_invalidate (mt , method , world );
2255+ jl_atomic_store_release (& jl_world_counter , world + 1 );
2256+ JL_UNLOCK (& mt -> writelock );
2257+ }
22552258 JL_UNLOCK (& world_counter_lock );
2259+ if (!enabled )
2260+ jl_errorf ("Method of %s already disabled" , jl_symbol_name (method -> name ));
22562261}
22572262
22582263static int jl_type_intersection2 (jl_value_t * t1 , jl_value_t * t2 , jl_value_t * * isect JL_REQUIRE_ROOTED_SLOT , jl_value_t * * isect2 JL_REQUIRE_ROOTED_SLOT )
@@ -2292,9 +2297,8 @@ jl_typemap_entry_t *jl_method_table_add(jl_methtable_t *mt, jl_method_t *method,
22922297 JL_LOCK (& mt -> writelock );
22932298 // add our new entry
22942299 assert (jl_atomic_load_relaxed (& method -> primary_world ) == ~(size_t )0 ); // min-world
2295- assert (jl_atomic_load_relaxed (& method -> deleted_world ) == 1 ); // max-world
2296- newentry = jl_typemap_alloc ((jl_tupletype_t * )method -> sig , simpletype , jl_emptysvec , (jl_value_t * )method ,
2297- jl_atomic_load_relaxed (& method -> primary_world ), jl_atomic_load_relaxed (& method -> deleted_world ));
2300+ assert (jl_atomic_load_relaxed (& method -> dispatch_status ) == 0 );
2301+ newentry = jl_typemap_alloc ((jl_tupletype_t * )method -> sig , simpletype , jl_emptysvec , (jl_value_t * )method , ~(size_t )0 , 1 );
22982302 jl_typemap_insert (& mt -> defs , (jl_value_t * )mt , newentry , jl_cachearg_offset (mt ));
22992303 update_max_args (mt , method -> sig );
23002304 JL_UNLOCK (& mt -> writelock );
@@ -2315,7 +2319,7 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
23152319 JL_LOCK (& mt -> writelock );
23162320 size_t world = jl_atomic_load_relaxed (& method -> primary_world );
23172321 assert (world == jl_atomic_load_relaxed (& jl_world_counter ) + 1 ); // min-world
2318- assert (jl_atomic_load_relaxed (& method -> deleted_world ) == ~( size_t ) 0 ); // max-world
2322+ assert (jl_atomic_load_relaxed (& method -> dispatch_status ) == 0 );
23192323 assert (jl_atomic_load_relaxed (& newentry -> min_world ) == ~(size_t )0 );
23202324 assert (jl_atomic_load_relaxed (& newentry -> max_world ) == 1 );
23212325 jl_atomic_store_relaxed (& newentry -> min_world , world );
@@ -2336,6 +2340,7 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
23362340 method_overwrite (newentry , replaced -> func .method );
23372341 // this is an optimized version of below, given we know the type-intersection is exact
23382342 jl_method_table_invalidate (mt , replaced -> func .method , max_world );
2343+ jl_atomic_store_relaxed (& replaced -> func .method -> dispatch_status , 0 );
23392344 }
23402345 else {
23412346 jl_method_t * const * d ;
@@ -2479,13 +2484,15 @@ void jl_method_table_activate(jl_methtable_t *mt, jl_typemap_entry_t *newentry)
24792484 }
24802485 }
24812486 }
2487+ // TODO: computed and store updates to METHOD_ISMINMAX_CALL_LATEST here
24822488 }
24832489 if (invalidated && _jl_debug_method_invalidation ) {
24842490 jl_array_ptr_1d_push (_jl_debug_method_invalidation , (jl_value_t * )method );
24852491 loctag = jl_cstr_to_string ("jl_method_table_insert" );
24862492 jl_array_ptr_1d_push (_jl_debug_method_invalidation , loctag );
24872493 }
2488- jl_atomic_store_relaxed (& newentry -> max_world , jl_atomic_load_relaxed (& method -> deleted_world ));
2494+ 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
24892496 JL_UNLOCK (& mt -> writelock );
24902497 JL_GC_POP ();
24912498}
@@ -2499,7 +2506,6 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
24992506 jl_error ("Method changes have been disabled via a call to disable_new_worlds." );
25002507 size_t world = jl_atomic_load_relaxed (& jl_world_counter ) + 1 ;
25012508 jl_atomic_store_relaxed (& method -> primary_world , world );
2502- jl_atomic_store_relaxed (& method -> deleted_world , ~(size_t )0 );
25032509 jl_method_table_activate (mt , newentry );
25042510 jl_atomic_store_release (& jl_world_counter , world );
25052511 JL_UNLOCK (& world_counter_lock );
@@ -3882,6 +3888,8 @@ static int ml_matches_visitor(jl_typemap_entry_t *ml, struct typemap_intersectio
38823888 closure -> match .min_valid = max_world + 1 ;
38833889 return 1 ;
38843890 }
3891+ if (closure -> match .max_valid > max_world )
3892+ closure -> match .max_valid = max_world ;
38853893 jl_method_t * meth = ml -> func .method ;
38863894 if (closure -> lim >= 0 && jl_is_dispatch_tupletype (meth -> sig )) {
38873895 int replaced = 0 ;
@@ -4554,12 +4562,9 @@ static jl_value_t *ml_matches(jl_methtable_t *mt,
45544562 jl_method_t * m = matc -> method ;
45554563 // method applicability is the same as typemapentry applicability
45564564 size_t min_world = jl_atomic_load_relaxed (& m -> primary_world );
4557- size_t max_world = jl_atomic_load_relaxed (& m -> deleted_world );
45584565 // intersect the env valid range with method lookup's inclusive valid range
45594566 if (env .match .min_valid < min_world )
45604567 env .match .min_valid = min_world ;
4561- if (env .match .max_valid > max_world )
4562- env .match .max_valid = max_world ;
45634568 }
45644569 if (mt && cache_result && ((jl_datatype_t * )unw )-> isdispatchtuple ) { // cache_result parameter keeps this from being recursive
45654570 if (len == 1 && !has_ambiguity ) {
0 commit comments